ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/text.c
Revision: 2.3
Committed: Tue Jun 16 13:24:23 1992 UTC (31 years, 10 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 2.2: +6 -1 lines
Log Message:
added checking of extents to inglyph()

File Contents

# User Rev Content
1 greg 1.7 /* Copyright (c) 1991 Regents of the University of California */
2 greg 1.1
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 greg 2.2 #include "font.h"
18    
19 greg 1.1 /*
20     * A text pattern is specified as the text (a file or line),
21     * the upper left anchor point, the right motion vector, the down
22     * motion vector, and the foreground and background brightness.
23     * For a file, the description is as follows:
24     *
25     * modifier brighttext id
26     * 2 fontfile textfile
27     * 0
28     * 11
29     * Ax Ay Az
30     * Rx Ry Rz
31     * Dx Dy Dz
32     * foreground background
33     *
34     * For a single line, we use:
35     *
36     * modifier brighttext id
37     * N+2 fontfile . This is a line with N words...
38     * 0
39     * 11
40     * Ax Ay Az
41     * Rx Ry Rz
42     * Dx Dy Dz
43     * foreground background
44     *
45     * Colortext is identical, except colors are given rather than
46     * brightnesses. Mixtext has foreground and background modifiers:
47     *
48     * modifier mixtext id
49     * 4+ foremod backmod fontfile text..
50     * 0
51     * 9
52     * Ax Ay Az
53     * Rx Ry Rz
54     * Dx Dy Dz
55     */
56    
57     #define fndx(m) ((m)->otype==MIX_TEXT ? 2 : 0)
58     #define tndx(m) ((m)->otype==MIX_TEXT ? 3 : 1)
59    
60 greg 1.8 typedef struct tline {
61     struct tline *next; /* pointer to next line */
62     /* followed by the string */
63     } TLINE;
64    
65 greg 1.9 #define TLSTR(l) ((char *)((l)+1))
66 greg 1.8
67 greg 1.7 typedef struct {
68     FVECT right, down; /* right and down unit vectors */
69     FONT *f; /* our font */
70 greg 1.8 TLINE tl; /* line list */
71 greg 1.7 } TEXT;
72    
73 greg 2.3 extern char *libpath;
74    
75 greg 1.6 extern char *fgetword();
76    
77 greg 1.7 TEXT *gettext();
78 greg 1.1
79 greg 1.8 TLINE *tlalloc();
80    
81 greg 1.1
82     text(m, r)
83     register OBJREC *m;
84     RAY *r;
85     {
86 greg 1.10 FVECT v;
87 greg 1.1 int foreground;
88 greg 1.7 /* get transformed position */
89 greg 1.4 if (r->rox != NULL)
90     multp3(v, r->rop, r->rox->b.xfm);
91     else
92     VCOPY(v, r->rop);
93 greg 1.7 /* check if we are within a text glyph */
94     foreground = intext(v, m);
95 greg 1.1 /* modify */
96     if (m->otype == MIX_TEXT) {
97     OBJECT omod;
98     char *modname = m->oargs.sarg[foreground ? 0 : 1];
99     if (!strcmp(modname, VOIDID))
100     omod = OVOID;
101     else if ((omod = modifier(modname)) == OVOID) {
102     sprintf(errmsg, "undefined modifier \"%s\"", modname);
103     objerror(m, USER, errmsg);
104     }
105 greg 1.7 raytexture(r, omod);
106 greg 1.1 } else if (m->otype == PAT_BTEXT) {
107     if (foreground)
108 greg 1.7 scalecolor(r->pcol, m->oargs.farg[9]);
109 greg 1.1 else
110 greg 1.7 scalecolor(r->pcol, m->oargs.farg[10]);
111 greg 1.1 } else { /* PAT_CTEXT */
112     COLOR cval;
113     if (foreground)
114 greg 1.7 setcolor(cval, m->oargs.farg[9],
115     m->oargs.farg[10],
116     m->oargs.farg[11]);
117 greg 1.1 else
118 greg 1.7 setcolor(cval, m->oargs.farg[12],
119     m->oargs.farg[13],
120     m->oargs.farg[14]);
121 greg 1.1 multcolor(r->pcol, cval);
122     }
123     }
124    
125    
126 greg 1.8 TLINE *
127     tlalloc(s) /* allocate and assign text line */
128     char *s;
129     {
130     extern char *strcpy();
131     register TLINE *tl;
132    
133     tl = (TLINE *)malloc(sizeof(TLINE)+1+strlen(s));
134     if (tl == NULL)
135     error(SYSTEM, "out of memory in tlalloc");
136     tl->next = NULL;
137     strcpy(TLSTR(tl), s);
138     return(tl);
139     }
140    
141    
142 greg 1.7 TEXT *
143     gettext(tm) /* get text structure for material */
144 greg 1.1 register OBJREC *tm;
145     {
146 greg 1.7 #define R (tm->oargs.farg+3)
147     #define D (tm->oargs.farg+6)
148 greg 1.1 extern char *strcpy(), *fgets();
149 greg 1.7 FVECT DxR;
150     double d;
151 greg 1.1 FILE *fp;
152     char linbuf[512];
153 greg 1.8 TEXT *t;
154 greg 1.1 register int i;
155 greg 1.8 register TLINE *tlp;
156 greg 1.1 register char *s;
157    
158 greg 1.7 if ((t = (TEXT *)tm->os) != NULL)
159     return(t);
160     /* check arguments */
161     if (tm->oargs.nsargs - tndx(tm) < 1 ||
162     tm->oargs.nfargs != (tm->otype == PAT_BTEXT ? 11 :
163     tm->otype == PAT_CTEXT ? 15 : 9))
164     objerror(tm, USER, "bad # arguments");
165     if ((t = (TEXT *)malloc(sizeof(TEXT))) == NULL)
166 greg 1.8 error(SYSTEM, "out of memory in gettext");
167 greg 1.7 /* compute vectors */
168     fcross(DxR, D, R);
169     fcross(t->right, DxR, D);
170 greg 1.9 d = DOT(D,D)/DOT(t->right,t->right);
171 greg 1.7 for (i = 0; i < 3; i++)
172     t->right[i] *= d;
173     fcross(t->down, R, DxR);
174 greg 1.9 d = DOT(R,R)/DOT(t->down,t->down);
175 greg 1.7 for (i = 0; i < 3; i++)
176     t->down[i] *= d;
177     /* get text */
178 greg 1.8 tlp = &t->tl;
179 greg 1.7 if (tm->oargs.nsargs - tndx(tm) > 1) { /* single line */
180     s = linbuf;
181     for (i = tndx(tm)+1; i < tm->oargs.nsargs; i++) {
182     strcpy(s, tm->oargs.sarg[i]);
183     s += strlen(s);
184     *s++ = ' ';
185 greg 1.1 }
186 greg 1.7 *--s = '\0';
187 greg 1.8 tlp->next = tlalloc(linbuf);
188     tlp = tlp->next;
189 greg 1.7 } else { /* text file */
190     if ((s = getpath(tm->oargs.sarg[tndx(tm)],
191     libpath, R_OK)) == NULL) {
192     sprintf(errmsg, "cannot find text file \"%s\"",
193     tm->oargs.sarg[tndx(tm)]);
194     error(USER, errmsg);
195     }
196     if ((fp = fopen(s, "r")) == NULL) {
197     sprintf(errmsg, "cannot open text file \"%s\"",
198     s);
199     error(SYSTEM, errmsg);
200     }
201 greg 1.8 while (fgets(linbuf, sizeof(linbuf), fp) != NULL) {
202 greg 1.7 s = linbuf + strlen(linbuf) - 1;
203     if (*s == '\n')
204     *s = '\0';
205 greg 1.8 tlp->next = tlalloc(linbuf);
206     tlp = tlp->next;
207 greg 1.7 }
208     fclose(fp);
209 greg 1.1 }
210 greg 1.8 tlp->next = NULL;
211 greg 1.7 /* get the font */
212     t->f = getfont(tm->oargs.sarg[fndx(tm)]);
213     /* we're done */
214     tm->os = (char *)t;
215     return(t);
216     #undef R
217     #undef D
218 greg 1.1 }
219    
220    
221 greg 1.7 freetext(m) /* free text structures associated with m */
222     OBJREC *m;
223     {
224     register TEXT *tp;
225 greg 1.8 register TLINE *tlp;
226 greg 1.7
227     tp = (TEXT *)m->os;
228     if (tp == NULL)
229     return;
230 greg 1.8 for (tlp = tp->tl.next; tlp != NULL; tlp = tlp->next);
231 greg 1.9 free((char *)tlp);
232 greg 1.7 free((char *)tp);
233     m->os = NULL;
234     }
235    
236    
237     intext(p, m) /* check to see if p is in text glyph */
238     FVECT p;
239 greg 1.8 OBJREC *m;
240 greg 1.7 {
241     register TEXT *tp;
242 greg 1.8 register TLINE *tlp;
243 greg 1.10 FVECT v;
244     double y, x;
245 greg 1.8 int col;
246     register int lno;
247 greg 1.7 /* first, compute position in text */
248 greg 1.9 tp = gettext(m);
249 greg 1.7 v[0] = p[0] - m->oargs.farg[0];
250     v[1] = p[1] - m->oargs.farg[1];
251     v[2] = p[2] - m->oargs.farg[2];
252     col = x = DOT(v, tp->right);
253     lno = y = DOT(v, tp->down);
254     if (x < 0.0 || y < 0.0)
255     return(0);
256     x -= (double)col;
257     y = (lno+1) - y;
258     /* get the font character */
259 greg 1.8 for (tlp = tp->tl.next; tlp != NULL; tlp = tlp->next)
260     if (--lno < 0)
261     break;
262     if (tlp == NULL || col >= strlen(TLSTR(tlp)))
263 greg 1.7 return(0);
264 greg 2.2 return(inglyph(x, y, tp->f->fg[TLSTR(tlp)[col]&0xff]));
265 greg 1.7 }
266    
267    
268 greg 1.1 inglyph(x, y, gl) /* (x,y) within font glyph gl? */
269     double x, y;
270 greg 2.3 register GLYPH *gl;
271 greg 1.1 {
272     int n, ncross;
273     int xlb, ylb;
274 greg 2.2 register GORD *p0, *p1;
275 greg 1.1
276 greg 1.7 if (gl == NULL)
277 greg 1.1 return(0);
278 greg 1.5 x *= 256.0; /* get glyph coordinates */
279     y *= 256.0;
280     xlb = x + 0.5;
281     ylb = y + 0.5;
282 greg 2.3 if (gl->left > xlb || gl->right <= xlb ||
283     gl->bottom > ylb || gl->top <= ylb)
284     return(0); /* outside extent */
285 greg 2.2 n = gl->nverts; /* get # of vertices */
286     p0 = gvlist(gl) + 2*(n-1); /* connect last to first */
287     p1 = gvlist(gl);
288 greg 1.1 ncross = 0;
289     /* positive x axis cross test */
290     while (n--) {
291     if ((p0[1] > ylb) ^ (p1[1] > ylb))
292     if (p0[0] > xlb && p1[0] > xlb)
293     ncross++;
294     else if (p0[0] > xlb || p1[0] > xlb)
295     ncross += (p1[1] > p0[1]) ^
296     ((p0[1]-y)*(p1[0]-x) >
297     (p0[0]-x)*(p1[1]-y));
298     p0 = p1;
299     p1 += 2;
300     }
301     return(ncross & 01);
302     }