diff options
author | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
---|---|---|
committer | Karl Berry <karl@freefriends.org> | 2006-01-17 21:41:51 +0000 |
commit | 487ca4806cc046076293cf6cc5fbba0db282bac7 (patch) | |
tree | 847b412ab5158dd7bdd7ed7e5a4cc3fbca94be32 /Build/source/texk/dvipsk/color.c | |
parent | a3d3111bfe26b8e5f5bc6049dfb2a4ca2edc7881 (diff) |
texk 1
git-svn-id: svn://tug.org/texlive/trunk@1485 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/texk/dvipsk/color.c')
-rw-r--r-- | Build/source/texk/dvipsk/color.c | 240 |
1 files changed, 240 insertions, 0 deletions
diff --git a/Build/source/texk/dvipsk/color.c b/Build/source/texk/dvipsk/color.c new file mode 100644 index 00000000000..803e8a7511a --- /dev/null +++ b/Build/source/texk/dvipsk/color.c @@ -0,0 +1,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) ; + } + } +} |