ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/text.c
Revision: 1.10
Committed: Wed Oct 23 13:43:49 1991 UTC (32 years, 6 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.9: +3 -2 lines
Log Message:
added FLOAT definition to better control size of structures

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 tline {
69 struct tline *next; /* pointer to next line */
70 /* followed by the string */
71 } TLINE;
72
73 #define TLSTR(l) ((char *)((l)+1))
74
75 typedef struct {
76 FVECT right, down; /* right and down unit vectors */
77 FONT *f; /* our font */
78 TLINE tl; /* line list */
79 } TEXT;
80
81 extern char *fgetword();
82
83 TEXT *gettext();
84
85 TLINE *tlalloc();
86
87 FONT *getfont();
88
89 static FONT *fontlist = NULL; /* our font list */
90
91
92 text(m, r)
93 register OBJREC *m;
94 RAY *r;
95 {
96 FVECT v;
97 int foreground;
98 /* get transformed position */
99 if (r->rox != NULL)
100 multp3(v, r->rop, r->rox->b.xfm);
101 else
102 VCOPY(v, r->rop);
103 /* check if we are within a text glyph */
104 foreground = intext(v, m);
105 /* modify */
106 if (m->otype == MIX_TEXT) {
107 OBJECT omod;
108 char *modname = m->oargs.sarg[foreground ? 0 : 1];
109 if (!strcmp(modname, VOIDID))
110 omod = OVOID;
111 else if ((omod = modifier(modname)) == OVOID) {
112 sprintf(errmsg, "undefined modifier \"%s\"", modname);
113 objerror(m, USER, errmsg);
114 }
115 raytexture(r, omod);
116 } else if (m->otype == PAT_BTEXT) {
117 if (foreground)
118 scalecolor(r->pcol, m->oargs.farg[9]);
119 else
120 scalecolor(r->pcol, m->oargs.farg[10]);
121 } else { /* PAT_CTEXT */
122 COLOR cval;
123 if (foreground)
124 setcolor(cval, m->oargs.farg[9],
125 m->oargs.farg[10],
126 m->oargs.farg[11]);
127 else
128 setcolor(cval, m->oargs.farg[12],
129 m->oargs.farg[13],
130 m->oargs.farg[14]);
131 multcolor(r->pcol, cval);
132 }
133 }
134
135
136 TLINE *
137 tlalloc(s) /* allocate and assign text line */
138 char *s;
139 {
140 extern char *strcpy();
141 register TLINE *tl;
142
143 tl = (TLINE *)malloc(sizeof(TLINE)+1+strlen(s));
144 if (tl == NULL)
145 error(SYSTEM, "out of memory in tlalloc");
146 tl->next = NULL;
147 strcpy(TLSTR(tl), s);
148 return(tl);
149 }
150
151
152 TEXT *
153 gettext(tm) /* get text structure for material */
154 register OBJREC *tm;
155 {
156 #define R (tm->oargs.farg+3)
157 #define D (tm->oargs.farg+6)
158 extern char *strcpy(), *fgets();
159 FVECT DxR;
160 double d;
161 FILE *fp;
162 char linbuf[512];
163 TEXT *t;
164 register int i;
165 register TLINE *tlp;
166 register char *s;
167
168 if ((t = (TEXT *)tm->os) != NULL)
169 return(t);
170 /* check arguments */
171 if (tm->oargs.nsargs - tndx(tm) < 1 ||
172 tm->oargs.nfargs != (tm->otype == PAT_BTEXT ? 11 :
173 tm->otype == PAT_CTEXT ? 15 : 9))
174 objerror(tm, USER, "bad # arguments");
175 if ((t = (TEXT *)malloc(sizeof(TEXT))) == NULL)
176 error(SYSTEM, "out of memory in gettext");
177 /* compute vectors */
178 fcross(DxR, D, R);
179 fcross(t->right, DxR, D);
180 d = DOT(D,D)/DOT(t->right,t->right);
181 for (i = 0; i < 3; i++)
182 t->right[i] *= d;
183 fcross(t->down, R, DxR);
184 d = DOT(R,R)/DOT(t->down,t->down);
185 for (i = 0; i < 3; i++)
186 t->down[i] *= d;
187 /* get text */
188 tlp = &t->tl;
189 if (tm->oargs.nsargs - tndx(tm) > 1) { /* single line */
190 s = linbuf;
191 for (i = tndx(tm)+1; i < tm->oargs.nsargs; i++) {
192 strcpy(s, tm->oargs.sarg[i]);
193 s += strlen(s);
194 *s++ = ' ';
195 }
196 *--s = '\0';
197 tlp->next = tlalloc(linbuf);
198 tlp = tlp->next;
199 } else { /* text file */
200 if ((s = getpath(tm->oargs.sarg[tndx(tm)],
201 libpath, R_OK)) == NULL) {
202 sprintf(errmsg, "cannot find text file \"%s\"",
203 tm->oargs.sarg[tndx(tm)]);
204 error(USER, errmsg);
205 }
206 if ((fp = fopen(s, "r")) == NULL) {
207 sprintf(errmsg, "cannot open text file \"%s\"",
208 s);
209 error(SYSTEM, errmsg);
210 }
211 while (fgets(linbuf, sizeof(linbuf), fp) != NULL) {
212 s = linbuf + strlen(linbuf) - 1;
213 if (*s == '\n')
214 *s = '\0';
215 tlp->next = tlalloc(linbuf);
216 tlp = tlp->next;
217 }
218 fclose(fp);
219 }
220 tlp->next = NULL;
221 /* get the font */
222 t->f = getfont(tm->oargs.sarg[fndx(tm)]);
223 /* we're done */
224 tm->os = (char *)t;
225 return(t);
226 #undef R
227 #undef D
228 }
229
230
231 freetext(m) /* free text structures associated with m */
232 OBJREC *m;
233 {
234 register TEXT *tp;
235 register TLINE *tlp;
236
237 tp = (TEXT *)m->os;
238 if (tp == NULL)
239 return;
240 for (tlp = tp->tl.next; tlp != NULL; tlp = tlp->next);
241 free((char *)tlp);
242 free((char *)tp);
243 m->os = NULL;
244 }
245
246
247 intext(p, m) /* check to see if p is in text glyph */
248 FVECT p;
249 OBJREC *m;
250 {
251 register TEXT *tp;
252 register TLINE *tlp;
253 FVECT v;
254 double y, x;
255 int col;
256 register int lno;
257 /* first, compute position in text */
258 tp = gettext(m);
259 v[0] = p[0] - m->oargs.farg[0];
260 v[1] = p[1] - m->oargs.farg[1];
261 v[2] = p[2] - m->oargs.farg[2];
262 col = x = DOT(v, tp->right);
263 lno = y = DOT(v, tp->down);
264 if (x < 0.0 || y < 0.0)
265 return(0);
266 x -= (double)col;
267 y = (lno+1) - y;
268 /* get the font character */
269 for (tlp = tp->tl.next; tlp != NULL; tlp = tlp->next)
270 if (--lno < 0)
271 break;
272 if (tlp == NULL || col >= strlen(TLSTR(tlp)))
273 return(0);
274 return(inglyph(x, y, tp->f->fg[TLSTR(tlp)[col]]));
275 }
276
277
278 FONT *
279 getfont(fname) /* return font fname */
280 char *fname;
281 {
282 char buf[16];
283 FILE *fp;
284 char *pathname, *err;
285 int gn, ngv, gv;
286 register GLYPH *g;
287 register FONT *f;
288
289 for (f = fontlist; f != NULL; f = f->next)
290 if (!strcmp(f->name, fname))
291 return(f);
292 /* load the font file */
293 if ((pathname = getpath(fname, libpath, R_OK)) == NULL) {
294 sprintf(errmsg, "cannot find font file \"%s\"", fname);
295 error(USER, errmsg);
296 }
297 f = (FONT *)calloc(1, sizeof(FONT));
298 if (f == NULL)
299 goto memerr;
300 f->name = savestr(fname);
301 if ((fp = fopen(pathname, "r")) == NULL) {
302 sprintf(errmsg, "cannot open font file \"%s\"",
303 pathname);
304 error(SYSTEM, errmsg);
305 }
306 while (fgetword(buf,sizeof(buf),fp) != NULL) { /* get each glyph */
307 if (!isint(buf))
308 goto nonint;
309 gn = atoi(buf);
310 if (gn < 0 || gn > 255) {
311 err = "illegal";
312 goto fonterr;
313 }
314 if (f->fg[gn] != NULL) {
315 err = "duplicate";
316 goto fonterr;
317 }
318 if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) ||
319 (ngv = atoi(buf)) < 0 || ngv > 255) {
320 err = "bad # vertices for";
321 goto fonterr;
322 }
323 g = (GLYPH *)malloc((2*ngv+1)*sizeof(GLYPH));
324 if (g == NULL)
325 goto memerr;
326 f->fg[gn] = g;
327 *g++ = ngv;
328 ngv *= 2;
329 while (ngv--) {
330 if (fgetword(buf,sizeof(buf),fp) == NULL ||
331 !isint(buf) ||
332 (gv = atoi(buf)) < 0 || gv > 255) {
333 err = "bad vertex for";
334 goto fonterr;
335 }
336 *g++ = gv;
337 }
338 }
339 fclose(fp);
340 f->next = fontlist;
341 return(fontlist = f);
342 nonint:
343 sprintf(errmsg, "non-integer in font file \"%s\"", pathname);
344 error(USER, errmsg);
345 fonterr:
346 sprintf(errmsg, "%s character (%d) in font file \"%s\"",
347 err, gn, pathname);
348 error(USER, errmsg);
349 memerr:
350 error(SYSTEM, "out of memory in fontglyph");
351 }
352
353
354 inglyph(x, y, gl) /* (x,y) within font glyph gl? */
355 double x, y;
356 GLYPH *gl;
357 {
358 int n, ncross;
359 int xlb, ylb;
360 register GLYPH *p0, *p1;
361
362 if (gl == NULL)
363 return(0);
364 x *= 256.0; /* get glyph coordinates */
365 y *= 256.0;
366 xlb = x + 0.5;
367 ylb = y + 0.5;
368 n = *gl++; /* get # of vertices */
369 p0 = gl + 2*(n-1); /* connect last to first */
370 p1 = gl;
371 ncross = 0;
372 /* positive x axis cross test */
373 while (n--) {
374 if ((p0[1] > ylb) ^ (p1[1] > ylb))
375 if (p0[0] > xlb && p1[0] > xlb)
376 ncross++;
377 else if (p0[0] > xlb || p1[0] > xlb)
378 ncross += (p1[1] > p0[1]) ^
379 ((p0[1]-y)*(p1[0]-x) >
380 (p0[0]-x)*(p1[1]-y));
381 p0 = p1;
382 p1 += 2;
383 }
384 return(ncross & 01);
385 }