--- ray/src/common/font.c 1992/06/06 07:38:40 2.1 +++ ray/src/common/font.c 1993/05/14 11:30:17 2.7 @@ -17,6 +17,8 @@ static char SCCSid[] = "$SunId$ LBL"; extern char *libpath; /* list of library directories */ +extern char *fgetword(); + static FONT *fontlist = NULL; /* list of loaded fonts */ @@ -27,9 +29,10 @@ char *fname; char buf[16]; FILE *fp; char *pathname, *err; + unsigned wsum, hsum, ngly; int gn, ngv; register int gv; - register GLYPH *g; + register GLYPH *g; GORD *gp; register FONT *f; @@ -50,11 +53,12 @@ char *fname; 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 < 0 || gn > 255) { + if (gn < 1 || gn > 255) { err = "illegal"; goto fonterr; } @@ -71,7 +75,7 @@ char *fname; if (g == NULL) goto memerr; g->nverts = ngv; - g->start = g->width = 128; + g->left = g->right = g->top = g->bottom = 128; ngv *= 2; gp = gvlist(g); while (ngv--) { @@ -82,16 +86,30 @@ char *fname; goto fonterr; } *gp++ = gv; - if (ngv & 1) /* follow x limits */ - if (gv < g->start) - g->start = gv; - else if (gv > g->width) - g->width = 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; + } } - g->width -= g->start; + 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: @@ -103,4 +121,126 @@ fonterr: error(USER, errmsg); memerr: error(SYSTEM, "out of memory in fontglyph"); +} + + +freefont(fname) /* free a font (free all if fname==NULL) */ +char *fname; +{ + FONT head; + register FONT *fl, *f; + register int i; + + head.next = fontlist; + fl = &head; + while ((f = fl->next) != NULL) + if (fname == NULL || !strcmp(fname, f->name)) { + fl->next = f->next; + for (i = 0; i < 256; i++) + if (f->fg[i] != NULL) + free((char *)f->fg[i]); + freestr(f->name); + free((char *)f); + } else + fl = f; + fontlist = head.next; +} + + +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 */ + width = *sp++; + while (*tp) { + len = alen = 0; + 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; + } + tp = tab; + } + return(width); }