Back to index

radiance  4R0+20100331
psign.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char    RCSid[] = "$Id: psign.c,v 2.26 2007/01/01 03:03:32 greg Exp $";
00003 #endif
00004 /*
00005  *  psign.c - produce picture from text.
00006  *
00007  *     7/1/87
00008  */
00009 
00010 #include  "copyright.h"
00011 
00012 #include  <string.h>
00013 
00014 #include  "platform.h"
00015 #include  "standard.h"
00016 #include  "resolu.h"
00017 #include  "color.h"
00018 #include  "font.h"
00019 
00020 #ifndef        SSS
00021 #define        SSS                 3      /* super-sample size */
00022 #endif
00023 
00024 #define        MAXLINE             512    /* longest allowable line */
00025 
00026 char  *fontfile = "helvet.fnt";           /* our font file */
00027 
00028 COLOR  bgcolor = WHTCOLOR;         /* background color */
00029 COLOR  fgcolor = BLKCOLOR;         /* foreground color */
00030 
00031 int  direct = 'r';                 /* direction (right, up, left, down) */
00032 
00033 int  cheight = 32*SSS;                    /* character height */
00034 double aspect = 1.67;                     /* height/width character aspect */
00035 double spacing = 0.0;                     /* character spacing */
00036 int  cwidth;                       /* computed character width */
00037 
00038 unsigned char  *ourbitmap;         /* our output bitmap */
00039 int  xsiz, ysiz;                   /* bitmap dimensions */
00040 int  xdim;                         /* size of horizontal scan (bytes) */
00041 
00042                             /* conflicting def's in param.h */
00043 #undef tstbit
00044 #undef setbit
00045 #undef clrbit
00046 #undef tglbit
00047 
00048 #define        bitop(x,y,op)              (ourbitmap[(y)*xdim+((x)>>3)] op (1<<((x)&7)))
00049 #define        tstbit(x,y)         bitop(x,y,&)
00050 #define        setbit(x,y)         bitop(x,y,|=)
00051 #define        clrbit(x,y)         bitop(x,y,&=~)
00052 #define        tglbit(x,y)         bitop(x,y,^=)
00053 
00054 FONT  *ourfont;                           /* our font */
00055 
00056 typedef struct line {
00057        char  *s;            /* line w/o LF */
00058        short  *sp;          /* character spacing */
00059        struct line  *next;  /* next line up */
00060 } LINE;
00061 
00062 LINE  *ourtext;                           /* our text */
00063 int  nlines, maxline;                     /* text dimensions */
00064 int  maxwidth;                            /* maximum line width (dvi) */
00065 
00066 static void makemap(void);
00067 static void get_text(FILE  *fp);
00068 static void arg_text(int  ac, char  *av[]);
00069 static void maptext(void);
00070 static void mapglyph(GLYPH  *gl, int  tx0, int  ty0);
00071 static void mapcoord(int  p[2], int  tx, int  ty);
00072 static void mapedge(int  x, int  y, int  run, int  rise);
00073 static void writemap(FILE  *fp);
00074 
00075 
00076 int
00077 main(
00078        int  argc,
00079        char  *argv[]
00080 )
00081 {
00082        int  an;
00083        SET_FILE_BINARY(stdout);
00084        for (an = 1; an < argc && argv[an][0] == '-'; an++)
00085               switch (argv[an][1]) {
00086               case 'c':                   /* color */
00087                      switch (argv[an][2]) {
00088                      case 'f':                   /* foreground */
00089                             setcolor(fgcolor, atof(argv[an+1]),
00090                                           atof(argv[an+2]),
00091                                           atof(argv[an+3]));
00092                             an += 3;
00093                             break;
00094                      case 'b':                   /* background */
00095                             setcolor(bgcolor, atof(argv[an+1]),
00096                                           atof(argv[an+2]),
00097                                           atof(argv[an+3]));
00098                             an += 3;
00099                             break;
00100                      default:
00101                             goto unkopt;
00102                      }
00103                      break;
00104               case 'f':                   /* font */
00105                      fontfile = argv[++an];
00106                      break;
00107               case 'd':                   /* direction */
00108                      switch (argv[an][2]) {
00109                      case 'r':                   /* right */
00110                      case 'u':                   /* up */
00111                      case 'l':                   /* left */
00112                      case 'd':                   /* down */
00113                             direct = argv[an][2];
00114                             break;
00115                      default:
00116                             goto unkopt;
00117                      }
00118                      break;
00119               case 'x':                   /* x resolution */
00120                      xsiz = atoi(argv[++an])*SSS;
00121                      break;
00122               case 'y':
00123                      ysiz = atoi(argv[++an])*SSS;
00124                      break;
00125               case 'h':                   /* height of characters */
00126                      cheight = atoi(argv[++an])*SSS;
00127                      break;
00128               case 'a':                   /* aspect ratio */
00129                      aspect = atof(argv[++an]);
00130                      break;
00131               case 's':                   /* spacing */
00132                      spacing = atof(argv[++an]);
00133                      break;
00134               default:;
00135 unkopt:
00136                      fprintf(stderr, "%s: unknown option: %s\n",
00137                                    argv[0], argv[an]);
00138                      exit(1);
00139               }
00140                                    /* load font file */
00141        ourfont = getfont(fontfile);
00142                                    /* get text */
00143        if (an == argc)
00144               get_text(stdin);
00145        else
00146               arg_text(argc-an, argv+an);
00147 
00148                                    /* create bit map */
00149        makemap();
00150                                    /* convert text to bitmap */
00151        maptext();
00152                                    /* print header */
00153        newheader("RADIANCE", stdout);
00154        printargs(argc, argv, stdout);
00155        fputformat(COLRFMT, stdout);
00156        putchar('\n');
00157                                    /* write out bitmap */
00158        writemap(stdout);
00159 
00160        exit(0);
00161 }
00162 
00163 
00164 static void
00165 makemap(void)               /* create the bit map */
00166 {
00167        double pictaspect;
00168        
00169        if (direct == 'r' || direct == 'l') {
00170               if (xsiz <= 0) {
00171                      cwidth = cheight/aspect + 0.5;
00172                      xsiz = (long)maxwidth*cwidth >> 8;
00173                      ysiz = nlines*cheight;
00174               } else if (aspect > FTINY) {
00175                      if (ysiz <= 0)
00176                             ysiz = cheight*nlines;
00177                      pictaspect = 256*nlines*aspect/maxwidth;
00178                      if (pictaspect*xsiz < ysiz)
00179                             ysiz = pictaspect*xsiz + 0.5;
00180                      else
00181                             xsiz = ysiz/pictaspect + 0.5;
00182                      cheight = ysiz/nlines;
00183                      cwidth = cheight/aspect;
00184               } else {
00185                      if (ysiz <= 0)
00186                             ysiz = cheight*nlines;
00187                      pictaspect = (double)ysiz/xsiz;
00188                      aspect = pictaspect*maxwidth/(256*nlines);
00189                      cheight = ysiz/nlines;
00190                      cwidth = cheight/aspect;
00191               }
00192        } else {                    /* reverse orientation */
00193               if (ysiz <= 0) {
00194                      cwidth = cheight/aspect + 0.5;
00195                      xsiz = nlines*cheight;
00196                      ysiz = (long)maxwidth*cwidth >> 8;
00197               } else if (aspect > FTINY) {
00198                      if (xsiz <= 0)
00199                             xsiz = cheight*nlines;
00200                      pictaspect = maxwidth/(256*nlines*aspect);
00201                      if (pictaspect*xsiz < ysiz)
00202                             ysiz = pictaspect*xsiz + 0.5;
00203                      else
00204                             xsiz = ysiz/pictaspect + 0.5;
00205                      cheight = xsiz/nlines;
00206                      cwidth = cheight/aspect;
00207               } else {
00208                      if (xsiz <= 0)
00209                             xsiz = cheight*nlines;
00210                      pictaspect = (double)ysiz/xsiz;
00211                      aspect = maxwidth/(256*nlines*pictaspect);
00212                      cheight = xsiz/nlines;
00213                      cwidth = cheight/aspect;
00214               }
00215        }
00216        if (xsiz % SSS)
00217               xsiz += SSS - xsiz%SSS;
00218        if (ysiz % SSS)
00219               ysiz += SSS - ysiz%SSS;
00220        xdim = (xsiz+7)/8;
00221        ourbitmap = (BYTE *)bmalloc(ysiz*xdim);
00222        if (ourbitmap == NULL)
00223               error(SYSTEM, "Out of memory in makemap");
00224        memset((char *)ourbitmap, '\0', ysiz*xdim);
00225 }
00226 
00227 
00228 static void
00229 get_text(                   /* get text from a file */
00230        FILE  *fp
00231 )
00232 {
00233        char  buf[MAXLINE];
00234        register LINE  *curl;
00235        int  len;
00236 
00237        maxline = 0;
00238        maxwidth = 0;
00239        nlines = 0;
00240        while (fgets(buf, MAXLINE, fp) != NULL) {
00241               curl = (LINE *)malloc(sizeof(LINE));
00242               if (curl == NULL)
00243                      goto memerr;
00244               len = strlen(buf);
00245               curl->s = (char *)malloc(len);
00246               curl->sp = (short *)malloc(sizeof(short)*len--);
00247               if ((curl->s == NULL) | (curl->sp == NULL))
00248                      goto memerr;
00249               if (len > maxline)
00250                      maxline = len;
00251               strncpy(curl->s, buf, len);
00252               curl->s[len] = '\0';
00253               if (spacing < -1./256.)
00254                      len = squeeztext(curl->sp, curl->s, ourfont,
00255                                    (int)(spacing*-256.));
00256               else if (spacing > 1./256.)
00257                      len = proptext(curl->sp, curl->s, ourfont,
00258                                    (int)(spacing*256.), 3);
00259               else
00260                      len = uniftext(curl->sp, curl->s, ourfont);
00261               if (len > maxwidth)
00262                      maxwidth = len;
00263               curl->next = ourtext;
00264               ourtext = curl;
00265               nlines++;
00266        }
00267        return;
00268 memerr:
00269        error(SYSTEM, "Out of memory in get_text");
00270 }
00271 
00272 
00273 static void
00274 arg_text(                   /* get text from arguments */
00275        int  ac,
00276        char  *av[]
00277 )
00278 {
00279        register char  *cp;
00280 
00281        ourtext = (LINE *)malloc(sizeof(LINE));
00282        if (ourtext == NULL)
00283               goto memerr;
00284        ourtext->s = (char *)malloc(MAXLINE);
00285        if (ourtext->s == NULL)
00286               goto memerr;
00287        for (cp = ourtext->s; ac-- > 0; av++) {
00288               strcpy(cp, *av);
00289               cp += strlen(*av);
00290               *cp++ = ' ';
00291        }
00292        *--cp = '\0';
00293        ourtext->next = NULL;
00294        maxline = strlen(ourtext->s);
00295        ourtext->sp = (short *)malloc(sizeof(short)*(maxline+1));
00296        if (ourtext->sp == NULL)
00297               goto memerr;
00298        if (spacing < -1./256.)
00299               maxwidth = squeeztext(ourtext->sp, ourtext->s, ourfont,
00300                             (int)(spacing*-256.));
00301        else if (spacing > 1./256.)
00302               maxwidth = proptext(ourtext->sp, ourtext->s, ourfont,
00303                             (int)(spacing*256.), 3);
00304        else
00305               maxwidth = uniftext(ourtext->sp, ourtext->s, ourfont);
00306        nlines = 1;
00307        return;
00308 memerr:
00309        error(SYSTEM, "Out of memory in arg_text");
00310 }
00311 
00312 
00313 static void
00314 maptext(void)               /* map our text */
00315 {
00316        register LINE  *curl;
00317        int  l, len;
00318        register int  i, c;
00319 
00320        for (l = 0, curl = ourtext; curl != NULL; l += 256, curl = curl->next) {
00321               len = strlen(curl->s); c = 0;
00322               for (i = 0; i < len; i++) {
00323                      c += curl->sp[i];
00324                      mapglyph(ourfont->fg[curl->s[i]&0xff], c, l);
00325               }
00326        }
00327 }
00328 
00329 
00330 static void
00331 mapglyph(            /* convert a glyph */
00332        GLYPH  *gl,
00333        int  tx0,
00334        int  ty0
00335 )
00336 {
00337        int  n;
00338        register GORD  *gp;
00339        int  p0[2], p1[2];
00340 
00341        if (gl == NULL)
00342               return;
00343 
00344        n = gl->nverts;
00345        gp = gvlist(gl);
00346        mapcoord(p0, gp[2*n-2]+tx0, gp[2*n-1]+ty0);
00347        while (n--) {
00348               mapcoord(p1, gp[0]+tx0, gp[1]+ty0);
00349               mapedge(p0[0], p0[1], p1[0]-p0[0], p1[1]-p0[1]);
00350               p0[0] = p1[0]; p0[1] = p1[1];
00351               gp += 2;
00352        }
00353 }
00354 
00355 
00356 static void
00357 mapcoord(            /* map text to picture coordinates */
00358        int  p[2],
00359        int  tx,
00360        int  ty
00361 )
00362 {
00363        tx = (long)tx*cwidth >> 8;
00364        ty = (long)ty*cheight >> 8;
00365 
00366        switch (direct) {
00367        case 'r':                   /* right */
00368               p[0] = tx;
00369               p[1] = ty;
00370               return;
00371        case 'u':                   /* up */
00372               p[0] = xsiz-1-ty;
00373               p[1] = tx;
00374               return;
00375        case 'l':                   /* left */
00376               p[0] = xsiz-1-tx;
00377               p[1] = ysiz-1-ty;
00378               return;
00379        case 'd':                   /* down */
00380               p[0] = ty;
00381               p[1] = ysiz-1-tx;
00382               return;
00383        }
00384 }
00385 
00386 
00387 static void
00388 mapedge(             /* map an edge */
00389        register int  x,
00390        register int  y,
00391        int  run,
00392        int  rise
00393 )
00394 {
00395        int  xstep;
00396        int  rise2, run2;
00397        int  n;
00398 
00399        if (rise == 0)
00400               return;
00401                                           /* always draw up */
00402        if (rise < 0) {
00403               x += run;
00404               y += rise;
00405               rise = -rise;
00406               run = -run;
00407        }
00408        if (run < 0) {
00409               xstep = -1;
00410               run = -run;
00411        } else
00412               xstep = 1;
00413        n = rise;
00414        run2 = rise2 = 0;
00415        while (n)
00416               if (rise2 >= run2) {
00417                      tglbit(x, y);
00418                      n--;
00419                      y++;
00420                      run2 += run;
00421               } else {
00422                      x += xstep;
00423                      rise2 += rise;
00424               }
00425 }
00426 
00427 
00428 static void
00429 writemap(                   /* write out bitmap */
00430        FILE  *fp
00431 )
00432 {
00433        COLR  pixval[SSS*SSS+1];    /* possible pixel values */
00434        COLOR  ctmp0, ctmp1;
00435        double d;
00436        COLR  *scanout;
00437        int  x, y;
00438        register int  i, j;
00439        int  cnt;
00440        register int  inglyph;
00441 
00442        fprintf(fp, "-Y %d +X %d\n", ysiz/SSS, xsiz/SSS);
00443 
00444        scanout = (COLR *)malloc(xsiz/SSS*sizeof(COLR));
00445        if (scanout == NULL)
00446               error(SYSTEM, "Out of memory in writemap");
00447        for (i = 0; i <= SSS*SSS; i++) {   /* compute possible values */
00448               copycolor(ctmp0, fgcolor);
00449               d = (double)i/(SSS*SSS);
00450               scalecolor(ctmp0, d);
00451               copycolor(ctmp1, bgcolor);
00452               d = 1.0 - d;
00453               scalecolor(ctmp1, d);
00454               addcolor(ctmp0, ctmp1);
00455               setcolr(pixval[i], colval(ctmp0,RED),
00456                             colval(ctmp0,GRN), colval(ctmp0,BLU));
00457        }
00458        for (y = ysiz/SSS-1; y >= 0; y--) {
00459               inglyph = 0;
00460               for (x = 0; x < xsiz/SSS; x++) {
00461                      cnt = 0;
00462                      for (j = 0; j < SSS; j++)
00463                             for (i = 0; i < SSS; i++) {
00464                                    if (tstbit(x*SSS+i, y*SSS+j))
00465                                           inglyph ^= 1<<j;
00466                                    if (inglyph & 1<<j)
00467                                           cnt++;
00468                             }
00469                      copycolr(scanout[x], pixval[cnt]);
00470               }
00471               if (fwritecolrs(scanout, xsiz/SSS, fp) < 0) {
00472                      fprintf(stderr, "write error in writemap\n");
00473                      exit(1);
00474               }
00475        }
00476        free((void *)scanout);
00477 }