home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 9 / FreshFishVol9-CD2.bin / bbs / gnu / unixtex-6.1b-src.lha / unixtex-6.1b / dvipsk / color.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-25  |  6.6 KB  |  243 lines

  1. /*  
  2.  *  This is a set of routines for dvips that are used to process color 
  3.  *  commands in the TeX file (passed by \special commands).  This was
  4.  *  orignally written by J. Hafner, E. Blanz and M. Flickner of IBM
  5.  *  Research, Almaden Research Center.  Contact hafner@almaden.ibm.com.
  6.  *  And then it was completely rewritten by Tomas Rokicki to:
  7.  *
  8.  *      - Be easier on the memory allocator (malloc/free)
  9.  *      - Use less memory overall (by a great deal) and be faster
  10.  *      - Work with the -C, -a, and other options
  11.  *      - Be more adaptable to other drivers and previewers.
  12.  *
  13.  *  The motivating idea:  we want to be able to process 5,000 page
  14.  *  documents using lots of colors on each page on a 640K IBM PC
  15.  *  relatively quickly.
  16.  */
  17. #include "dvips.h" /* The copyright notice in that file is included too! */
  18. #include <stdio.h>
  19. /*
  20.  *   Externals we use.
  21.  */
  22. extern void cmdout(), error() ;
  23. extern void error() ;
  24. extern integer pagenum ;
  25. extern FILE *dvifile ;
  26. /*
  27.  *   Here we set some limits on some color stuff.
  28.  */
  29. #define COLORHASH (89)
  30. #define MAXCOLORLEN (120)     /* maximum color length for background */
  31. #define TOTALCOLORLEN (3000)  /* sum of lengths of pending colors */
  32. /*
  33.  *   This is where we store the color information for a particular page.
  34.  *   If we free all of these, we free all of the allocated color
  35.  *   stuff; we do no allocations (but one) other than when we allocate
  36.  *   these.
  37.  */
  38. static struct colorpage {
  39.    struct colorpage *next ;
  40.    integer boploc ; /* we use the bop loc as a page indicator */
  41.    char *bg ;
  42.    char colordat[2] ;
  43. } *colorhash[COLORHASH] ;
  44. static char cstack[TOTALCOLORLEN], *csp, *cend, *bg ;
  45. /*
  46.  *   This routine sends a color command out.  If the command is a
  47.  *   single `word' or starts with a double quote, we send it out
  48.  *   exactly as is (except for any double quote.)  If the command
  49.  *   is a word followed by arguments, we send out the arguments and
  50.  *   then the word prefixed by "TeXcolor".
  51.  */
  52. void colorcmdout(s)
  53. char *s ;
  54. {
  55.    char *p ;
  56.    char tempword[100] ;
  57.  
  58.    while (*s <= ' ')
  59.       s++ ;
  60.    if (*s == '"') {
  61.       cmdout(s+1) ;
  62.       return ;
  63.    }
  64.    for (p=s; *p && *p > ' '; p++) ;
  65.    for (; *p && *p <= ' '; p++) ;
  66.    if (*p == 0) {
  67.       cmdout(s) ;
  68.       return ;
  69.    }
  70.    cmdout(p) ;
  71.    strcpy(tempword, "TeXcolor") ;
  72.    for (p=tempword + strlen(tempword); *s && *s > ' '; p++, s++)
  73.       *p = *s ;
  74.    *p = 0 ;
  75.    cmdout(tempword) ;
  76.    return ;
  77. }
  78. /*
  79.  *   For a new dvi file, call this.  Frees all allocated memory.
  80.  */
  81. #define DEFAULTCOLOR "Black"
  82. void initcolor() {
  83.    int i ;
  84.    struct colorpage *p, *q ;
  85.  
  86.    for (i=0; i<COLORHASH; i++) {
  87.       for (p=colorhash[i]; p; p = q) {
  88.          q = p->next ;
  89.          free(p) ;
  90.       }
  91.       colorhash[i] = 0 ;
  92.    }
  93.    strcpy(cstack, "\n") ;
  94.    strcat(cstack, DEFAULTCOLOR) ;
  95.    csp = cstack + strlen(cstack) ;
  96.    cend = cstack + TOTALCOLORLEN - 3 ; /* for conservativeness */
  97.    bg = 0 ;
  98. }
  99. /*
  100.  * This takes a call from predospecial to set the background color for
  101.  * the current page.  It is saved in stackdepth and backed down the
  102.  * stack during popcolors.
  103.  */
  104. void
  105. background(bkgrnd)
  106. char *bkgrnd ;
  107. {
  108.    if (bkgrnd && *bkgrnd) {
  109.       if (strlen(bkgrnd) > MAXCOLORLEN)
  110.          error(" color name too long; ignored") ;
  111.       else
  112.          strcpy(bg, bkgrnd) ;
  113.    }
  114. }
  115. /*
  116.  * This routine puts a call from \special for color on the colorstack
  117.  * and sets the color in the PostScript.
  118.  */
  119. void
  120. pushcolor(p,outtops)
  121. char *p ;
  122. Boolean outtops ;
  123. {
  124.    if (strlen(p) + csp > cend)
  125.       error("! out of color stack space") ;
  126.    *csp++ = '\n' ;
  127.    strcpy(csp, p) ;
  128.    csp += strlen(p) ;
  129.    if (outtops) {
  130.       colorcmdout(p) ;
  131.    }
  132. }
  133. /*
  134.  * This routine removes a color from the colorstack and resets the color
  135.  * in the PostScript to the previous color.
  136.  */
  137. void
  138. popcolor(outtops)
  139. Boolean outtops ;
  140. {
  141.    char *p = csp - 1 ;
  142.  
  143.    while (p >= cstack && *p != '\n')
  144.       p-- ;
  145.    if (p == cstack)
  146.       return ;  /* We don't pop the last color as that is global */
  147.    *p = 0 ;
  148.    csp = p ;
  149.    for (p--; p >= cstack && *p != '\n'; p--) ;
  150.    p++ ;
  151.    if ( outtops ) {
  152.       colorcmdout(p) ;
  153.    }
  154. }
  155. /*
  156.  * This routine clears the colorstack, pushes a new color onto the stack
  157.  * (this is now the root or global color).
  158.  */
  159. void
  160. resetcolorstack(p,outtops)
  161. char *p ;
  162. int outtops ;
  163. {
  164.    char *q = csp - 1 ;
  165.  
  166.    while (q > cstack && *q != '\n')
  167.       q-- ;
  168.    if (q > cstack && outtops == 0) {
  169. #ifdef SHORTINT
  170.      (void)fprintf(stderr, "You've mistakenly made a global color change ") ;
  171.      (void)fprintf(stderr, "to %s within nested colors\n", p) ;
  172.      (void)fprintf(stderr, "on page %ld. Will try to recover.\n", pagenum) ;
  173. #else   /* ~SHORTINT */
  174.      (void)fprintf(stderr, "You've mistakenly made a global color change ") ;
  175.      (void)fprintf(stderr, "to %s within nested colors\n", p) ;
  176.      (void)fprintf(stderr, "on page %d. Will try to recover.\n", pagenum) ;
  177. #endif  /* ~SHORTINT */
  178.    }
  179.    csp = cstack ;
  180.    *csp = 0 ;
  181.    pushcolor(p, outtops) ;
  182. }
  183. /*
  184.  *   This routine is a bit magic.  It looks up the page in the current
  185.  *   hash table.  If the page is already entered in the hash table, then
  186.  *   it restores the color to what that page had, and sets the last
  187.  *   color.  This will occur if this is not the first time that this
  188.  *   page has been encountered.
  189.  *
  190.  *   If, on the other hand, this is the first time that the page has
  191.  *   been encountered, then it will create a new hash entry and copy the
  192.  *   current color information into it.  Since we can only encounter a
  193.  *   new page after having just finished scanning the previous page,
  194.  *   this is safe.
  195.  */
  196. void
  197. bopcolor(outtops)
  198. int outtops ;
  199. {
  200.    integer pageloc = ftell(dvifile) ;
  201.    int h = pageloc % COLORHASH ;
  202.    struct colorpage *p = colorhash[h] ;
  203.  
  204.    while (p) {
  205.       if (p->boploc == pageloc)
  206.          break ;
  207.       else
  208.          p = p->next ;
  209.    }
  210.    if (p) {
  211.       strcpy(cstack, p->colordat) ;
  212.       csp = cstack + strlen(cstack) ;
  213.       bg = p->bg ;
  214.       if (outtops && strcmp(bg, "White")!=0 && bg[0]) {
  215.          cmdout("gsave") ;
  216.          colorcmdout(bg) ;
  217.          cmdout("clippath fill grestore") ;
  218.       }
  219.    } else {
  220.       p = (struct colorpage *)mymalloc((integer)
  221.                   (strlen(cstack) + sizeof(struct colorpage) + MAXCOLORLEN)) ;
  222.       p->next = colorhash[h] ;
  223.       p->boploc = pageloc ;
  224.       strcpy(p->colordat, cstack) ;
  225.       p->bg = p->colordat + strlen(cstack) + 1 ;
  226.       if (bg)
  227.          strcpy(p->bg, bg) ;
  228.       else
  229.          *(p->bg) = 0 ;
  230.       bg = p->bg ;
  231.       colorhash[h] = p ;
  232.    }
  233.    if (outtops) {
  234.       char *p = csp - 1 ;
  235.       while (p >= cstack && *p != '\n')
  236.          p-- ;
  237.       p++ ;
  238.       if (strcmp(p, DEFAULTCOLOR)!=0) {
  239.          colorcmdout(p) ;
  240.       }
  241.    }
  242. }
  243.