ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/text.c
Revision: 1.7
Committed: Mon Aug 5 09:32:12 1991 UTC (32 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.6: +140 -87 lines
Log Message:
fixed long-standing bug in slanted text

File Contents

# Content
1 /* Copyright (c) 1991 Regents of the University of California */
2
3 #ifndef lint
4 static char SCCSid[] = "$SunId$ LBL";
5 #endif
6
7 /*
8 * text.c - functions for text patterns and mixtures.
9 *
10 * 11/12/86
11 */
12
13 #include "ray.h"
14
15 #include "otypes.h"
16
17 /*
18 * A text pattern is specified as the text (a file or line),
19 * the upper left anchor point, the right motion vector, the down
20 * motion vector, and the foreground and background brightness.
21 * For a file, the description is as follows:
22 *
23 * modifier brighttext id
24 * 2 fontfile textfile
25 * 0
26 * 11
27 * Ax Ay Az
28 * Rx Ry Rz
29 * Dx Dy Dz
30 * foreground background
31 *
32 * For a single line, we use:
33 *
34 * modifier brighttext id
35 * N+2 fontfile . This is a line with N words...
36 * 0
37 * 11
38 * Ax Ay Az
39 * Rx Ry Rz
40 * Dx Dy Dz
41 * foreground background
42 *
43 * Colortext is identical, except colors are given rather than
44 * brightnesses. Mixtext has foreground and background modifiers:
45 *
46 * modifier mixtext id
47 * 4+ foremod backmod fontfile text..
48 * 0
49 * 9
50 * Ax Ay Az
51 * Rx Ry Rz
52 * Dx Dy Dz
53 */
54
55 #define fndx(m) ((m)->otype==MIX_TEXT ? 2 : 0)
56 #define tndx(m) ((m)->otype==MIX_TEXT ? 3 : 1)
57
58 extern char *libpath; /* library search path */
59
60 typedef unsigned char GLYPH;
61
62 typedef struct font {
63 GLYPH *fg[256]; /* font glyphs */
64 char *name; /* font file name */
65 struct font *next; /* next font in list */
66 } FONT;
67
68 typedef struct {
69 char **t; /* text array */
70 FVECT right, down; /* right and down unit vectors */
71 FONT *f; /* our font */
72 } TEXT;
73
74 extern char *fgetword();
75
76 TEXT *gettext();
77
78 FONT *getfont();
79
80 static FONT *fontlist = NULL; /* our font list */
81
82
83 text(m, r)
84 register OBJREC *m;
85 RAY *r;
86 {
87 double v[3];
88 int foreground;
89 /* get transformed position */
90 if (r->rox != NULL)
91 multp3(v, r->rop, r->rox->b.xfm);
92 else
93 VCOPY(v, r->rop);
94 /* check if we are within a text glyph */
95 foreground = intext(v, m);
96 /* modify */
97 if (m->otype == MIX_TEXT) {
98 OBJECT omod;
99 char *modname = m->oargs.sarg[foreground ? 0 : 1];
100 if (!strcmp(modname, VOIDID))
101 omod = OVOID;
102 else if ((omod = modifier(modname)) == OVOID) {
103 sprintf(errmsg, "undefined modifier \"%s\"", modname);
104 objerror(m, USER, errmsg);
105 }
106 raytexture(r, omod);
107 } else if (m->otype == PAT_BTEXT) {
108 if (foreground)
109 scalecolor(r->pcol, m->oargs.farg[9]);
110 else
111 scalecolor(r->pcol, m->oargs.farg[10]);
112 } else { /* PAT_CTEXT */
113 COLOR cval;
114 if (foreground)
115 setcolor(cval, m->oargs.farg[9],
116 m->oargs.farg[10],
117 m->oargs.farg[11]);
118 else
119 setcolor(cval, m->oargs.farg[12],
120 m->oargs.farg[13],
121 m->oargs.farg[14]);
122 multcolor(r->pcol, cval);
123 }
124 }
125
126
127 TEXT *
128 gettext(tm) /* get text structure for material */
129 register OBJREC *tm;
130 {
131 #define R (tm->oargs.farg+3)
132 #define D (tm->oargs.farg+6)
133 extern char *strcpy(), *fgets();
134 FVECT DxR;
135 double d;
136 FILE *fp;
137 char linbuf[512];
138 register TEXT *t;
139 register int i;
140 register char *s;
141
142 if ((t = (TEXT *)tm->os) != NULL)
143 return(t);
144 /* check arguments */
145 if (tm->oargs.nsargs - tndx(tm) < 1 ||
146 tm->oargs.nfargs != (tm->otype == PAT_BTEXT ? 11 :
147 tm->otype == PAT_CTEXT ? 15 : 9))
148 objerror(tm, USER, "bad # arguments");
149 if ((t = (TEXT *)malloc(sizeof(TEXT))) == NULL)
150 goto memerr;
151 /* compute vectors */
152 fcross(DxR, D, R);
153 fcross(t->right, DxR, D);
154 d = DOT(D,D) / DOT(t->right,t->right);
155 for (i = 0; i < 3; i++)
156 t->right[i] *= d;
157 fcross(t->down, R, DxR);
158 d = DOT(R,R) / DOT(t->down,t->down);
159 for (i = 0; i < 3; i++)
160 t->down[i] *= d;
161 /* get text */
162 t->t = (char **)malloc(2*sizeof(char **));
163 if (t->t == NULL)
164 goto memerr;
165 if (tm->oargs.nsargs - tndx(tm) > 1) { /* single line */
166 s = linbuf;
167 for (i = tndx(tm)+1; i < tm->oargs.nsargs; i++) {
168 strcpy(s, tm->oargs.sarg[i]);
169 s += strlen(s);
170 *s++ = ' ';
171 }
172 *--s = '\0';
173 t->t[0] = savqstr(linbuf);
174 t->t[1] = NULL;
175 } else { /* text file */
176 if ((s = getpath(tm->oargs.sarg[tndx(tm)],
177 libpath, R_OK)) == NULL) {
178 sprintf(errmsg, "cannot find text file \"%s\"",
179 tm->oargs.sarg[tndx(tm)]);
180 error(USER, errmsg);
181 }
182 if ((fp = fopen(s, "r")) == NULL) {
183 sprintf(errmsg, "cannot open text file \"%s\"",
184 s);
185 error(SYSTEM, errmsg);
186 }
187 for (i=0; fgets(linbuf,sizeof(linbuf),fp)!=NULL; i++) {
188 s = linbuf + strlen(linbuf) - 1;
189 if (*s == '\n')
190 *s = '\0';
191 t->t=(char **)realloc((char *)t->t,
192 (i+2)*sizeof(char **));
193 if (t->t == NULL)
194 goto memerr;
195 t->t[i] = savqstr(linbuf);
196 }
197 t->t[i] = NULL;
198 fclose(fp);
199 }
200 /* get the font */
201 t->f = getfont(tm->oargs.sarg[fndx(tm)]);
202 /* we're done */
203 tm->os = (char *)t;
204 return(t);
205 memerr:
206 error(SYSTEM, "out of memory in gettext");
207 #undef R
208 #undef D
209 }
210
211
212 freetext(m) /* free text structures associated with m */
213 OBJREC *m;
214 {
215 register TEXT *tp;
216 register int i;
217
218 tp = (TEXT *)m->os;
219 if (tp == NULL)
220 return;
221 for (i = 0; tp->t[i] != NULL; i++)
222 freeqstr(tp->t[i]);
223 free((char *)tp->t);
224 free((char *)tp);
225 m->os = NULL;
226 }
227
228
229 intext(p, m) /* check to see if p is in text glyph */
230 FVECT p;
231 register OBJREC *m;
232 {
233 register TEXT *tp;
234 register int i;
235 double v[3], y, x;
236 int col, lno;
237 /* first, compute position in text */
238 v[0] = p[0] - m->oargs.farg[0];
239 v[1] = p[1] - m->oargs.farg[1];
240 v[2] = p[2] - m->oargs.farg[2];
241 col = x = DOT(v, tp->right);
242 lno = y = DOT(v, tp->down);
243 if (x < 0.0 || y < 0.0)
244 return(0);
245 x -= (double)col;
246 y = (lno+1) - y;
247 /* get the font character */
248 tp = gettext(m);
249 for (i = 0; i < lno; i++)
250 if (tp->t[i] == NULL)
251 return(0);
252 if (col >= strlen(tp->t[i]))
253 return(0);
254 return(inglyph(x, y, tp->f->fg[tp->t[i][col]]));
255 }
256
257
258 FONT *
259 getfont(fname) /* return font fname */
260 char *fname;
261 {
262 char buf[16];
263 FILE *fp;
264 char *pathname, *err;
265 int gn, ngv, gv;
266 register GLYPH *g;
267 register FONT *f;
268
269 for (f = fontlist; f != NULL; f = f->next)
270 if (!strcmp(f->name, fname))
271 return(f);
272 /* load the font file */
273 if ((pathname = getpath(fname, libpath, R_OK)) == NULL) {
274 sprintf(errmsg, "cannot find font file \"%s\"", fname);
275 error(USER, errmsg);
276 }
277 f = (FONT *)calloc(1, sizeof(FONT));
278 if (f == NULL)
279 goto memerr;
280 f->name = savestr(fname);
281 if ((fp = fopen(pathname, "r")) == NULL) {
282 sprintf(errmsg, "cannot open font file \"%s\"",
283 pathname);
284 error(SYSTEM, errmsg);
285 }
286 while (fgetword(buf,sizeof(buf),fp) != NULL) { /* get each glyph */
287 if (!isint(buf))
288 goto nonint;
289 gn = atoi(buf);
290 if (gn < 0 || gn > 255) {
291 err = "illegal";
292 goto fonterr;
293 }
294 if (f->fg[gn] != NULL) {
295 err = "duplicate";
296 goto fonterr;
297 }
298 if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) ||
299 (ngv = atoi(buf)) < 0 || ngv > 255) {
300 err = "bad # vertices for";
301 goto fonterr;
302 }
303 g = (GLYPH *)malloc((2*ngv+1)*sizeof(GLYPH));
304 if (g == NULL)
305 goto memerr;
306 f->fg[gn] = g;
307 *g++ = ngv;
308 ngv *= 2;
309 while (ngv--) {
310 if (fgetword(buf,sizeof(buf),fp) == NULL ||
311 !isint(buf) ||
312 (gv = atoi(buf)) < 0 || gv > 255) {
313 err = "bad vertex for";
314 goto fonterr;
315 }
316 *g++ = gv;
317 }
318 }
319 fclose(fp);
320 f->next = fontlist;
321 return(fontlist = f);
322 nonint:
323 sprintf(errmsg, "non-integer in font file \"%s\"", pathname);
324 error(USER, errmsg);
325 fonterr:
326 sprintf(errmsg, "%s character (%d) in font file \"%s\"",
327 err, gn, pathname);
328 error(USER, errmsg);
329 memerr:
330 error(SYSTEM, "out of memory in fontglyph");
331 }
332
333
334 inglyph(x, y, gl) /* (x,y) within font glyph gl? */
335 double x, y;
336 GLYPH *gl;
337 {
338 int n, ncross;
339 int xlb, ylb;
340 register GLYPH *p0, *p1;
341
342 if (gl == NULL)
343 return(0);
344 x *= 256.0; /* get glyph coordinates */
345 y *= 256.0;
346 xlb = x + 0.5;
347 ylb = y + 0.5;
348 n = *gl++; /* get # of vertices */
349 p0 = gl + 2*(n-1); /* connect last to first */
350 p1 = gl;
351 ncross = 0;
352 /* positive x axis cross test */
353 while (n--) {
354 if ((p0[1] > ylb) ^ (p1[1] > ylb))
355 if (p0[0] > xlb && p1[0] > xlb)
356 ncross++;
357 else if (p0[0] > xlb || p1[0] > xlb)
358 ncross += (p1[1] > p0[1]) ^
359 ((p0[1]-y)*(p1[0]-x) >
360 (p0[0]-x)*(p1[1]-y));
361 p0 = p1;
362 p1 += 2;
363 }
364 return(ncross & 01);
365 }