[net.micro.amiga] Fonts on the Amiga

jimb@daisy.UUCP (Jim Becker) (01/03/86)

I am trying to figure out how to add fonts to the
publically available fonts on the Amiga.. (to use 
some of the disk fonts). The documentation is incomplete..


Anyone willing to provide a code example of this process ?

- Jim Becker

robp@amiga.UUCP (Robert A. Peck) (01/09/86)

/* "whichfont.c" */

/* sample program that asks AvailFonts() to make a list of the fonts
 * that are available and makes a list of them, then opens a separate
 * window and prints a description of the various attributes that can
 * be applied to the fonts, in the font itself.  Notice that not all
 * fonts accept all attributes (garnet9 for example, won't underline)
 *
 * Also note, if you run this, that not all fonts are as easily readable
 * in the various bold and italicized modes.... this rendering is done
 * in a fixed manner by software and the fonts were not necessarily
 * designed to accept it.  It is always best to have a font that has
 * been designed with a bold or italic characteristic built-in rather
 * than try to bold-ize or italicize and existing plain font.
 */

/* Author:  Rob Peck  10/28/85  */

#define AFTABLESIZE 2000

#include <exec/types.h>
#include <exec/memory.h>
#include <libraries/dos.h>
#include <graphics/text.h>
#include <libraries/diskfont.h>
#include <intuition/intuition.h>

struct AvailFonts *af;
struct AvailFontsHeader *afh;
extern int AvailFonts();

struct TextFont *tf;
struct TextAttr ta;

ULONG DosBase;
ULONG DiskfontBase;
ULONG IntuitionBase;
ULONG GfxBase;

struct NewWindow nw = {
        10, 10,        /* starting position (left,top) */
        620,40,        /* width, height */
        -1,-1,          /* detailpen, blockpen */
        0,		/* flags for idcmp */
  WINDOWDEPTH|WINDOWSIZING|WINDOWDRAG|SIMPLE_REFRESH|ACTIVATE|GIMMEZEROZERO,
			/* window gadget flags */
        0,              /* pointer to 1st user gadget */
        NULL,           /* pointer to user check */
        "Text Font Test", /* title */
        NULL,           /* pointer to window screen */
        NULL,           /* pointer to super bitmap */
        100,45,         /* min width, height */
        640,200,        /* max width, height */
        WBENCHSCREEN};

struct Window *w;
struct RastPort *rp;

SHORT text_styles[ ] = { FS_NORMAL, FSF_UNDERLINED, FSF_ITALIC, FSF_BOLD, 
			FSF_ITALIC | FSF_BOLD, FSF_BOLD | FSF_UNDERLINED,
			FSF_ITALIC | FSF_BOLD | FSF_UNDERLINED };
		
char *text[ ] = { " Normal Text", " Underlined", " Italicized", " Bold", 
		  " Bold Italics", " Bold Underlined", 
		  " Bold Italic Underlined" };
char textlength[ ] = { 12, 11, 11, 5, 13, 16, 23 };

char *pointsize[] = { " 0"," 1"," 2"," 3"," 4"," 5"," 6"," 7"," 8"," 9",
                   "10","11","12","13","14","15","16","17","18","19",
                   "20","21","22","23","24","25","26","27","28","29",
                   "30","31"};

char fontname[40];
char dummy[100]; 	/* provided for string length calculation */
char outst[100];	/* build something to give to Text, see note in 
			 * the program body about algorithmically
			 * generated styles 
			 */

