ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.12
Committed: Sat Feb 22 02:07:22 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.11: +78 -16 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# User Rev Content
1 greg 2.1 #ifndef lint
2 greg 2.12 static const char RCSid[] = "$Id$";
3 greg 2.1 #endif
4     /*
5     * Polygonal font handling routines
6     */
7    
8 greg 2.12 /* ====================================================================
9     * The Radiance Software License, Version 1.0
10     *
11     * Copyright (c) 1990 - 2002 The Regents of the University of California,
12     * through Lawrence Berkeley National Laboratory. All rights reserved.
13     *
14     * Redistribution and use in source and binary forms, with or without
15     * modification, are permitted provided that the following conditions
16     * are met:
17     *
18     * 1. Redistributions of source code must retain the above copyright
19     * notice, this list of conditions and the following disclaimer.
20     *
21     * 2. Redistributions in binary form must reproduce the above copyright
22     * notice, this list of conditions and the following disclaimer in
23     * the documentation and/or other materials provided with the
24     * distribution.
25     *
26     * 3. The end-user documentation included with the redistribution,
27     * if any, must include the following acknowledgment:
28     * "This product includes Radiance software
29     * (http://radsite.lbl.gov/)
30     * developed by the Lawrence Berkeley National Laboratory
31     * (http://www.lbl.gov/)."
32     * Alternately, this acknowledgment may appear in the software itself,
33     * if and wherever such third-party acknowledgments normally appear.
34     *
35     * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36     * and "The Regents of the University of California" must
37     * not be used to endorse or promote products derived from this
38     * software without prior written permission. For written
39     * permission, please contact [email protected].
40     *
41     * 5. Products derived from this software may not be called "Radiance",
42     * nor may "Radiance" appear in their name, without prior written
43     * permission of Lawrence Berkeley National Laboratory.
44     *
45     * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46     * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47     * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48     * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49     * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50     * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51     * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52     * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53     * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54     * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56     * SUCH DAMAGE.
57     * ====================================================================
58     *
59     * This software consists of voluntary contributions made by many
60     * individuals on behalf of Lawrence Berkeley National Laboratory. For more
61     * information on Lawrence Berkeley National Laboratory, please see
62     * <http://www.lbl.gov/>.
63     */
64    
65 greg 2.1 #include "standard.h"
66    
67     #include "font.h"
68    
69     #define galloc(nv) (GLYPH *)malloc(sizeof(GLYPH)+2*sizeof(GORD)*(nv))
70    
71    
72 greg 2.12 int retainfonts = 0; /* retain loaded fonts? */
73 greg 2.1
74     static FONT *fontlist = NULL; /* list of loaded fonts */
75    
76    
77     FONT *
78     getfont(fname) /* return font fname */
79     char *fname;
80     {
81     FILE *fp;
82     char *pathname, *err;
83 greg 2.3 unsigned wsum, hsum, ngly;
84 greg 2.11 int gn, ngv, gv;
85 greg 2.5 register GLYPH *g;
86 greg 2.1 GORD *gp;
87     register FONT *f;
88    
89     for (f = fontlist; f != NULL; f = f->next)
90 greg 2.12 if (!strcmp(f->name, fname)) {
91     f->nref++;
92 greg 2.1 return(f);
93 greg 2.12 }
94 greg 2.1 /* load the font file */
95 greg 2.9 if ((pathname = getpath(fname, getlibpath(), R_OK)) == NULL) {
96 greg 2.1 sprintf(errmsg, "cannot find font file \"%s\"", fname);
97     error(USER, errmsg);
98     }
99     f = (FONT *)calloc(1, sizeof(FONT));
100     if (f == NULL)
101     goto memerr;
102     f->name = savestr(fname);
103 greg 2.12 f->nref = 1;
104 greg 2.1 if ((fp = fopen(pathname, "r")) == NULL) {
105     sprintf(errmsg, "cannot open font file \"%s\"",
106     pathname);
107     error(SYSTEM, errmsg);
108     }
109 greg 2.12 wsum = hsum = ngly = 0; /* get each glyph */
110     while ((ngv = fgetval(fp, 'i', (char *)&gn)) != EOF) {
111 greg 2.11 if (ngv == 0)
112 greg 2.1 goto nonint;
113 greg 2.3 if (gn < 1 || gn > 255) {
114 greg 2.1 err = "illegal";
115     goto fonterr;
116     }
117     if (f->fg[gn] != NULL) {
118     err = "duplicate";
119     goto fonterr;
120     }
121 greg 2.12 if (fgetval(fp, 'i', (char *)&ngv) <= 0 ||
122     ngv < 0 || ngv > 32000) {
123 greg 2.1 err = "bad # vertices for";
124     goto fonterr;
125     }
126     g = galloc(ngv);
127     if (g == NULL)
128     goto memerr;
129     g->nverts = ngv;
130 greg 2.2 g->left = g->right = g->top = g->bottom = 128;
131 greg 2.1 ngv *= 2;
132     gp = gvlist(g);
133     while (ngv--) {
134 greg 2.12 if (fgetval(fp, 'i', (char *)&gv) <= 0 ||
135     gv < 0 || gv > 255) {
136 greg 2.1 err = "bad vertex for";
137     goto fonterr;
138     }
139     *gp++ = gv;
140 greg 2.2 if (ngv & 1) { /* follow x limits */
141     if (gv < g->left)
142     g->left = gv;
143     else if (gv > g->right)
144     g->right = gv;
145     } else { /* follow y limits */
146     if (gv < g->bottom)
147     g->bottom = gv;
148     else if (gv > g->top)
149     g->top = gv;
150     }
151 greg 2.1 }
152 greg 2.3 if (g->right - g->left && g->top - g->bottom) {
153     ngly++;
154     wsum += g->right - g->left;
155     hsum += g->top - g->bottom;
156     }
157 greg 2.1 f->fg[gn] = g;
158     }
159     fclose(fp);
160 greg 2.3 if (ngly) {
161     f->mwidth = wsum / ngly;
162     f->mheight = hsum / ngly;
163     }
164 greg 2.1 f->next = fontlist;
165     return(fontlist = f);
166     nonint:
167     sprintf(errmsg, "non-integer in font file \"%s\"", pathname);
168     error(USER, errmsg);
169     fonterr:
170     sprintf(errmsg, "%s character (%d) in font file \"%s\"",
171     err, gn, pathname);
172     error(USER, errmsg);
173     memerr:
174     error(SYSTEM, "out of memory in fontglyph");
175     }
176 greg 2.2
177    
178 greg 2.12 void
179     freefont(fnt) /* release a font (free all if NULL) */
180     FONT *fnt;
181 greg 2.6 {
182     FONT head;
183     register FONT *fl, *f;
184     register int i;
185 greg 2.12 /* check reference count */
186     if (fnt != NULL && (fnt->nref-- > 1 | retainfonts))
187     return;
188 greg 2.6 head.next = fontlist;
189     fl = &head;
190     while ((f = fl->next) != NULL)
191 greg 2.12 if ((fnt == NULL | fnt == f)) {
192 greg 2.6 fl->next = f->next;
193     for (i = 0; i < 256; i++)
194     if (f->fg[i] != NULL)
195 greg 2.12 free((void *)f->fg[i]);
196 greg 2.6 freestr(f->name);
197 greg 2.12 free((void *)f);
198 greg 2.6 } else
199     fl = f;
200     fontlist = head.next;
201     }
202    
203    
204 greg 2.2 int
205 greg 2.3 uniftext(sp, tp, f) /* uniformly space text line */
206 greg 2.5 register short *sp; /* returned character spacing */
207 greg 2.3 register char *tp; /* text line */
208     register FONT *f; /* font */
209     {
210     int linelen;
211    
212     linelen = *sp++ = 0;
213     while (*tp)
214     if (f->fg[*tp++&0xff] == NULL)
215     *sp++ = 0;
216     else
217 greg 2.10 linelen += *sp++ = 255;
218 greg 2.3 return(linelen);
219     }
220    
221    
222     int
223 greg 2.2 squeeztext(sp, tp, f, cis) /* squeeze text line */
224     short *sp; /* returned character spacing */
225     char *tp; /* text line */
226     FONT *f; /* font */
227     int cis; /* intercharacter spacing */
228     {
229     int linelen;
230 greg 2.5 register GLYPH *gp;
231 greg 2.2
232 greg 2.8 linelen = 0;
233 greg 2.2 gp = NULL;
234     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
235     *sp++ = 0;
236     cis /= 2;
237 greg 2.8 *sp = cis;
238 greg 2.2 while (gp != NULL) {
239     if (gp->nverts) { /* regular character */
240     linelen += *sp++ += cis - gp->left;
241     *sp = gp->right + cis;
242     } else { /* space */
243     linelen += *sp++;
244 greg 2.3 *sp = f->mwidth;
245 greg 2.2 }
246     gp = NULL;
247     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
248     linelen += *sp++;
249     *sp = 0;
250     }
251     }
252 greg 2.3 linelen += *sp += cis;
253 greg 2.2 return(linelen);
254     }
255    
256    
257 greg 2.3 int
258 greg 2.2 proptext(sp, tp, f, cis, nsi) /* space line proportionally */
259     short *sp; /* returned character spacing */
260     char *tp; /* text line */
261     FONT *f; /* font */
262     int cis; /* target intercharacter spacing */
263     int nsi; /* minimum number of spaces for indent */
264     {
265 greg 2.3 register char *end, *tab;
266     GLYPH *gp;
267     short *nsp;
268     int alen, len, width;
269     /* start by squeezing it */
270     squeeztext(sp, tp, f, cis);
271     /* now, realign spacing */
272 greg 2.7 width = *sp++;
273 greg 2.3 while (*tp) {
274 greg 2.7 len = alen = 0;
275 greg 2.3 nsp = sp;
276     for (end = tp; *end; end = tab) {
277     tab = end + 1;
278     alen += *nsp++;
279     if (f->fg[*end&0xff]) {
280     while ((gp = f->fg[*tab&0xff]) != NULL &&
281     gp->nverts == 0) { /* tab in */
282     alen += *nsp++;
283     tab++;
284     }
285     len += tab - end;
286     }
287 greg 2.4 if (nsi && tab - end > nsi)
288 greg 2.3 break;
289     }
290     len *= f->mwidth + cis; /* compute target length */
291     width += len;
292     len -= alen; /* necessary adjustment */
293     while (sp < nsp) {
294     alen = len/(nsp-sp);
295     *sp++ += alen;
296     len -= alen;
297     }
298     tp = tab;
299     }
300     return(width);
301 greg 2.2 }