ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.26
Committed: Wed Feb 2 00:03:40 2022 UTC (2 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.25: +2 -2 lines
Log Message:
fix: syntax(!)

File Contents

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