home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume10 / lemming / part01 / lemfont.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-08-05  |  6.6 KB  |  263 lines

  1. /*
  2.  * lemfont.c - routines to create and access binary level strike fonts
  3.  *
  4.  * copyright (c) by Alan W. Paeth, 1987. All rights reserved.
  5.  *
  6.  * Programmed by Alan Paeth, University of Waterloo, February, 1984
  7.  *
  8.  * NOTE: these fonts began life as 16-bit integers, with opposite byte-
  9.  * order conventions of the VAX. This explains the appearance of short
  10.  * integers, and size counts done in terms of shorts.
  11.  *
  12.  * Also, fonts are represented as a pointer to a contiguous, variable-
  13.  * length structure. Because the actual bitmap is the only data part
  14.  * which varies from font to font, its declaration is ultimate in the
  15.  * structure declaration. FONTHEADERSIZE is the short word offset to it.
  16.  *
  17.  * patched by Alan Paeth, May 1985, to deal with null print strings
  18.  */
  19.  
  20. #include "lem.h"
  21. #include "lemfont.h"
  22.  
  23. /* system constants */
  24.  
  25. #define NULL 0
  26. #define READMODE 0
  27. #define OPENFAIL -1
  28.  
  29. /* bit masking constants useful with non sign-extended shifts */
  30.  
  31. #define MAXPOS 0x77777777
  32. #define MAXNEG 0x80000000
  33.  
  34. /* private tables to speed up bit test operations */
  35.  
  36. short intab[17] =
  37.     { 0x0000,
  38.       0x0001, 0x0002, 0x0004, 0x0008, 0x0010, 0x0020, 0x0040, 0x0080,
  39.       0x0100, 0x0200, 0x0400, 0x0800, 0x1000, 0x2000, 0x4000, 0x8000 };
  40.  
  41. int outtab[33] =
  42.     { 0x00000000,
  43.       0x00000001, 0x00000002, 0x00000004, 0x00000008,
  44.       0x00000010, 0x00000020, 0x00000040, 0x00000080,
  45.       0x00000100, 0x00000200, 0x00000400, 0x00000800,
  46.       0x00001000, 0x00002000, 0x00004000, 0x00008000,
  47.       0x00010000, 0x00020000, 0x00040000, 0x00080000,
  48.       0x00100000, 0x00200000, 0x00400000, 0x00800000,
  49.       0x01000000, 0x02000000, 0x04000000, 0x08000000,
  50.       0x10000000, 0x20000000, 0x40000000, 0x80000000 };
  51.  
  52.  
  53. /* PUBLIC PROCEDURES */
  54.  
  55. BFont fontload(filename)
  56. char *filename;
  57.     {
  58.     BFont curfont;
  59.     short xxx, minascii, maxascii, ascent;
  60.     short mwidth, descent, rasterx, height;
  61.     int i;
  62.     long fd, readlen;
  63.  
  64.     if ((fd = open(filename, READMODE)) == OPENFAIL) return (NULL);
  65.  
  66.     sread(fd, &xxx, 2);        /* first word is a throwaway */
  67.     sread(fd, &minascii, 2);
  68.     sread(fd, &maxascii, 2);
  69.     sread(fd, &mwidth, 2);
  70.     sread(fd, &xxx, 2);        /* length is a throwaway */
  71.     sread(fd, &ascent, 2);
  72.     sread(fd, &descent, 2);
  73.     sread(fd, &xxx, 2);        /* xoffset unused unless kerned fonts */
  74.     sread(fd, &rasterx, 2);
  75.  
  76.     height = ascent + descent;
  77.  
  78.     curfont = (BFont)(calloc( rasterx*height + FONTHEADERSIZE , 2));
  79.     if (curfont == NULL)
  80.     {
  81.     close(fd);
  82.     return (NULL);
  83.     }
  84.  
  85.     curfont->ascent = ascent;
  86.     curfont->descent = descent;
  87.     curfont->mwidth = mwidth;
  88.     curfont->rasterx = rasterx;
  89.  
  90.     readlen = rasterx * height * 2;    /* convert shorts to bytes */
  91.     if (sread(fd, &(curfont->glyphs[0]), readlen) != readlen)
  92.     {
  93.     close(fd);
  94.     free(curfont);
  95.     return (NULL);
  96.     }
  97.  
  98.     for (i=0; i<256; i++) curfont->widths[i] = 0;
  99.  
  100.     readlen = (maxascii - minascii + 2) * 2;    /* n+1 widths (short ints) */
  101.     if (sread(fd, &(curfont->widths[minascii]), readlen ) != readlen)
  102.     {
  103.     close(fd);
  104.     free(curfont);
  105.     return (NULL);
  106.     }
  107.     close(fd);
  108.     return (curfont);
  109.     }
  110.  
  111. fontfree(arg)
  112.     BFont arg;
  113.     {
  114.     free(arg);
  115.     }
  116.  
  117. fontmeasure(font, string, emph)
  118. BFont font;
  119. char *string;
  120.     {
  121.     int ch;
  122.     int len = 0;
  123.     if (font == NULL) err("font == NULL\n");
  124.     while (ch = *(string++)) len += (font->widths[ch+1] - font->widths[ch]);
  125.     if (len == 0) return(0);        /* no emphasis fudge if no string */
  126.     if (emph == EMPHITAL) len += font->ascent / 4;
  127.     if (emph == EMPHBOLD) ++len;
  128.     return(len);
  129.     }
  130.  
  131. fontwrite(font, x, y, string, emph, fontcol)
  132.     {
  133.     privfontwrite(bfont[font], x, y, string, emph, fontcol);
  134.     }
  135.  
  136. privfontwrite(font, x, y, string, emph, fontcol)
  137. BFont font;
  138. int x, y;
  139. char *string;
  140.     {
  141.     static long bitbuf[MAXWIDTH/32];
  142.  
  143.     int smeasure, bufsize, bufsizew, rows, inlen;
  144.     char ch, *strcopy;
  145.     short *inbase, *inaddr, *widthptr, inoffset;
  146.     int i, curpos, skew, inmaski, outmaski;
  147.     long *outaddr;
  148.  
  149.     y = screenh - y;
  150.     smeasure = fontmeasure(font, string, emph);
  151.     if (smeasure == 0) return;        /* QUICK RETURN: no string */
  152.     bufsize = MIN(x + smeasure, RIGHT) - MAX(x, LEFT);
  153.  
  154. /* clip to physical resources */
  155.  
  156.     bufsize = MIN(bufsize, MAXWIDTH);
  157.  
  158.     bufsizew = (bufsize-1) / 32 + 1;    /* words to hold bits, rounded up */
  159.     inbase = &(font->glyphs[0]);
  160.     rows = font->ascent+font->descent;    /* +1 for predecrementing */
  161. /* y adjust */
  162. /*  y -= 0;                    /* upper lh-corner */
  163. /*  y -= font->ascent;                /* lh baseline */
  164. /**/y -= (font->ascent+font->descent)/2;    /* lh center line */
  165.  
  166.     ++rows;
  167.     while (--rows)            /* +1 for predecrementing speed */
  168.     {
  169.     if (bufsize > 0 && y >= BOTTOM && y < TOP)
  170.         {
  171.         if (emph == EMPHITAL)
  172.         skew = rows / 4;
  173.         else skew = 0;
  174.         curpos= MIN(x+skew-LEFT,0);    /* bitpos in output buffer */
  175.         i = bufsizew;
  176.         while (i) bitbuf[--i] = 0;    /* clear ALL output buffer */
  177.  
  178.         strcopy = string;        /* set up for output */
  179.         outmaski = 32;
  180.         outaddr = bitbuf;
  181.  
  182.         while (ch = *(strcopy++))    /* character loop */
  183.         {
  184.         widthptr = &(font->widths[ch]);
  185.         inoffset = *widthptr;
  186.  
  187. /* inlen is min of (room left in buffer), (char width) */
  188.  
  189.         inlen = min(bufsize-skew-curpos, (*(++widthptr) - inoffset) );
  190.  
  191.         inaddr = inbase + inoffset/16;
  192.         inmaski = 16 - (inoffset & 15);    /* 15+1 for predecrementing */
  193.         ++inlen;            /*   +1 for predecrementing */
  194.         while (--inlen)            /* draw while char/room left */
  195.             {
  196.             if (++curpos > 0)        /* position at end of draw */
  197.             {
  198.             if (*inaddr&intab[inmaski]) *outaddr|=outtab[outmaski];
  199.             if (!(--outmaski)) { outmaski = 32; ++outaddr; }
  200.             }
  201.             if (!(--inmaski)) {  inmaski = 16; ++inaddr ; }
  202.             }
  203.         }
  204.         if (emph == EMPHBOLD)
  205.         {
  206.         for(i = bufsizew - 1; i > 0; --i)
  207.             {
  208.             bitbuf[i] |= (bitbuf[i])>>1;
  209.             if (bitbuf[i-1]&1) bitbuf[i] |= MAXNEG;
  210.             }
  211.         bitbuf[i] |= (bitbuf[i])>>1;
  212.         }
  213. /*
  214.         if ((emph == EMPHUNDERSCORE) && (rows == font->descent))
  215.         {
  216.         i = bufsizew;
  217.         while (i) bitbuf[--i] = -1;
  218.         }
  219. */
  220.         writescan( MAX(x+skew, LEFT), y, bufsize-skew, bitbuf, fontcol);
  221.         }
  222.     ++y;
  223.     inbase += font->rasterx;
  224.     }
  225.     }
  226.  
  227. /* PRIVATE PROCEDURES */
  228.  
  229. static min(a,b)
  230.     long a,b;
  231.     {
  232.     return( (a < b) ? a : b );
  233.     }
  234.  
  235. /*
  236.  * sread is analogous to unix read, but will swap bytes on machines with
  237.  * byte order opposite that of the VAX. This makes the font files portable.
  238.  */
  239.  
  240. sread(d, buf, nbytes)
  241.     register char *buf;
  242.     register int nbytes;
  243.     {
  244.     register char *test, l, r;
  245.     short order = 1;
  246.     int ret;
  247.     test = (char*)(&order);
  248.     ret = read(d, buf, nbytes);
  249.     if (*test != '\001')
  250.     {
  251.     while( nbytes > 1)    /* non-vax: do byte swap */
  252.         {
  253.         l = *buf++;
  254.         r = *buf;
  255.         *buf = l;
  256.         *--buf = r;
  257.         buf += 2;
  258.         nbytes -= 2;
  259.         }
  260.     }
  261.     return(ret);
  262.     }
  263.