ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.23
Committed: Sat Nov 20 15:53:24 2021 UTC (2 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.22: +11 -6 lines
Log Message:
fix: switched call back from fprintf() to eputs() for error messages

File Contents

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