--- ray/src/common/font.c 1992/06/24 17:52:58 2.3 +++ ray/src/common/font.c 2022/02/02 00:01:48 2.25 @@ -1,61 +1,65 @@ -/* Copyright (c) 1992 Regents of the University of California */ - #ifndef lint -static char SCCSid[] = "$SunId$ LBL"; +static const char RCSid[] = "$Id: font.c,v 2.25 2022/02/02 00:01:48 greg Exp $"; #endif - /* * Polygonal font handling routines */ -#include "standard.h" +#include "copyright.h" +#include + +#include "paths.h" +#include "rtio.h" +#include "rterror.h" #include "font.h" #define galloc(nv) (GLYPH *)malloc(sizeof(GLYPH)+2*sizeof(GORD)*(nv)) +int retainfonts = 0; /* retain loaded fonts? */ -extern char *libpath; /* list of library directories */ - static FONT *fontlist = NULL; /* list of loaded fonts */ FONT * -getfont(fname) /* return font fname */ -char *fname; +getfont( /* return font fname */ + char *fname +) { - char buf[16]; + char embuf[512]; FILE *fp; - char *pathname, *err; + char *pathname, *err = NULL; unsigned wsum, hsum, ngly; - int gn, ngv; - register int gv; - register GLYPH *g; + int gn, ngv, gv; + GLYPH *g; GORD *gp; - register FONT *f; + FONT *f; for (f = fontlist; f != NULL; f = f->next) - if (!strcmp(f->name, fname)) + if (!strcmp(f->name, fname)) { + f->nref++; 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); + if ((pathname = getpath(fname, getrlibpath(), R_OK)) == NULL) { + sprintf(embuf, "cannot find font file \"%s\"\n", fname); + eputs(embuf); + return(NULL); } + if ((fp = fopen(pathname, "r")) == NULL) { + sprintf(embuf, "cannot open font file \"%s\"\n", pathname); + eputs(embuf); + return(NULL); + } 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)) + strcpy(f->name, fname); + f->nref = 1; + wsum = hsum = ngly = 0; /* get each glyph */ + while ((ngv = fgetval(fp, 'i', (char *)&gn)) != EOF) { + if (ngv == 0) goto nonint; - gn = atoi(buf); if (gn < 1 || gn > 255) { err = "illegal"; goto fonterr; @@ -64,11 +68,13 @@ char *fname; err = "duplicate"; goto fonterr; } - if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) || - (ngv = atoi(buf)) < 0 || ngv > 32000) { + if (fgetval(fp, 'i', (char *)&ngv) <= 0 || + ngv < 0 || ngv > 32000) { err = "bad # vertices for"; goto fonterr; } + if (ngv > f->maxgv) + f->maxgv = ngv; g = galloc(ngv); if (g == NULL) goto memerr; @@ -77,9 +83,8 @@ char *fname; ngv *= 2; gp = gvlist(g); while (ngv--) { - if (fgetword(buf,sizeof(buf),fp) == NULL || - !isint(buf) || - (gv = atoi(buf)) < 0 || gv > 255) { + if (fgetval(fp, 'i', (char *)&gv) <= 0 || + gv < 0 || gv > 255) { err = "bad vertex for"; goto fonterr; } @@ -111,22 +116,55 @@ char *fname; f->next = fontlist; return(fontlist = f); nonint: - sprintf(errmsg, "non-integer in font file \"%s\"", pathname); - error(USER, errmsg); + sprintf(embuf, "non-integer in font file \"%s\"\n", pathname); + eputs(embuf); + fclose(fp); + return(NULL); fonterr: - sprintf(errmsg, "%s character (%d) in font file \"%s\"", + sprintf(embuf, "%s character (%d) in font file \"%s\"\n", err, gn, pathname); - error(USER, errmsg); + eputs(embuf); + fclose(fp); + return(NULL); memerr: - error(SYSTEM, "out of memory in fontglyph"); + eputs("out of memory in getfont()\n"); + fclose(fp); + return(NULL); } +void +freefont( /* release a font (free all if NULL) */ + FONT *fnt +) +{ + FONT head; + FONT *fl, *f; + int i; + /* check reference count */ + if (fnt != NULL && (fnt->nref -= (f->nref > 0)) | retainfonts)) + return; + head.next = fontlist; + fl = &head; + while ((f = fl->next) != NULL) + if ((fnt == NULL) | (fnt == f)) { + fl->next = f->next; + for (i = 0; i < 256; i++) + if (f->fg[i] != NULL) + free((void *)f->fg[i]); + free((void *)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 */ +uniftext( /* uniformly space text line */ + short *sp, /* returned character spacing */ + char *tp, /* text line */ + FONT *f /* font */ +) { int linelen; @@ -135,26 +173,28 @@ register FONT *f; /* font */ if (f->fg[*tp++&0xff] == NULL) *sp++ = 0; else - linelen += *sp++ = 256; + linelen += *sp++ = 255; 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 */ +squeeztext( /* squeeze text line */ + short *sp, /* returned character spacing */ + char *tp, /* text line */ + FONT *f, /* font */ + int cis /* intercharacter spacing */ +) { int linelen; - register GLYPH *gp; + GLYPH *gp; + linelen = 0; gp = NULL; while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) *sp++ = 0; cis /= 2; - linelen = *sp = cis; + *sp = cis; while (gp != NULL) { if (gp->nverts) { /* regular character */ linelen += *sp++ += cis - gp->left; @@ -175,23 +215,24 @@ int cis; /* intercharacter spacing */ 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 */ +proptext( /* 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; + char *end, *tab = NULL; 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++; + width = *sp++; while (*tp) { + len = alen = 0; nsp = sp; for (end = tp; *end; end = tab) { tab = end + 1; @@ -204,7 +245,7 @@ int nsi; /* minimum number of spaces for indent */ } len += tab - end; } - if (tab - end > nsi) + if (nsi && tab - end > nsi) break; } len *= f->mwidth + cis; /* compute target length */ @@ -215,8 +256,6 @@ int nsi; /* minimum number of spaces for indent */ *sp++ += alen; len -= alen; } - len = 0; - alen = 0; tp = tab; } return(width);