/* this is bfont.c, by Burt Solomon, roughly 1984 or 1985: SET YOUR EDITOR TO EXPAND TABS TO 4 SPACES!!! RELEASE 0.3 NOTES: Defining a character with "^a >" instead of "" makes it a control character. ---------------------------------- BS doesn't comment very well, but he sure is clever. It compiles to a program which: (1) inputs a file like font.1, and (2) outputs a file like font1.d; 1987: porting to CP/M, AZTEC C: first tried changing some ints to longs (character size wider than 16 won't work with int); then discovered that no manipulations of longs work correctly in AZTEC C. Please note that my version of AZTEC C dates from 1982, and they may have improved things since then. However, severe compiler braindamage requires extensive rewriting. FORMAT OF (1) input file: # # # # # # ## # # # # # # % # says "this is the letter x and its width is as specified by the <>" ## lines make a picture of the letter; the number of lines defines the height of the letter. % the ## lines that follow describe desenders (sic), as spelled by the author. ## lines describe the descender. < start of a new i.d. line ends the letter. NOTE: allowing more than one letter definition on the same line complicates the program. FORMAT OF (2) output: 'C' program source -- declarations for static initializers to be used by newfont.c -- to be #included there. #ifdef DEBUG lines added while porting to aztec C 1987 */ /* #define DEBUG */ #include "stdio.h" #define nchars 128 /* number of chars in char set*/ /* changed for release 0.3: in a new font, ^A (for example) might ** be used for a special effect: to print some pretty picture... */ #define nlines 16 /*number of lines above base line in a banner character*/ #define dlines 3 /*number of lines desending in a banner character*/ #define mxl 19 /*number of lines max. in a banner character*/ #define mxw 32 /*max width of a banner character. */ #define wbytes 4 /* bytes used in a bitmask for this width. */ /* define the states for input to be in */ #define def_next 0 #define def_char 1 #define def_end 2 #define fil_char 3 #define desend 4 int inputchar; /* current character */ int line; /* current line being worked on */ int col; /* column on current line */ char curmap[wbytes]; /* working bitmap. */ char ctrlflag = 0; struct chr { int tablechar; /* this character */ int startcol; /* starting column for this character */ int width; /* width of this character */ int height; /* height of this character */ int descent; /* decesending amount for this character */ char bitmap[mxl*wbytes]; /* one mask for each line */ } ch[nchars]; main(argc,argp) char **argp;int argc; { int bitnumber; /* number of bit in current scan. */ register int curchar; /* current character being worded on */ int first; /* first character current line */ int last; /* last character current line */ int dflag; /* desender flag */ int state; /* current state of affairs */ int workheight; /* working height of character. */ int bb, findflag; for (curchar = 0; curchar < nchars; curchar++) { ch[curchar].tablechar = -1; ch[curchar].startcol = ch[curchar].width = ch[curchar].height = ch[curchar].descent = 0; } line = curchar = first = last = col = dflag = 0; /* guarantee initial values. */ clrcmap(); /* clear working bitmap */ state = def_next; /* current working state */ while ((inputchar = getchar()) != EOF) /* till end of file */ { if (inputchar == 13) continue; /* don't trust CP/M I/O */ if (inputchar == '!' && col == 0) /* comment in any state. */ while ((inputchar = getchar()) != EOF && inputchar != '\n'); /* do nothing. */ switch (state) { case def_next: /* start of a new character */ if (inputchar == '<' || inputchar == '^') { /* yes it starts a definition. */ ch[curchar].startcol = col; /* curchar starts at column */ state = def_char; /* next get characters name */ ctrlflag = (inputchar == '^'); } else if (inputchar == '\n' || inputchar == '!') { /* end of "start definitions" line. */ if (curchar != first) { /* we had at least one full definition. */ state = fil_char; /* get contents of char. */ curchar = first; /* point to first on line. */ } /* else it is a blank line. */ if (inputchar == '!') { /* comment. */ while ((inputchar = getchar()) != EOF && inputchar != '\n'); /* do nothing. */ } } else if (inputchar != ' ') err ("Invalid define character"); break; case def_char: /* name this character now */ if (inputchar < 0 || inputchar > 128) { err ("Invalid character name"); } /* changed release 0.3: allow definitions of funny ** characters. \n and \r will not work of course! */ if (ctrlflag) inputchar &= 0x1f; ctrlflag = 0; ch[curchar].tablechar = inputchar; state = def_end; break; case def_end: /* mark the size of this character */ if (inputchar == '>') { /* found the end. */ ch[curchar].width = col - ch[curchar].startcol + 1; if (ch[curchar].width > mxw) err ( "character too wide!" ); dflag = ch[curchar].height = ch[curchar].descent = 0; clrOmap(curchar); /* clear out its map. */ clrcmap(); /* clear working bitmap */ state = def_next; /* look for another on same line. */ curchar = ++last; /* point to next char. */ } else if (inputchar != ' ') err ("Invalid define character"); break; case desend: /* processing the start of desending */ if (dflag < 0) { /* waiting for end of "%" line. */ if (inputchar != '\n') err ("Invalid desending character"); dflag = 0; break; } /* else fall through to case fil_char */ case fil_char: /* fill in this characters mask now */ if (ch[curchar].startcol == col) { /* begin working on curchar. */ clrcmap(); /* clear working bitmap */ bitnumber = ch[curchar].width; #ifdef DEBUG printf("start curchar=%d dflag=%d workheight=%d bitnumber=%d\n", curchar, dflag, workheight, bitnumber); #endif } bitnumber--; /* proceed to next bit in final mask. */ #ifdef DEBUG printf("curchar=%d dflag=%d workheight=%d bitnumber=%d\n", curchar, dflag, workheight, bitnumber); #endif if (inputchar == '#') { /* specifies a position to be set. */ if (bitnumber < 0) err("unexpected '#', check space between characters\n"); setcmap(bitnumber); /* set bit in curmap. */ } if (bitnumber == 0) { /* width of curchar was used up. */ #ifdef DEBUG printf("end of curchar=%d dflag=%d workheight=%d\n", curchar, dflag, workheight); #endif if (col != (ch[curchar].startcol + ch[curchar].width -1)) err("Internal error 1!"); bitnumber = -1; /* yes this is a kludge */ workheight = ch[curchar].height + dflag; cpycmap(curchar, workheight); curchar++; /* point to next character. */ clrcmap(); /* clear working bitmap */ if (inputchar == ' ' || inputchar == '#') break; } if (inputchar == ' ') break; if (inputchar == '#' && bitnumber >= 0) break; if (inputchar == '\n') { /* end-of-line may be "premature" */ workheight = ch[curchar].height + dflag; if (tstcmap()) cpycmap(curchar, workheight); if (state == desend) { /* we are processing descenders. */ for (curchar = first; curchar < last; curchar++) { /* check all characters defined on these lines. */ workheight = ch[curchar].height + dflag; if (tstOmap(curchar, workheight)) ch[curchar].descent = dflag + 1; } dflag++; } else { /* not descenders. workheight == ch[].height */ for (curchar = first; curchar < last; curchar++) if (tstOmap(curchar, 0)) ch[curchar].height++; } clrcmap(); /* clear working bitmap */ } else if (col == 0 && (inputchar == '<' || inputchar == '^')) { /* a new set of definitions. */ ctrlflag = (inputchar == '^'); state = def_char; first = curchar = last; ch[curchar].startcol = 0; } else if (col == 0 && inputchar == '%') { /* next line starts descenders. */ dflag = -1; state = desend; } else { printf("curchar=%d workheight=%d state=%d\n", curchar, workheight, state); printf("first=%d last=%d dflag=%d\n", first,last,dflag); printf("ch[curchar].startcol=%d bitnumber=%d\n", ch[curchar].startcol, bitnumber); for (bb = 0; bb < curchar; bb++) { printf( "ch[%d].tablechar=%x startcol=%d width=%d height=%d descent=%d\n", bb, ch[bb].tablechar, ch[bb].startcol, ch[bb].width, ch[bb].height, ch[bb].descent); } err ("Invalid fill character"); } break; default: break; } col++; if (inputchar == '\n') { curchar = first; col = 0; line++; } } /* write out the table now */ for (inputchar = 0; inputchar < 128; inputchar++) { /* scan all possible banner characters in order. */ findflag = 0; for (curchar = 0; curchar < nchars; curchar++) if (ch[curchar].tablechar == inputchar) { /* curchar was defined. */ findflag = 1; break; } if (findflag) { /* character was defined. */ #ifdef DEBUG printf (" /* character 0x%x was defined: */\n", inputchar); #endif printf ("{%d,%d,%d", ch[curchar].width, ch[curchar].height, ch[curchar].descent); findflag = (ch[curchar].descent + ch[curchar].height) * wbytes; for (bb = 0; bb < findflag; bb++) { printf(",0x%x%s",ch[curchar].bitmap[bb], ( ( bb % 8 ) == 7 ) ? "\n\t" : " " ); } if (inputchar == 127 || inputchar <= ' ') printf("}%s \/* 0x%x */\n", ((inputchar == 127) ? "" : ","), inputchar); else printf("}%s \/* %c *\/\n", ((inputchar == 127) ? "" : ","), inputchar); } else { /* undefined character. */ printf ("{0,0,0}%s \/* 0x%x *\/\n", ((inputchar == 127) ? "" : ","), inputchar); } } } err(str) char *str; { printf ("%s, inputchar=%x, line=%d, col=%d\n", str, inputchar, line, col); exit (1); } clrcmap() { int i; for (i = 0; i < wbytes; i++) curmap[i] = 0; } clrOmap(index) { int i; for (i = 0; i < (mxl*wbytes); i++) ch[index].bitmap[i] = 0; } cpycmap(index, entry) { int i, base; base = entry * wbytes; for (i = 0; i < wbytes; i++) ch[index].bitmap[base+i] = curmap[i]; } tstcmap() { /* is the working bitmap not all zeroes? */ int i; for (i = 0; i < wbytes; i++) if (curmap[i] != 0) return (1); return (0); } tstOmap(index, entry) { /* see if a "long" in ch[index].bitmap[] is not all zeroes. */ int i, base; base = entry * wbytes; for (i = 0; i < wbytes; i++) if (ch[index].bitmap[base + i] != 0) return (1); return (0); } setcmap(bitno) { /* set a bit in curmap: 0 is curmap[wbytes-1]&1, max curmap[0]&0x80 */ int index; char localmask; index = wbytes - 1 - ( bitno / 8 ); /* bitno result (wbytes==4) 0 to 7 (4 - 1 - (0/8)) == 3 8 to 15 (3 - (15/8) == 2 and so forth. */ localmask = 1 << ( bitno % 8 ); curmap[index] |= localmask; }