summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipng/set.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipng/set.c')
-rw-r--r--Build/source/texk/dvipng/set.c423
1 files changed, 108 insertions, 315 deletions
diff --git a/Build/source/texk/dvipng/set.c b/Build/source/texk/dvipng/set.c
index 1b73930a1fe..a6fa3945e49 100644
--- a/Build/source/texk/dvipng/set.c
+++ b/Build/source/texk/dvipng/set.c
@@ -19,7 +19,7 @@
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
02111-1307, USA.
- Copyright (C) 2002-2005 Jan-Åke Larsson
+ Copyright (C) 2002-2006 Jan-Åke Larsson
************************************************************************/
@@ -29,62 +29,62 @@
#endif
#include <math.h>
+#ifndef HAVE_GDIMAGECREATETRUECOLOR
+#define gdImageColorAllocateAlpha(i,r,g,b,a) gdImageColorAllocate(i,r,g,b)
+#define gdImageColorResolveAlpha(i,r,g,b,a) gdImageColorResolve(i,r,g,b)
+#define gdImageAlpha(i,c) 0
+#define gdAlphaMax 127
+#endif
+#ifndef HAVE_GDIMAGEPNGEX
+#define gdImagePngEX(i,f,z) gdImagePng(i,f)
+#endif
+
+/* Persistent color cache. Index is ink thickness,
+ 0=no ink, 127=total coverage */
+static int ColorCache[gdAlphaMax+1];
+
void CreateImage(pixels x_width,pixels y_width)
{
- int Background;
-
if (page_imagep)
gdImageDestroy(page_imagep);
if (x_width <= 0) x_width=1;
if (y_width <= 0) y_width=1;
#ifdef HAVE_GDIMAGECREATETRUECOLOR
- if (flags & RENDER_TRUECOLOR)
+ /* GIFs are 256-color */
+ if (flags & (FORCE_TRUECOLOR|PAGE_TRUECOLOR) && ~flags & GIF_OUTPUT
+ && ~flags & FORCE_PALETTE)
page_imagep=gdImageCreateTrueColor(x_width,y_width);
else
#endif
page_imagep=gdImageCreate(x_width,y_width);
- /* Set bg color */
-#ifdef HAVE_GDIMAGECOLORRESOLVEALPHA
- if (flags & BG_TRANSPARENT_ALPHA
-#ifdef HAVE_GDIMAGEGIF
- /* GIFs cannot handle an alpha channel, resort to transparent
- color index */
- && ~flags & GIF_OUTPUT
-#endif /* HAVE_GDIMAGEGIF */
- ) {
- Background = gdImageColorAllocateAlpha(page_imagep,
- cstack[0].red,
- cstack[0].green,
- cstack[0].blue,127);
-#ifdef HAVE_GDIMAGEALPHABLENDING
- /* Draw without blending to allow the background of the _viewer_
- to shine through. Color blending is calculated where needed. */
- gdImageAlphaBlending(page_imagep, 0);
- gdImageSaveAlpha(page_imagep, 1);
-#endif
- }
- else
-#endif /* HAVE_GDIMAGECOLORRESOLVEALPHA */
- {
- Background = gdImageColorAllocate(page_imagep,
- cstack[0].red,
- cstack[0].green,
- cstack[0].blue);
- /* maybe alpha is not available or perhaps we are producing
- GIFs, so test for BG_TRANSPARENT_ALPHA too */
- if (flags & (BG_TRANSPARENT|BG_TRANSPARENT_ALPHA))
- gdImageColorTransparent(page_imagep,Background);
- }
+ /* Set bg color. GIFs cannot handle an alpha channel, resort to
+ transparent color index, set in WriteImage */
+ ColorCache[0]
+ = gdImageColorAllocateAlpha(page_imagep,
+ cstack[0].red,
+ cstack[0].green,
+ cstack[0].blue,
+ (flags & BG_TRANSPARENT_ALPHA
+ && ~flags & GIF_OUTPUT) ? 127 : 0);
+ ColorCache[gdAlphaMax]=-1;
#ifdef HAVE_GDIMAGECREATETRUECOLOR
- if (flags & RENDER_TRUECOLOR)
+ /* Alpha blending in libgd is only performed for truecolor images.
+ We need it for palette images also. Turn libgd alpha blending off
+ and calculate color blending where needed. We turn it back on
+ briefly for image inclusion. */
+ gdImageAlphaBlending(page_imagep, 0);
+ if (flags & BG_TRANSPARENT_ALPHA)
+ gdImageSaveAlpha(page_imagep, 1);
+ if (page_imagep->trueColor)
/* Truecolor: there is no background color index, fill image instead. */
gdImageFilledRectangle(page_imagep, 0, 0,
- x_width-1, y_width-1, Background);
+ x_width-1, y_width-1, ColorCache[0]);
#endif
}
-void ChangeColor(gdImagePtr imagep,int x1,int y1,int x2,int y2,int color1,int color2)
+void ChangeColor(gdImagePtr imagep,int x1,int y1,
+ int x2,int y2,int color1,int color2)
/* In the given rectangle, change color1 to color2 */
{
int x,y;
@@ -101,30 +101,41 @@ void WriteImage(char *pngname, int pagenum)
char* pos;
FILE* outfp=NULL;
+ /* Set transparent background. Maybe alpha is not available or
+ perhaps we are producing GIFs, so test for BG_TRANSPARENT_ALPHA
+ too */
+ if (flags & (BG_TRANSPARENT|BG_TRANSPARENT_ALPHA))
+ gdImageColorTransparent(page_imagep,ColorCache[0]);
/* Transparent border */
if (borderwidth>0) {
- int Transparent,bgcolor;
+ int Transparent;
pixels x_width,y_width;
x_width=gdImageSX(page_imagep);
y_width=gdImageSY(page_imagep);
- bgcolor = gdImageColorResolve(page_imagep,
- cstack[0].red,cstack[0].green,cstack[0].blue);
/* Set ANOTHER bg color, transparent this time */
/* No semi-transparency here, given the motivation for this code
* (box cursor visibility in Emacs) */
if (userbordercolor)
Transparent = gdImageColorAllocate(page_imagep,
- bordercolor.red,bordercolor.green,bordercolor.blue);
+ bordercolor.red,
+ bordercolor.green,
+ bordercolor.blue);
else
Transparent = gdImageColorAllocate(page_imagep,
- cstack[0].red,cstack[0].green,cstack[0].blue);
+ gdImageRed(page_imagep,ColorCache[0]),
+ gdImageGreen(page_imagep,ColorCache[0]),
+ gdImageBlue(page_imagep,ColorCache[0]));
gdImageColorTransparent(page_imagep,Transparent);
- ChangeColor(page_imagep,0,0,x_width-1,borderwidth-1,bgcolor,Transparent);
- ChangeColor(page_imagep,0,0,borderwidth-1,y_width-1,bgcolor,Transparent);
- ChangeColor(page_imagep,x_width-borderwidth,0,x_width-1,y_width-1,bgcolor,Transparent);
- ChangeColor(page_imagep,0,y_width-borderwidth,x_width-1,y_width-1,bgcolor,Transparent);
+ ChangeColor(page_imagep,0,0,x_width-1,borderwidth-1,
+ ColorCache[0],Transparent);
+ ChangeColor(page_imagep,0,0,borderwidth-1,y_width-1,
+ ColorCache[0],Transparent);
+ ChangeColor(page_imagep,x_width-borderwidth,0,x_width-1,y_width-1,
+ ColorCache[0],Transparent);
+ ChangeColor(page_imagep,0,y_width-borderwidth,x_width-1,y_width-1,
+ ColorCache[0],Transparent);
}
if ((pos=strchr(pngname,'%')) != NULL) {
@@ -156,11 +167,7 @@ void WriteImage(char *pngname, int pagenum)
gdImageGif(page_imagep,outfp);
else
#endif
-#ifdef HAVE_GDIMAGEPNGEX
- gdImagePngEx(page_imagep,outfp,compression);
-#else
- gdImagePng(page_imagep,outfp);
-#endif
+ gdImagePngEx(page_imagep,outfp,compression);
fclose(outfp);
DEBUG_PRINT(DEBUG_DVI,("\n WROTE: \t%s\n",pngname));
DestroyImage();
@@ -180,155 +187,71 @@ static int gammatable[]=
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,241,242,243,244,245,246,247,248,249,
- 250,251,252,253,254,255};
+ 120,121,122,123,124,125,126,127};
void Gamma(double gamma)
{
int i=0;
- while (i<=255) {
- gammatable[i]=255-(int)(pow((double)(255-i)/255.0,gamma)*255);
- DEBUG_PRINT(DEBUG_GLYPH,("\n GAMMA GREYSCALE: %d -> %d ",i,gammatable[i]));
+ while (i<=gdAlphaMax) {
+ gammatable[i]=gdAlphaMax-
+ (int)(pow((gdAlphaMax-i)/((double)gdAlphaMax),gamma)*gdAlphaMax);
+ DEBUG_PRINT(DEBUG_GLYPH,
+ ("\n GAMMA GREYSCALE: %d -> %d ",i,gammatable[i]));
i++;
}
}
-
-#define GREYS 255
dviunits SetGlyph(int32_t c, int32_t hh,int32_t vv)
+/* gdImageChar can only do monochrome glyphs */
{
register struct char_entry *ptr = currentfont->chr[c];
- /* temporary char_entry pointer */
- int red,green,blue;
- int *Color=alloca(sizeof(int)*(GREYS+1));
- int x,y;
- int pos=0;
+ int dst_alpha,dst_weight,tot_weight,alpha;
+ int x,y,pos=0;
int bgColor,pixelgrey,pixelcolor;
+
hh -= ptr->xOffset/shrinkfactor;
vv -= ptr->yOffset/shrinkfactor;
-
- for( x=1; x<=GREYS ; x++)
- Color[x] = -1;
-#ifdef HAVE_GDIMAGECOLORRESOLVEALPHA
- if (flags & BG_TRANSPARENT_ALPHA
-#ifdef HAVE_GDIMAGEGIF
- /* GIFs cannot handle an alpha channel, resort to transparent
- color index */
- && ~flags & GIF_OUTPUT
-#endif /* HAVE_GDIMAGEGIF */
- ) {
- int alpha;
- Color[0] = gdImageColorResolveAlpha(page_imagep,
- cstack[0].red,
- cstack[0].green,
- cstack[0].blue,127);
- for( y=0; y<ptr->h; y++) {
- for( x=0; x<ptr->w; x++) {
- if (ptr->data[pos]>0) {
- pixelgrey=gammatable[(int)ptr->data[pos]];
- bgColor = gdImageGetPixel(page_imagep, hh + x, vv + y);
- if (bgColor == Color[0]) {
- if (Color[pixelgrey]==-1) {
- DEBUG_PRINT(DEBUG_GLYPH,("\n GAMMA GREYSCALE: %d -> %d ",ptr->data[pos],pixelgrey));
- /* Standard background: use cached value if present */
- /* 127-alpha/2: 0=opaque,127=full_trans */
- Color[pixelgrey]=gdImageColorResolveAlpha(page_imagep,
- cstack[csp].red,
- cstack[csp].green,
- cstack[csp].blue,
- 127-pixelgrey/2);
- }
- pixelcolor=Color[pixelgrey];
- } else {
- /* Overstrike: No cache */
- red =gdImageRed(page_imagep, bgColor);
- green=gdImageGreen(page_imagep, bgColor);
- blue =gdImageBlue(page_imagep, bgColor);
- alpha=255-2*gdImageAlpha(page_imagep, bgColor);
- red =red-(red-cstack[csp].red)*pixelgrey/GREYS;
- green=green-(green-cstack[csp].green)*pixelgrey/GREYS;
- blue =blue-(blue-cstack[csp].blue)*pixelgrey/GREYS;
- /* 255=opaque */
- alpha=alpha-(alpha-255)*pixelgrey/GREYS;
- /* 127-alpha/2: 0=opaque,127=full_trans */
- pixelcolor = gdImageColorResolveAlpha(page_imagep,
- red,green,blue,127-alpha/2);
- }
- gdImageSetPixel(page_imagep, hh + x, vv + y, pixelcolor);
- }
- pos++;
- }
- }
- } else
-#endif /* HAVE_GDIMAGECOLORRESOLVEALPHA */
- {
- Color[0] = gdImageColorResolve(page_imagep,
- cstack[0].red,
- cstack[0].green,
- cstack[0].blue);
- for( y=0; y<ptr->h; y++) {
- for( x=0; x<ptr->w; x++) {
- if (ptr->data[pos]>0) {
- pixelgrey=gammatable[(int)ptr->data[pos]];
- bgColor = gdImageGetPixel(page_imagep, hh + x, vv + y);
- if (bgColor == Color[0]) {
- /* Standard background: use cached value if present */
- if (Color[pixelgrey]==-1) {
- DEBUG_PRINT(DEBUG_GLYPH,("\n GAMMA GREYSCALE: %d -> %d ",ptr->data[pos],pixelgrey));
- red = cstack[0].red
- - (cstack[0].red-cstack[csp].red)*pixelgrey/GREYS;
- green = cstack[0].green
- - (cstack[0].green-cstack[csp].green)*pixelgrey/GREYS;
- blue = cstack[0].blue
- - (cstack[0].blue-cstack[csp].blue)*pixelgrey/GREYS;
- Color[pixelgrey] =
- gdImageColorResolve(page_imagep,red,green,blue);
- }
- pixelcolor=Color[pixelgrey];
- } else {
- /* Overstrike: No cache */
- red=gdImageRed(page_imagep, bgColor);
- green=gdImageGreen(page_imagep, bgColor);
- blue=gdImageBlue(page_imagep, bgColor);
- red = red-(red-cstack[csp].red)*pixelgrey/GREYS;
- green = green-(green-cstack[csp].green)*pixelgrey/GREYS;
- blue = blue-(blue-cstack[csp].blue)*pixelgrey/GREYS;
- pixelcolor = gdImageColorResolve(page_imagep, red, green, blue);
- }
- gdImageSetPixel(page_imagep, hh + x, vv + y, pixelcolor);
- }
- pos++;
- }
+ /* Initialize persistent color cache. Perhaps this should be in
+ color.c? */
+ pixelcolor=gdImageColorResolve(page_imagep,
+ cstack[csp].red,
+ cstack[csp].green,
+ cstack[csp].blue);
+ if (ColorCache[gdAlphaMax]!=pixelcolor) {
+ for( x=1; x<gdAlphaMax; x++ )
+ ColorCache[x]=-1;
+ ColorCache[gdAlphaMax]=pixelcolor;
+ }
+ for( y=0; y<ptr->h; y++) {
+ for( x=0; x<ptr->w; x++) {
+ if (ptr->data[pos]>0) {
+ pixelgrey=gammatable[(int)ptr->data[pos]/2];
+ bgColor = gdImageGetPixel(page_imagep, hh + x, vv + y);
+ if (ColorCache[0]!=bgColor || ColorCache[pixelgrey]==-1) {
+ DEBUG_PRINT(DEBUG_GLYPH,("\n GAMMA GREYSCALE: %d -> %d ",
+ ptr->data[pos]/2,pixelgrey));
+ alpha = gdAlphaMax-pixelgrey;
+ dst_alpha = gdImageAlpha(page_imagep,bgColor);
+ dst_weight = (gdAlphaMax - dst_alpha) * alpha / gdAlphaMax;
+ tot_weight = pixelgrey + dst_weight;
+ pixelcolor = gdImageColorResolveAlpha(page_imagep,
+ (cstack[csp].red*pixelgrey
+ + gdImageRed(page_imagep,bgColor)*dst_weight)/tot_weight,
+ (cstack[csp].green*pixelgrey
+ + gdImageGreen(page_imagep,bgColor)*dst_weight)/tot_weight,
+ (cstack[csp].blue*pixelgrey
+ + gdImageBlue(page_imagep,bgColor)*dst_weight)/tot_weight,
+ alpha*dst_alpha/gdAlphaMax);
+ if (ColorCache[0]==bgColor)
+ ColorCache[pixelgrey]=pixelcolor;
+ } else
+ pixelcolor=ColorCache[pixelgrey];
+ gdImageSetPixel(page_imagep, hh + x, vv + y, pixelcolor);
}
+ pos++;
}
- /* This code saved _no_ execution time, strangely.
- * Also, it cannot gamma correct; needs that in loaded glyphs
- *
- * #ifdef HAVE_GDIMAGECREATETRUECOLOR
- * if (truecolor)
- * for( i=1; i<=ptr->glyph.nchars ; i++) {
- * Color = gdImageColorResolveAlpha(page_imagep,Red,Green,Blue,
- * 128-128*i/ptr->glyph.nchars);
- * gdImageChar(page_imagep, &(ptr->glyph),
- * hh - ptr->xOffset/shrinkfactor,
- * vv - ptr->yOffset/shrinkfactor,
- * i,Color);
- * }
- * else {
- * #endif */
+ }
return(ptr->tfmw);
}
@@ -365,133 +288,3 @@ dviunits SetRule(dviunits a, dviunits b, subpixels hh,subpixels vv)
}
return(b);
}
-
-
-#if 0
- if (page_imagep != NULL) {
- if ((a>0) && (b>0)) {
- int width,height,left=-1,right=-1,bottom=-1,top=-1;
- gdImagePtr rule;
-
-
- width = (h+b+dvi->conv*shrinkfactor-1)/dvi->conv/shrinkfactor
- - h/dvi->conv/shrinkfactor;
- /* Calculate height, round up on the bottom and down on the top */
- height = (v+dvi->conv*shrinkfactor-1)/dvi->conv/shrinkfactor
- - (v-a)/dvi->conv/shrinkfactor;
- rule = gdImageCreate(width,height);
- /* Set background */
- gdImageColorAllocate(rule,Red,Green,Blue);
-
- /* Calculate blackness of edges of wide rule */
- left = shrinkfactor - h/dvi->conv%shrinkfactor;
- right = (h+b+dvi->conv-1)/dvi->conv%shrinkfactor;
- if (right==0) right = shrinkfactor;
- if (width==1) {
- /* Adjust blackness of narrow rule */
- left = shrinkfactor;
- /* The (correct) alternative produces "fuzzy" tables */
- /* left = ((h+b+dvi->conv-1)/dvi->conv - h/dvi->conv)%shrinkfactor;
- */
- }
- if (width==2 && right+left <= shrinkfactor +1) {
- /* Adjust blackness of narrow rule when spread across two columns */
- /* Cheat to make it sharp (+1 above, and wedging it around below) */
- if (right>left) { right=shrinkfactor; left=0; }
- if (right<left) { left=shrinkfactor; right=0; }
- if (right==left) { left=right=(shrinkfactor+1)/2; }
- }
-
- /* Calculate blackness of edges of tall rule */
- bottom = (v+dvi->conv-1)/dvi->conv%shrinkfactor;
- if (bottom==0) bottom = shrinkfactor;
- top = shrinkfactor-(v-a)/dvi->conv%shrinkfactor;
- if (height == 1) {
- /* Adjust blackness of short rule */
- bottom = shrinkfactor;
- /* The (correct) alternative produces "fuzzy" tables */
- /* bottom = ((v+dvi->conv-1)/dvi->conv - (v-a)/dvi->conv)%shrinkfactor;
- */
- }
- if (height==2 && top+bottom <= shrinkfactor +1) {
- /* Adjust blackness of short rule when spread across two columns */
- /* Cheat to make it sharp (+1 above, and wedging it around below) */
- if (top>bottom) { top=shrinkfactor; bottom=0; }
- if (top<bottom) { bottom=shrinkfactor; top=0; }
- if (right==left) { left=right=(shrinkfactor+1)/2; }
- }
-
- Color = gdImageColorResolve(rule,
- bRed-(bRed-Red)*left*bottom/shrinkfactor/shrinkfactor,
- bGreen-(bGreen-Green)*left*bottom/shrinkfactor/shrinkfactor,
- bBlue-(bBlue-Blue)*left*bottom/shrinkfactor/shrinkfactor);
- gdImageSetPixel(rule,0,height-1,Color);
- if (width>1) {
- Color = gdImageColorResolve(rule,
- bRed-(bRed-Red)*right*bottom/shrinkfactor/shrinkfactor,
- bGreen-(bGreen-Green)*right*bottom/shrinkfactor/shrinkfactor,
- bBlue-(bBlue-Blue)*right*bottom/shrinkfactor/shrinkfactor);
- gdImageSetPixel(rule,width-1,height-1,Color);
- }
- if (height>1) {
- Color = gdImageColorResolve(rule,
- bRed-(bRed-Red)*left*top/shrinkfactor/shrinkfactor,
- bGreen-(bGreen-Green)*left*top/shrinkfactor/shrinkfactor,
- bBlue-(bBlue-Blue)*left*top/shrinkfactor/shrinkfactor);
- gdImageSetPixel(rule,0,0,Color);
- }
- if (height>1 && width>1) {
- Color = gdImageColorResolve(rule,
- bRed-(bRed-Red)*right*top/shrinkfactor/shrinkfactor,
- bGreen-(bGreen-Green)*right*top/shrinkfactor/shrinkfactor,
- bBlue-(bBlue-Blue)*right*top/shrinkfactor/shrinkfactor);
- gdImageSetPixel(rule,width-1,0,Color);
- }
-
- if (width>2) {
- Color = gdImageColorResolve(rule,
- bRed-(bRed-Red)*bottom/shrinkfactor,
- bGreen-(bGreen-Green)*bottom/shrinkfactor,
- bBlue-(bBlue-Blue)*bottom/shrinkfactor);
- gdImageFilledRectangle(rule,1,height-1,width-2,height-1,Color);
- }
- if (height>2) {
- Color = gdImageColorResolve(rule,
- bRed-(bRed-Red)*left/shrinkfactor,
- bGreen-(bGreen-Green)*left/shrinkfactor,
- bBlue-(bBlue-Blue)*left/shrinkfactor);
- gdImageFilledRectangle(rule,0,1,0,height-2,Color);
- }
- if (height>1 && width>2) {
- Color = gdImageColorResolve(rule,
- bRed-(bRed-Red)*top/shrinkfactor,
- bGreen-(bGreen-Green)*top/shrinkfactor,
- bBlue-(bBlue-Blue)*top/shrinkfactor);
- gdImageFilledRectangle(rule,1,0,width-2,0,Color);
- }
- if (height>2 && width>1) {
- Color = gdImageColorResolve(rule,
- bRed-(bRed-Red)*right/shrinkfactor,
- bGreen-(bGreen-Green)*right/shrinkfactor,
- bBlue-(bBlue-Blue)*right/shrinkfactor);
- gdImageFilledRectangle(rule,width-1,1,width-1,height-2,Color);
- }
- gdImageCopy(page_imagep,rule,
- h/dvi->conv/shrinkfactor,
- (v-a)/dvi->conv/shrinkfactor,
- 0,0,width,height);
- DEBUG_PRINT(DEBUG_DVI,("\n RULE \t%dx%d at (%d,%d)",
- width,height,
- PIXROUND(h, dvi->conv*shrinkfactor),
- PIXROUND(v, dvi->conv*shrinkfactor)));
- DEBUG_PRINT(DEBUG_DVI,(" (lrtb %d %d %d %d)",left,right,top,bottom));
- }
- } else {
- min(x_min,hh);
- min(y_min,vv-height+1);
- max(x_max,hh+width);
- max(y_max,vv+1);
- }
-#endif
-
-