ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.22
Committed: Fri Nov 19 22:51:31 2021 UTC (2 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.21: +17 -18 lines
Log Message:
refactor: made font load errors non-fatal

File Contents

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