home *** CD-ROM | disk | FTP | other *** search
- /*
- * lemfont.c - routines to create and access binary level strike fonts
- *
- * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
- *
- * Programmed by Alan Paeth, University of Waterloo, February, 1984
- *
- * NOTE: these fonts began life as 16-bit integers, with opposite byte-
- * order conventions of the VAX. This explains the appearance of short
- * integers, and size counts done in terms of shorts.
- *
- * Also, fonts are represented as a pointer to a contiguous, variable-
- * length structure. Because the actual bitmap is the only data part
- * which varies from font to font, its declaration is ultimate in the
- * structure declaration. FONTHEADERSIZE is the short word offset to it.
- *
- * patched by Alan Paeth, May 1985, to deal with null print strings
- */
-
- #include "lem.h"
- #include "lemfont.h"
-
- /* system constants */
-
- #define NULL 0
- #define READMODE 0
- #define OPENFAIL -1
-
- /* bit masking constants useful with non sign-extended shifts */
-
- #define MAXPOS 0x77777777
- #define MAXNEG 0x80000000
-
- /* private tables to speed up bit test operations */
-
- short intab[17] =
- { 0x0000,
- 0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
- 0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
-
- int outtab[33] =
- { 0x00000000,
- 0x00000001, 0x00000002, 0x00000004, 0x00000008,
- 0x00000010, 0x00000020, 0x00000040, 0x00000080,
- 0x00000100, 0x00000200, 0x00000400, 0x00000800,
- 0x00001000, 0x00002000, 0x00004000, 0x00008000,
- 0x00010000, 0x00020000, 0x00040000, 0x00080000,
- 0x00100000, 0x00200000, 0x00400000, 0x00800000,
- 0x01000000, 0x02000000, 0x04000000, 0x08000000,
- 0x10000000, 0x20000000, 0x40000000, 0x80000000 };
-
-
- /* PUBLIC PROCEDURES */
-
- BFont fontload(filename)
- char *filename;
- {
- BFont curfont;
- short xxx, minascii, maxascii, ascent;
- short mwidth, descent, rasterx, height;
- int i;
- long fd, readlen;
-
- if ((fd = open(filename, READMODE)) == OPENFAIL) return (NULL);
-
- sread(fd, &xxx, 2); /* first word is a throwaway */
- sread(fd, &minascii, 2);
- sread(fd, &maxascii, 2);
- sread(fd, &mwidth, 2);
- sread(fd, &xxx, 2); /* length is a throwaway */
- sread(fd, &ascent, 2);
- sread(fd, &descent, 2);
- sread(fd, &xxx, 2); /* xoffset unused unless kerned fonts */
- sread(fd, &rasterx, 2);
-
- height = ascent + descent;
-
- curfont = (BFont)(calloc( rasterx*height + FONTHEADERSIZE , 2));
- if (curfont == NULL)
- {
- close(fd);
- return (NULL);
- }
-
- curfont->ascent = ascent;
- curfont->descent = descent;
- curfont->mwidth = mwidth;
- curfont->rasterx = rasterx;
-
- readlen = rasterx * height * 2; /* convert shorts to bytes */
- if (sread(fd, &(curfont->glyphs[0]), readlen) != readlen)
- {
- close(fd);
- free(curfont);
- return (NULL);
- }
-
- for (i=0; i<256; i++) curfont->widths[i] = 0;
-
- readlen = (maxascii - minascii + 2) * 2; /* n+1 widths (short ints) */
- if (sread(fd, &(curfont->widths[minascii]), readlen ) != readlen)
- {
- close(fd);
- free(curfont);
- return (NULL);
- }
- close(fd);
- return (curfont);
- }
-
- fontfree(arg)
- BFont arg;
- {
- free(arg);
- }
-
- fontmeasure(font, string, emph)
- BFont font;
- char *string;
- {
- int ch;
- int len = 0;
- if (font == NULL) err("font == NULL\n");
- while (ch = *(string++)) len += (font->widths[ch+1] - font->widths[ch]);
- if (len == 0) return(0); /* no emphasis fudge if no string */
- if (emph == EMPHITAL) len += font->ascent / 4;
- if (emph == EMPHBOLD) ++len;
- return(len);
- }
-
- fontwrite(font, x, y, string, emph, fontcol)
- {
- privfontwrite(bfont[font], x, y, string, emph, fontcol);
- }
-
- privfontwrite(font, x, y, string, emph, fontcol)
- BFont font;
- int x, y;
- char *string;
- {
- static long bitbuf[MAXWIDTH/32];
-
- int smeasure, bufsize, bufsizew, rows, inlen;
- char ch, *strcopy;
- short *inbase, *inaddr, *widthptr, inoffset;
- int i, curpos, skew, inmaski, outmaski;
- long *outaddr;
-
- y = screenh - y;
- smeasure = fontmeasure(font, string, emph);
- if (smeasure == 0) return; /* QUICK RETURN: no string */
- bufsize = MIN(x + smeasure, RIGHT) - MAX(x, LEFT);
-
- /* clip to physical resources */
-
- bufsize = MIN(bufsize, MAXWIDTH);
-
- bufsizew = (bufsize-1) / 32 + 1; /* words to hold bits, rounded up */
- inbase = &(font->glyphs[0]);
- rows = font->ascent+font->descent; /* +1 for predecrementing */
- /* y adjust */
- /* y -= 0; /* upper lh-corner */
- /* y -= font->ascent; /* lh baseline */
- /**/y -= (font->ascent+font->descent)/2; /* lh center line */
-
- ++rows;
- while (--rows) /* +1 for predecrementing speed */
- {
- if (bufsize > 0 && y >= BOTTOM && y < TOP)
- {
- if (emph == EMPHITAL)
- skew = rows / 4;
- else skew = 0;
- curpos= MIN(x+skew-LEFT,0); /* bitpos in output buffer */
- i = bufsizew;
- while (i) bitbuf[--i] = 0; /* clear ALL output buffer */
-
- strcopy = string; /* set up for output */
- outmaski = 32;
- outaddr = bitbuf;
-
- while (ch = *(strcopy++)) /* character loop */
- {
- widthptr = &(font->widths[ch]);
- inoffset = *widthptr;
-
- /* inlen is min of (room left in buffer), (char width) */
-
- inlen = min(bufsize-skew-curpos, (*(++widthptr) - inoffset) );
-
- inaddr = inbase + inoffset/16;
- inmaski = 16 - (inoffset & 15); /* 15+1 for predecrementing */
- ++inlen; /* +1 for predecrementing */
- while (--inlen) /* draw while char/room left */
- {
- if (++curpos > 0) /* position at end of draw */
- {
- if (*inaddr&intab[inmaski]) *outaddr|=outtab[outmaski];
- if (!(--outmaski)) { outmaski = 32; ++outaddr; }
- }
- if (!(--inmaski)) { inmaski = 16; ++inaddr ; }
- }
- }
- if (emph == EMPHBOLD)
- {
- for(i = bufsizew - 1; i > 0; --i)
- {
- bitbuf[i] |= (bitbuf[i])>>1;
- if (bitbuf[i-1]&1) bitbuf[i] |= MAXNEG;
- }
- bitbuf[i] |= (bitbuf[i])>>1;
- }
- /*
- if ((emph == EMPHUNDERSCORE) && (rows == font->descent))
- {
- i = bufsizew;
- while (i) bitbuf[--i] = -1;
- }
- */
- writescan( MAX(x+skew, LEFT), y, bufsize-skew, bitbuf, fontcol);
- }
- ++y;
- inbase += font->rasterx;
- }
- }
-
- /* PRIVATE PROCEDURES */
-
- static min(a,b)
- long a,b;
- {
- return( (a < b) ? a : b );
- }
-
- /*
- * sread is analogous to unix read, but will swap bytes on machines with
- * byte order opposite that of the VAX. This makes the font files portable.
- */
-
- sread(d, buf, nbytes)
- register char *buf;
- register int nbytes;
- {
- register char *test, l, r;
- short order = 1;
- int ret;
- test = (char*)(&order);
- ret = read(d, buf, nbytes);
- if (*test != '\001')
- {
- while( nbytes > 1) /* non-vax: do byte swap */
- {
- l = *buf++;
- r = *buf;
- *buf = l;
- *--buf = r;
- buf += 2;
- nbytes -= 2;
- }
- }
- return(ret);
- }
-