ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.17
Committed: Fri Nov 14 17:22:06 2003 UTC (20 years, 5 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.16: +5 -5 lines
Log Message:
Reduced compile warnings, and other compatibility fixes.

File Contents

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