ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/text.c
Revision: 2.20
Committed: Sat Feb 22 02:07:29 2003 UTC (21 years, 2 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.19: +62 -13 lines
Log Message:
Changes and check-in for 3.5 release
Includes new source files and modifications not recorded for many years
See ray/doc/notes/ReleaseNotes for notes between 3.1 and 3.5 release

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id$";
3 #endif
4 /*
5 * text.c - functions for text patterns and mixtures.
6 */
7
8 /* ====================================================================
9 * The Radiance Software License, Version 1.0
10 *
11 * Copyright (c) 1990 - 2002 The Regents of the University of California,
12 * through Lawrence Berkeley National Laboratory. All rights reserved.
13 *
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
16 * are met:
17 *
18 * 1. Redistributions of source code must retain the above copyright
19 * notice, this list of conditions and the following disclaimer.
20 *
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in
23 * the documentation and/or other materials provided with the
24 * distribution.
25 *
26 * 3. The end-user documentation included with the redistribution,
27 * if any, must include the following acknowledgment:
28 * "This product includes Radiance software
29 * (http://radsite.lbl.gov/)
30 * developed by the Lawrence Berkeley National Laboratory
31 * (http://www.lbl.gov/)."
32 * Alternately, this acknowledgment may appear in the software itself,
33 * if and wherever such third-party acknowledgments normally appear.
34 *
35 * 4. The names "Radiance," "Lawrence Berkeley National Laboratory"
36 * and "The Regents of the University of California" must
37 * not be used to endorse or promote products derived from this
38 * software without prior written permission. For written
39 * permission, please contact [email protected].
40 *
41 * 5. Products derived from this software may not be called "Radiance",
42 * nor may "Radiance" appear in their name, without prior written
43 * permission of Lawrence Berkeley National Laboratory.
44 *
45 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
46 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
47 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
48 * DISCLAIMED. IN NO EVENT SHALL Lawrence Berkeley National Laboratory OR
49 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
50 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
51 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
52 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
53 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
54 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
55 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
56 * SUCH DAMAGE.
57 * ====================================================================
58 *
59 * This software consists of voluntary contributions made by many
60 * individuals on behalf of Lawrence Berkeley National Laboratory. For more
61 * information on Lawrence Berkeley National Laboratory, please see
62 * <http://www.lbl.gov/>.
63 */
64
65 #include "ray.h"
66
67 #include "otypes.h"
68
69 #include "font.h"
70
71 /*
72 * A text pattern is specified as the text (a file or line),
73 * the upper left anchor point, the right motion vector, the down
74 * motion vector, and the foreground and background brightness.
75 * For a file, the description is as follows:
76 *
77 * modifier brighttext id
78 * 2 fontfile textfile
79 * 0
80 * 11+
81 * Ax Ay Az
82 * Rx Ry Rz
83 * Dx Dy Dz
84 * foreground background
85 * [spacing]
86 *
87 * For a single line, we use:
88 *
89 * modifier brighttext id
90 * N+2 fontfile . This is a line with N words...
91 * 0
92 * 11+
93 * Ax Ay Az
94 * Rx Ry Rz
95 * Dx Dy Dz
96 * foreground background
97 * [spacing]
98 *
99 * Colortext is identical, except colors are given rather than
100 * brightnesses.
101 *
102 * Mixtext has foreground and background modifiers:
103 *
104 * modifier mixtext id
105 * 4+ foremod backmod fontfile text..
106 * 0
107 * 9+
108 * Ax Ay Az
109 * Rx Ry Rz
110 * Dx Dy Dz
111 * [spacing]
112 */
113
114 #define fndx(m) ((m)->otype==MIX_TEXT ? 2 : 0)
115 #define tndx(m) ((m)->otype==MIX_TEXT ? 3 : 1)
116 #define sndx(m) ((m)->otype==PAT_BTEXT ? 11 : \
117 (m)->otype==PAT_CTEXT ? 15 : 9)
118
119 typedef struct tline {
120 struct tline *next; /* pointer to next line */
121 short *spc; /* character spacing */
122 int width; /* total line width */
123 /* followed by the string */
124 } TLINE;
125
126 #define TLSTR(l) ((char *)((l)+1))
127
128 typedef struct {
129 FVECT right, down; /* right and down unit vectors */
130 FONT *f; /* our font */
131 TLINE tl; /* line list */
132 } TEXT;
133
134 TEXT *gettext();
135
136 TLINE *tlalloc();
137
138
139 do_text(m, r)
140 register OBJREC *m;
141 RAY *r;
142 {
143 FVECT v;
144 int foreground;
145 /* get transformed position */
146 if (r->rox != NULL)
147 multp3(v, r->rop, r->rox->b.xfm);
148 else
149 VCOPY(v, r->rop);
150 /* check if we are within a text glyph */
151 foreground = intext(v, m);
152 /* modify */
153 if (m->otype == MIX_TEXT) {
154 OBJECT omod;
155 char *modname = m->oargs.sarg[foreground ? 0 : 1];
156 if (!strcmp(modname, VOIDID))
157 omod = OVOID;
158 else if ((omod = lastmod(objndx(m), modname)) == OVOID) {
159 sprintf(errmsg, "undefined modifier \"%s\"", modname);
160 objerror(m, USER, errmsg);
161 }
162 if (rayshade(r, omod)) {
163 if (m->omod != OVOID)
164 objerror(m, USER, "inappropriate modifier");
165 return(1);
166 }
167 } else if (m->otype == PAT_BTEXT) {
168 if (foreground)
169 scalecolor(r->pcol, m->oargs.farg[9]);
170 else
171 scalecolor(r->pcol, m->oargs.farg[10]);
172 } else { /* PAT_CTEXT */
173 COLOR cval;
174 if (foreground)
175 setcolor(cval, m->oargs.farg[9],
176 m->oargs.farg[10],
177 m->oargs.farg[11]);
178 else
179 setcolor(cval, m->oargs.farg[12],
180 m->oargs.farg[13],
181 m->oargs.farg[14]);
182 multcolor(r->pcol, cval);
183 }
184 return(0);
185 }
186
187
188 TLINE *
189 tlalloc(s) /* allocate and assign text line */
190 char *s;
191 {
192 register int siz;
193 register TLINE *tl;
194
195 siz = strlen(s) + 1;
196 if ((tl=(TLINE *)malloc(sizeof(TLINE)+siz)) == NULL ||
197 (tl->spc=(short *)malloc(siz*sizeof(short))) == NULL)
198 error(SYSTEM, "out of memory in tlalloc");
199 tl->next = NULL;
200 strcpy(TLSTR(tl), s);
201 return(tl);
202 }
203
204
205 TEXT *
206 gettext(tm) /* get text structure for material */
207 register OBJREC *tm;
208 {
209 #define R (tm->oargs.farg+3)
210 #define D (tm->oargs.farg+6)
211 FVECT DxR;
212 double d;
213 FILE *fp;
214 char linbuf[512];
215 TEXT *t;
216 register int i;
217 register TLINE *tlp;
218 register char *s;
219
220 if ((t = (TEXT *)tm->os) != NULL)
221 return(t);
222 /* check arguments */
223 if (tm->oargs.nsargs - tndx(tm) < 1 || tm->oargs.nfargs < sndx(tm))
224 objerror(tm, USER, "bad # arguments");
225 if ((t = (TEXT *)malloc(sizeof(TEXT))) == NULL)
226 error(SYSTEM, "out of memory in gettext");
227 /* compute vectors */
228 fcross(DxR, D, R);
229 fcross(t->right, DxR, D);
230 d = DOT(t->right,t->right);
231 if (d <= FTINY*FTINY*FTINY*FTINY)
232 objerror(tm, USER, "illegal motion vector");
233 d = DOT(D,D)/d;
234 for (i = 0; i < 3; i++)
235 t->right[i] *= d;
236 fcross(t->down, R, DxR);
237 d = DOT(R,R)/DOT(t->down,t->down);
238 for (i = 0; i < 3; i++)
239 t->down[i] *= d;
240 /* get text */
241 tlp = &t->tl;
242 if (tm->oargs.nsargs - tndx(tm) > 1) { /* single line */
243 s = linbuf;
244 for (i = tndx(tm)+1; i < tm->oargs.nsargs; i++) {
245 strcpy(s, tm->oargs.sarg[i]);
246 s += strlen(s);
247 *s++ = ' ';
248 }
249 *--s = '\0';
250 tlp->next = tlalloc(linbuf);
251 tlp = tlp->next;
252 } else { /* text file */
253 if ((s = getpath(tm->oargs.sarg[tndx(tm)],
254 getlibpath(), R_OK)) == NULL) {
255 sprintf(errmsg, "cannot find text file \"%s\"",
256 tm->oargs.sarg[tndx(tm)]);
257 error(USER, errmsg);
258 }
259 if ((fp = fopen(s, "r")) == NULL) {
260 sprintf(errmsg, "cannot open text file \"%s\"", s);
261 error(SYSTEM, errmsg);
262 }
263 while (fgets(linbuf, sizeof(linbuf), fp) != NULL) {
264 s = linbuf + strlen(linbuf) - 1;
265 if (*s == '\n')
266 *s = '\0';
267 tlp->next = tlalloc(linbuf);
268 tlp = tlp->next;
269 }
270 fclose(fp);
271 }
272 tlp->next = NULL;
273 /* get the font */
274 t->f = getfont(tm->oargs.sarg[fndx(tm)]);
275 /* compute character spacing */
276 i = sndx(tm);
277 d = i < tm->oargs.nfargs ? tm->oargs.farg[i] : 0.0;
278 i = d * 255.0;
279 t->tl.width = 0;
280 for (tlp = t->tl.next; tlp != NULL; tlp = tlp->next) {
281 if (i < 0)
282 tlp->width = squeeztext(tlp->spc, TLSTR(tlp), t->f, -i);
283 else if (i > 0)
284 tlp->width = proptext(tlp->spc, TLSTR(tlp), t->f, i, 3);
285 else
286 tlp->width = uniftext(tlp->spc, TLSTR(tlp), t->f);
287 if (tlp->width > t->tl.width)
288 t->tl.width = tlp->width;
289 }
290 /* we're done */
291 tm->os = (char *)t;
292 return(t);
293 #undef R
294 #undef D
295 }
296
297
298 freetext(m) /* free text structures associated with m */
299 OBJREC *m;
300 {
301 register TEXT *tp;
302 register TLINE *tlp;
303
304 tp = (TEXT *)m->os;
305 if (tp == NULL)
306 return;
307 while ((tlp = tp->tl.next) != NULL) {
308 tp->tl.next = tlp->next;
309 free((void *)tlp->spc);
310 free((void *)tlp);
311 }
312 freefont(tp->f); /* release font reference */
313 free((void *)tp);
314 m->os = NULL;
315 }
316
317
318 intext(p, m) /* check to see if p is in text glyph */
319 FVECT p;
320 OBJREC *m;
321 {
322 register TEXT *tp;
323 register TLINE *tlp;
324 FVECT v;
325 double y, x;
326 register int i, h;
327 /* first, compute position in text */
328 tp = gettext(m);
329 v[0] = p[0] - m->oargs.farg[0];
330 v[1] = p[1] - m->oargs.farg[1];
331 v[2] = p[2] - m->oargs.farg[2];
332 x = DOT(v, tp->right);
333 i = sndx(m);
334 if (i < m->oargs.nfargs)
335 x *= tp->f->mwidth + 255.*fabs(m->oargs.farg[i]);
336 else
337 x *= 255.;
338 h = x;
339 i = y = DOT(v, tp->down);
340 if (x < 0.0 || y < 0.0)
341 return(0);
342 x -= (double)h;
343 y = ((i+1) - y)*255.;
344 /* find the line position */
345 for (tlp = tp->tl.next; tlp != NULL; tlp = tlp->next)
346 if (--i < 0)
347 break;
348 if (tlp == NULL || h >= tlp->width)
349 return(0);
350 for (i = 0; (h -= tlp->spc[i]) >= 0; i++)
351 if (h < 255 && inglyph(h+x, y,
352 tp->f->fg[TLSTR(tlp)[i]&0xff]))
353 return(1);
354 return(0);
355 }
356
357
358 inglyph(x, y, gl) /* (x,y) within font glyph gl? */
359 double x, y; /* real coordinates in range [0,255) */
360 register GLYPH *gl;
361 {
362 int n, ncross;
363 int xlb, ylb;
364 int tv;
365 register GORD *p0, *p1;
366
367 if (gl == NULL)
368 return(0);
369 xlb = x;
370 ylb = y;
371 if (gl->left > xlb || gl->right <= xlb || /* check extent */
372 gl->bottom > ylb || gl->top <= ylb)
373 return(0);
374 xlb = xlb<<1 | 1; /* add 1/2 to test points... */
375 ylb = ylb<<1 | 1; /* ...so no equal comparisons */
376 n = gl->nverts; /* get # of vertices */
377 p0 = gvlist(gl) + 2*(n-1); /* connect last to first */
378 p1 = gvlist(gl);
379 ncross = 0;
380 /* positive x axis cross test */
381 while (n--) {
382 if ((p0[1]<<1 > ylb) ^ (p1[1]<<1 > ylb)) {
383 tv = p0[0]<<1 > xlb | (p1[0]<<1 > xlb) << 1;
384 if (tv == 03)
385 ncross++;
386 else if (tv)
387 ncross += (p1[1] > p0[1]) ^
388 ((p0[1]-y)*(p1[0]-x) >
389 (p0[0]-x)*(p1[1]-y));
390 }
391 p0 = p1;
392 p1 += 2;
393 }
394 return(ncross & 01);
395 }