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