home *** CD-ROM | disk | FTP | other *** search
- /* Copyright (c) 1992 Regents of the University of California */
-
- #ifndef lint
- static char SCCSid[] = "@(#)font.c 2.4 6/24/92 LBL";
- #endif
-
- /*
- * Polygonal font handling routines
- */
-
- #include "standard.h"
-
- #include "font.h"
-
- #define galloc(nv) (GLYPH *)malloc(sizeof(GLYPH)+2*sizeof(GORD)*(nv))
-
-
- extern char *libpath; /* list of library directories */
-
- extern char *fgetword();
-
- static FONT *fontlist = NULL; /* list of loaded fonts */
-
-
- FONT *
- getfont(fname) /* return font fname */
- char *fname;
- {
- char buf[16];
- FILE *fp;
- char *pathname, *err;
- unsigned wsum, hsum, ngly;
- int gn, ngv;
- register int gv;
- register GLYPH *g;
- GORD *gp;
- register FONT *f;
-
- for (f = fontlist; f != NULL; f = f->next)
- if (!strcmp(f->name, fname))
- return(f);
- /* load the font file */
- if ((pathname = getpath(fname, libpath, R_OK)) == NULL) {
- sprintf(errmsg, "cannot find font file \"%s\"", fname);
- error(USER, errmsg);
- }
- f = (FONT *)calloc(1, sizeof(FONT));
- if (f == NULL)
- goto memerr;
- f->name = savestr(fname);
- if ((fp = fopen(pathname, "r")) == NULL) {
- sprintf(errmsg, "cannot open font file \"%s\"",
- pathname);
- error(SYSTEM, errmsg);
- }
- wsum = hsum = ngly = 0;
- while (fgetword(buf,sizeof(buf),fp) != NULL) { /* get each glyph */
- if (!isint(buf))
- goto nonint;
- gn = atoi(buf);
- if (gn < 1 || gn > 255) {
- err = "illegal";
- goto fonterr;
- }
- if (f->fg[gn] != NULL) {
- err = "duplicate";
- goto fonterr;
- }
- if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) ||
- (ngv = atoi(buf)) < 0 || ngv > 32000) {
- err = "bad # vertices for";
- goto fonterr;
- }
- g = galloc(ngv);
- if (g == NULL)
- goto memerr;
- g->nverts = ngv;
- g->left = g->right = g->top = g->bottom = 128;
- ngv *= 2;
- gp = gvlist(g);
- while (ngv--) {
- if (fgetword(buf,sizeof(buf),fp) == NULL ||
- !isint(buf) ||
- (gv = atoi(buf)) < 0 || gv > 255) {
- err = "bad vertex for";
- goto fonterr;
- }
- *gp++ = gv;
- if (ngv & 1) { /* follow x limits */
- if (gv < g->left)
- g->left = gv;
- else if (gv > g->right)
- g->right = gv;
- } else { /* follow y limits */
- if (gv < g->bottom)
- g->bottom = gv;
- else if (gv > g->top)
- g->top = gv;
- }
- }
- if (g->right - g->left && g->top - g->bottom) {
- ngly++;
- wsum += g->right - g->left;
- hsum += g->top - g->bottom;
- }
- f->fg[gn] = g;
- }
- fclose(fp);
- if (ngly) {
- f->mwidth = wsum / ngly;
- f->mheight = hsum / ngly;
- }
- f->next = fontlist;
- return(fontlist = f);
- nonint:
- sprintf(errmsg, "non-integer in font file \"%s\"", pathname);
- error(USER, errmsg);
- fonterr:
- sprintf(errmsg, "%s character (%d) in font file \"%s\"",
- err, gn, pathname);
- error(USER, errmsg);
- memerr:
- error(SYSTEM, "out of memory in fontglyph");
- }
-
-
- int
- uniftext(sp, tp, f) /* uniformly space text line */
- register short *sp; /* returned character spacing */
- register char *tp; /* text line */
- register FONT *f; /* font */
- {
- int linelen;
-
- linelen = *sp++ = 0;
- while (*tp)
- if (f->fg[*tp++&0xff] == NULL)
- *sp++ = 0;
- else
- linelen += *sp++ = 256;
- return(linelen);
- }
-
-
- int
- squeeztext(sp, tp, f, cis) /* squeeze text line */
- short *sp; /* returned character spacing */
- char *tp; /* text line */
- FONT *f; /* font */
- int cis; /* intercharacter spacing */
- {
- int linelen;
- register GLYPH *gp;
-
- gp = NULL;
- while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
- *sp++ = 0;
- cis /= 2;
- linelen = *sp = cis;
- while (gp != NULL) {
- if (gp->nverts) { /* regular character */
- linelen += *sp++ += cis - gp->left;
- *sp = gp->right + cis;
- } else { /* space */
- linelen += *sp++;
- *sp = f->mwidth;
- }
- gp = NULL;
- while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
- linelen += *sp++;
- *sp = 0;
- }
- }
- linelen += *sp += cis;
- return(linelen);
- }
-
-
- int
- proptext(sp, tp, f, cis, nsi) /* space line proportionally */
- short *sp; /* returned character spacing */
- char *tp; /* text line */
- FONT *f; /* font */
- int cis; /* target intercharacter spacing */
- int nsi; /* minimum number of spaces for indent */
- {
- register char *end, *tab;
- GLYPH *gp;
- short *nsp;
- int alen, len, width;
- /* start by squeezing it */
- squeeztext(sp, tp, f, cis);
- /* now, realign spacing */
- len = 0;
- width = alen = *sp++;
- while (*tp) {
- nsp = sp;
- for (end = tp; *end; end = tab) {
- tab = end + 1;
- alen += *nsp++;
- if (f->fg[*end&0xff]) {
- while ((gp = f->fg[*tab&0xff]) != NULL &&
- gp->nverts == 0) { /* tab in */
- alen += *nsp++;
- tab++;
- }
- len += tab - end;
- }
- if (nsi && tab - end > nsi)
- break;
- }
- len *= f->mwidth + cis; /* compute target length */
- width += len;
- len -= alen; /* necessary adjustment */
- while (sp < nsp) {
- alen = len/(nsp-sp);
- *sp++ += alen;
- len -= alen;
- }
- len = 0;
- alen = 0;
- tp = tab;
- }
- return(width);
- }
-