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, 11 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

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