home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / COMMON / FONT.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  5KB  |  226 lines

  1. /* Copyright (c) 1992 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)font.c 2.4 6/24/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  * Polygonal font handling routines
  9.  */
  10.  
  11. #include "standard.h"
  12.  
  13. #include "font.h"
  14.  
  15. #define galloc(nv)      (GLYPH *)malloc(sizeof(GLYPH)+2*sizeof(GORD)*(nv))
  16.  
  17.  
  18. extern char  *libpath;                  /* list of library directories */
  19.  
  20. extern char  *fgetword();
  21.  
  22. static FONT     *fontlist = NULL;       /* list of loaded fonts */
  23.  
  24.  
  25. FONT *
  26. getfont(fname)                          /* return font fname */
  27. char  *fname;
  28. {
  29.     char  buf[16];
  30.     FILE  *fp;
  31.     char  *pathname, *err;
  32.     unsigned  wsum, hsum, ngly;
  33.     int  gn, ngv;
  34.     register int  gv;
  35.     register GLYPH  *g;
  36.     GORD  *gp;
  37.     register FONT  *f;
  38.  
  39.     for (f = fontlist; f != NULL; f = f->next)
  40.         if (!strcmp(f->name, fname))
  41.             return(f);
  42.                         /* load the font file */
  43.     if ((pathname = getpath(fname, libpath, R_OK)) == NULL) {
  44.         sprintf(errmsg, "cannot find font file \"%s\"", fname);
  45.         error(USER, errmsg);
  46.     }
  47.     f = (FONT *)calloc(1, sizeof(FONT));
  48.     if (f == NULL)
  49.         goto memerr;
  50.     f->name = savestr(fname);
  51.     if ((fp = fopen(pathname, "r")) == NULL) {
  52.         sprintf(errmsg, "cannot open font file \"%s\"",
  53.                 pathname);
  54.         error(SYSTEM, errmsg);
  55.     }
  56.     wsum = hsum = ngly = 0;
  57.     while (fgetword(buf,sizeof(buf),fp) != NULL) {  /* get each glyph */
  58.         if (!isint(buf))
  59.             goto nonint;
  60.         gn = atoi(buf);
  61.         if (gn < 1 || gn > 255) {
  62.             err = "illegal";
  63.             goto fonterr;
  64.         }
  65.         if (f->fg[gn] != NULL) {
  66.             err = "duplicate";
  67.             goto fonterr;
  68.         }
  69.         if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) ||
  70.                 (ngv = atoi(buf)) < 0 || ngv > 32000) {
  71.             err = "bad # vertices for";
  72.             goto fonterr;
  73.         }
  74.         g = galloc(ngv);
  75.         if (g == NULL)
  76.             goto memerr;
  77.         g->nverts = ngv;
  78.         g->left = g->right = g->top = g->bottom = 128;
  79.         ngv *= 2;
  80.         gp = gvlist(g);
  81.         while (ngv--) {
  82.             if (fgetword(buf,sizeof(buf),fp) == NULL ||
  83.                     !isint(buf) ||
  84.                     (gv = atoi(buf)) < 0 || gv > 255) {
  85.                 err = "bad vertex for";
  86.                 goto fonterr;
  87.             }
  88.             *gp++ = gv;
  89.             if (ngv & 1) {          /* follow x limits */
  90.                 if (gv < g->left)
  91.                     g->left = gv;
  92.                 else if (gv > g->right)
  93.                     g->right = gv;
  94.             } else {                /* follow y limits */
  95.                 if (gv < g->bottom)
  96.                     g->bottom = gv;
  97.                 else if (gv > g->top)
  98.                     g->top = gv;
  99.             }
  100.         }
  101.         if (g->right - g->left && g->top - g->bottom) {
  102.             ngly++;
  103.             wsum += g->right - g->left;
  104.             hsum += g->top - g->bottom;
  105.         }
  106.         f->fg[gn] = g;
  107.     }
  108.     fclose(fp);
  109.     if (ngly) {
  110.         f->mwidth = wsum / ngly;
  111.         f->mheight = hsum / ngly;
  112.     }
  113.     f->next = fontlist;
  114.     return(fontlist = f);
  115. nonint:
  116.     sprintf(errmsg, "non-integer in font file \"%s\"", pathname);
  117.     error(USER, errmsg);
  118. fonterr:
  119.     sprintf(errmsg, "%s character (%d) in font file \"%s\"",
  120.             err, gn, pathname);
  121.     error(USER, errmsg);
  122. memerr:
  123.     error(SYSTEM, "out of memory in fontglyph");
  124. }
  125.  
  126.  
  127. int
  128. uniftext(sp, tp, f)                     /* uniformly space text line */
  129. register short  *sp;            /* returned character spacing */
  130. register char  *tp;             /* text line */
  131. register FONT  *f;              /* font */
  132. {
  133.     int  linelen;
  134.  
  135.     linelen = *sp++ = 0;
  136.     while (*tp)
  137.         if (f->fg[*tp++&0xff] == NULL)
  138.             *sp++ = 0;
  139.         else
  140.             linelen += *sp++ = 256;
  141.     return(linelen);
  142. }
  143.  
  144.  
  145. int
  146. squeeztext(sp, tp, f, cis)              /* squeeze text line */
  147. short  *sp;                     /* returned character spacing */
  148. char  *tp;                      /* text line */
  149. FONT  *f;                       /* font */
  150. int  cis;                       /* intercharacter spacing */
  151. {
  152.     int  linelen;
  153.     register GLYPH  *gp;
  154.  
  155.     gp = NULL;
  156.     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
  157.         *sp++ = 0;
  158.     cis /= 2;
  159.     linelen = *sp = cis;
  160.     while (gp != NULL) {
  161.         if (gp->nverts) {               /* regular character */
  162.             linelen += *sp++ += cis - gp->left;
  163.             *sp = gp->right + cis;
  164.         } else {                        /* space */
  165.             linelen += *sp++;
  166.             *sp = f->mwidth;
  167.         }
  168.         gp = NULL;
  169.         while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
  170.             linelen += *sp++;
  171.             *sp = 0;
  172.         }
  173.     }
  174.     linelen += *sp += cis;
  175.     return(linelen);
  176. }
  177.  
  178.  
  179. int
  180. proptext(sp, tp, f, cis, nsi)           /* space line proportionally */
  181. short  *sp;                     /* returned character spacing */
  182. char  *tp;                      /* text line */
  183. FONT  *f;                       /* font */
  184. int  cis;                       /* target intercharacter spacing */
  185. int  nsi;                       /* minimum number of spaces for indent */
  186. {
  187.     register char  *end, *tab;
  188.     GLYPH  *gp;
  189.     short  *nsp;
  190.     int  alen, len, width;
  191.                     /* start by squeezing it */
  192.     squeeztext(sp, tp, f, cis);
  193.                     /* now, realign spacing */
  194.     len = 0;
  195.     width = alen = *sp++;
  196.     while (*tp) {
  197.         nsp = sp;
  198.         for (end = tp; *end; end = tab) {
  199.             tab = end + 1;
  200.             alen += *nsp++;
  201.             if (f->fg[*end&0xff]) {
  202.                 while ((gp = f->fg[*tab&0xff]) != NULL &&
  203.                         gp->nverts == 0) { /* tab in */
  204.                     alen += *nsp++;
  205.                     tab++;
  206.                 }
  207.                 len += tab - end;
  208.             }
  209.             if (nsi && tab - end > nsi)
  210.                 break;
  211.         }
  212.         len *= f->mwidth + cis;         /* compute target length */
  213.         width += len;
  214.         len -= alen;                    /* necessary adjustment */
  215.         while (sp < nsp) {
  216.             alen = len/(nsp-sp);
  217.             *sp++ += alen;
  218.             len -= alen;
  219.         }
  220.         len = 0;
  221.         alen = 0;
  222.         tp = tab;
  223.     }
  224.     return(width);
  225. }
  226.