Back to index

tetex-bin  3.0
color.c
Go to the documentation of this file.
00001 /* color.c */
00002 
00003 /************************************************************************
00004 
00005   Part of the dvipng distribution
00006 
00007   This program is free software; you can redistribute it and/or modify
00008   it under the terms of the GNU General Public License as published by
00009   the Free Software Foundation; either version 2 of the License, or
00010   (at your option) any later version.
00011 
00012   This program is distributed in the hope that it will be useful, but
00013   WITHOUT ANY WARRANTY; without even the implied warranty of
00014   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015   General Public License for more details.
00016 
00017   You should have received a copy of the GNU General Public License
00018   along with this program; if not, write to the Free Software
00019   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
00020   02111-1307, USA.
00021 
00022   Copyright (C) 2002-2005 Jan-Åke Larsson
00023 
00024 ************************************************************************/
00025 
00026 #include "dvipng.h"
00027 #if HAVE_ALLOCA_H
00028 # include <alloca.h>
00029 #endif
00030 
00031 /*
00032  * Color. We delete and recreate the gdImage for each new page. This
00033  * means that the stack must contain rgb value not color index.
00034  * Besides, the current antialiasing implementation needs rgb anyway.
00035 */
00036 
00037 struct colorname {
00038   char*             name;
00039   char*             color;
00040 } *colornames=NULL;
00041 
00042 void initcolor() 
00043 {
00044    csp = 1;
00045    cstack[0].red=255; 
00046    cstack[0].green=255; 
00047    cstack[0].blue=255; 
00048    cstack[1].red=0; 
00049    cstack[1].green=0; 
00050    cstack[1].blue=0; 
00051 }
00052 
00053 void LoadDvipsNam (void)
00054 {
00055   char *pos,*max,*buf,*dvipsnam_file;
00056   struct colorname *tmp=NULL;
00057   struct filemmap fmmap;
00058 
00059   TEMPSTR(dvipsnam_file,kpse_find_file("dvipsnam.def",kpse_tex_format,false));
00060   if (dvipsnam_file == NULL) {
00061     Warning("color name file dvipsnam.def could not be found");
00062     return;
00063   }
00064   DEBUG_PRINT(DEBUG_COLOR,("\n  OPEN COLOR NAMES:\t'%s'", dvipsnam_file));
00065   if (MmapFile(dvipsnam_file,&fmmap)) return;
00066   if ((colornames = malloc(fmmap.size*2))==NULL) 
00067     Fatal("cannot alloc space for color names");
00068   pos=fmmap.mmap;
00069   max=fmmap.mmap+fmmap.size;
00070   tmp=colornames;
00071   buf=(char*)colornames+fmmap.size;
00072   while (pos<max && *pos!='\\') pos++;
00073   while(pos+9<max && strncmp(pos,"\\endinput",9)!=0) {
00074     while (pos+17<max && strncmp(pos,"\\DefineNamedColor",17)!=0) {
00075       pos++;
00076       while (pos<max && *pos!='\\') pos++;
00077     }
00078     while(pos<max && *pos!='}') pos++; /* skip first argument */
00079     while(pos<max && *pos!='{') pos++; /* find second argument */
00080     pos++;
00081     tmp->name=buf;
00082     while(pos<max && *pos!='}')        /* copy color name */
00083       *buf++=*pos++;
00084     *buf++='\0';
00085     while(pos<max && *pos!='{') pos++; /* find third argument */
00086     pos++;
00087     tmp->color=buf;
00088     while(pos<max && *pos!='}')        /* copy color model */
00089       *buf++=*pos++;
00090     *buf++=' ';
00091     while(pos<max && *pos!='{') pos++; /* find fourth argument */
00092     pos++;
00093     while(pos<max && *pos!='}') {      /* copy color values */
00094       *buf++=*pos++;
00095       if (*(buf-1)==',') *(buf-1)=' '; /* commas should become blanks */
00096     }
00097     *buf++='\0';
00098     while (pos<max && *pos!='\\') pos++;
00099     DEBUG_PRINT(DEBUG_COLOR,("\n  COLOR NAME:\t'%s' '%s'",
00100                           tmp->name,tmp->color)); 
00101     tmp++;
00102   }
00103   tmp->name=NULL;
00104   UnMmapFile(&fmmap);
00105 }
00106 
00107 void ClearDvipsNam(void)
00108 {
00109   if (colornames!=NULL)
00110     free(colornames);
00111   colornames=NULL;
00112 }
00113 
00114 float toktof(char* token)
00115 {
00116   if (token!=NULL)
00117     return(atof(token));
00118   flags |= PAGE_GAVE_WARN;
00119   Warning("Missing color-specification value, treated as zero\n");
00120   return(0.0);
00121 }
00122 
00123 void stringrgb(char* p,int *r,int *g,int *b)
00124 {
00125   char* token;
00126 
00127   DEBUG_PRINT(DEBUG_COLOR,("\n  COLOR SPEC:\t'%s' ",p));
00128   token=strtok(p," ");
00129   if (strcmp(token,"Black")==0) {
00130     p+=5;
00131     *r = *g = *b = 0;
00132   } else if (strcmp(token,"White")==0) {
00133     p+=5;
00134     *r = *g = *b = 255;
00135   } else if (strcmp(token,"gray")==0) {
00136     p+=4;
00137     *r = *g = *b = (int) (255 * toktof(strtok(NULL," ")));
00138   } else if (strcmp(token,"rgb")==0) {
00139     p+=3;
00140     *r = (int) (255 * toktof(strtok(NULL," ")));
00141     *g = (int) (255 * toktof(strtok(NULL," ")));
00142     *b = (int) (255 * toktof(strtok(NULL," ")));
00143   } else if (strncmp(p,"cmyk",4)==0) {
00144     double c,m,y,k;
00145 
00146     p+=4;
00147     c = toktof(strtok(NULL," "));
00148     m = toktof(strtok(NULL," "));
00149     y = toktof(strtok(NULL," "));
00150     k = toktof(strtok(NULL," "));
00151     *r = (int) (255 * ((1-c)*(1-k)));
00152     *g = (int) (255 * ((1-m)*(1-k)));
00153     *b = (int) (255 * ((1-y)*(1-k)));
00154   } else {
00155     struct colorname *tmp;
00156 
00157     if (colornames==NULL) 
00158       LoadDvipsNam();
00159     tmp=colornames;
00160     while(tmp!=NULL && tmp->name!=NULL && strcmp(tmp->name,token)) 
00161       tmp++;
00162     if (tmp!=NULL && tmp->name!=NULL) {
00163       /* One-level recursion */
00164       char* colorspec=alloca(sizeof(char)*strlen(tmp->color+1));
00165       strcpy(colorspec,tmp->color);
00166       stringrgb(colorspec,r,g,b);
00167     } else {
00168       char* t2=strtok(NULL,"");  
00169       if (t2!=NULL) 
00170        Warning("Unimplemented color specification '%s %s'\n",p,t2);
00171       else 
00172        Warning("Unimplemented color specification '%s'\n",p);
00173       flags |= PAGE_GAVE_WARN;
00174     }
00175   }
00176   DEBUG_PRINT(DEBUG_COLOR,("(%d %d %d) ",*r,*g,*b))
00177 }
00178 
00179 void background(char* p)
00180 {
00181   stringrgb(p, &cstack[0].red, &cstack[0].green, &cstack[0].blue);
00182   DEBUG_PRINT(DEBUG_COLOR,("\n  BACKGROUND:\t(%d %d %d) ",
00183                         cstack[0].red, cstack[0].green, cstack[0].blue));
00184 }
00185 
00186 void pushcolor(char * p)
00187 {
00188   if ( ++csp == STACK_SIZE )
00189     Fatal("Out of color stack space") ;
00190   stringrgb(p, &cstack[csp].red, &cstack[csp].green, &cstack[csp].blue);
00191   DEBUG_PRINT(DEBUG_COLOR,("\n  COLOR PUSH:\t(%d %d %d) ",
00192                         cstack[csp].red, cstack[csp].green, cstack[csp].blue))
00193 }
00194 
00195 void popcolor()
00196 {
00197   if (csp > 1) csp--; /* Last color is global */
00198   DEBUG_PRINT(DEBUG_COLOR,("\n  COLOR POP\t"))
00199 }
00200 
00201 void resetcolorstack(char * p)
00202 {
00203   if ( csp > 1 )
00204     Warning("Global color change within nested colors\n");
00205   csp=0;
00206   pushcolor(p) ;
00207   DEBUG_PRINT(DEBUG_COLOR,("\n  RESET COLOR:\tbottom of stack:"))
00208 }
00209 
00210 void StoreColorStack(struct page_list *tpagep)
00211 {
00212   int i=0;
00213 
00214   DEBUG_PRINT(DEBUG_COLOR,("\n  STORE COLOR STACK:\t %d ", csp));
00215   tpagep->csp=csp;
00216   while ( i <= csp ) {
00217     DEBUG_PRINT(DEBUG_COLOR,("\n  COLOR STACK:\t %d (%d %d %d) ",i,
00218                           cstack[i].red, cstack[i].green, cstack[i].blue));
00219     tpagep->cstack[i].red = cstack[i].red;
00220     tpagep->cstack[i].green = cstack[i].green;
00221     tpagep->cstack[i].blue = cstack[i].blue;
00222     i++;
00223   }
00224 }
00225 
00226 void ReadColorStack(struct page_list *tpagep)
00227 {
00228   int i=0;
00229 
00230   DEBUG_PRINT(DEBUG_COLOR,("\n  READ COLOR STACK:\t %d ", tpagep->csp));
00231   csp=tpagep->csp;
00232   while ( i <= tpagep->csp ) {
00233     DEBUG_PRINT(DEBUG_COLOR,("\n  COLOR STACK:\t %d (%d %d %d) ",i,
00234                           cstack[i].red, cstack[i].green, cstack[i].blue));
00235     cstack[i].red = tpagep->cstack[i].red;
00236     cstack[i].green = tpagep->cstack[i].green;
00237     cstack[i].blue = tpagep->cstack[i].blue;
00238     i++;
00239   }
00240 }
00241 
00242 void StoreBackgroundColor(struct page_list *tpagep)
00243 {
00244   /* Background color changes affect the _whole_ page */
00245   tpagep->cstack[0].red = cstack[0].red;
00246   tpagep->cstack[0].green = cstack[0].green;
00247   tpagep->cstack[0].blue = cstack[0].blue;
00248 }