Back to index

tetex-bin  3.0
set.c
Go to the documentation of this file.
00001 /* set.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 #include <math.h>
00031 
00032 void CreateImage(pixels x_width,pixels y_width)
00033 {
00034   int Background;
00035 
00036   if (page_imagep) 
00037     gdImageDestroy(page_imagep);
00038   if (x_width <= 0) x_width=1;
00039   if (y_width <= 0) y_width=1;
00040 #ifdef HAVE_GDIMAGECREATETRUECOLOR
00041   if (flags & RENDER_TRUECOLOR) 
00042     page_imagep=gdImageCreateTrueColor(x_width,y_width);
00043   else
00044 #endif
00045     page_imagep=gdImageCreate(x_width,y_width);
00046   /* Set bg color */
00047   Background = gdImageColorAllocate(page_imagep,
00048                                 cstack[0].red,cstack[0].green,cstack[0].blue);
00049   if (flags & BG_TRANSPARENT) {
00050     gdImageColorTransparent(page_imagep,Background); 
00051   }
00052 #ifdef HAVE_GDIMAGECREATETRUECOLOR
00053   if (flags & RENDER_TRUECOLOR) 
00054     /* Truecolor: there is no background color index, fill image instead. */
00055     gdImageFilledRectangle(page_imagep, 0, 0, 
00056                         x_width-1, y_width-1, Background);
00057 #endif
00058 }
00059 
00060 
00061 void ChangeColor(gdImagePtr imagep,int x1,int y1,int x2,int y2,int color1,int color2)
00062 /* In the given rectangle, change color1 to color2 */
00063 {
00064   int x,y;
00065   for( y=y1; y<=y2; y++) {
00066     for( x=x1; x<=x2; x++) {
00067       if (gdImageGetPixel(imagep, x, y)==color1) 
00068        gdImageSetPixel(imagep, x, y, color2);
00069     }
00070   }
00071 }
00072 
00073 void WriteImage(char *pngname, int pagenum)
00074 {
00075   char* pos;
00076   FILE* outfp=NULL;
00077 
00078   /* Transparent border */
00079   if (borderwidth>0) {
00080     int Transparent,bgcolor;
00081     pixels x_width,y_width;
00082 
00083     x_width=gdImageSX(page_imagep);
00084     y_width=gdImageSY(page_imagep);
00085     
00086     bgcolor = gdImageColorResolve(page_imagep,
00087                               cstack[0].red,cstack[0].green,cstack[0].blue);
00088     /* Set ANOTHER bg color, transparent this time */
00089     if (userbordercolor)
00090       Transparent = gdImageColorAllocate(page_imagep,
00091                                     bordercolor.red,bordercolor.green,bordercolor.blue); 
00092     else
00093       Transparent = gdImageColorAllocate(page_imagep,
00094                                     cstack[0].red,cstack[0].green,cstack[0].blue); 
00095     gdImageColorTransparent(page_imagep,Transparent); 
00096     ChangeColor(page_imagep,0,0,x_width-1,borderwidth-1,bgcolor,Transparent);
00097     ChangeColor(page_imagep,0,0,borderwidth-1,y_width-1,bgcolor,Transparent);
00098     ChangeColor(page_imagep,x_width-borderwidth,0,x_width-1,y_width-1,bgcolor,Transparent);
00099     ChangeColor(page_imagep,0,y_width-borderwidth,x_width-1,y_width-1,bgcolor,Transparent);
00100   }
00101 
00102   if ((pos=strchr(pngname,'%')) != NULL) {
00103     if (strchr(++pos,'%'))
00104       Fatal("too many %%'s in output file name");
00105     if (*pos == 'd' 
00106        || (*pos=='0' && pos[1]>='1' && pos[1]<='9' && pos[2]=='d')) {
00107       /* %d -> pagenumber, so add 9 string positions 
00108         since pagenumber max +-2^31 or +-2*10^9 */
00109       char* tempname = alloca(strlen(pngname)+9);
00110       sprintf(tempname,pngname,pagenum);
00111       pngname = tempname;
00112     } else {
00113       Fatal("unacceptible format spec. in output file name");
00114     }
00115   }
00116 #ifdef HAVE_GDIMAGEGIF
00117   if (flags & GIF_OUTPUT && (pos=strrchr(pngname,'.')) != NULL 
00118       && strcmp(pos,".png")==0) {
00119     *(pos+1)='g';
00120     *(pos+2)='i';
00121     *(pos+3)='f';
00122   }
00123 #endif
00124   if ((outfp = fopen(pngname,"wb")) == NULL)
00125       Fatal("Cannot open output file %s",pngname);
00126 #ifdef HAVE_GDIMAGEGIF
00127   if (flags & GIF_OUTPUT) 
00128     gdImageGif(page_imagep,outfp);
00129   else
00130 #endif
00131 #ifdef HAVE_GDIMAGEPNGEX
00132   gdImagePngEx(page_imagep,outfp,compression);
00133 #else
00134   gdImagePng(page_imagep,outfp);
00135 #endif
00136   fclose(outfp);
00137   DEBUG_PRINT(DEBUG_DVI,("\n  WROTE:   \t%s\n",pngname));
00138   DestroyImage();
00139 }
00140 
00141 void DestroyImage(void)
00142 {
00143   gdImageDestroy(page_imagep);
00144   page_imagep=NULL;
00145 }
00146 
00147 static int gammatable[]=
00148   {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,
00149    20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,
00150    40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,
00151    60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
00152    80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,
00153    100,101,102,103,104,105,106,107,108,109,
00154    110,111,112,113,114,115,116,117,118,119,
00155    120,121,122,123,124,125,126,127,128,129,
00156    130,131,132,133,134,135,136,137,138,139,
00157    140,141,142,143,144,145,146,147,148,149,
00158    150,151,152,153,154,155,156,157,158,159,
00159    160,161,162,163,164,165,166,167,168,169,
00160    170,171,172,173,174,175,176,177,178,179,
00161    180,181,182,183,184,185,186,187,188,189,
00162    190,191,192,193,194,195,196,197,198,199,
00163    200,201,202,203,204,205,206,207,208,209,
00164    210,211,212,213,214,215,216,217,218,219,
00165    220,221,222,223,224,225,226,227,228,229,
00166    230,231,232,233,234,235,236,237,238,239,
00167    240,241,242,243,244,245,246,247,248,249,
00168    250,251,252,253,254,255};
00169 
00170 void Gamma(double gamma)
00171 {
00172   int i=0;
00173   
00174   while (i<=255) {
00175     gammatable[i]=255-(int)(pow((double)(255-i)/255.0,gamma)*255);
00176     DEBUG_PRINT(DEBUG_GLYPH,("\n  GAMMA GREYSCALE: %d -> %d ",i,gammatable[i]));
00177     i++;
00178   }
00179 }
00180 
00181 
00182 #define GREYS 255
00183 dviunits SetGlyph(int32_t c, int32_t hh,int32_t vv)
00184 {
00185   register struct char_entry *ptr = currentfont->chr[c];
00186                                       /* temporary char_entry pointer */
00187   int red,green,blue;
00188   int *Color=alloca(sizeof(int)*(GREYS+1));
00189   int x,y;
00190   int pos=0;
00191   int bgColor,pixelgrey,pixelcolor;
00192   hh -= ptr->xOffset/shrinkfactor;
00193   vv -= ptr->yOffset/shrinkfactor;
00194   
00195   Color[0] = gdImageColorResolve(page_imagep,
00196                              cstack[0].red,cstack[0].green,cstack[0].blue);
00197   for( x=1; x<=GREYS ; x++) 
00198     Color[x] = -1;
00199   for( y=0; y<ptr->h; y++) {
00200     for( x=0; x<ptr->w; x++) {
00201       if (ptr->data[pos]>0) {
00202        pixelgrey=gammatable[(int)ptr->data[pos]];
00203        DEBUG_PRINT(DEBUG_GLYPH,("\n  GAMMA GREYSCALE: %d -> %d ",ptr->data[pos],pixelgrey));
00204        bgColor = gdImageGetPixel(page_imagep, hh + x, vv + y);
00205        if (bgColor == Color[0]) {
00206          /* Standard background: use cached value if present */
00207          pixelcolor=Color[pixelgrey];
00208          if (pixelcolor==-1) {
00209            red = cstack[0].red 
00210              - (cstack[0].red-cstack[csp].red)*pixelgrey/GREYS;
00211            green = cstack[0].green
00212              - (cstack[0].green-cstack[csp].green)*pixelgrey/GREYS;
00213            blue = cstack[0].blue
00214              - (cstack[0].blue-cstack[csp].blue)*pixelgrey/GREYS;
00215            Color[pixelgrey] = 
00216              gdImageColorResolve(page_imagep,red,green,blue);
00217            pixelcolor=Color[pixelgrey];
00218          }
00219        } else {
00220          /* Overstrike: No cache */
00221          red=gdImageRed(page_imagep, bgColor);
00222          green=gdImageGreen(page_imagep, bgColor);
00223          blue=gdImageBlue(page_imagep, bgColor);
00224          red = red-(red-cstack[csp].red)*pixelgrey/GREYS;
00225          green = green-(green-cstack[csp].green)*pixelgrey/GREYS;
00226          blue = blue-(blue-cstack[csp].blue)*pixelgrey/GREYS;
00227          pixelcolor = gdImageColorResolve(page_imagep, red, green, blue);
00228        }
00229        gdImageSetPixel(page_imagep, hh + x, vv + y, pixelcolor);
00230       }
00231       pos++;
00232     }
00233   }
00234   /* This code saved _no_ execution time, strangely.
00235    * Also, it cannot gamma correct; needs that in loaded glyphs
00236    *
00237    * #ifdef HAVE_GDIMAGECREATETRUECOLOR 
00238    *   if (truecolor) 
00239    *     for( i=1; i<=ptr->glyph.nchars ; i++) {
00240    *       Color = gdImageColorResolveAlpha(page_imagep,Red,Green,Blue,
00241    *                                        128-128*i/ptr->glyph.nchars);
00242    *       gdImageChar(page_imagep, &(ptr->glyph),
00243    *                  hh - ptr->xOffset/shrinkfactor,
00244    *                 vv - ptr->yOffset/shrinkfactor,
00245    *                 i,Color);
00246    *       }
00247    *    else {
00248    *  #endif */
00249   return(ptr->tfmw);
00250 }
00251 
00252 dviunits SetRule(dviunits a, dviunits b, subpixels hh,subpixels vv)
00253 {
00254   /*                               This routine will draw a \rule */
00255   int Color;
00256   pixels    width=0, height=0;
00257 
00258   if ( a > 0 && b > 0 ) {
00259     /* Calculate width and height, round up */
00260     width = (b+dvi->conv*shrinkfactor-1)/dvi->conv/shrinkfactor;
00261     height = (a+dvi->conv*shrinkfactor-1)/dvi->conv/shrinkfactor;
00262   }
00263   if (page_imagep != NULL) {
00264     if ((height>0) && (width>0)) {
00265       /* This code produces too dark rules. But what the hell. Grey
00266        * rules look fuzzy. */
00267       Color = gdImageColorResolve(page_imagep, 
00268                               cstack[csp].red,
00269                               cstack[csp].green,
00270                               cstack[csp].blue);
00271       /* +1 and -1 are because the Rectangle coords include last pixels */
00272       gdImageFilledRectangle(page_imagep,hh,vv-height+1,hh+width-1,vv,Color);
00273       DEBUG_PRINT(DEBUG_DVI,("\n  RULE \t%dx%d at (%d,%d)",
00274                  width, height, hh, vv));
00275     }
00276   } else {
00277     /* The +1's are because things are cut _at_that_coordinate_. */
00278     min(x_min,hh);
00279     min(y_min,vv-height+1);
00280     max(x_max,hh+width);
00281     max(y_max,vv+1);
00282   }
00283   return(b);
00284 }
00285 
00286 
00287 #if 0
00288   if (page_imagep != NULL) {
00289     if ((a>0) && (b>0)) {
00290       int width,height,left=-1,right=-1,bottom=-1,top=-1;
00291       gdImagePtr rule;
00292       
00293 
00294       width  = (h+b+dvi->conv*shrinkfactor-1)/dvi->conv/shrinkfactor
00295        - h/dvi->conv/shrinkfactor;
00296       /* Calculate height, round up on the bottom and down on the top */
00297       height = (v+dvi->conv*shrinkfactor-1)/dvi->conv/shrinkfactor
00298        - (v-a)/dvi->conv/shrinkfactor;
00299       rule = gdImageCreate(width,height);
00300       /* Set background */
00301       gdImageColorAllocate(rule,Red,Green,Blue);
00302       
00303       /* Calculate blackness of edges of wide rule */
00304       left   = shrinkfactor - h/dvi->conv%shrinkfactor;
00305       right  = (h+b+dvi->conv-1)/dvi->conv%shrinkfactor;
00306       if (right==0)  right  = shrinkfactor;
00307       if (width==1) {
00308        /* Adjust blackness of narrow rule */
00309        left = shrinkfactor;
00310        /* The (correct) alternative produces "fuzzy" tables */ 
00311        /* left = ((h+b+dvi->conv-1)/dvi->conv - h/dvi->conv)%shrinkfactor;
00312         */
00313       } 
00314       if (width==2 && right+left <= shrinkfactor +1) {
00315        /* Adjust blackness of narrow rule when spread across two columns */
00316        /* Cheat to make it sharp (+1 above, and wedging it around below) */
00317        if (right>left) { right=shrinkfactor; left=0; }
00318        if (right<left) { left=shrinkfactor; right=0; }
00319        if (right==left) { left=right=(shrinkfactor+1)/2; }
00320       }
00321 
00322       /* Calculate blackness of edges of tall rule */
00323       bottom = (v+dvi->conv-1)/dvi->conv%shrinkfactor;
00324       if (bottom==0) bottom = shrinkfactor;
00325       top    = shrinkfactor-(v-a)/dvi->conv%shrinkfactor;
00326       if (height == 1) {
00327        /* Adjust blackness of short rule */
00328        bottom = shrinkfactor;
00329        /* The (correct) alternative produces "fuzzy" tables */ 
00330        /* bottom = ((v+dvi->conv-1)/dvi->conv - (v-a)/dvi->conv)%shrinkfactor;
00331         */
00332       } 
00333       if (height==2 && top+bottom <= shrinkfactor +1) {
00334        /* Adjust blackness of short rule when spread across two columns */
00335        /* Cheat to make it sharp (+1 above, and wedging it around below) */
00336        if (top>bottom) { top=shrinkfactor; bottom=0; }
00337        if (top<bottom) { bottom=shrinkfactor; top=0; }
00338        if (right==left) { left=right=(shrinkfactor+1)/2; }
00339       }
00340        
00341       Color = gdImageColorResolve(rule,
00342                 bRed-(bRed-Red)*left*bottom/shrinkfactor/shrinkfactor,
00343                 bGreen-(bGreen-Green)*left*bottom/shrinkfactor/shrinkfactor,
00344                 bBlue-(bBlue-Blue)*left*bottom/shrinkfactor/shrinkfactor);
00345       gdImageSetPixel(rule,0,height-1,Color);
00346       if (width>1) {
00347        Color = gdImageColorResolve(rule, 
00348                 bRed-(bRed-Red)*right*bottom/shrinkfactor/shrinkfactor,
00349                 bGreen-(bGreen-Green)*right*bottom/shrinkfactor/shrinkfactor,
00350                 bBlue-(bBlue-Blue)*right*bottom/shrinkfactor/shrinkfactor);
00351        gdImageSetPixel(rule,width-1,height-1,Color);
00352       }
00353       if (height>1) {
00354        Color = gdImageColorResolve(rule, 
00355                          bRed-(bRed-Red)*left*top/shrinkfactor/shrinkfactor,
00356                   bGreen-(bGreen-Green)*left*top/shrinkfactor/shrinkfactor,
00357                   bBlue-(bBlue-Blue)*left*top/shrinkfactor/shrinkfactor);
00358        gdImageSetPixel(rule,0,0,Color);
00359       }
00360       if (height>1 && width>1) {
00361        Color = gdImageColorResolve(rule, 
00362                   bRed-(bRed-Red)*right*top/shrinkfactor/shrinkfactor,
00363                   bGreen-(bGreen-Green)*right*top/shrinkfactor/shrinkfactor,
00364                   bBlue-(bBlue-Blue)*right*top/shrinkfactor/shrinkfactor);
00365        gdImageSetPixel(rule,width-1,0,Color);
00366       }
00367 
00368       if (width>2) {
00369        Color = gdImageColorResolve(rule, 
00370                                 bRed-(bRed-Red)*bottom/shrinkfactor,
00371                                 bGreen-(bGreen-Green)*bottom/shrinkfactor,
00372                                 bBlue-(bBlue-Blue)*bottom/shrinkfactor);
00373        gdImageFilledRectangle(rule,1,height-1,width-2,height-1,Color);
00374       }
00375       if (height>2) {
00376        Color = gdImageColorResolve(rule, 
00377                                 bRed-(bRed-Red)*left/shrinkfactor,
00378                                 bGreen-(bGreen-Green)*left/shrinkfactor,
00379                                 bBlue-(bBlue-Blue)*left/shrinkfactor);
00380        gdImageFilledRectangle(rule,0,1,0,height-2,Color);
00381       }
00382       if (height>1 && width>2) {
00383        Color = gdImageColorResolve(rule, 
00384                                 bRed-(bRed-Red)*top/shrinkfactor,
00385                                 bGreen-(bGreen-Green)*top/shrinkfactor,
00386                                 bBlue-(bBlue-Blue)*top/shrinkfactor);
00387        gdImageFilledRectangle(rule,1,0,width-2,0,Color);
00388       }
00389       if (height>2 && width>1) {
00390        Color = gdImageColorResolve(rule, 
00391                                 bRed-(bRed-Red)*right/shrinkfactor,
00392                                 bGreen-(bGreen-Green)*right/shrinkfactor,
00393                                 bBlue-(bBlue-Blue)*right/shrinkfactor);
00394        gdImageFilledRectangle(rule,width-1,1,width-1,height-2,Color);
00395       }
00396       gdImageCopy(page_imagep,rule,
00397                 h/dvi->conv/shrinkfactor,
00398                 (v-a)/dvi->conv/shrinkfactor,
00399                 0,0,width,height);
00400       DEBUG_PRINT(DEBUG_DVI,("\n  RULE \t%dx%d at (%d,%d)",
00401                  width,height,
00402                  PIXROUND(h, dvi->conv*shrinkfactor),
00403                  PIXROUND(v, dvi->conv*shrinkfactor)));
00404       DEBUG_PRINT(DEBUG_DVI,(" (lrtb %d %d %d %d)",left,right,top,bottom));
00405     }
00406   } else {
00407     min(x_min,hh);
00408     min(y_min,vv-height+1);
00409     max(x_max,hh+width);
00410     max(y_max,vv+1);
00411   }
00412 #endif
00413 
00414