ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/psign.c
Revision: 2.25
Committed: Sun Mar 28 20:33:14 2004 UTC (20 years, 1 month ago) by schorsch
Content type: text/plain
Branch: MAIN
CVS Tags: rad3R7P2, rad3R7P1, rad3R6, rad3R6P1, rad3R8
Changes since 2.24: +52 -21 lines
Log Message:
Continued ANSIfication, and other fixes and clarifications.

File Contents

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