ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/common/font.c
Revision: 2.7
Committed: Fri May 14 11:30:17 1993 UTC (30 years, 11 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.6: +2 -4 lines
Log Message:
fixed bug in proptext() that caused it to report incorrect width

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     extern char *libpath; /* list of library directories */
19    
20 greg 2.5 extern char *fgetword();
21    
22 greg 2.1 static FONT *fontlist = NULL; /* list of loaded fonts */
23    
24    
25     FONT *
26     getfont(fname) /* return font fname */
27     char *fname;
28     {
29     char buf[16];
30     FILE *fp;
31     char *pathname, *err;
32 greg 2.3 unsigned wsum, hsum, ngly;
33 greg 2.1 int gn, ngv;
34     register int gv;
35 greg 2.5 register GLYPH *g;
36 greg 2.1 GORD *gp;
37     register FONT *f;
38    
39     for (f = fontlist; f != NULL; f = f->next)
40     if (!strcmp(f->name, fname))
41     return(f);
42     /* load the font file */
43     if ((pathname = getpath(fname, libpath, R_OK)) == NULL) {
44     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     if ((fp = fopen(pathname, "r")) == NULL) {
52     sprintf(errmsg, "cannot open font file \"%s\"",
53     pathname);
54     error(SYSTEM, errmsg);
55     }
56 greg 2.3 wsum = hsum = ngly = 0;
57 greg 2.1 while (fgetword(buf,sizeof(buf),fp) != NULL) { /* get each glyph */
58     if (!isint(buf))
59     goto nonint;
60     gn = atoi(buf);
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     if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) ||
70     (ngv = atoi(buf)) < 0 || ngv > 32000) {
71     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     if (fgetword(buf,sizeof(buf),fp) == NULL ||
83     !isint(buf) ||
84     (gv = atoi(buf)) < 0 || gv > 255) {
85     err = "bad vertex for";
86     goto fonterr;
87     }
88     *gp++ = gv;
89 greg 2.2 if (ngv & 1) { /* follow x limits */
90     if (gv < g->left)
91     g->left = gv;
92     else if (gv > g->right)
93     g->right = gv;
94     } else { /* follow y limits */
95     if (gv < g->bottom)
96     g->bottom = gv;
97     else if (gv > g->top)
98     g->top = gv;
99     }
100 greg 2.1 }
101 greg 2.3 if (g->right - g->left && g->top - g->bottom) {
102     ngly++;
103     wsum += g->right - g->left;
104     hsum += g->top - g->bottom;
105     }
106 greg 2.1 f->fg[gn] = g;
107     }
108     fclose(fp);
109 greg 2.3 if (ngly) {
110     f->mwidth = wsum / ngly;
111     f->mheight = hsum / ngly;
112     }
113 greg 2.1 f->next = fontlist;
114     return(fontlist = f);
115     nonint:
116     sprintf(errmsg, "non-integer in font file \"%s\"", pathname);
117     error(USER, errmsg);
118     fonterr:
119     sprintf(errmsg, "%s character (%d) in font file \"%s\"",
120     err, gn, pathname);
121     error(USER, errmsg);
122     memerr:
123     error(SYSTEM, "out of memory in fontglyph");
124     }
125 greg 2.2
126    
127 greg 2.6 freefont(fname) /* free a font (free all if fname==NULL) */
128     char *fname;
129     {
130     FONT head;
131     register FONT *fl, *f;
132     register int i;
133    
134     head.next = fontlist;
135     fl = &head;
136     while ((f = fl->next) != NULL)
137     if (fname == NULL || !strcmp(fname, f->name)) {
138     fl->next = f->next;
139     for (i = 0; i < 256; i++)
140     if (f->fg[i] != NULL)
141     free((char *)f->fg[i]);
142     freestr(f->name);
143     free((char *)f);
144     } 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     linelen += *sp++ = 256;
164     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     gp = NULL;
179     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
180     *sp++ = 0;
181     cis /= 2;
182 greg 2.3 linelen = *sp = cis;
183 greg 2.2 while (gp != NULL) {
184     if (gp->nverts) { /* regular character */
185     linelen += *sp++ += cis - gp->left;
186     *sp = gp->right + cis;
187     } else { /* space */
188     linelen += *sp++;
189 greg 2.3 *sp = f->mwidth;
190 greg 2.2 }
191     gp = NULL;
192     while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
193     linelen += *sp++;
194     *sp = 0;
195     }
196     }
197 greg 2.3 linelen += *sp += cis;
198 greg 2.2 return(linelen);
199     }
200    
201    
202 greg 2.3 int
203 greg 2.2 proptext(sp, tp, f, cis, nsi) /* space line proportionally */
204     short *sp; /* returned character spacing */
205     char *tp; /* text line */
206     FONT *f; /* font */
207     int cis; /* target intercharacter spacing */
208     int nsi; /* minimum number of spaces for indent */
209     {
210 greg 2.3 register char *end, *tab;
211     GLYPH *gp;
212     short *nsp;
213     int alen, len, width;
214     /* start by squeezing it */
215     squeeztext(sp, tp, f, cis);
216     /* now, realign spacing */
217 greg 2.7 width = *sp++;
218 greg 2.3 while (*tp) {
219 greg 2.7 len = alen = 0;
220 greg 2.3 nsp = sp;
221     for (end = tp; *end; end = tab) {
222     tab = end + 1;
223     alen += *nsp++;
224     if (f->fg[*end&0xff]) {
225     while ((gp = f->fg[*tab&0xff]) != NULL &&
226     gp->nverts == 0) { /* tab in */
227     alen += *nsp++;
228     tab++;
229     }
230     len += tab - end;
231     }
232 greg 2.4 if (nsi && tab - end > nsi)
233 greg 2.3 break;
234     }
235     len *= f->mwidth + cis; /* compute target length */
236     width += len;
237     len -= alen; /* necessary adjustment */
238     while (sp < nsp) {
239     alen = len/(nsp-sp);
240     *sp++ += alen;
241     len -= alen;
242     }
243     tp = tab;
244     }
245     return(width);
246 greg 2.2 }