ViewVC Help
View File | Revision Log | Show Annotations | Download File | Root Listing
root/radiance/ray/src/px/psign.c
Revision: 2.28
Committed: Fri Nov 19 22:51:31 2021 UTC (2 years, 5 months ago) by greg
Content type: text/plain
Branch: MAIN
CVS Tags: rad5R4, HEAD
Changes since 2.27: +3 -1 lines
Log Message:
refactor: made font load errors non-fatal

File Contents

# Content
1 #ifndef lint
2 static const char RCSid[] = "$Id: psign.c,v 2.27 2011/05/20 02:06:39 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 get_text(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 if (!ourfont)
143 exit(1);
144 /* get text */
145 if (an == argc)
146 get_text(stdin);
147 else
148 arg_text(argc-an, argv+an);
149
150 /* create bit map */
151 makemap();
152 /* convert text to bitmap */
153 maptext();
154 /* print header */
155 newheader("RADIANCE", stdout);
156 printargs(argc, argv, stdout);
157 fputformat(COLRFMT, stdout);
158 putchar('\n');
159 /* write out bitmap */
160 writemap(stdout);
161
162 exit(0);
163 }
164
165
166 static void
167 makemap(void) /* create the bit map */
168 {
169 double pictaspect;
170
171 if (direct == 'r' || direct == 'l') {
172 if (xsiz <= 0) {
173 cwidth = cheight/aspect + 0.5;
174 xsiz = (long)maxwidth*cwidth >> 8;
175 ysiz = nlines*cheight;
176 } else if (aspect > FTINY) {
177 if (ysiz <= 0)
178 ysiz = cheight*nlines;
179 pictaspect = 256*nlines*aspect/maxwidth;
180 if (pictaspect*xsiz < ysiz)
181 ysiz = pictaspect*xsiz + 0.5;
182 else
183 xsiz = ysiz/pictaspect + 0.5;
184 cheight = ysiz/nlines;
185 cwidth = cheight/aspect;
186 } else {
187 if (ysiz <= 0)
188 ysiz = cheight*nlines;
189 pictaspect = (double)ysiz/xsiz;
190 aspect = pictaspect*maxwidth/(256*nlines);
191 cheight = ysiz/nlines;
192 cwidth = cheight/aspect;
193 }
194 } else { /* reverse orientation */
195 if (ysiz <= 0) {
196 cwidth = cheight/aspect + 0.5;
197 xsiz = nlines*cheight;
198 ysiz = (long)maxwidth*cwidth >> 8;
199 } else if (aspect > FTINY) {
200 if (xsiz <= 0)
201 xsiz = cheight*nlines;
202 pictaspect = maxwidth/(256*nlines*aspect);
203 if (pictaspect*xsiz < ysiz)
204 ysiz = pictaspect*xsiz + 0.5;
205 else
206 xsiz = ysiz/pictaspect + 0.5;
207 cheight = xsiz/nlines;
208 cwidth = cheight/aspect;
209 } else {
210 if (xsiz <= 0)
211 xsiz = cheight*nlines;
212 pictaspect = (double)ysiz/xsiz;
213 aspect = maxwidth/(256*nlines*pictaspect);
214 cheight = xsiz/nlines;
215 cwidth = cheight/aspect;
216 }
217 }
218 if (xsiz % SSS)
219 xsiz += SSS - xsiz%SSS;
220 if (ysiz % SSS)
221 ysiz += SSS - ysiz%SSS;
222 xdim = (xsiz+7)/8;
223 ourbitmap = (uby8 *)bmalloc(ysiz*xdim);
224 if (ourbitmap == NULL)
225 error(SYSTEM, "Out of memory in makemap");
226 memset((char *)ourbitmap, '\0', ysiz*xdim);
227 }
228
229
230 static void
231 get_text( /* get text from a file */
232 FILE *fp
233 )
234 {
235 char buf[MAXLINE];
236 register LINE *curl;
237 int len;
238
239 maxline = 0;
240 maxwidth = 0;
241 nlines = 0;
242 while (fgets(buf, MAXLINE, fp) != NULL) {
243 curl = (LINE *)malloc(sizeof(LINE));
244 if (curl == NULL)
245 goto memerr;
246 len = strlen(buf);
247 curl->s = (char *)malloc(len);
248 curl->sp = (short *)malloc(sizeof(short)*len--);
249 if ((curl->s == NULL) | (curl->sp == NULL))
250 goto memerr;
251 if (len > maxline)
252 maxline = len;
253 strncpy(curl->s, buf, len);
254 curl->s[len] = '\0';
255 if (spacing < -1./256.)
256 len = squeeztext(curl->sp, curl->s, ourfont,
257 (int)(spacing*-256.));
258 else if (spacing > 1./256.)
259 len = proptext(curl->sp, curl->s, ourfont,
260 (int)(spacing*256.), 3);
261 else
262 len = uniftext(curl->sp, curl->s, ourfont);
263 if (len > maxwidth)
264 maxwidth = len;
265 curl->next = ourtext;
266 ourtext = curl;
267 nlines++;
268 }
269 return;
270 memerr:
271 error(SYSTEM, "Out of memory in get_text");
272 }
273
274
275 static void
276 arg_text( /* get text from arguments */
277 int ac,
278 char *av[]
279 )
280 {
281 register char *cp;
282
283 ourtext = (LINE *)malloc(sizeof(LINE));
284 if (ourtext == NULL)
285 goto memerr;
286 ourtext->s = (char *)malloc(MAXLINE);
287 if (ourtext->s == NULL)
288 goto memerr;
289 for (cp = ourtext->s; ac-- > 0; av++) {
290 strcpy(cp, *av);
291 cp += strlen(*av);
292 *cp++ = ' ';
293 }
294 *--cp = '\0';
295 ourtext->next = NULL;
296 maxline = strlen(ourtext->s);
297 ourtext->sp = (short *)malloc(sizeof(short)*(maxline+1));
298 if (ourtext->sp == NULL)
299 goto memerr;
300 if (spacing < -1./256.)
301 maxwidth = squeeztext(ourtext->sp, ourtext->s, ourfont,
302 (int)(spacing*-256.));
303 else if (spacing > 1./256.)
304 maxwidth = proptext(ourtext->sp, ourtext->s, ourfont,
305 (int)(spacing*256.), 3);
306 else
307 maxwidth = uniftext(ourtext->sp, ourtext->s, ourfont);
308 nlines = 1;
309 return;
310 memerr:
311 error(SYSTEM, "Out of memory in arg_text");
312 }
313
314
315 static void
316 maptext(void) /* map our text */
317 {
318 register LINE *curl;
319 int l, len;
320 register int i, c;
321
322 for (l = 0, curl = ourtext; curl != NULL; l += 256, curl = curl->next) {
323 len = strlen(curl->s); c = 0;
324 for (i = 0; i < len; i++) {
325 c += curl->sp[i];
326 mapglyph(ourfont->fg[curl->s[i]&0xff], c, l);
327 }
328 }
329 }
330
331
332 static void
333 mapglyph( /* convert a glyph */
334 GLYPH *gl,
335 int tx0,
336 int ty0
337 )
338 {
339 int n;
340 register GORD *gp;
341 int p0[2], p1[2];
342
343 if (gl == NULL)
344 return;
345
346 n = gl->nverts;
347 gp = gvlist(gl);
348 mapcoord(p0, gp[2*n-2]+tx0, gp[2*n-1]+ty0);
349 while (n--) {
350 mapcoord(p1, gp[0]+tx0, gp[1]+ty0);
351 mapedge(p0[0], p0[1], p1[0]-p0[0], p1[1]-p0[1]);
352 p0[0] = p1[0]; p0[1] = p1[1];
353 gp += 2;
354 }
355 }
356
357
358 static void
359 mapcoord( /* map text to picture coordinates */
360 int p[2],
361 int tx,
362 int ty
363 )
364 {
365 tx = (long)tx*cwidth >> 8;
366 ty = (long)ty*cheight >> 8;
367
368 switch (direct) {
369 case 'r': /* right */
370 p[0] = tx;
371 p[1] = ty;
372 return;
373 case 'u': /* up */
374 p[0] = xsiz-1-ty;
375 p[1] = tx;
376 return;
377 case 'l': /* left */
378 p[0] = xsiz-1-tx;
379 p[1] = ysiz-1-ty;
380 return;
381 case 'd': /* down */
382 p[0] = ty;
383 p[1] = ysiz-1-tx;
384 return;
385 }
386 }
387
388
389 static void
390 mapedge( /* map an edge */
391 register int x,
392 register int y,
393 int run,
394 int rise
395 )
396 {
397 int xstep;
398 int rise2, run2;
399 int n;
400
401 if (rise == 0)
402 return;
403 /* always draw up */
404 if (rise < 0) {
405 x += run;
406 y += rise;
407 rise = -rise;
408 run = -run;
409 }
410 if (run < 0) {
411 xstep = -1;
412 run = -run;
413 } else
414 xstep = 1;
415 n = rise;
416 run2 = rise2 = 0;
417 while (n)
418 if (rise2 >= run2) {
419 tglbit(x, y);
420 n--;
421 y++;
422 run2 += run;
423 } else {
424 x += xstep;
425 rise2 += rise;
426 }
427 }
428
429
430 static void
431 writemap( /* write out bitmap */
432 FILE *fp
433 )
434 {
435 COLR pixval[SSS*SSS+1]; /* possible pixel values */
436 COLOR ctmp0, ctmp1;
437 double d;
438 COLR *scanout;
439 int x, y;
440 register int i, j;
441 int cnt;
442 register int inglyph;
443
444 fprintf(fp, "-Y %d +X %d\n", ysiz/SSS, xsiz/SSS);
445
446 scanout = (COLR *)malloc(xsiz/SSS*sizeof(COLR));
447 if (scanout == NULL)
448 error(SYSTEM, "Out of memory in writemap");
449 for (i = 0; i <= SSS*SSS; i++) { /* compute possible values */
450 copycolor(ctmp0, fgcolor);
451 d = (double)i/(SSS*SSS);
452 scalecolor(ctmp0, d);
453 copycolor(ctmp1, bgcolor);
454 d = 1.0 - d;
455 scalecolor(ctmp1, d);
456 addcolor(ctmp0, ctmp1);
457 setcolr(pixval[i], colval(ctmp0,RED),
458 colval(ctmp0,GRN), colval(ctmp0,BLU));
459 }
460 for (y = ysiz/SSS-1; y >= 0; y--) {
461 inglyph = 0;
462 for (x = 0; x < xsiz/SSS; x++) {
463 cnt = 0;
464 for (j = 0; j < SSS; j++)
465 for (i = 0; i < SSS; i++) {
466 if (tstbit(x*SSS+i, y*SSS+j))
467 inglyph ^= 1<<j;
468 if (inglyph & 1<<j)
469 cnt++;
470 }
471 copycolr(scanout[x], pixval[cnt]);
472 }
473 if (fwritecolrs(scanout, xsiz/SSS, fp) < 0) {
474 fprintf(stderr, "write error in writemap\n");
475 exit(1);
476 }
477 }
478 free((void *)scanout);
479 }