ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/rt/text.c
Revision: 1.3
Committed: Thu Jul 27 22:25:17 1989 UTC (34 years, 9 months ago) by greg
Content type: text/plain
Branch: MAIN
Changes since 1.2: +2 -2 lines
Log Message:
Changed getpath to check permissions

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