ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/text.c
Revision: 1.8
Committed: Tue Aug 6 09:04:41 1991 UTC (32 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.7: +48 -29 lines
Log Message:
changed storage of text lines

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 double v[3];
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(TLSTR(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 double v[3], y, x;
254 int col;
255 register int lno;
256 /* first, compute position in text */
257 v[0] = p[0] - m->oargs.farg[0];
258 v[1] = p[1] - m->oargs.farg[1];
259 v[2] = p[2] - m->oargs.farg[2];
260 col = x = DOT(v, tp->right);
261 lno = y = DOT(v, tp->down);
262 if (x < 0.0 || y < 0.0)
263 return(0);
264 x -= (double)col;
265 y = (lno+1) - y;
266 /* get the font character */
267 tp = gettext(m);
268 for (tlp = tp->tl.next; tlp != NULL; tlp = tlp->next)
269 if (--lno < 0)
270 break;
271 if (tlp == NULL || col >= strlen(TLSTR(tlp)))
272 return(0);
273 return(inglyph(x, y, tp->f->fg[TLSTR(tlp)[col]]));
274 }
275
276
277 FONT *
278 getfont(fname) /* return font fname */
279 char *fname;
280 {
281 char buf[16];
282 FILE *fp;
283 char *pathname, *err;
284 int gn, ngv, gv;
285 register GLYPH *g;
286 register FONT *f;
287
288 for (f = fontlist; f != NULL; f = f->next)
289 if (!strcmp(f->name, fname))
290 return(f);
291 /* load the font file */
292 if ((pathname = getpath(fname, libpath, R_OK)) == NULL) {
293 sprintf(errmsg, "cannot find font file \"%s\"", fname);
294 error(USER, errmsg);
295 }
296 f = (FONT *)calloc(1, sizeof(FONT));
297 if (f == NULL)
298 goto memerr;
299 f->name = savestr(fname);
300 if ((fp = fopen(pathname, "r")) == NULL) {
301 sprintf(errmsg, "cannot open font file \"%s\"",
302 pathname);
303 error(SYSTEM, errmsg);
304 }
305 while (fgetword(buf,sizeof(buf),fp) != NULL) { /* get each glyph */
306 if (!isint(buf))
307 goto nonint;
308 gn = atoi(buf);
309 if (gn < 0 || gn > 255) {
310 err = "illegal";
311 goto fonterr;
312 }
313 if (f->fg[gn] != NULL) {
314 err = "duplicate";
315 goto fonterr;
316 }
317 if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) ||
318 (ngv = atoi(buf)) < 0 || ngv > 255) {
319 err = "bad # vertices for";
320 goto fonterr;
321 }
322 g = (GLYPH *)malloc((2*ngv+1)*sizeof(GLYPH));
323 if (g == NULL)
324 goto memerr;
325 f->fg[gn] = g;
326 *g++ = ngv;
327 ngv *= 2;
328 while (ngv--) {
329 if (fgetword(buf,sizeof(buf),fp) == NULL ||
330 !isint(buf) ||
331 (gv = atoi(buf)) < 0 || gv > 255) {
332 err = "bad vertex for";
333 goto fonterr;
334 }
335 *g++ = gv;
336 }
337 }
338 fclose(fp);
339 f->next = fontlist;
340 return(fontlist = f);
341 nonint:
342 sprintf(errmsg, "non-integer in font file \"%s\"", pathname);
343 error(USER, errmsg);
344 fonterr:
345 sprintf(errmsg, "%s character (%d) in font file \"%s\"",
346 err, gn, pathname);
347 error(USER, errmsg);
348 memerr:
349 error(SYSTEM, "out of memory in fontglyph");
350 }
351
352
353 inglyph(x, y, gl) /* (x,y) within font glyph gl? */
354 double x, y;
355 GLYPH *gl;
356 {
357 int n, ncross;
358 int xlb, ylb;
359 register GLYPH *p0, *p1;
360
361 if (gl == NULL)
362 return(0);
363 x *= 256.0; /* get glyph coordinates */
364 y *= 256.0;
365 xlb = x + 0.5;
366 ylb = y + 0.5;
367 n = *gl++; /* get # of vertices */
368 p0 = gl + 2*(n-1); /* connect last to first */
369 p1 = gl;
370 ncross = 0;
371 /* positive x axis cross test */
372 while (n--) {
373 if ((p0[1] > ylb) ^ (p1[1] > ylb))
374 if (p0[0] > xlb && p1[0] > xlb)
375 ncross++;
376 else if (p0[0] > xlb || p1[0] > xlb)
377 ncross += (p1[1] > p0[1]) ^
378 ((p0[1]-y)*(p1[0]-x) >
379 (p0[0]-x)*(p1[1]-y));
380 p0 = p1;
381 p1 += 2;
382 }
383 return(ncross & 01);
384 }