ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/psign.c
Revision: 2.23
Committed: Sun Jul 27 22:12:03 2003 UTC (20 years, 9 months ago) by schorsch
Content type: text/plain
Branch: MAIN
Changes since 2.22: +2 -2 lines
Log Message:
Added grouping parens to reduce ambiguity warnings.

File Contents

# User Rev Content
1 greg 1.1 #ifndef lint
2 schorsch 2.23 static const char RCSid[] = "$Id: psign.c,v 2.22 2003/06/30 14:59:12 schorsch Exp $";
3 greg 1.1 #endif
4     /*
5     * psign.c - produce picture from text.
6     *
7     * 7/1/87
8     */
9    
10 schorsch 2.22 #include "copyright.h"
11    
12     #include <string.h>
13    
14 greg 2.3 #include "standard.h"
15 schorsch 2.20 #include "platform.h"
16 greg 1.1 #include "color.h"
17 greg 2.3 #include "font.h"
18    
19 greg 2.13 #ifndef SSS
20     #define SSS 3 /* super-sample size */
21 greg 2.5 #endif
22 greg 2.4
23 greg 2.13 #define MAXLINE 512 /* longest allowable line */
24 greg 1.1
25 greg 1.2 char *fontfile = "helvet.fnt"; /* our font file */
26 greg 1.1
27 greg 2.5 COLOR bgcolor = WHTCOLOR; /* background color */
28     COLOR fgcolor = BLKCOLOR; /* foreground color */
29 greg 1.1
30     int direct = 'r'; /* direction (right, up, left, down) */
31    
32 greg 2.5 int cheight = 32*SSS; /* character height */
33 greg 2.13 double aspect = 1.67; /* height/width character aspect */
34     double spacing = 0.0; /* character spacing */
35 greg 1.1 int cwidth; /* computed character width */
36    
37     unsigned char *ourbitmap; /* our output bitmap */
38     int xsiz, ysiz; /* bitmap dimensions */
39     int xdim; /* size of horizontal scan (bytes) */
40 greg 2.21
41     /* conflicting def's in param.h */
42     #undef tstbit
43     #undef setbit
44     #undef clrbit
45     #undef tglbit
46 greg 1.1
47 greg 2.13 #define bitop(x,y,op) (ourbitmap[(y)*xdim+((x)>>3)] op (1<<((x)&7)))
48     #define tstbit(x,y) bitop(x,y,&)
49     #define setbit(x,y) bitop(x,y,|=)
50     #define clrbit(x,y) bitop(x,y,&=~)
51     #define tglbit(x,y) bitop(x,y,^=)
52 greg 1.1
53 greg 2.3 FONT *ourfont; /* our font */
54 greg 1.1
55     typedef struct line {
56     char *s; /* line w/o LF */
57 greg 2.4 short *sp; /* character spacing */
58 greg 1.1 struct line *next; /* next line up */
59     } LINE;
60    
61     LINE *ourtext; /* our text */
62     int nlines, maxline; /* text dimensions */
63 greg 2.4 int maxwidth; /* maximum line width (dvi) */
64 greg 1.1
65    
66     main(argc, argv)
67     int argc;
68     char *argv[];
69     {
70     int an;
71 schorsch 2.19 SET_FILE_BINARY(stdout);
72 greg 1.1 for (an = 1; an < argc && argv[an][0] == '-'; an++)
73     switch (argv[an][1]) {
74     case 'c': /* color */
75     switch (argv[an][2]) {
76     case 'f': /* foreground */
77 greg 2.5 setcolor(fgcolor, atof(argv[an+1]),
78 greg 1.1 atof(argv[an+2]),
79     atof(argv[an+3]));
80     an += 3;
81     break;
82     case 'b': /* background */
83 greg 2.5 setcolor(bgcolor, atof(argv[an+1]),
84 greg 1.1 atof(argv[an+2]),
85     atof(argv[an+3]));
86     an += 3;
87     break;
88     default:
89     goto unkopt;
90     }
91     break;
92     case 'f': /* font */
93     fontfile = argv[++an];
94     break;
95     case 'd': /* direction */
96     switch (argv[an][2]) {
97     case 'r': /* right */
98     case 'u': /* up */
99     case 'l': /* left */
100     case 'd': /* down */
101     direct = argv[an][2];
102     break;
103     default:
104     goto unkopt;
105     }
106     break;
107 greg 2.9 case 'x': /* x resolution */
108     xsiz = atoi(argv[++an])*SSS;
109     break;
110     case 'y':
111     ysiz = atoi(argv[++an])*SSS;
112     break;
113 greg 1.1 case 'h': /* height of characters */
114 greg 2.5 cheight = atoi(argv[++an])*SSS;
115 greg 1.1 break;
116     case 'a': /* aspect ratio */
117     aspect = atof(argv[++an]);
118     break;
119 greg 2.6 case 's': /* spacing */
120     spacing = atof(argv[++an]);
121     break;
122 greg 1.1 default:;
123     unkopt:
124     fprintf(stderr, "%s: unknown option: %s\n",
125     argv[0], argv[an]);
126     exit(1);
127     }
128 greg 2.4 /* load font file */
129     ourfont = getfont(fontfile);
130 greg 1.1 /* get text */
131     if (an == argc)
132     gettext(stdin);
133     else
134     arg_text(argc-an, argv+an);
135    
136     /* create bit map */
137     makemap();
138     /* convert text to bitmap */
139     maptext();
140     /* print header */
141 greg 2.16 newheader("RADIANCE", stdout);
142 greg 1.1 printargs(argc, argv, stdout);
143 greg 1.3 fputformat(COLRFMT, stdout);
144     putchar('\n');
145 greg 1.1 /* write out bitmap */
146     writemap(stdout);
147    
148     exit(0);
149     }
150    
151    
152     makemap() /* create the bit map */
153     {
154 greg 2.13 double pictaspect;
155 greg 2.9
156 greg 1.1 if (direct == 'r' || direct == 'l') {
157 greg 2.11 if (xsiz <= 0) {
158 greg 2.9 cwidth = cheight/aspect + 0.5;
159     xsiz = (long)maxwidth*cwidth >> 8;
160     ysiz = nlines*cheight;
161 greg 2.10 } else if (aspect > FTINY) {
162 greg 2.11 if (ysiz <= 0)
163     ysiz = cheight*nlines;
164 greg 2.9 pictaspect = 256*nlines*aspect/maxwidth;
165     if (pictaspect*xsiz < ysiz)
166     ysiz = pictaspect*xsiz + 0.5;
167     else
168     xsiz = ysiz/pictaspect + 0.5;
169     cheight = ysiz/nlines;
170 greg 2.14 cwidth = cheight/aspect;
171 greg 2.10 } else {
172 greg 2.11 if (ysiz <= 0)
173     ysiz = cheight*nlines;
174 greg 2.10 pictaspect = (double)ysiz/xsiz;
175     aspect = pictaspect*maxwidth/(256*nlines);
176     cheight = ysiz/nlines;
177 greg 2.14 cwidth = cheight/aspect;
178 greg 2.9 }
179 greg 1.1 } else { /* reverse orientation */
180 greg 2.11 if (ysiz <= 0) {
181 greg 2.9 cwidth = cheight/aspect + 0.5;
182     xsiz = nlines*cheight;
183     ysiz = (long)maxwidth*cwidth >> 8;
184 greg 2.10 } else if (aspect > FTINY) {
185 greg 2.11 if (xsiz <= 0)
186     xsiz = cheight*nlines;
187 greg 2.9 pictaspect = maxwidth/(256*nlines*aspect);
188     if (pictaspect*xsiz < ysiz)
189     ysiz = pictaspect*xsiz + 0.5;
190     else
191     xsiz = ysiz/pictaspect + 0.5;
192 greg 2.10 cheight = xsiz/nlines;
193 greg 2.14 cwidth = cheight/aspect;
194 greg 2.10 } else {
195 greg 2.11 if (xsiz <= 0)
196     xsiz = cheight*nlines;
197 greg 2.10 pictaspect = (double)ysiz/xsiz;
198     aspect = maxwidth/(256*nlines*pictaspect);
199 greg 2.9 cheight = xsiz/nlines;
200 greg 2.14 cwidth = cheight/aspect;
201 greg 2.9 }
202 greg 1.1 }
203 greg 2.5 if (xsiz % SSS)
204     xsiz += SSS - xsiz%SSS;
205     if (ysiz % SSS)
206     ysiz += SSS - ysiz%SSS;
207 greg 1.1 xdim = (xsiz+7)/8;
208 greg 2.8 ourbitmap = (BYTE *)bmalloc(ysiz*xdim);
209 greg 2.5 if (ourbitmap == NULL)
210     error(SYSTEM, "Out of memory in makemap");
211 schorsch 2.22 memset((char *)ourbitmap, '\0', ysiz*xdim);
212 greg 1.1 }
213    
214    
215     gettext(fp) /* get text from a file */
216     FILE *fp;
217     {
218     char buf[MAXLINE];
219     register LINE *curl;
220     int len;
221    
222     maxline = 0;
223 greg 2.4 maxwidth = 0;
224 greg 1.1 nlines = 0;
225     while (fgets(buf, MAXLINE, fp) != NULL) {
226     curl = (LINE *)malloc(sizeof(LINE));
227     if (curl == NULL)
228     goto memerr;
229     len = strlen(buf);
230 greg 2.18 curl->s = (char *)malloc(len);
231 greg 2.4 curl->sp = (short *)malloc(sizeof(short)*len--);
232 schorsch 2.23 if ((curl->s == NULL) | (curl->sp == NULL))
233 greg 1.1 goto memerr;
234 greg 2.4 if (len > maxline)
235     maxline = len;
236 greg 1.1 strncpy(curl->s, buf, len);
237     curl->s[len] = '\0';
238 greg 2.7 if (spacing < -1./256.)
239 greg 2.6 len = squeeztext(curl->sp, curl->s, ourfont,
240 greg 2.14 (int)(spacing*-256.));
241 greg 2.7 else if (spacing > 1./256.)
242 greg 2.6 len = proptext(curl->sp, curl->s, ourfont,
243 greg 2.14 (int)(spacing*256.), 3);
244 greg 2.6 else
245     len = uniftext(curl->sp, curl->s, ourfont);
246 greg 2.4 if (len > maxwidth)
247     maxwidth = len;
248 greg 1.1 curl->next = ourtext;
249     ourtext = curl;
250     nlines++;
251     }
252     return;
253     memerr:
254 greg 2.5 error(SYSTEM, "Out of memory in gettext");
255 greg 1.1 }
256    
257    
258     arg_text(ac, av) /* get text from arguments */
259     int ac;
260     char *av[];
261     {
262     register char *cp;
263    
264     ourtext = (LINE *)malloc(sizeof(LINE));
265     if (ourtext == NULL)
266     goto memerr;
267 greg 2.18 ourtext->s = (char *)malloc(MAXLINE);
268 greg 1.1 if (ourtext->s == NULL)
269     goto memerr;
270     for (cp = ourtext->s; ac-- > 0; av++) {
271     strcpy(cp, *av);
272     cp += strlen(*av);
273     *cp++ = ' ';
274     }
275     *--cp = '\0';
276     ourtext->next = NULL;
277     maxline = strlen(ourtext->s);
278 greg 2.4 ourtext->sp = (short *)malloc(sizeof(short)*(maxline+1));
279     if (ourtext->sp == NULL)
280     goto memerr;
281 greg 2.14 if (spacing < -1./256.)
282 greg 2.6 maxwidth = squeeztext(ourtext->sp, ourtext->s, ourfont,
283 greg 2.14 (int)(spacing*-256.));
284     else if (spacing > 1./256.)
285 greg 2.6 maxwidth = proptext(ourtext->sp, ourtext->s, ourfont,
286 greg 2.14 (int)(spacing*256.), 3);
287 greg 2.6 else
288     maxwidth = uniftext(ourtext->sp, ourtext->s, ourfont);
289 greg 1.1 nlines = 1;
290     return;
291     memerr:
292 greg 2.5 error(SYSTEM, "Out of memory in arg_text");
293 greg 1.1 }
294    
295    
296     maptext() /* map our text */
297     {
298     register LINE *curl;
299 greg 2.4 int l, len;
300     register int i, c;
301 greg 1.1
302 greg 2.4 for (l = 0, curl = ourtext; curl != NULL; l += 256, curl = curl->next) {
303     len = strlen(curl->s); c = 0;
304     for (i = 0; i < len; i++) {
305     c += curl->sp[i];
306     mapglyph(ourfont->fg[curl->s[i]&0xff], c, l);
307     }
308     }
309 greg 1.1 }
310    
311    
312     mapglyph(gl, tx0, ty0) /* convert a glyph */
313 greg 2.3 GLYPH *gl;
314 greg 1.1 int tx0, ty0;
315     {
316     int n;
317 greg 2.3 register GORD *gp;
318 greg 1.1 int p0[2], p1[2];
319    
320     if (gl == NULL)
321     return;
322    
323 greg 2.3 n = gl->nverts;
324     gp = gvlist(gl);
325     mapcoord(p0, gp[2*n-2]+tx0, gp[2*n-1]+ty0);
326 greg 1.1 while (n--) {
327 greg 2.3 mapcoord(p1, gp[0]+tx0, gp[1]+ty0);
328 greg 1.1 mapedge(p0[0], p0[1], p1[0]-p0[0], p1[1]-p0[1]);
329     p0[0] = p1[0]; p0[1] = p1[1];
330 greg 2.3 gp += 2;
331 greg 1.1 }
332     }
333    
334    
335     mapcoord(p, tx, ty) /* map text to picture coordinates */
336     int p[2], tx, ty;
337     {
338     tx = (long)tx*cwidth >> 8;
339     ty = (long)ty*cheight >> 8;
340    
341     switch (direct) {
342     case 'r': /* right */
343     p[0] = tx;
344     p[1] = ty;
345     return;
346     case 'u': /* up */
347     p[0] = xsiz-1-ty;
348     p[1] = tx;
349     return;
350     case 'l': /* left */
351     p[0] = xsiz-1-tx;
352     p[1] = ysiz-1-ty;
353     return;
354     case 'd': /* down */
355     p[0] = ty;
356     p[1] = ysiz-1-tx;
357     return;
358     }
359     }
360    
361    
362     mapedge(x, y, run, rise) /* map an edge */
363     register int x, y;
364     int run, rise;
365     {
366     int xstep;
367     int rise2, run2;
368     int n;
369    
370     if (rise == 0)
371     return;
372     /* always draw up */
373     if (rise < 0) {
374     x += run;
375     y += rise;
376     rise = -rise;
377     run = -run;
378     }
379     if (run < 0) {
380     xstep = -1;
381     run = -run;
382     } else
383     xstep = 1;
384     n = rise;
385     run2 = rise2 = 0;
386     while (n)
387     if (rise2 >= run2) {
388     tglbit(x, y);
389     n--;
390     y++;
391     run2 += run;
392     } else {
393     x += xstep;
394     rise2 += rise;
395     }
396     }
397    
398    
399     writemap(fp) /* write out bitmap */
400     FILE *fp;
401     {
402 greg 2.5 COLR pixval[SSS*SSS+1]; /* possible pixel values */
403     COLOR ctmp0, ctmp1;
404 greg 2.13 double d;
405 greg 1.1 COLR *scanout;
406 greg 2.5 int x, y;
407     register int i, j;
408     int cnt;
409 greg 1.1 register int inglyph;
410    
411 greg 2.5 fprintf(fp, "-Y %d +X %d\n", ysiz/SSS, xsiz/SSS);
412 greg 1.1
413 greg 2.5 scanout = (COLR *)malloc(xsiz/SSS*sizeof(COLR));
414     if (scanout == NULL)
415     error(SYSTEM, "Out of memory in writemap");
416     for (i = 0; i <= SSS*SSS; i++) { /* compute possible values */
417     copycolor(ctmp0, fgcolor);
418     d = (double)i/(SSS*SSS);
419     scalecolor(ctmp0, d);
420     copycolor(ctmp1, bgcolor);
421     d = 1.0 - d;
422     scalecolor(ctmp1, d);
423     addcolor(ctmp0, ctmp1);
424     setcolr(pixval[i], colval(ctmp0,RED),
425     colval(ctmp0,GRN), colval(ctmp0,BLU));
426 greg 1.1 }
427 greg 2.5 for (y = ysiz/SSS-1; y >= 0; y--) {
428 greg 1.1 inglyph = 0;
429 greg 2.5 for (x = 0; x < xsiz/SSS; x++) {
430     cnt = 0;
431     for (j = 0; j < SSS; j++)
432     for (i = 0; i < SSS; i++) {
433     if (tstbit(x*SSS+i, y*SSS+j))
434     inglyph ^= 1<<j;
435     if (inglyph & 1<<j)
436     cnt++;
437     }
438     copycolr(scanout[x], pixval[cnt]);
439 greg 1.1 }
440 greg 2.5 if (fwritecolrs(scanout, xsiz/SSS, fp) < 0) {
441 greg 1.1 fprintf(stderr, "write error in writemap\n");
442     exit(1);
443     }
444     }
445 greg 2.18 free((void *)scanout);
446 greg 1.1 }