ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.19
Committed: Fri Mar 26 23:04:23 2004 UTC (20 years ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad4R2P2, rad5R0, rad3R7P2, rad3R7P1, rad4R2, rad4R1, rad4R0, rad3R6, rad3R6P1, rad3R8, rad3R9, rad4R2P1
Changes since 2.18: +2 -1 lines
Log Message:
Fixed missing R_OK definition under Unix

File Contents

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