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