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

# User Rev Content
1 greg 2.1 #ifndef lint
2 schorsch 2.18 static const char RCSid[] = "$Id: font.c,v 2.17 2003/11/14 17:22:06 schorsch 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 schorsch 2.17 #include "rtio.h"
13     #include "rterror.h"
14 greg 2.1 #include "font.h"
15    
16     #define galloc(nv) (GLYPH *)malloc(sizeof(GLYPH)+2*sizeof(GORD)*(nv))
17    
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     getfont(fname) /* return font fname */
26     char *fname;
27     {
28     FILE *fp;
29 schorsch 2.17 char *pathname, *err = NULL;
30 greg 2.3 unsigned wsum, hsum, ngly;
31 greg 2.11 int gn, ngv, gv;
32 greg 2.5 register GLYPH *g;
33 greg 2.1 GORD *gp;
34     register FONT *f;
35    
36     for (f = fontlist; f != NULL; f = f->next)
37 greg 2.12 if (!strcmp(f->name, fname)) {
38     f->nref++;
39 greg 2.1 return(f);
40 greg 2.12 }
41 greg 2.1 /* load the font file */
42 greg 2.14 if ((pathname = getpath(fname, getrlibpath(), R_OK)) == NULL) {
43 greg 2.1 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 greg 2.12 f->nref = 1;
51 greg 2.1 if ((fp = fopen(pathname, "r")) == NULL) {
52     sprintf(errmsg, "cannot open font file \"%s\"",
53     pathname);
54     error(SYSTEM, errmsg);
55     }
56 greg 2.12 wsum = hsum = ngly = 0; /* get each glyph */
57     while ((ngv = fgetval(fp, 'i', (char *)&gn)) != EOF) {
58 greg 2.11 if (ngv == 0)
59 greg 2.1 goto nonint;
60 greg 2.3 if (gn < 1 || gn > 255) {
61 greg 2.1 err = "illegal";
62     goto fonterr;
63     }
64     if (f->fg[gn] != NULL) {
65     err = "duplicate";
66     goto fonterr;
67     }
68 greg 2.12 if (fgetval(fp, 'i', (char *)&ngv) <= 0 ||
69     ngv < 0 || ngv > 32000) {
70 greg 2.1 err = "bad # vertices for";
71     goto fonterr;
72     }
73     g = galloc(ngv);
74     if (g == NULL)
75     goto memerr;
76     g->nverts = ngv;
77 greg 2.2 g->left = g->right = g->top = g->bottom = 128;
78 greg 2.1 ngv *= 2;
79     gp = gvlist(g);
80     while (ngv--) {
81 greg 2.12 if (fgetval(fp, 'i', (char *)&gv) <= 0 ||
82     gv < 0 || gv > 255) {
83 greg 2.1 err = "bad vertex for";
84     goto fonterr;
85     }
86     *gp++ = gv;
87 greg 2.2 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 greg 2.1 }
99 greg 2.3 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 greg 2.1 f->fg[gn] = g;
105     }
106     fclose(fp);
107 greg 2.3 if (ngly) {
108     f->mwidth = wsum / ngly;
109     f->mheight = hsum / ngly;
110     }
111 greg 2.1 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 schorsch 2.15 return NULL; /* pro forma return */
123 greg 2.1 }
124 greg 2.2
125    
126 greg 2.12 void
127     freefont(fnt) /* release a font (free all if NULL) */
128     FONT *fnt;
129 greg 2.6 {
130     FONT head;
131     register FONT *fl, *f;
132     register int i;
133 greg 2.12 /* check reference count */
134 schorsch 2.16 if (fnt != NULL && ((fnt->nref-- > 1) | retainfonts))
135 greg 2.12 return;
136 greg 2.6 head.next = fontlist;
137     fl = &head;
138     while ((f = fl->next) != NULL)
139 schorsch 2.16 if ((fnt == NULL) | (fnt == f)) {
140 greg 2.6 fl->next = f->next;
141     for (i = 0; i < 256; i++)
142     if (f->fg[i] != NULL)
143 greg 2.12 free((void *)f->fg[i]);
144 greg 2.6 freestr(f->name);
145 greg 2.12 free((void *)f);
146 greg 2.6 } else
147     fl = f;
148     fontlist = head.next;
149     }
150    
151    
152 greg 2.2 int
153 greg 2.3 uniftext(sp, tp, f) /* uniformly space text line */
154 greg 2.5 register short *sp; /* returned character spacing */
155 greg 2.3 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 greg 2.10 linelen += *sp++ = 255;
166 greg 2.3 return(linelen);
167     }
168    
169    
170     int
171 greg 2.2 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 greg 2.5 register GLYPH *gp;
179 greg 2.2
180 greg 2.8 linelen = 0;
181 greg 2.2 gp = NULL;
182     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
183     *sp++ = 0;
184     cis /= 2;
185 greg 2.8 *sp = cis;
186 greg 2.2 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 greg 2.3 *sp = f->mwidth;
193 greg 2.2 }
194     gp = NULL;
195     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
196     linelen += *sp++;
197     *sp = 0;
198     }
199     }
200 greg 2.3 linelen += *sp += cis;
201 greg 2.2 return(linelen);
202     }
203    
204    
205 greg 2.3 int
206 greg 2.2 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 schorsch 2.17 register char *end, *tab = NULL;
214 greg 2.3 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 greg 2.7 width = *sp++;
221 greg 2.3 while (*tp) {
222 greg 2.7 len = alen = 0;
223 greg 2.3 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 greg 2.4 if (nsi && tab - end > nsi)
236 greg 2.3 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 greg 2.2 }