main()
{
	UBYTE fonttypes;
	int i,j,k,m;
	SHORT afsize;
	SHORT style;
	SHORT sEnd;	/* numerical position of end of string terminator,
			 * and coincidently the length of the string. */

	if( (DosBase = OpenLibrary("dos.library", 0)) == NULL) exit(-1);
	if((DiskfontBase=OpenLibrary("diskfont.library",0))==NULL) exit(-4);
	if((IntuitionBase=OpenLibrary("intuition.library",0))==NULL) exit(-2);
	if((GfxBase=OpenLibrary("graphics.library",0))==NULL) exit(-3);
	
	tf=NULL;	/* no font currently selected */
	afsize = AFTABLESIZE;	/* show how large a buffer is available */
	fonttypes = 0xff;	/* show us all font types */
	
	afh = (struct AvailFontsHeader *) AllocMem(afsize, MEMF_CLEAR);
	if(afh == NULL) exit(-5);
	
	printf("\nSearching for Fonts\n");
	AvailFonts(afh, afsize, fonttypes);

	af = (struct AvailFonts *) &afh[1];  /* bypass header to get to the
					      * first of the availfonts */

	for (j = 0; j < afh->afh_NumEntries; j++)
    	{
	if((af->af_Attr.ta_Flags & FPF_REMOVED) ||
	   (af->af_Attr.ta_Flags & FPF_REVPATH) ||
                    ((af->af_Type&AFF_MEMORY)&&
			(af->af_Attr.ta_Flags&FPF_DISKFONT)))
			;	/* do nothing if font is removed, or if
				 * font designed to be rendered rt->left
				 * (simple example writes left to right)
				 * or if font both on disk and in ram, 
				 * don't list it twice. */

	/* AvailFonts performs an AddFont to the system list;
	 * if run twice, you get two entries, one of "af_Type 1" saying
	 * that the font is memory resident, and the other of "af_Type 2"
	 * saying the font is disk-based.  The third part of the 
	 * if-statement lets you tell them apart if you are scanning
	 * the list for unique elements;  it says "if its in memory and
	 * it is from disk, then don't list it because you'll find another
	 * entry in the table that says it is not in memory, but is on disk.
	 * (Another task might have been using the font as well, creating
	 * the same effect).
	 */

	else
	   {
		printf("\nFont name found was: %ls",af->af_Attr.ta_Name);
		printf("  and its point size is: %ld",af->af_Attr.ta_YSize);
		/* Style parameter is in af->af_Attr.ta_Style,
		 * Flags parameter is in af->af_Attr.ta_Flags.
		 */		
	   }
	af++;
        }
	/* now that we've listed the fonts, lets look at them */

	w = (struct Window *)OpenWindow(&nw);
	rp = w->RPort;

    for(m=0; m<2; m++)	/* do normal video, then inverse video */
     {

	af = (struct AvailFonts *)&afh[1]; /* reset value of af to original */
	SetAPen(rp,1);		

	if(m == 0)SetDrMd(rp,JAM1);
	else SetDrMd(rp,JAM1+INVERSVID);

	/* now print a line that says what font and what style it is */

	for (j=0; j < afh->afh_NumEntries; j++)
	{
	CStringAppend(&fontname[0],af->af_Attr.ta_Name);  
			/* copy name into build-name area */
			/* already has ".font" onto end of it */
	
	ta.ta_Name = &fontname[0];
	ta.ta_YSize = af->af_Attr.ta_YSize;	/* ask for this size */
	ta.ta_Style = af->af_Attr.ta_Style;	/* ask for designed style */
	ta.ta_Flags = FPF_ROMFONT|FPF_DISKFONT|FPF_PROPORTIONAL|FPF_DESIGNED;
		/* accept it from anywhere it exists */
	style = ta.ta_Style;

	if(!((af->af_Attr.ta_Flags & FPF_REMOVED) ||
	   (af->af_Attr.ta_Flags & FPF_REVPATH) ||
           ((af->af_Type&AFF_MEMORY)&&
	   (af->af_Attr.ta_Flags&FPF_DISKFONT))))

	   /* this is an IF-NOT, the reverse of the earlier if-test on
	    * these same parameters 
	    */
           {
		tf = (struct TextFont *) OpenDiskFont(&ta);
	
        	if (tf != 0) 
	    	{ 
            	SetFont(w->RPort, tf);
	    	for(k=0; k<7; k++)
		    {
		    style = text_styles[k];
                    SetSoftStyle(w->RPort,style,255);
		    SetRast(rp,0);	/* erase any previous text */
		    Move(rp,10,20);	/* move down a bit from the top */
		    sEnd = CStringAppend(&outst[0],af->af_Attr.ta_Name);
		    sEnd = sEnd + CStringAppend(&outst[sEnd],"  ");
		    sEnd = sEnd + CStringAppend(&outst[sEnd],
					     pointsize[af->af_Attr.ta_YSize]);
		    sEnd = sEnd + CStringAppend(&outst[sEnd]," Points, ");
		    CStringAppend(&outst[sEnd],text[k]);
		    Text(rp,&outst[0],CStringAppend(&dummy[0],&outst[0]));

		    /* Have to build the string before sending it out to
		     * text IF ALGORITHMICALLY GENERATING THE STYLE since 
		     * the kerning and spacing tables are based on the
		     * vanilla text, and not the algorithmically generated
		     * style.  If you send characters out individually,
		     * it is possible that the enclosing rectangle of
	 	     * a later character will chop off the trailing edge
		     * of a preceding character 
		     */

		    /* ************************************************** 
		    This alternate method, when in INVERSVID, exhibits the
		    problem described above.
 
		    Text(rp,af->af_Attr.ta_Name,STRLEN(af->af_Attr.ta_Name));
		    Text(rp,"  ",2);
		    Text(rp,pointsize[af->af_Attr.ta_YSize],2);
		    Text(rp," Points, ",9);
	
		    Text(rp,text[k],textlength[k]);  
		    **************************************************  */ 

		    Delay(40);	/* use the DOS time delay function 
			  	 * specifies 60ths of a second */
		    }
            	CloseFont(tf); /* close the old one */
	
            }	/* end of if-tf-ne-0 */
	  }	/* end of if-(in memory but from disk) */
	af++;
	}	/* Do next font now */
     }		/* end of for-loop, controlled by m */
 
	FreeMem(afh,AFTABLESIZE);
	CloseWindow(w);
	CloseLibrary(IntuitionBase);   
	CloseLibrary(DosBase);  
	CloseLibrary(DiskfontBase);   
	CloseLibrary(GfxBase);   

}

/* copy a string and return the number of characters added to 
 * a string.  Effectively returns the length of the string if
 * not adding anything */

int CStringAppend(dest, source)	
char *dest;
char *source;
{
    int i=0; 
    char *s = source; 
    char *d = dest; 
    while (( i <79 )&&( *d = *s )) { d++; s++; i++; } 
	/* if find a NULL in source, end the copy, but the NULL itself
	 * gets copied over to the destination.  If no NULL, then 79
	 * characters get copied, then a terminating NULL is added */
    if(i < 79) return(i);
    else {*d = 0; return(i);	}
	/* value returned is the position of the terminating NULL
	 * to allow other strings to be appended simply using the
	 * next append command in sequence */

}