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

# 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     /*
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 greg 1.7 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 greg 1.6 extern char *fgetword();
75    
76 greg 1.7 TEXT *gettext();
77 greg 1.1
78 greg 1.7 FONT *getfont();
79 greg 1.1
80     static FONT *fontlist = NULL; /* our font list */
81    
82    
83     text(m, r)
84     register OBJREC *m;
85     RAY *r;
86     {
87 greg 1.7 double v[3];
88 greg 1.1 int foreground;
89 greg 1.7 /* get transformed position */
90 greg 1.4 if (r->rox != NULL)
91     multp3(v, r->rop, r->rox->b.xfm);
92     else
93     VCOPY(v, r->rop);
94 greg 1.7 /* check if we are within a text glyph */
95     foreground = intext(v, m);
96 greg 1.1 /* 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 greg 1.7 raytexture(r, omod);
107 greg 1.1 } else if (m->otype == PAT_BTEXT) {
108     if (foreground)
109 greg 1.7 scalecolor(r->pcol, m->oargs.farg[9]);
110 greg 1.1 else
111 greg 1.7 scalecolor(r->pcol, m->oargs.farg[10]);
112 greg 1.1 } else { /* PAT_CTEXT */
113     COLOR cval;
114     if (foreground)
115 greg 1.7 setcolor(cval, m->oargs.farg[9],
116     m->oargs.farg[10],
117     m->oargs.farg[11]);
118 greg 1.1 else
119 greg 1.7 setcolor(cval, m->oargs.farg[12],
120     m->oargs.farg[13],
121     m->oargs.farg[14]);
122 greg 1.1 multcolor(r->pcol, cval);
123     }
124     }
125    
126    
127 greg 1.7 TEXT *
128     gettext(tm) /* get text structure for material */
129 greg 1.1 register OBJREC *tm;
130     {
131 greg 1.7 #define R (tm->oargs.farg+3)
132     #define D (tm->oargs.farg+6)
133 greg 1.1 extern char *strcpy(), *fgets();
134 greg 1.7 FVECT DxR;
135     double d;
136 greg 1.1 FILE *fp;
137     char linbuf[512];
138 greg 1.7 register TEXT *t;
139 greg 1.1 register int i;
140     register char *s;
141    
142 greg 1.7 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 greg 1.1 }
172 greg 1.7 *--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 greg 1.1 }
200 greg 1.7 /* 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 greg 1.1 memerr:
206 greg 1.7 error(SYSTEM, "out of memory in gettext");
207     #undef R
208     #undef D
209 greg 1.1 }
210    
211    
212 greg 1.7 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 greg 1.1 FONT *
259     getfont(fname) /* return font fname */
260     char *fname;
261     {
262 greg 1.6 char buf[16];
263 greg 1.1 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 greg 1.3 if ((pathname = getpath(fname, libpath, R_OK)) == NULL) {
274 greg 1.1 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 greg 1.6 while (fgetword(buf,sizeof(buf),fp) != NULL) { /* get each glyph */
287     if (!isint(buf))
288     goto nonint;
289     gn = atoi(buf);
290 greg 1.1 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 greg 1.6 if (fgetword(buf,sizeof(buf),fp) == NULL || !isint(buf) ||
299     (ngv = atoi(buf)) < 0 || ngv > 255) {
300 greg 1.1 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 greg 1.6 if (fgetword(buf,sizeof(buf),fp) == NULL ||
311     !isint(buf) ||
312     (gv = atoi(buf)) < 0 || gv > 255) {
313 greg 1.1 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 greg 1.6 nonint:
323     sprintf(errmsg, "non-integer in font file \"%s\"", pathname);
324     error(USER, errmsg);
325 greg 1.1 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 greg 1.7 if (gl == NULL)
343 greg 1.1 return(0);
344 greg 1.5 x *= 256.0; /* get glyph coordinates */
345     y *= 256.0;
346     xlb = x + 0.5;
347     ylb = y + 0.5;
348 greg 1.1 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     }