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 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

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: psign.c,v 2.24 2003/10/22 02:06:35 greg Exp $";
3 #endif
4 /*
5 * psign.c - produce picture from text.
6 *
7 * 7/1/87
8 */
9
10 #include "copyright.h"
11
12 #include <string.h>
13
14 #include "platform.h"
15 #include "standard.h"
16 #include "resolu.h"
17 #include "color.h"
18 #include "font.h"
19
20 #ifndef SSS
21 #define SSS 3 /* super-sample size */
22 #endif
23
24 #define MAXLINE 512 /* longest allowable line */
25
26 char *fontfile = "helvet.fnt"; /* our font file */
27
28 COLOR bgcolor = WHTCOLOR; /* background color */
29 COLOR fgcolor = BLKCOLOR; /* foreground color */
30
31 int direct = 'r'; /* direction (right, up, left, down) */
32
33 int cheight = 32*SSS; /* character height */
34 double aspect = 1.67; /* height/width character aspect */
35 double spacing = 0.0; /* character spacing */
36 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
42 /* conflicting def's in param.h */
43 #undef tstbit
44 #undef setbit
45 #undef clrbit
46 #undef tglbit
47
48 #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
54 FONT *ourfont; /* our font */
55
56 typedef struct line {
57 char *s; /* line w/o LF */
58 short *sp; /* character spacing */
59 struct line *next; /* next line up */
60 } LINE;
61
62 LINE *ourtext; /* our text */
63 int nlines, maxline; /* text dimensions */
64 int maxwidth; /* maximum line width (dvi) */
65
66 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
75
76 int
77 main(
78 int argc,
79 char *argv[]
80 )
81 {
82 int an;
83 SET_FILE_BINARY(stdout);
84 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 setcolor(fgcolor, atof(argv[an+1]),
90 atof(argv[an+2]),
91 atof(argv[an+3]));
92 an += 3;
93 break;
94 case 'b': /* background */
95 setcolor(bgcolor, atof(argv[an+1]),
96 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 case 'x': /* x resolution */
120 xsiz = atoi(argv[++an])*SSS;
121 break;
122 case 'y':
123 ysiz = atoi(argv[++an])*SSS;
124 break;
125 case 'h': /* height of characters */
126 cheight = atoi(argv[++an])*SSS;
127 break;
128 case 'a': /* aspect ratio */
129 aspect = atof(argv[++an]);
130 break;
131 case 's': /* spacing */
132 spacing = atof(argv[++an]);
133 break;
134 default:;
135 unkopt:
136 fprintf(stderr, "%s: unknown option: %s\n",
137 argv[0], argv[an]);
138 exit(1);
139 }
140 /* load font file */
141 ourfont = getfont(fontfile);
142 /* 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 newheader("RADIANCE", stdout);
154 printargs(argc, argv, stdout);
155 fputformat(COLRFMT, stdout);
156 putchar('\n');
157 /* write out bitmap */
158 writemap(stdout);
159
160 exit(0);
161 }
162
163
164 static void
165 makemap(void) /* create the bit map */
166 {
167 double pictaspect;
168
169 if (direct == 'r' || direct == 'l') {
170 if (xsiz <= 0) {
171 cwidth = cheight/aspect + 0.5;
172 xsiz = (long)maxwidth*cwidth >> 8;
173 ysiz = nlines*cheight;
174 } else if (aspect > FTINY) {
175 if (ysiz <= 0)
176 ysiz = cheight*nlines;
177 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 cwidth = cheight/aspect;
184 } else {
185 if (ysiz <= 0)
186 ysiz = cheight*nlines;
187 pictaspect = (double)ysiz/xsiz;
188 aspect = pictaspect*maxwidth/(256*nlines);
189 cheight = ysiz/nlines;
190 cwidth = cheight/aspect;
191 }
192 } else { /* reverse orientation */
193 if (ysiz <= 0) {
194 cwidth = cheight/aspect + 0.5;
195 xsiz = nlines*cheight;
196 ysiz = (long)maxwidth*cwidth >> 8;
197 } else if (aspect > FTINY) {
198 if (xsiz <= 0)
199 xsiz = cheight*nlines;
200 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 cheight = xsiz/nlines;
206 cwidth = cheight/aspect;
207 } else {
208 if (xsiz <= 0)
209 xsiz = cheight*nlines;
210 pictaspect = (double)ysiz/xsiz;
211 aspect = maxwidth/(256*nlines*pictaspect);
212 cheight = xsiz/nlines;
213 cwidth = cheight/aspect;
214 }
215 }
216 if (xsiz % SSS)
217 xsiz += SSS - xsiz%SSS;
218 if (ysiz % SSS)
219 ysiz += SSS - ysiz%SSS;
220 xdim = (xsiz+7)/8;
221 ourbitmap = (BYTE *)bmalloc(ysiz*xdim);
222 if (ourbitmap == NULL)
223 error(SYSTEM, "Out of memory in makemap");
224 memset((char *)ourbitmap, '\0', ysiz*xdim);
225 }
226
227
228 static void
229 gettext( /* get text from a file */
230 FILE *fp
231 )
232 {
233 char buf[MAXLINE];
234 register LINE *curl;
235 int len;
236
237 maxline = 0;
238 maxwidth = 0;
239 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 curl->s = (char *)malloc(len);
246 curl->sp = (short *)malloc(sizeof(short)*len--);
247 if ((curl->s == NULL) | (curl->sp == NULL))
248 goto memerr;
249 if (len > maxline)
250 maxline = len;
251 strncpy(curl->s, buf, len);
252 curl->s[len] = '\0';
253 if (spacing < -1./256.)
254 len = squeeztext(curl->sp, curl->s, ourfont,
255 (int)(spacing*-256.));
256 else if (spacing > 1./256.)
257 len = proptext(curl->sp, curl->s, ourfont,
258 (int)(spacing*256.), 3);
259 else
260 len = uniftext(curl->sp, curl->s, ourfont);
261 if (len > maxwidth)
262 maxwidth = len;
263 curl->next = ourtext;
264 ourtext = curl;
265 nlines++;
266 }
267 return;
268 memerr:
269 error(SYSTEM, "Out of memory in gettext");
270 }
271
272
273 static void
274 arg_text( /* get text from arguments */
275 int ac,
276 char *av[]
277 )
278 {
279 register char *cp;
280
281 ourtext = (LINE *)malloc(sizeof(LINE));
282 if (ourtext == NULL)
283 goto memerr;
284 ourtext->s = (char *)malloc(MAXLINE);
285 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 ourtext->sp = (short *)malloc(sizeof(short)*(maxline+1));
296 if (ourtext->sp == NULL)
297 goto memerr;
298 if (spacing < -1./256.)
299 maxwidth = squeeztext(ourtext->sp, ourtext->s, ourfont,
300 (int)(spacing*-256.));
301 else if (spacing > 1./256.)
302 maxwidth = proptext(ourtext->sp, ourtext->s, ourfont,
303 (int)(spacing*256.), 3);
304 else
305 maxwidth = uniftext(ourtext->sp, ourtext->s, ourfont);
306 nlines = 1;
307 return;
308 memerr:
309 error(SYSTEM, "Out of memory in arg_text");
310 }
311
312
313 static void
314 maptext(void) /* map our text */
315 {
316 register LINE *curl;
317 int l, len;
318 register int i, c;
319
320 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 }
328
329
330 static void
331 mapglyph( /* convert a glyph */
332 GLYPH *gl,
333 int tx0,
334 int ty0
335 )
336 {
337 int n;
338 register GORD *gp;
339 int p0[2], p1[2];
340
341 if (gl == NULL)
342 return;
343
344 n = gl->nverts;
345 gp = gvlist(gl);
346 mapcoord(p0, gp[2*n-2]+tx0, gp[2*n-1]+ty0);
347 while (n--) {
348 mapcoord(p1, gp[0]+tx0, gp[1]+ty0);
349 mapedge(p0[0], p0[1], p1[0]-p0[0], p1[1]-p0[1]);
350 p0[0] = p1[0]; p0[1] = p1[1];
351 gp += 2;
352 }
353 }
354
355
356 static void
357 mapcoord( /* map text to picture coordinates */
358 int p[2],
359 int tx,
360 int ty
361 )
362 {
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 static void
388 mapedge( /* map an edge */
389 register int x,
390 register int y,
391 int run,
392 int rise
393 )
394 {
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 static void
429 writemap( /* write out bitmap */
430 FILE *fp
431 )
432 {
433 COLR pixval[SSS*SSS+1]; /* possible pixel values */
434 COLOR ctmp0, ctmp1;
435 double d;
436 COLR *scanout;
437 int x, y;
438 register int i, j;
439 int cnt;
440 register int inglyph;
441
442 fprintf(fp, "-Y %d +X %d\n", ysiz/SSS, xsiz/SSS);
443
444 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 }
458 for (y = ysiz/SSS-1; y >= 0; y--) {
459 inglyph = 0;
460 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 }
471 if (fwritecolrs(scanout, xsiz/SSS, fp) < 0) {
472 fprintf(stderr, "write error in writemap\n");
473 exit(1);
474 }
475 }
476 free((void *)scanout);
477 }