home *** CD-ROM | disk | FTP | other *** search
/ DP Tool Club 8 / CDASC08.ISO / NEWS / RADIANCE / SRC / RT / TEXT.C < prev    next >
C/C++ Source or Header  |  1993-10-07  |  8KB  |  345 lines

  1. /* Copyright (c) 1991 Regents of the University of California */
  2.  
  3. #ifndef lint
  4. static char SCCSid[] = "@(#)text.c 2.8 11/10/92 LBL";
  5. #endif
  6.  
  7. /*
  8.  *  text.c - functions for text patterns and mixtures.
  9.  *
  10.  *     11/12/86
  11.  */
  12.  
  13. #include  "ray.h"
  14.  
  15. #include  "otypes.h"
  16.  
  17. #include  "font.h"
  18.  
  19. /*
  20.  *    A text pattern is specified as the text (a file or line),
  21.  *  the upper left anchor point, the right motion vector, the down
  22.  *  motion vector, and the foreground and background brightness.
  23.  *  For a file, the description is as follows:
  24.  *
  25.  *    modifier brighttext id
  26.  *    2 fontfile textfile
  27.  *    0
  28.  *    11+
  29.  *        Ax Ay Az
  30.  *        Rx Ry Rz
  31.  *        Dx Dy Dz
  32.  *        foreground background
  33.  *        [spacing]
  34.  *
  35.  *  For a single line, we use:
  36.  *
  37.  *    modifier brighttext id
  38.  *    N+2 fontfile . This is a line with N words...
  39.  *    0
  40.  *    11+
  41.  *        Ax Ay Az
  42.  *        Rx Ry Rz
  43.  *        Dx Dy Dz
  44.  *        foreground background
  45.  *        [spacing]
  46.  *
  47.  *  Colortext is identical, except colors are given rather than
  48.  *  brightnesses.  Mixtext has foreground and background modifiers:
  49.  *
  50.  *    modifier mixtext id
  51.  *    4+ foremod backmod fontfile text..
  52.  *    0
  53.  *    9+
  54.  *        Ax Ay Az
  55.  *        Rx Ry Rz
  56.  *        Dx Dy Dz
  57.  *        [spacing]
  58.  */
  59.  
  60. #define  fndx(m)    ((m)->otype==MIX_TEXT ? 2 : 0)
  61. #define  tndx(m)    ((m)->otype==MIX_TEXT ? 3 : 1)
  62. #define  sndx(m)    ((m)->otype==PAT_BTEXT ? 11 : \
  63.                 (m)->otype==PAT_CTEXT ? 15 : 9)
  64.  
  65. typedef struct tline {
  66.     struct tline  *next;        /* pointer to next line */
  67.     short  *spc;            /* character spacing */
  68.     int  width;            /* total line width */
  69.                     /* followed by the string */
  70. }  TLINE;
  71.  
  72. #define  TLSTR(l)    ((char *)((l)+1))
  73.  
  74. typedef struct {
  75.     FVECT  right, down;        /* right and down unit vectors */
  76.     FONT  *f;            /* our font */
  77.     TLINE  tl;            /* line list */
  78. }  TEXT;
  79.  
  80. extern char  *libpath;
  81.  
  82. extern char  *fgetword();
  83.  
  84. TEXT  *gettext();
  85.  
  86. TLINE  *tlalloc();
  87.  
  88.  
  89. text(m, r)
  90. register OBJREC  *m;
  91. RAY  *r;
  92. {
  93.     FVECT  v;
  94.     int  foreground;
  95.                 /* get transformed position */
  96.     if (r->rox != NULL)
  97.         multp3(v, r->rop, r->rox->b.xfm);
  98.     else
  99.         VCOPY(v, r->rop);
  100.                 /* check if we are within a text glyph */
  101.     foreground = intext(v, m);
  102.                 /* modify */
  103.     if (m->otype == MIX_TEXT) {
  104.         OBJECT  omod;
  105.         char  *modname = m->oargs.sarg[foreground ? 0 : 1];
  106.         if (!strcmp(modname, VOIDID))
  107.             omod = OVOID;
  108.         else if ((omod = modifier(modname)) == OVOID) {
  109.             sprintf(errmsg, "undefined modifier \"%s\"", modname);
  110.             objerror(m, USER, errmsg);
  111.         }
  112.         raytexture(r, omod);
  113.     } else if (m->otype == PAT_BTEXT) {
  114.         if (foreground)
  115.             scalecolor(r->pcol, m->oargs.farg[9]);
  116.         else
  117.             scalecolor(r->pcol, m->oargs.farg[10]);
  118.     } else { /* PAT_CTEXT */
  119.         COLOR  cval;
  120.         if (foreground)
  121.             setcolor(cval, m->oargs.farg[9],
  122.                     m->oargs.farg[10],
  123.                     m->oargs.farg[11]);
  124.         else
  125.             setcolor(cval, m->oargs.farg[12],
  126.                     m->oargs.farg[13],
  127.                     m->oargs.farg[14]);
  128.         multcolor(r->pcol, cval);
  129.     }
  130. }
  131.  
  132.  
  133. TLINE *
  134. tlalloc(s)            /* allocate and assign text line */
  135. char  *s;
  136. {
  137.     extern char  *strcpy();
  138.     register int  siz;
  139.     register TLINE  *tl;
  140.  
  141.     siz = strlen(s) + 1;
  142.     if ((tl=(TLINE *)malloc(sizeof(TLINE)+siz)) == NULL ||
  143.             (tl->spc=(short *)malloc(siz*sizeof(short))) == NULL)
  144.         error(SYSTEM, "out of memory in tlalloc");
  145.     tl->spc = NULL;
  146.     tl->next = NULL;
  147.     strcpy(TLSTR(tl), s);
  148.     return(tl);
  149. }
  150.  
  151.  
  152. TEXT *
  153. gettext(tm)            /* get text structure for material */
  154. register OBJREC  *tm;
  155. {
  156. #define  R    (tm->oargs.farg+3)
  157. #define  D    (tm->oargs.farg+6)
  158.     extern char  *strcpy(), *fgets();
  159.     FVECT  DxR;
  160.     double  d;
  161.     FILE  *fp;
  162.     char  linbuf[512];
  163.     TEXT  *t;
  164.     register int  i;
  165.     register TLINE  *tlp;
  166.     register char  *s;
  167.  
  168.     if ((t = (TEXT *)tm->os) != NULL)
  169.         return(t);
  170.                         /* check arguments */
  171.     if (tm->oargs.nsargs - tndx(tm) < 1 || tm->oargs.nfargs < sndx(tm))
  172.         objerror(tm, USER, "bad # arguments");
  173.     if ((t = (TEXT *)malloc(sizeof(TEXT))) == NULL)
  174.         goto memerr;
  175.                         /* compute vectors */
  176.     fcross(DxR, D, R);
  177.     fcross(t->right, DxR, D);
  178.     d = DOT(D,D)/DOT(t->right,t->right);
  179.     for (i = 0; i < 3; i++)
  180.         t->right[i] *= d;
  181.     fcross(t->down, R, DxR);
  182.     d = DOT(R,R)/DOT(t->down,t->down);
  183.     for (i = 0; i < 3; i++)
  184.         t->down[i] *= d;
  185.                         /* get text */
  186.     tlp = &t->tl;
  187.     if (tm->oargs.nsargs - tndx(tm) > 1) {    /* single line */
  188.         s = linbuf;
  189.         for (i = tndx(tm)+1; i < tm->oargs.nsargs; i++) {
  190.             strcpy(s, tm->oargs.sarg[i]);
  191.             s += strlen(s);
  192.             *s++ = ' ';
  193.         }
  194.         *--s = '\0';
  195.         tlp->next = tlalloc(linbuf);
  196.         tlp = tlp->next;
  197.     } else {                /* text file */
  198.         if ((s = getpath(tm->oargs.sarg[tndx(tm)],
  199.                 libpath, R_OK)) == NULL) {
  200.             sprintf(errmsg, "cannot find text file \"%s\"",
  201.                     tm->oargs.sarg[tndx(tm)]);
  202.             error(USER, errmsg);
  203.         }
  204.         if ((fp = fopen(s, "r")) == NULL) {
  205.             sprintf(errmsg, "cannot open text file \"%s\"", s);
  206.             error(SYSTEM, errmsg);
  207.         }
  208.         while (fgets(linbuf, sizeof(linbuf), fp) != NULL) {
  209.             s = linbuf + strlen(linbuf) - 1;
  210.             if (*s == '\n')
  211.                 *s = '\0';
  212.             tlp->next = tlalloc(linbuf);
  213.             tlp = tlp->next;
  214.         }
  215.         fclose(fp);
  216.     }
  217.     tlp->next = NULL;
  218.                         /* get the font */
  219.     t->f = getfont(tm->oargs.sarg[fndx(tm)]);
  220.                         /* compute character spacing */
  221.     i = sndx(tm);
  222.     d = i < tm->oargs.nfargs ? tm->oargs.farg[i] : 0.0;
  223.     i = d * 256.0;
  224.     t->tl.width = 0;
  225.     for (tlp = t->tl.next; tlp != NULL; tlp = tlp->next) {
  226.         if ((tlp->spc = (short *)malloc(
  227.                 (strlen(TLSTR(tlp))+1)*sizeof(short))) == NULL)
  228.             goto memerr;
  229.         if (i < 0)
  230.             tlp->width = squeeztext(tlp->spc, TLSTR(tlp), t->f, -i);
  231.         else if (i > 0)
  232.             tlp->width = proptext(tlp->spc, TLSTR(tlp), t->f, i, 3);
  233.         else
  234.             tlp->width = uniftext(tlp->spc, TLSTR(tlp), t->f);
  235.         if (tlp->width > t->tl.width)
  236.             t->tl.width = tlp->width;
  237.     }
  238.                         /* we're done */
  239.     tm->os = (char *)t;
  240.     return(t);
  241. memerr:
  242.     error(SYSTEM, "out of memory in gettext");
  243. #undef  R
  244. #undef  D
  245. }
  246.  
  247.  
  248. freetext(m)            /* free text structures associated with m */
  249. OBJREC  *m;
  250. {
  251.     TEXT  *tp;
  252.     register TLINE  *tlp, *tln;
  253.  
  254.     tp = (TEXT *)m->os;
  255.     if (tp == NULL)
  256.         return;
  257.     for (tlp = tp->tl.next; tlp != NULL; tlp = tln) {
  258.         tln = tlp->next;
  259.         free((char *)tlp->spc);
  260.         free((char *)tlp);
  261.     }
  262.     free((char *)tp);
  263.     m->os = NULL;
  264. }
  265.  
  266.  
  267. intext(p, m)            /* check to see if p is in text glyph */
  268. FVECT  p;
  269. OBJREC  *m;
  270. {
  271.     register TEXT  *tp;
  272.     register TLINE  *tlp;
  273.     FVECT  v;
  274.     double  y, x;
  275.     register int  i, h;
  276.                 /* first, compute position in text */
  277.     tp = gettext(m);
  278.     v[0] = p[0] - m->oargs.farg[0];
  279.     v[1] = p[1] - m->oargs.farg[1];
  280.     v[2] = p[2] - m->oargs.farg[2];
  281.     x = DOT(v, tp->right);
  282.     i = sndx(m);
  283.     if (i < m->oargs.nfargs)
  284.         x *= tp->f->mwidth + 256.*fabs(m->oargs.farg[i]);
  285.     else
  286.         x *= 256.;
  287.     h = x;
  288.     i = y = DOT(v, tp->down);
  289.     if (x < 0.0 || y < 0.0)
  290.         return(0);
  291.     x -= (double)h;
  292.     y = ((i+1) - y)*256.;
  293.                 /* find the line position */
  294.     for (tlp = tp->tl.next; tlp != NULL; tlp = tlp->next)
  295.         if (--i < 0)
  296.             break;
  297.     if (tlp == NULL || h >= tlp->width)
  298.         return(0);
  299.     for (i = 0; (h -= tlp->spc[i]) >= 0; i++)
  300.         if (h < 256 && inglyph(h+x, y,
  301.                 tp->f->fg[TLSTR(tlp)[i]&0xff]))
  302.             return(1);
  303.     return(0);
  304. }
  305.  
  306.  
  307. inglyph(x, y, gl)        /* (x,y) within font glyph gl? */
  308. double  x, y;        /* real coordinates in range [0,256) */
  309. register GLYPH  *gl;
  310. {
  311.     int  n, ncross;
  312.     int  xlb, ylb;
  313.     int  tv;
  314.     register GORD  *p0, *p1;
  315.  
  316.     if (gl == NULL)
  317.         return(0);
  318.     xlb = x;
  319.     ylb = y;
  320.     if (gl->left > xlb || gl->right <= xlb ||    /* check extent */
  321.             gl->bottom > ylb || gl->top <= ylb)
  322.         return(0);
  323.     xlb = xlb<<1 | 1;        /* add 1/2 to test points... */
  324.     ylb = ylb<<1 | 1;        /* ...so no equal comparisons */
  325.     n = gl->nverts;            /* get # of vertices */
  326.     p0 = gvlist(gl) + 2*(n-1);    /* connect last to first */
  327.     p1 = gvlist(gl);
  328.     ncross = 0;
  329.                     /* positive x axis cross test */
  330.     while (n--) {
  331.         if ((p0[1]<<1 > ylb) ^ (p1[1]<<1 > ylb)) {
  332.             tv = p0[0]<<1 > xlb | (p1[0]<<1 > xlb) << 1;
  333.             if (tv == 03)
  334.                 ncross++;
  335.             else if (tv)
  336.                 ncross += (p1[1] > p0[1]) ^
  337.                         ((p0[1]-y)*(p1[0]-x) >
  338.                         (p0[0]-x)*(p1[1]-y));
  339.         }
  340.         p0 = p1;
  341.         p1 += 2;
  342.     }
  343.     return(ncross & 01);
  344. }
  345.