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

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.23 static const char RCSid[] = "$Id: font.c,v 2.22 2021/11/19 22:51:31 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.23 #include "rterror.h"
15 greg 2.1 #include "font.h"
16    
17     #define galloc(nv) (GLYPH *)malloc(sizeof(GLYPH)+2*sizeof(GORD)*(nv))
18    
19 greg 2.12 int retainfonts = 0; /* retain loaded fonts? */
20 greg 2.1
21     static FONT *fontlist = NULL; /* list of loaded fonts */
22    
23    
24     FONT *
25 greg 2.21 getfont( /* return font fname */
26     char *fname
27     )
28 greg 2.1 {
29     FILE *fp;
30 schorsch 2.17 char *pathname, *err = NULL;
31 greg 2.3 unsigned wsum, hsum, ngly;
32 greg 2.11 int gn, ngv, gv;
33 greg 2.21 GLYPH *g;
34 greg 2.1 GORD *gp;
35 greg 2.21 FONT *f;
36 greg 2.1
37     for (f = fontlist; f != NULL; f = f->next)
38 greg 2.12 if (!strcmp(f->name, fname)) {
39     f->nref++;
40 greg 2.1 return(f);
41 greg 2.12 }
42 greg 2.1 /* load the font file */
43 greg 2.14 if ((pathname = getpath(fname, getrlibpath(), R_OK)) == NULL) {
44 greg 2.23 sprintf(errmsg, "cannot find font file \"%s\"\n", fname);
45     eputs(errmsg);
46 greg 2.22 return(NULL);
47     }
48     if ((fp = fopen(pathname, "r")) == NULL) {
49 greg 2.23 sprintf(errmsg, "cannot open font file \"%s\"\n", pathname);
50     eputs(errmsg);
51 greg 2.22 return(NULL);
52 greg 2.1 }
53     f = (FONT *)calloc(1, sizeof(FONT));
54     if (f == NULL)
55     goto memerr;
56 greg 2.22 strcpy(f->name, fname);
57 greg 2.12 f->nref = 1;
58     wsum = hsum = ngly = 0; /* get each glyph */
59     while ((ngv = fgetval(fp, 'i', (char *)&gn)) != EOF) {
60 greg 2.11 if (ngv == 0)
61 greg 2.1 goto nonint;
62 greg 2.3 if (gn < 1 || gn > 255) {
63 greg 2.1 err = "illegal";
64     goto fonterr;
65     }
66     if (f->fg[gn] != NULL) {
67     err = "duplicate";
68     goto fonterr;
69     }
70 greg 2.12 if (fgetval(fp, 'i', (char *)&ngv) <= 0 ||
71     ngv < 0 || ngv > 32000) {
72 greg 2.1 err = "bad # vertices for";
73     goto fonterr;
74     }
75     g = galloc(ngv);
76     if (g == NULL)
77     goto memerr;
78     g->nverts = ngv;
79 greg 2.2 g->left = g->right = g->top = g->bottom = 128;
80 greg 2.1 ngv *= 2;
81     gp = gvlist(g);
82     while (ngv--) {
83 greg 2.12 if (fgetval(fp, 'i', (char *)&gv) <= 0 ||
84     gv < 0 || gv > 255) {
85 greg 2.1 err = "bad vertex for";
86     goto fonterr;
87     }
88     *gp++ = gv;
89 greg 2.2 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 greg 2.1 }
101 greg 2.3 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 greg 2.1 f->fg[gn] = g;
107     }
108     fclose(fp);
109 greg 2.3 if (ngly) {
110     f->mwidth = wsum / ngly;
111     f->mheight = hsum / ngly;
112     }
113 greg 2.1 f->next = fontlist;
114     return(fontlist = f);
115     nonint:
116 greg 2.23 sprintf(errmsg, "non-integer in font file \"%s\"\n", pathname);
117     eputs(errmsg);
118 greg 2.22 fclose(fp);
119     return(NULL);
120 greg 2.1 fonterr:
121 greg 2.23 sprintf(errmsg, "%s character (%d) in font file \"%s\"\n",
122 greg 2.1 err, gn, pathname);
123 greg 2.23 eputs(errmsg);
124 greg 2.22 fclose(fp);
125     return(NULL);
126 greg 2.1 memerr:
127 greg 2.23 eputs("out of memory in getfont()\n");
128 greg 2.22 fclose(fp);
129     return(NULL);
130 greg 2.1 }
131 greg 2.2
132    
133 greg 2.12 void
134 greg 2.21 freefont( /* release a font (free all if NULL) */
135     FONT *fnt
136     )
137 greg 2.6 {
138     FONT head;
139 greg 2.21 FONT *fl, *f;
140     int i;
141 greg 2.12 /* check reference count */
142 schorsch 2.16 if (fnt != NULL && ((fnt->nref-- > 1) | retainfonts))
143 greg 2.12 return;
144 greg 2.6 head.next = fontlist;
145     fl = &head;
146     while ((f = fl->next) != NULL)
147 schorsch 2.16 if ((fnt == NULL) | (fnt == f)) {
148 greg 2.6 fl->next = f->next;
149     for (i = 0; i < 256; i++)
150     if (f->fg[i] != NULL)
151 greg 2.12 free((void *)f->fg[i]);
152     free((void *)f);
153 greg 2.6 } else
154     fl = f;
155     fontlist = head.next;
156     }
157    
158    
159 greg 2.2 int
160 greg 2.21 uniftext( /* uniformly space text line */
161     short *sp, /* returned character spacing */
162     char *tp, /* text line */
163     FONT *f /* font */
164     )
165 greg 2.3 {
166     int linelen;
167    
168     linelen = *sp++ = 0;
169     while (*tp)
170     if (f->fg[*tp++&0xff] == NULL)
171     *sp++ = 0;
172     else
173 greg 2.10 linelen += *sp++ = 255;
174 greg 2.3 return(linelen);
175     }
176    
177    
178     int
179 greg 2.21 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 greg 2.2 {
186     int linelen;
187 greg 2.21 GLYPH *gp;
188 greg 2.2
189 greg 2.8 linelen = 0;
190 greg 2.2 gp = NULL;
191     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
192     *sp++ = 0;
193     cis /= 2;
194 greg 2.8 *sp = cis;
195 greg 2.2 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 greg 2.3 *sp = f->mwidth;
202 greg 2.2 }
203     gp = NULL;
204     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
205     linelen += *sp++;
206     *sp = 0;
207     }
208     }
209 greg 2.3 linelen += *sp += cis;
210 greg 2.2 return(linelen);
211     }
212    
213    
214 greg 2.3 int
215 greg 2.21 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 greg 2.2 {
223 greg 2.21 char *end, *tab = NULL;
224 greg 2.3 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 greg 2.7 width = *sp++;
231 greg 2.3 while (*tp) {
232 greg 2.7 len = alen = 0;
233 greg 2.3 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 greg 2.4 if (nsi && tab - end > nsi)
246 greg 2.3 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 greg 2.2 }