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

# Content
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 extern char *fgetword();
21
22 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 unsigned wsum, hsum, ngly;
33 int gn, ngv;
34 register int gv;
35 register GLYPH *g;
36 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 wsum = hsum = ngly = 0;
57 while (fgetword(buf,sizeof(buf),fp) != NULL) { /* get each glyph */
58 if (!isint(buf))
59 goto nonint;
60 gn = atoi(buf);
61 if (gn < 1 || gn > 255) {
62 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 g->left = g->right = g->top = g->bottom = 128;
79 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 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 }
101 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 f->fg[gn] = g;
107 }
108 fclose(fp);
109 if (ngly) {
110 f->mwidth = wsum / ngly;
111 f->mheight = hsum / ngly;
112 }
113 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
126
127 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 int
151 uniftext(sp, tp, f) /* uniformly space text line */
152 register short *sp; /* returned character spacing */
153 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 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 register GLYPH *gp;
177
178 gp = NULL;
179 while (*tp && (gp = f->fg[*tp++&0xff]) == NULL)
180 *sp++ = 0;
181 cis /= 2;
182 linelen = *sp = cis;
183 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 *sp = f->mwidth;
190 }
191 gp = NULL;
192 while (*tp && (gp = f->fg[*tp++&0xff]) == NULL) {
193 linelen += *sp++;
194 *sp = 0;
195 }
196 }
197 linelen += *sp += cis;
198 return(linelen);
199 }
200
201
202 int
203 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 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 width = *sp++;
218 while (*tp) {
219 len = alen = 0;
220 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 if (nsi && tab - end > nsi)
233 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 }