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

# User Rev Content
1 greg 1.1 #ifndef lint
2 greg 2.28 static const char RCSid[] = "$Id: psign.c,v 2.27 2011/05/20 02:06:39 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 greg 2.26 static void get_text(FILE *fp);
68 schorsch 2.25 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 2.28 if (!ourfont)
143     exit(1);
144 greg 1.1 /* get text */
145     if (an == argc)
146 greg 2.26 get_text(stdin);
147 greg 1.1 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 greg 2.16 newheader("RADIANCE", stdout);
156 greg 1.1 printargs(argc, argv, stdout);
157 greg 1.3 fputformat(COLRFMT, stdout);
158     putchar('\n');
159 greg 1.1 /* write out bitmap */
160     writemap(stdout);
161    
162     exit(0);
163     }
164    
165    
166 schorsch 2.25 static void
167     makemap(void) /* create the bit map */
168 greg 1.1 {
169 greg 2.13 double pictaspect;
170 greg 2.9
171 greg 1.1 if (direct == 'r' || direct == 'l') {
172 greg 2.11 if (xsiz <= 0) {
173 greg 2.9 cwidth = cheight/aspect + 0.5;
174     xsiz = (long)maxwidth*cwidth >> 8;
175     ysiz = nlines*cheight;
176 greg 2.10 } else if (aspect > FTINY) {
177 greg 2.11 if (ysiz <= 0)
178     ysiz = cheight*nlines;
179 greg 2.9 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 greg 2.14 cwidth = cheight/aspect;
186 greg 2.10 } else {
187 greg 2.11 if (ysiz <= 0)
188     ysiz = cheight*nlines;
189 greg 2.10 pictaspect = (double)ysiz/xsiz;
190     aspect = pictaspect*maxwidth/(256*nlines);
191     cheight = ysiz/nlines;
192 greg 2.14 cwidth = cheight/aspect;
193 greg 2.9 }
194 greg 1.1 } else { /* reverse orientation */
195 greg 2.11 if (ysiz <= 0) {
196 greg 2.9 cwidth = cheight/aspect + 0.5;
197     xsiz = nlines*cheight;
198     ysiz = (long)maxwidth*cwidth >> 8;
199 greg 2.10 } else if (aspect > FTINY) {
200 greg 2.11 if (xsiz <= 0)
201     xsiz = cheight*nlines;
202 greg 2.9 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 greg 2.10 cheight = xsiz/nlines;
208 greg 2.14 cwidth = cheight/aspect;
209 greg 2.10 } else {
210 greg 2.11 if (xsiz <= 0)
211     xsiz = cheight*nlines;
212 greg 2.10 pictaspect = (double)ysiz/xsiz;
213     aspect = maxwidth/(256*nlines*pictaspect);
214 greg 2.9 cheight = xsiz/nlines;
215 greg 2.14 cwidth = cheight/aspect;
216 greg 2.9 }
217 greg 1.1 }
218 greg 2.5 if (xsiz % SSS)
219     xsiz += SSS - xsiz%SSS;
220     if (ysiz % SSS)
221     ysiz += SSS - ysiz%SSS;
222 greg 1.1 xdim = (xsiz+7)/8;
223 greg 2.27 ourbitmap = (uby8 *)bmalloc(ysiz*xdim);
224 greg 2.5 if (ourbitmap == NULL)
225     error(SYSTEM, "Out of memory in makemap");
226 schorsch 2.22 memset((char *)ourbitmap, '\0', ysiz*xdim);
227 greg 1.1 }
228    
229    
230 schorsch 2.25 static void
231 greg 2.26 get_text( /* get text from a file */
232 schorsch 2.25 FILE *fp
233     )
234 greg 1.1 {
235     char buf[MAXLINE];
236     register LINE *curl;
237     int len;
238    
239     maxline = 0;
240 greg 2.4 maxwidth = 0;
241 greg 1.1 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 greg 2.18 curl->s = (char *)malloc(len);
248 greg 2.4 curl->sp = (short *)malloc(sizeof(short)*len--);
249 schorsch 2.23 if ((curl->s == NULL) | (curl->sp == NULL))
250 greg 1.1 goto memerr;
251 greg 2.4 if (len > maxline)
252     maxline = len;
253 greg 1.1 strncpy(curl->s, buf, len);
254     curl->s[len] = '\0';
255 greg 2.7 if (spacing < -1./256.)
256 greg 2.6 len = squeeztext(curl->sp, curl->s, ourfont,
257 greg 2.14 (int)(spacing*-256.));
258 greg 2.7 else if (spacing > 1./256.)
259 greg 2.6 len = proptext(curl->sp, curl->s, ourfont,
260 greg 2.14 (int)(spacing*256.), 3);
261 greg 2.6 else
262     len = uniftext(curl->sp, curl->s, ourfont);
263 greg 2.4 if (len > maxwidth)
264     maxwidth = len;
265 greg 1.1 curl->next = ourtext;
266     ourtext = curl;
267     nlines++;
268     }
269     return;
270     memerr:
271 greg 2.26 error(SYSTEM, "Out of memory in get_text");
272 greg 1.1 }
273    
274    
275 schorsch 2.25 static void
276     arg_text( /* get text from arguments */
277     int ac,
278     char *av[]
279     )
280 greg 1.1 {
281     register char *cp;
282    
283     ourtext = (LINE *)malloc(sizeof(LINE));
284     if (ourtext == NULL)
285     goto memerr;
286 greg 2.18 ourtext->s = (char *)malloc(MAXLINE);
287 greg 1.1 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 greg 2.4 ourtext->sp = (short *)malloc(sizeof(short)*(maxline+1));
298     if (ourtext->sp == NULL)
299     goto memerr;
300 greg 2.14 if (spacing < -1./256.)
301 greg 2.6 maxwidth = squeeztext(ourtext->sp, ourtext->s, ourfont,
302 greg 2.14 (int)(spacing*-256.));
303     else if (spacing > 1./256.)
304 greg 2.6 maxwidth = proptext(ourtext->sp, ourtext->s, ourfont,
305 greg 2.14 (int)(spacing*256.), 3);
306 greg 2.6 else
307     maxwidth = uniftext(ourtext->sp, ourtext->s, ourfont);
308 greg 1.1 nlines = 1;
309     return;
310     memerr:
311 greg 2.5 error(SYSTEM, "Out of memory in arg_text");
312 greg 1.1 }
313    
314    
315 schorsch 2.25 static void
316     maptext(void) /* map our text */
317 greg 1.1 {
318     register LINE *curl;
319 greg 2.4 int l, len;
320     register int i, c;
321 greg 1.1
322 greg 2.4 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 greg 1.1 }
330    
331    
332 schorsch 2.25 static void
333     mapglyph( /* convert a glyph */
334     GLYPH *gl,
335     int tx0,
336     int ty0
337     )
338 greg 1.1 {
339     int n;
340 greg 2.3 register GORD *gp;
341 greg 1.1 int p0[2], p1[2];
342    
343     if (gl == NULL)
344     return;
345    
346 greg 2.3 n = gl->nverts;
347     gp = gvlist(gl);
348     mapcoord(p0, gp[2*n-2]+tx0, gp[2*n-1]+ty0);
349 greg 1.1 while (n--) {
350 greg 2.3 mapcoord(p1, gp[0]+tx0, gp[1]+ty0);
351 greg 1.1 mapedge(p0[0], p0[1], p1[0]-p0[0], p1[1]-p0[1]);
352     p0[0] = p1[0]; p0[1] = p1[1];
353 greg 2.3 gp += 2;
354 greg 1.1 }
355     }
356    
357    
358 schorsch 2.25 static void
359     mapcoord( /* map text to picture coordinates */
360     int p[2],
361     int tx,
362     int ty
363     )
364 greg 1.1 {
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 schorsch 2.25 static void
390     mapedge( /* map an edge */
391     register int x,
392     register int y,
393     int run,
394     int rise
395     )
396 greg 1.1 {
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 schorsch 2.25 static void
431     writemap( /* write out bitmap */
432     FILE *fp
433     )
434 greg 1.1 {
435 greg 2.5 COLR pixval[SSS*SSS+1]; /* possible pixel values */
436     COLOR ctmp0, ctmp1;
437 greg 2.13 double d;
438 greg 1.1 COLR *scanout;
439 greg 2.5 int x, y;
440     register int i, j;
441     int cnt;
442 greg 1.1 register int inglyph;
443    
444 greg 2.5 fprintf(fp, "-Y %d +X %d\n", ysiz/SSS, xsiz/SSS);
445 greg 1.1
446 greg 2.5 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 greg 1.1 }
460 greg 2.5 for (y = ysiz/SSS-1; y >= 0; y--) {
461 greg 1.1 inglyph = 0;
462 greg 2.5 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 greg 1.1 }
473 greg 2.5 if (fwritecolrs(scanout, xsiz/SSS, fp) < 0) {
474 greg 1.1 fprintf(stderr, "write error in writemap\n");
475     exit(1);
476     }
477     }
478 greg 2.18 free((void *)scanout);
479 greg 1.1 }