home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Raytrace & Morphing / SOS-RAYTRACE.ISO / programm / source / radsrc22 / src / px / psign.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-09-19  |  10.7 KB  |  449 lines

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