ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.18
Committed: Fri Mar 26 21:29:19 2004 UTC (20 years, 1 month ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.17: +3 -1 lines
Log Message:
Small fixes to reduce warnings. Added bmpfile.c to SConscript.

File Contents

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