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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.22 static const char RCSid[] = "$Id: font.c,v 2.21 2021/11/19 21:56:48 greg Exp $";
3 greg 2.1 #endif
4     /*
5     * Polygonal font handling routines
6     */
7    
8 greg 2.13 #include "copyright.h"
9 greg 2.12
10 schorsch 2.18 #include <stdlib.h>
11    
12 greg 2.19 #include "paths.h"
13 schorsch 2.17 #include "rtio.h"
14 greg 2.1 #include "font.h"
15    
16     #define galloc(nv) (GLYPH *)malloc(sizeof(GLYPH)+2*sizeof(GORD)*(nv))
17    
18 greg 2.12 int retainfonts = 0; /* retain loaded fonts? */
19 greg 2.1
20     static FONT *fontlist = NULL; /* list of loaded fonts */
21    
22    
23     FONT *
24 greg 2.21 getfont( /* return font fname */
25     char *fname
26     )
27 greg 2.1 {
28     FILE *fp;
29 schorsch 2.17 char *pathname, *err = NULL;
30 greg 2.3 unsigned wsum, hsum, ngly;
31 greg 2.11 int gn, ngv, gv;
32 greg 2.21 GLYPH *g;
33 greg 2.1 GORD *gp;
34 greg 2.21 FONT *f;
35 greg 2.1
36     for (f = fontlist; f != NULL; f = f->next)
37 greg 2.12 if (!strcmp(f->name, fname)) {
38     f->nref++;
39 greg 2.1 return(f);
40 greg 2.12 }
41 greg 2.1 /* load the font file */
42 greg 2.14 if ((pathname = getpath(fname, getrlibpath(), R_OK)) == NULL) {
43 greg 2.22 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 greg 2.1 }
50     f = (FONT *)calloc(1, sizeof(FONT));
51     if (f == NULL)
52     goto memerr;
53 greg 2.22 strcpy(f->name, fname);
54 greg 2.12 f->nref = 1;
55     wsum = hsum = ngly = 0; /* get each glyph */
56     while ((ngv = fgetval(fp, 'i', (char *)&gn)) != EOF) {
57 greg 2.11 if (ngv == 0)
58 greg 2.1 goto nonint;
59 greg 2.3 if (gn < 1 || gn > 255) {
60 greg 2.1 err = "illegal";
61     goto fonterr;
62     }
63     if (f->fg[gn] != NULL) {
64     err = "duplicate";
65     goto fonterr;
66     }
67 greg 2.12 if (fgetval(fp, 'i', (char *)&ngv) <= 0 ||
68     ngv < 0 || ngv > 32000) {
69 greg 2.1 err = "bad # vertices for";
70     goto fonterr;
71     }
72     g = galloc(ngv);
73     if (g == NULL)
74     goto memerr;
75     g->nverts = ngv;
76 greg 2.2 g->left = g->right = g->top = g->bottom = 128;
77 greg 2.1 ngv *= 2;
78     gp = gvlist(g);
79     while (ngv--) {
80 greg 2.12 if (fgetval(fp, 'i', (char *)&gv) <= 0 ||
81     gv < 0 || gv > 255) {
82 greg 2.1 err = "bad vertex for";
83     goto fonterr;
84     }
85     *gp++ = gv;
86 greg 2.2 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 greg 2.1 }
98 greg 2.3 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 greg 2.1 f->fg[gn] = g;
104     }
105     fclose(fp);
106 greg 2.3 if (ngly) {
107     f->mwidth = wsum / ngly;
108     f->mheight = hsum / ngly;
109     }
110 greg 2.1 f->next = fontlist;
111     return(fontlist = f);
112     nonint:
113 greg 2.22 fprintf(stderr, "non-integer in font file \"%s\"\n", pathname);
114     fclose(fp);
115     return(NULL);
116 greg 2.1 fonterr:
117 greg 2.22 fprintf(stderr, "%s character (%d) in font file \"%s\"\n",
118 greg 2.1 err, gn, pathname);
119 greg 2.22 fclose(fp);
120     return(NULL);
121 greg 2.1 memerr:
122 greg 2.22 fprintf(stderr, "out of memory in getfont()\n");
123     fclose(fp);
124     return(NULL);
125 greg 2.1 }
126 greg 2.2
127    
128 greg 2.12 void
129 greg 2.21 freefont( /* release a font (free all if NULL) */
130     FONT *fnt
131     )
132 greg 2.6 {
133     FONT head;
134 greg 2.21 FONT *fl, *f;
135     int i;
136 greg 2.12 /* check reference count */
137 schorsch 2.16 if (fnt != NULL && ((fnt->nref-- > 1) | retainfonts))
138 greg 2.12 return;
139 greg 2.6 head.next = fontlist;
140     fl = &head;
141     while ((f = fl->next) != NULL)
142 schorsch 2.16 if ((fnt == NULL) | (fnt == f)) {
143 greg 2.6 fl->next = f->next;
144     for (i = 0; i < 256; i++)
145     if (f->fg[i] != NULL)
146 greg 2.12 free((void *)f->fg[i]);
147     free((void *)f);
148 greg 2.6 } else
149     fl = f;
150     fontlist = head.next;
151     }
152    
153    
154 greg 2.2 int
155 greg 2.21 uniftext( /* uniformly space text line */
156     short *sp, /* returned character spacing */
157     char *tp, /* text line */
158     FONT *f /* font */
159     )
160 greg 2.3 {
161     int linelen;
162    
163     linelen = *sp++ = 0;
164     while (*tp)
165     if (f->fg[*tp++&0xff] == NULL)
166     *sp++ = 0;
167     else
168 greg 2.10 linelen += *sp++ = 255;
169 greg 2.3 return(linelen);
170     }
171    
172    
173     int
174 greg 2.21 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 greg 2.2 {
181     int linelen;
182 greg 2.21 GLYPH *gp;
183 greg 2.2
184 greg 2.8 linelen = 0;
185 greg 2.2 gp = NULL;
186     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
187     *sp++ = 0;
188     cis /= 2;
189 greg 2.8 *sp = cis;
190 greg 2.2 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 greg 2.3 *sp = f->mwidth;
197 greg 2.2 }
198     gp = NULL;
199     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
200     linelen += *sp++;
201     *sp = 0;
202     }
203     }
204 greg 2.3 linelen += *sp += cis;
205 greg 2.2 return(linelen);
206     }
207    
208    
209 greg 2.3 int
210 greg 2.21 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 greg 2.2 {
218 greg 2.21 char *end, *tab = NULL;
219 greg 2.3 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 greg 2.7 width = *sp++;
226 greg 2.3 while (*tp) {
227 greg 2.7 len = alen = 0;
228 greg 2.3 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 greg 2.4 if (nsi && tab - end > nsi)
241 greg 2.3 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 greg 2.2 }