ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/text.c
Revision: 1.1
Committed: Thu Feb 2 10:41:47 1989 UTC (35 years, 3 months ago) by greg
Content type: text/plain
Branch: MAIN
Log Message:
Initial revision

File Contents

# User Rev Content
1 greg 1.1 /* Copyright (c) 1986 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     extern GLYPH *getglyph();
69    
70     extern FONT *getfont();
71    
72     static FONT *fontlist = NULL; /* our font list */
73    
74    
75     text(m, r)
76     register OBJREC *m;
77     RAY *r;
78     {
79     double v[3], y, x;
80     int col, lno;
81     int foreground;
82     GLYPH *g;
83     register double *ap;
84    
85     if (m->oargs.nsargs - tndx(m) < 1 ||
86     m->oargs.nfargs != (m->otype == PAT_BTEXT ? 11 :
87     m->otype == PAT_CTEXT ? 15 : 9))
88     objerror(m, USER, "bad # arguments");
89    
90     /* first, discover position in text */
91     ap = m->oargs.farg;
92     v[0] = r->rop[0] - ap[0];
93     v[1] = r->rop[1] - ap[1];
94     v[2] = r->rop[2] - ap[2];
95     col = x = DOT(v, ap+3) / DOT(ap+3, ap+3);
96     lno = y = DOT(v, ap+6) / DOT(ap+6, ap+6);
97     x -= col;
98     y = (lno+1) - y;
99     /* get the font character, check it */
100     if ((g = getglyph(m, lno, col)) == NULL)
101     foreground = 0;
102     else
103     foreground = inglyph(x, y, g);
104     /* modify */
105     if (m->otype == MIX_TEXT) {
106     OBJECT omod;
107     char *modname = m->oargs.sarg[foreground ? 0 : 1];
108     if (!strcmp(modname, VOIDID))
109     omod = OVOID;
110     else if ((omod = modifier(modname)) == OVOID) {
111     sprintf(errmsg, "undefined modifier \"%s\"", modname);
112     objerror(m, USER, errmsg);
113     }
114     raymixture(r, omod, OVOID, 1.0);
115     } else if (m->otype == PAT_BTEXT) {
116     if (foreground)
117     scalecolor(r->pcol, ap[9]);
118     else
119     scalecolor(r->pcol, ap[10]);
120     } else { /* PAT_CTEXT */
121     COLOR cval;
122     if (foreground)
123     setcolor(cval, ap[9], ap[10], ap[11]);
124     else
125     setcolor(cval, ap[12], ap[13], ap[14]);
126     multcolor(r->pcol, cval);
127     }
128     }
129    
130    
131     GLYPH *
132     getglyph(tm, lno, col) /* get a glyph from a text description */
133     register OBJREC *tm;
134     int lno;
135     int col;
136     {
137     extern char *strcpy(), *fgets();
138     FILE *fp;
139     char linbuf[512];
140     register int i;
141     register char **txt;
142     register char *s;
143    
144     if (lno < 0 || col < 0)
145     return(NULL);
146     if (tm->os == NULL) {
147     txt = (char **)malloc(2*sizeof(char **));
148     if (txt == NULL)
149     goto memerr;
150     if (tm->oargs.nsargs - tndx(tm) > 1) { /* single line */
151     s = linbuf;
152     for (i = tndx(tm)+1; i < tm->oargs.nsargs; i++) {
153     strcpy(s, tm->oargs.sarg[i]);
154     s += strlen(s);
155     *s++ = ' ';
156     }
157     *--s = '\0';
158     txt[0] = savqstr(linbuf);
159     txt[1] = NULL;
160     } else { /* text file */
161     if ((s = getpath(tm->oargs.sarg[tndx(tm)],
162     libpath)) == NULL) {
163     sprintf(errmsg, "cannot find text file \"%s\"",
164     tm->oargs.sarg[tndx(tm)]);
165     error(USER, errmsg);
166     }
167     if ((fp = fopen(s, "r")) == NULL) {
168     sprintf(errmsg, "cannot open text file \"%s\"",
169     s);
170     error(SYSTEM, errmsg);
171     }
172     for (i=0; fgets(linbuf,sizeof(linbuf),fp)!=NULL; i++) {
173     s = linbuf + strlen(linbuf) - 1;
174     if (*s == '\n')
175     *s = '\0';
176     txt=(char **)realloc(txt,(i+2)*sizeof(char **));
177     if (txt == NULL)
178     goto memerr;
179     txt[i] = savqstr(linbuf);
180     }
181     txt[i] = NULL;
182     fclose(fp);
183     }
184     tm->os = (char *)txt;
185     }
186     txt = (char **)tm->os;
187     for (i = 0; i < lno; i++)
188     if (txt[i] == NULL)
189     break;
190     if ((s = txt[i]) == NULL || col >= strlen(s))
191     return(NULL);
192     else
193     return(getfont(tm->oargs.sarg[fndx(tm)])->fg[s[col]]);
194     memerr:
195     error(SYSTEM, "out of memory in getglyph");
196     }
197    
198    
199     FONT *
200     getfont(fname) /* return font fname */
201     char *fname;
202     {
203     FILE *fp;
204     char *pathname, *err;
205     int gn, ngv, gv;
206     register GLYPH *g;
207     register FONT *f;
208    
209     for (f = fontlist; f != NULL; f = f->next)
210     if (!strcmp(f->name, fname))
211     return(f);
212     /* load the font file */
213     if ((pathname = getpath(fname, libpath)) == NULL) {
214     sprintf(errmsg, "cannot find font file \"%s\"", fname);
215     error(USER, errmsg);
216     }
217     f = (FONT *)calloc(1, sizeof(FONT));
218     if (f == NULL)
219     goto memerr;
220     f->name = savestr(fname);
221     if ((fp = fopen(pathname, "r")) == NULL) {
222     sprintf(errmsg, "cannot open font file \"%s\"",
223     pathname);
224     error(SYSTEM, errmsg);
225     }
226     while (fscanf(fp, "%d", &gn) == 1) { /* get each glyph */
227     if (gn < 0 || gn > 255) {
228     err = "illegal";
229     goto fonterr;
230     }
231     if (f->fg[gn] != NULL) {
232     err = "duplicate";
233     goto fonterr;
234     }
235     if (fscanf(fp, "%d", &ngv) != 1 ||
236     ngv < 0 || ngv > 255) {
237     err = "bad # vertices for";
238     goto fonterr;
239     }
240     g = (GLYPH *)malloc((2*ngv+1)*sizeof(GLYPH));
241     if (g == NULL)
242     goto memerr;
243     f->fg[gn] = g;
244     *g++ = ngv;
245     ngv *= 2;
246     while (ngv--) {
247     if (fscanf(fp, "%d", &gv) != 1 ||
248     gv < 0 || gv > 255) {
249     err = "bad vertex for";
250     goto fonterr;
251     }
252     *g++ = gv;
253     }
254     }
255     fclose(fp);
256     f->next = fontlist;
257     return(fontlist = f);
258     fonterr:
259     sprintf(errmsg, "%s character (%d) in font file \"%s\"",
260     err, gn, pathname);
261     error(USER, errmsg);
262     memerr:
263     error(SYSTEM, "out of memory in fontglyph");
264     }
265    
266    
267     inglyph(x, y, gl) /* (x,y) within font glyph gl? */
268     double x, y;
269     GLYPH *gl;
270     {
271     int n, ncross;
272     int xlb, ylb;
273     register GLYPH *p0, *p1;
274    
275     if (x < 0.0 || y < 0.0)
276     return(0);
277     xlb = x *= 255.0; /* get glyph coordinates */
278     ylb = y *= 255.0;
279     n = *gl++; /* get # of vertices */
280     p0 = gl + 2*(n-1); /* connect last to first */
281     p1 = gl;
282     ncross = 0;
283     /* positive x axis cross test */
284     while (n--) {
285     if ((p0[1] > ylb) ^ (p1[1] > ylb))
286     if (p0[0] > xlb && p1[0] > xlb)
287     ncross++;
288     else if (p0[0] > xlb || p1[0] > xlb)
289     ncross += (p1[1] > p0[1]) ^
290     ((p0[1]-y)*(p1[0]-x) >
291     (p0[0]-x)*(p1[1]-y));
292     p0 = p1;
293     p1 += 2;
294     }
295     return(ncross & 01);
296     }