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, 1 month 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

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