ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.9
Committed: Thu Apr 14 04:44:43 1994 UTC (30 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.8: +2 -4 lines
Log Message:
changed extern *libpath to extern *getlibpath()

File Contents

# User Rev Content
1 greg 2.1 /* Copyright (c) 1992 Regents of the University of California */
2    
3     #ifndef lint
4     static char SCCSid[] = "$SunId$ LBL";
5     #endif
6    
7     /*
8     * Polygonal font handling routines
9     */
10    
11     #include "standard.h"
12    
13     #include "font.h"
14    
15     #define galloc(nv) (GLYPH *)malloc(sizeof(GLYPH)+2*sizeof(GORD)*(nv))
16    
17    
18 greg 2.9 extern char *fgetword(), *getlibpath();
19 greg 2.1
20     static FONT *fontlist = NULL; /* list of loaded fonts */
21    
22    
23     FONT *
24     getfont(fname) /* return font fname */
25     char *fname;
26     {
27     char buf[16];
28     FILE *fp;
29     char *pathname, *err;
30 greg 2.3 unsigned wsum, hsum, ngly;
31 greg 2.1 int gn, ngv;
32     register int 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     if (!strcmp(f->name, fname))
39     return(f);
40     /* load the font file */
41 greg 2.9 if ((pathname = getpath(fname, getlibpath(), R_OK)) == NULL) {
42 greg 2.1 sprintf(errmsg, "cannot find font file \"%s\"", fname);
43     error(USER, errmsg);
44     }
45     f = (FONT *)calloc(1, sizeof(FONT));
46     if (f == NULL)
47     goto memerr;
48     f->name = savestr(fname);
49     if ((fp = fopen(pathname, "r")) == NULL) {
50     sprintf(errmsg, "cannot open font file \"%s\"",
51     pathname);
52     error(SYSTEM, errmsg);
53     }
54 greg 2.3 wsum = hsum = ngly = 0;
55 greg 2.1 while (fgetword(buf,sizeof(buf),fp) != NULL) { /* get each glyph */
56     if (!isint(buf))
57     goto nonint;
58     gn = atoi(buf);
59 greg 2.3 if (gn < 1 || gn > 255) {
60 greg 2.1 err = "illegal";
61     goto fonterr;
62     }
63     if (f->fg[gn] != NULL) {
64     err = "duplicate";
65     goto fonterr;
66     }
67     if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) ||
68     (ngv = atoi(buf)) < 0 || ngv > 32000) {
69     err = "bad # vertices for";
70     goto fonterr;
71     }
72     g = galloc(ngv);
73     if (g == NULL)
74     goto memerr;
75     g->nverts = ngv;
76 greg 2.2 g->left = g->right = g->top = g->bottom = 128;
77 greg 2.1 ngv *= 2;
78     gp = gvlist(g);
79     while (ngv--) {
80     if (fgetword(buf,sizeof(buf),fp) == NULL ||
81     !isint(buf) ||
82     (gv = atoi(buf)) < 0 || gv > 255) {
83     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     }
123 greg 2.2
124    
125 greg 2.6 freefont(fname) /* free a font (free all if fname==NULL) */
126     char *fname;
127     {
128     FONT head;
129     register FONT *fl, *f;
130     register int i;
131    
132     head.next = fontlist;
133     fl = &head;
134     while ((f = fl->next) != NULL)
135     if (fname == NULL || !strcmp(fname, f->name)) {
136     fl->next = f->next;
137     for (i = 0; i < 256; i++)
138     if (f->fg[i] != NULL)
139     free((char *)f->fg[i]);
140     freestr(f->name);
141     free((char *)f);
142     } else
143     fl = f;
144     fontlist = head.next;
145     }
146    
147    
148 greg 2.2 int
149 greg 2.3 uniftext(sp, tp, f) /* uniformly space text line */
150 greg 2.5 register short *sp; /* returned character spacing */
151 greg 2.3 register char *tp; /* text line */
152     register FONT *f; /* font */
153     {
154     int linelen;
155    
156     linelen = *sp++ = 0;
157     while (*tp)
158     if (f->fg[*tp++&0xff] == NULL)
159     *sp++ = 0;
160     else
161     linelen += *sp++ = 256;
162     return(linelen);
163     }
164    
165    
166     int
167 greg 2.2 squeeztext(sp, tp, f, cis) /* squeeze text line */
168     short *sp; /* returned character spacing */
169     char *tp; /* text line */
170     FONT *f; /* font */
171     int cis; /* intercharacter spacing */
172     {
173     int linelen;
174 greg 2.5 register GLYPH *gp;
175 greg 2.2
176 greg 2.8 linelen = 0;
177 greg 2.2 gp = NULL;
178     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
179     *sp++ = 0;
180     cis /= 2;
181 greg 2.8 *sp = cis;
182 greg 2.2 while (gp != NULL) {
183     if (gp->nverts) { /* regular character */
184     linelen += *sp++ += cis - gp->left;
185     *sp = gp->right + cis;
186     } else { /* space */
187     linelen += *sp++;
188 greg 2.3 *sp = f->mwidth;
189 greg 2.2 }
190     gp = NULL;
191     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
192     linelen += *sp++;
193     *sp = 0;
194     }
195     }
196 greg 2.3 linelen += *sp += cis;
197 greg 2.2 return(linelen);
198     }
199    
200    
201 greg 2.3 int
202 greg 2.2 proptext(sp, tp, f, cis, nsi) /* space line proportionally */
203     short *sp; /* returned character spacing */
204     char *tp; /* text line */
205     FONT *f; /* font */
206     int cis; /* target intercharacter spacing */
207     int nsi; /* minimum number of spaces for indent */
208     {
209 greg 2.3 register char *end, *tab;
210     GLYPH *gp;
211     short *nsp;
212     int alen, len, width;
213     /* start by squeezing it */
214     squeeztext(sp, tp, f, cis);
215     /* now, realign spacing */
216 greg 2.7 width = *sp++;
217 greg 2.3 while (*tp) {
218 greg 2.7 len = alen = 0;
219 greg 2.3 nsp = sp;
220     for (end = tp; *end; end = tab) {
221     tab = end + 1;
222     alen += *nsp++;
223     if (f->fg[*end&0xff]) {
224     while ((gp = f->fg[*tab&0xff]) != NULL &&
225     gp->nverts == 0) { /* tab in */
226     alen += *nsp++;
227     tab++;
228     }
229     len += tab - end;
230     }
231 greg 2.4 if (nsi && tab - end > nsi)
232 greg 2.3 break;
233     }
234     len *= f->mwidth + cis; /* compute target length */
235     width += len;
236     len -= alen; /* necessary adjustment */
237     while (sp < nsp) {
238     alen = len/(nsp-sp);
239     *sp++ += alen;
240     len -= alen;
241     }
242     tp = tab;
243     }
244     return(width);
245 greg 2.2 }