Splash.cc (xpdf-4.03) | : | Splash.cc (xpdf-4.04) | ||
---|---|---|---|---|
skipping to change at line 472 | skipping to change at line 472 | |||
// dynamic pattern | // dynamic pattern | |||
if (pipe->pattern) { | if (pipe->pattern) { | |||
pipe->pattern->getColor(x, y, pipe->cSrcVal); | pipe->pattern->getColor(x, y, pipe->cSrcVal); | |||
} | } | |||
cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy | cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy | |||
if (pipe->noTransparency && !state->blendFunc) { | if (pipe->noTransparency && !state->blendFunc) { | |||
//----- handle overprint | ||||
if (overprintMaskPtr) { | ||||
*overprintMaskPtr++ = 0xffffffff; | ||||
} | ||||
//----- result color | //----- result color | |||
switch (bitmap->mode) { | switch (bitmap->mode) { | |||
case splashModeMono1: | case splashModeMono1: | |||
case splashModeMono8: | case splashModeMono8: | |||
cResult0 = state->grayTransfer[cSrcPtr[0]]; | cResult0 = state->grayTransfer[cSrcPtr[0]]; | |||
break; | break; | |||
case splashModeRGB8: | case splashModeRGB8: | |||
case splashModeBGR8: | case splashModeBGR8: | |||
cResult0 = state->rgbTransferR[cSrcPtr[0]]; | cResult0 = state->rgbTransferR[cSrcPtr[0]]; | |||
skipping to change at line 653 | skipping to change at line 659 | |||
} else { | } else { | |||
aSrc = pipe->aInput; | aSrc = pipe->aInput; | |||
} | } | |||
//----- non-isolated group correction | //----- non-isolated group correction | |||
if (pipe->nonIsolatedGroup) { | if (pipe->nonIsolatedGroup) { | |||
// This path is only used when Splash::composite() is called to | // This path is only used when Splash::composite() is called to | |||
// composite a non-isolated group onto the backdrop. In this | // composite a non-isolated group onto the backdrop. In this | |||
// case, shape is the source (group) alpha. | // case, shape is the source (group) alpha. | |||
t = (aDest * 255) / shape - aDest; | // | |||
// In a nested non-isolated group, i.e., if the destination is | ||||
// also a non-isolated group (state->inNonIsolatedGroup), we | ||||
// need to compute the corrected alpha, because the | ||||
// destination is is storing group alpha (same computation as | ||||
// blitCorrectedAlpha). | ||||
if (alpha0Ptr) { | ||||
t = *alpha0Ptr; | ||||
t = (Guchar)(aDest + t - div255(aDest * t)); | ||||
} else { | ||||
t = aDest; | ||||
} | ||||
t = (t * 255) / shape - t; | ||||
switch (bitmap->mode) { | switch (bitmap->mode) { | |||
#if SPLASH_CMYK | #if SPLASH_CMYK | |||
case splashModeCMYK8: | case splashModeCMYK8: | |||
cSrc[3] = clip255(cSrc[3] + ((cSrc[3] - cDest[3]) * t) / 255); | cSrc[3] = clip255(cSrc[3] + ((cSrc[3] - cDest[3]) * t) / 255); | |||
#endif | #endif | |||
case splashModeRGB8: | case splashModeRGB8: | |||
case splashModeBGR8: | case splashModeBGR8: | |||
cSrc[2] = clip255(cSrc[2] + ((cSrc[2] - cDest[2]) * t) / 255); | cSrc[2] = clip255(cSrc[2] + ((cSrc[2] - cDest[2]) * t) / 255); | |||
cSrc[1] = clip255(cSrc[1] + ((cSrc[1] - cDest[1]) * t) / 255); | cSrc[1] = clip255(cSrc[1] + ((cSrc[1] - cDest[1]) * t) / 255); | |||
case splashModeMono1: | case splashModeMono1: | |||
skipping to change at line 3914 | skipping to change at line 3932 | |||
} | } | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
// ImageMaskScaler | // ImageMaskScaler | |||
//------------------------------------------------------------------------ | //------------------------------------------------------------------------ | |||
class ImageMaskScaler { | class ImageMaskScaler { | |||
public: | public: | |||
// Set up a MaskScaler to scale from [srcWidth]x[srcHeight] to | // Set up a MaskScaler to scale from [srcWidth]x[srcHeight] to | |||
// [scaledWidth]x[scaledHeight]. | // [scaledWidth]x[scaledHeight]. The [interpolate] flag controls | |||
// filtering on upsampling, and the [antialias] flag controls | ||||
// filtering on downsampling. | ||||
ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData, | ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData, | |||
int aSrcWidth, int aSrcHeight, | int aSrcWidth, int aSrcHeight, | |||
int aScaledWidth, int aScaledHeight, GBool aInterpolate); | int aScaledWidth, int aScaledHeight, | |||
GBool aInterpolate, GBool aAntialias); | ||||
~ImageMaskScaler(); | ~ImageMaskScaler(); | |||
// Compute the next line of the scaled image mask. This can be | // Compute the next line of the scaled image mask. This can be | |||
// called up to [scaledHeight] times. | // called up to [scaledHeight] times. | |||
void nextLine(); | void nextLine(); | |||
// Retrieve the data generated by the most recent call to | // Retrieve the data generated by the most recent call to | |||
// nextLine(). | // nextLine(). | |||
Guchar *data() { return line; } | Guchar *data() { return line; } | |||
private: | private: | |||
void vertDownscaleHorizDownscale(); | void vertDownscaleHorizDownscale(); | |||
void vertDownscaleHorizDownscaleThresh(); | ||||
void vertDownscaleHorizUpscaleNoInterp(); | void vertDownscaleHorizUpscaleNoInterp(); | |||
void vertDownscaleHorizUpscaleInterp(); | void vertDownscaleHorizUpscaleInterp(); | |||
void vertDownscaleHorizUpscaleThresh(); | ||||
void vertUpscaleHorizDownscaleNoInterp(); | void vertUpscaleHorizDownscaleNoInterp(); | |||
void vertUpscaleHorizDownscaleInterp(); | void vertUpscaleHorizDownscaleInterp(); | |||
void vertUpscaleHorizDownscaleThresh(); | ||||
void vertUpscaleHorizUpscaleNoInterp(); | void vertUpscaleHorizUpscaleNoInterp(); | |||
void vertUpscaleHorizUpscaleInterp(); | void vertUpscaleHorizUpscaleInterp(); | |||
// source image data function | // source image data function | |||
SplashImageMaskSource src; | SplashImageMaskSource src; | |||
void *srcData; | void *srcData; | |||
// source image size | // source image size | |||
int srcWidth; | int srcWidth; | |||
int srcHeight; | int srcHeight; | |||
skipping to change at line 3977 | skipping to change at line 4001 | |||
Guchar *tmpBuf2; | Guchar *tmpBuf2; | |||
Guint *accBuf; | Guint *accBuf; | |||
// output of horizontal scaling | // output of horizontal scaling | |||
Guchar *line; | Guchar *line; | |||
}; | }; | |||
ImageMaskScaler::ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData, | ImageMaskScaler::ImageMaskScaler(SplashImageMaskSource aSrc, void *aSrcData, | |||
int aSrcWidth, int aSrcHeight, | int aSrcWidth, int aSrcHeight, | |||
int aScaledWidth, int aScaledHeight, | int aScaledWidth, int aScaledHeight, | |||
GBool aInterpolate) { | GBool aInterpolate, GBool aAntialias) { | |||
tmpBuf0 = NULL; | tmpBuf0 = NULL; | |||
tmpBuf1 = NULL; | tmpBuf1 = NULL; | |||
tmpBuf2 = NULL; | tmpBuf2 = NULL; | |||
accBuf = NULL; | accBuf = NULL; | |||
line = NULL; | line = NULL; | |||
src = aSrc; | src = aSrc; | |||
srcData = aSrcData; | srcData = aSrcData; | |||
srcWidth = aSrcWidth; | srcWidth = aSrcWidth; | |||
srcHeight = aSrcHeight; | srcHeight = aSrcHeight; | |||
skipping to change at line 4000 | skipping to change at line 4024 | |||
// select scaling function; allocate buffers | // select scaling function; allocate buffers | |||
if (scaledHeight <= srcHeight) { | if (scaledHeight <= srcHeight) { | |||
// vertical downscaling | // vertical downscaling | |||
yp = srcHeight / scaledHeight; | yp = srcHeight / scaledHeight; | |||
yq = srcHeight % scaledHeight; | yq = srcHeight % scaledHeight; | |||
yt = 0; | yt = 0; | |||
tmpBuf0 = (Guchar *)gmalloc(srcWidth); | tmpBuf0 = (Guchar *)gmalloc(srcWidth); | |||
accBuf = (Guint *)gmallocn(srcWidth, sizeof(Guint)); | accBuf = (Guint *)gmallocn(srcWidth, sizeof(Guint)); | |||
if (scaledWidth <= srcWidth) { | if (scaledWidth <= srcWidth) { | |||
scalingFunc = &ImageMaskScaler::vertDownscaleHorizDownscale; | if (!aAntialias) { | |||
scalingFunc = &ImageMaskScaler::vertDownscaleHorizDownscaleThresh; | ||||
} else { | ||||
scalingFunc = &ImageMaskScaler::vertDownscaleHorizDownscale; | ||||
} | ||||
} else { | } else { | |||
if (aInterpolate) { | if (!aAntialias) { | |||
scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleThresh; | ||||
} else if (aInterpolate) { | ||||
scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleInterp; | scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleInterp; | |||
} else { | } else { | |||
scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleNoInterp; | scalingFunc = &ImageMaskScaler::vertDownscaleHorizUpscaleNoInterp; | |||
} | } | |||
} | } | |||
} else { | } else { | |||
// vertical upscaling | // vertical upscaling | |||
yp = scaledHeight / srcHeight; | yp = scaledHeight / srcHeight; | |||
yq = scaledHeight % srcHeight; | yq = scaledHeight % srcHeight; | |||
yt = 0; | yt = 0; | |||
yn = 0; | yn = 0; | |||
if (aInterpolate) { | if (!aAntialias) { | |||
tmpBuf0 = (Guchar *)gmalloc(srcWidth); | ||||
if (scaledWidth <= srcWidth) { | ||||
scalingFunc = &ImageMaskScaler::vertUpscaleHorizDownscaleThresh; | ||||
} else { | ||||
scalingFunc = &ImageMaskScaler::vertUpscaleHorizUpscaleNoInterp; | ||||
} | ||||
} else if (aInterpolate) { | ||||
yInvScale = (SplashCoord)srcHeight / (SplashCoord)scaledHeight; | yInvScale = (SplashCoord)srcHeight / (SplashCoord)scaledHeight; | |||
tmpBuf0 = (Guchar *)gmalloc(srcWidth); | tmpBuf0 = (Guchar *)gmalloc(srcWidth); | |||
tmpBuf1 = (Guchar *)gmalloc(srcWidth); | tmpBuf1 = (Guchar *)gmalloc(srcWidth); | |||
ySrcCur = 0; | ySrcCur = 0; | |||
yScaledCur = 0; | yScaledCur = 0; | |||
if (scaledWidth <= srcWidth) { | if (scaledWidth <= srcWidth) { | |||
scalingFunc = &ImageMaskScaler::vertUpscaleHorizDownscaleInterp; | scalingFunc = &ImageMaskScaler::vertUpscaleHorizDownscaleInterp; | |||
} else { | } else { | |||
tmpBuf2 = (Guchar *)gmalloc(srcWidth); | tmpBuf2 = (Guchar *)gmalloc(srcWidth); | |||
scalingFunc = &ImageMaskScaler::vertUpscaleHorizUpscaleInterp; | scalingFunc = &ImageMaskScaler::vertUpscaleHorizUpscaleInterp; | |||
skipping to change at line 4097 | skipping to change at line 4134 | |||
acc = 0; | acc = 0; | |||
for (int i = 0; i < xStep; ++i) { | for (int i = 0; i < xStep; ++i) { | |||
acc += accBuf[unscaledIdx]; | acc += accBuf[unscaledIdx]; | |||
++unscaledIdx; | ++unscaledIdx; | |||
} | } | |||
line[scaledIdx] = (Guchar)((255 * acc) / (xStep * yStep)); | line[scaledIdx] = (Guchar)((255 * acc) / (xStep * yStep)); | |||
} | } | |||
} | } | |||
void ImageMaskScaler::vertDownscaleHorizDownscaleThresh() { | ||||
//--- vert downscale | ||||
int yStep = yp; | ||||
yt += yq; | ||||
if (yt >= scaledHeight) { | ||||
yt -= scaledHeight; | ||||
++yStep; | ||||
} | ||||
memset(accBuf, 0, srcWidth * sizeof(Guint)); | ||||
for (int i = 0; i < yStep; ++i) { | ||||
(*src)(srcData, tmpBuf0); | ||||
for (int j = 0; j < srcWidth; ++j) { | ||||
accBuf[j] += tmpBuf0[j]; | ||||
} | ||||
} | ||||
//--- horiz downscale | ||||
int acc; | ||||
int xt = 0; | ||||
int unscaledIdx = 0; | ||||
for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) { | ||||
int xStep = xp; | ||||
xt += xq; | ||||
if (xt >= scaledWidth) { | ||||
xt -= scaledWidth; | ||||
++xStep; | ||||
} | ||||
acc = 0; | ||||
for (int i = 0; i < xStep; ++i) { | ||||
acc += accBuf[unscaledIdx]; | ||||
++unscaledIdx; | ||||
} | ||||
line[scaledIdx] = acc > ((xStep * yStep) >> 1) ? (Guchar)255 : (Guchar)0; | ||||
} | ||||
} | ||||
void ImageMaskScaler::vertDownscaleHorizUpscaleNoInterp() { | void ImageMaskScaler::vertDownscaleHorizUpscaleNoInterp() { | |||
//--- vert downscale | //--- vert downscale | |||
int yStep = yp; | int yStep = yp; | |||
yt += yq; | yt += yq; | |||
if (yt >= scaledHeight) { | if (yt >= scaledHeight) { | |||
yt -= scaledHeight; | yt -= scaledHeight; | |||
++yStep; | ++yStep; | |||
} | } | |||
memset(accBuf, 0, srcWidth * sizeof(Guint)); | memset(accBuf, 0, srcWidth * sizeof(Guint)); | |||
for (int i = 0; i < yStep; ++i) { | for (int i = 0; i < yStep; ++i) { | |||
skipping to change at line 4167 | skipping to change at line 4241 | |||
if (x0 < 0) { | if (x0 < 0) { | |||
x0 = 0; | x0 = 0; | |||
} | } | |||
if (x1 >= srcWidth) { | if (x1 >= srcWidth) { | |||
x1 = srcWidth - 1; | x1 = srcWidth - 1; | |||
} | } | |||
line[scaledIdx] = (Guchar)(int)(s0 * accBuf[x0] + s1 * accBuf[x1]); | line[scaledIdx] = (Guchar)(int)(s0 * accBuf[x0] + s1 * accBuf[x1]); | |||
} | } | |||
} | } | |||
void ImageMaskScaler::vertDownscaleHorizUpscaleThresh() { | ||||
//--- vert downscale | ||||
int yStep = yp; | ||||
yt += yq; | ||||
if (yt >= scaledHeight) { | ||||
yt -= scaledHeight; | ||||
++yStep; | ||||
} | ||||
memset(accBuf, 0, srcWidth * sizeof(Guint)); | ||||
for (int i = 0; i < yStep; ++i) { | ||||
(*src)(srcData, tmpBuf0); | ||||
for (int j = 0; j < srcWidth; ++j) { | ||||
accBuf[j] += tmpBuf0[j]; | ||||
} | ||||
} | ||||
//--- horiz upscale | ||||
int xt = 0; | ||||
int scaledIdx = 0; | ||||
for (int srcIdx = 0; srcIdx < srcWidth; ++srcIdx) { | ||||
int xStep = xp; | ||||
xt += xq; | ||||
if (xt >= srcWidth) { | ||||
xt -= srcWidth; | ||||
++xStep; | ||||
} | ||||
Guchar buf = accBuf[srcIdx] > (Guint)(yStep >> 1) ? (Guchar)255 : (Guchar)0; | ||||
for (int i = 0; i < xStep; ++i) { | ||||
line[scaledIdx] = buf; | ||||
++scaledIdx; | ||||
} | ||||
} | ||||
} | ||||
void ImageMaskScaler::vertUpscaleHorizDownscaleNoInterp() { | void ImageMaskScaler::vertUpscaleHorizDownscaleNoInterp() { | |||
//--- vert upscale | //--- vert upscale | |||
if (yn == 0) { | if (yn == 0) { | |||
yn = yp; | yn = yp; | |||
yt += yq; | yt += yq; | |||
if (yt >= srcHeight) { | if (yt >= srcHeight) { | |||
yt -= srcHeight; | yt -= srcHeight; | |||
++yn; | ++yn; | |||
} | } | |||
(*src)(srcData, tmpBuf0); | (*src)(srcData, tmpBuf0); | |||
skipping to change at line 4254 | skipping to change at line 4362 | |||
acc = 0; | acc = 0; | |||
for (int i = 0; i < xStep; ++i) { | for (int i = 0; i < xStep; ++i) { | |||
acc += (int)(vs0 * (int)mask0[unscaledIdx] + | acc += (int)(vs0 * (int)mask0[unscaledIdx] + | |||
vs1 * (int)mask1[unscaledIdx]); | vs1 * (int)mask1[unscaledIdx]); | |||
++unscaledIdx; | ++unscaledIdx; | |||
} | } | |||
line[scaledIdx] = (Guchar)((255 * acc) / xStep); | line[scaledIdx] = (Guchar)((255 * acc) / xStep); | |||
} | } | |||
} | } | |||
void ImageMaskScaler::vertUpscaleHorizDownscaleThresh() { | ||||
//--- vert upscale | ||||
if (yn == 0) { | ||||
yn = yp; | ||||
yt += yq; | ||||
if (yt >= srcHeight) { | ||||
yt -= srcHeight; | ||||
++yn; | ||||
} | ||||
(*src)(srcData, tmpBuf0); | ||||
} | ||||
--yn; | ||||
//--- horiz downscale | ||||
int acc; | ||||
int xt = 0; | ||||
int unscaledIdx = 0; | ||||
for (int scaledIdx = 0; scaledIdx < scaledWidth; ++scaledIdx) { | ||||
int xStep = xp; | ||||
xt += xq; | ||||
if (xt >= scaledWidth) { | ||||
xt -= scaledWidth; | ||||
++xStep; | ||||
} | ||||
acc = 0; | ||||
for (int i = 0; i < xStep; ++i) { | ||||
acc += tmpBuf0[unscaledIdx]; | ||||
++unscaledIdx; | ||||
} | ||||
line[scaledIdx] = acc > (xStep >> 1) ? (Guchar)255 : (Guchar)0; | ||||
} | ||||
} | ||||
void ImageMaskScaler::vertUpscaleHorizUpscaleNoInterp() { | void ImageMaskScaler::vertUpscaleHorizUpscaleNoInterp() { | |||
//--- vert upscale | //--- vert upscale | |||
if (yn == 0) { | if (yn == 0) { | |||
yn = yp; | yn = yp; | |||
yt += yq; | yt += yq; | |||
if (yt >= srcHeight) { | if (yt >= srcHeight) { | |||
yt -= srcHeight; | yt -= srcHeight; | |||
++yn; | ++yn; | |||
} | } | |||
(*src)(srcData, tmpBuf0); | (*src)(srcData, tmpBuf0); | |||
skipping to change at line 4583 | skipping to change at line 4725 | |||
SplashError Splash::clipToRect(SplashCoord x0, SplashCoord y0, | SplashError Splash::clipToRect(SplashCoord x0, SplashCoord y0, | |||
SplashCoord x1, SplashCoord y1) { | SplashCoord x1, SplashCoord y1) { | |||
return state->clipToRect(x0, y0, x1, y1); | return state->clipToRect(x0, y0, x1, y1); | |||
} | } | |||
SplashError Splash::clipToPath(SplashPath *path, GBool eo) { | SplashError Splash::clipToPath(SplashPath *path, GBool eo) { | |||
return state->clipToPath(path, eo); | return state->clipToPath(path, eo); | |||
} | } | |||
void Splash::setSoftMask(SplashBitmap *softMask) { | void Splash::setSoftMask(SplashBitmap *softMask, GBool deleteBitmap) { | |||
state->setSoftMask(softMask); | state->setSoftMask(softMask, deleteBitmap); | |||
} | } | |||
void Splash::setInTransparencyGroup(SplashBitmap *groupBackBitmapA, | void Splash::setInTransparencyGroup(SplashBitmap *groupBackBitmapA, | |||
int groupBackXA, int groupBackYA, | int groupBackXA, int groupBackYA, | |||
SplashGroupDestInitMode groupDestInitModeA, | SplashGroupDestInitMode groupDestInitModeA, | |||
GBool nonIsolated, GBool knockout) { | GBool nonIsolated, GBool knockout) { | |||
groupBackBitmap = groupBackBitmapA; | groupBackBitmap = groupBackBitmapA; | |||
groupBackX = groupBackXA; | groupBackX = groupBackXA; | |||
groupBackY = groupBackYA; | groupBackY = groupBackYA; | |||
groupDestInitMode = groupDestInitModeA; | groupDestInitMode = groupDestInitModeA; | |||
skipping to change at line 4606 | skipping to change at line 4748 | |||
groupDestInitYMax = 0; | groupDestInitYMax = 0; | |||
state->inNonIsolatedGroup = nonIsolated; | state->inNonIsolatedGroup = nonIsolated; | |||
state->inKnockoutGroup = knockout; | state->inKnockoutGroup = knockout; | |||
} | } | |||
void Splash::forceDeferredInit(int y, int h) { | void Splash::forceDeferredInit(int y, int h) { | |||
useDestRow(y); | useDestRow(y); | |||
useDestRow(y + h - 1); | useDestRow(y + h - 1); | |||
} | } | |||
// Check that alpha is 0 in the specified rectangle. | ||||
// NB: This doesn't work correctly in a non-isolated group, because | ||||
// the rasterizer temporarily stores alpha_g instead of alpha. | ||||
GBool Splash::checkTransparentRect(int x, int y, int w, int h) { | ||||
if (state->inNonIsolatedGroup) { | ||||
return gFalse; | ||||
} | ||||
if (!bitmap->alpha) { | ||||
return gFalse; | ||||
} | ||||
int yy0, yy1; | ||||
if (groupDestInitMode == splashGroupDestPreInit) { | ||||
yy0 = y; | ||||
yy1 = y + h - 1; | ||||
} else { | ||||
// both splashGroupDestInitZero and splashGroupDestInitCopy set | ||||
// alpha to zero, so anything outside of groupDestInit[YMin,YMax] | ||||
// will have alpha=0 | ||||
yy0 = (y > groupDestInitYMin) ? y : groupDestInitYMin; | ||||
yy1 = (y + h - 1 < groupDestInitYMax) ? y + h - 1 : groupDestInitYMax; | ||||
} | ||||
Guchar *alphaP = &bitmap->alpha[yy0 * bitmap->alphaRowSize + x]; | ||||
for (int yy = yy0; yy <= yy1; ++yy) { | ||||
for (int xx = 0; xx < w; ++xx) { | ||||
if (alphaP[xx] != 0) { | ||||
return gFalse; | ||||
} | ||||
} | ||||
alphaP += bitmap->getAlphaRowSize(); | ||||
} | ||||
return gTrue; | ||||
} | ||||
void Splash::setTransfer(Guchar *red, Guchar *green, Guchar *blue, | void Splash::setTransfer(Guchar *red, Guchar *green, Guchar *blue, | |||
Guchar *gray) { | Guchar *gray) { | |||
state->setTransfer(red, green, blue, gray); | state->setTransfer(red, green, blue, gray); | |||
} | } | |||
void Splash::setOverprintMask(Guint overprintMask) { | void Splash::setOverprintMask(Guint overprintMask) { | |||
state->overprintMask = overprintMask; | state->overprintMask = overprintMask; | |||
} | } | |||
void Splash::setEnablePathSimplification(GBool en) { | void Splash::setEnablePathSimplification(GBool en) { | |||
skipping to change at line 5746 | skipping to change at line 5922 | |||
struct SplashDrawImageMaskRowData { | struct SplashDrawImageMaskRowData { | |||
SplashPipe pipe; | SplashPipe pipe; | |||
}; | }; | |||
// The glyphMode flag is not currently used, but may be useful if the | // The glyphMode flag is not currently used, but may be useful if the | |||
// stroke adjustment behavior is changed. | // stroke adjustment behavior is changed. | |||
SplashError Splash::fillImageMask(GString *imageTag, | SplashError Splash::fillImageMask(GString *imageTag, | |||
SplashImageMaskSource src, void *srcData, | SplashImageMaskSource src, void *srcData, | |||
int w, int h, SplashCoord *mat, | int w, int h, SplashCoord *mat, | |||
GBool glyphMode, GBool interpolate) { | GBool glyphMode, GBool interpolate, | |||
GBool antialias) { | ||||
if (debugMode) { | if (debugMode) { | |||
printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", | printf("fillImageMask: w=%d h=%d mat=[%.2f %.2f %.2f %.2f %.2f %.2f]\n", | |||
w, h, (double)mat[0], (double)mat[1], (double)mat[2], | w, h, (double)mat[0], (double)mat[1], (double)mat[2], | |||
(double)mat[3], (double)mat[4], (double)mat[5]); | (double)mat[3], (double)mat[4], (double)mat[5]); | |||
} | } | |||
//--- check for singular matrix | //--- check for singular matrix | |||
if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.000001)) { | if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.000001)) { | |||
return splashErrSingularMatrix; | return splashErrSingularMatrix; | |||
} | } | |||
//--- compute image bbox, check clipping | //--- compute image bbox, check clipping | |||
GBool flipsOnly = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001; | GBool flipsOnly = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001; | |||
GBool rot90Only = splashAbs(mat[0]) <= 0.0001 && splashAbs(mat[3]) <= 0.0001; | ||||
GBool horizFlip = gFalse; | GBool horizFlip = gFalse; | |||
GBool vertFlip = gFalse; | GBool vertFlip = gFalse; | |||
int xMin, yMin, xMax, yMax; | int xMin, yMin, xMax, yMax; | |||
if (flipsOnly) { | if (flipsOnly) { | |||
horizFlip = mat[0] < 0; | horizFlip = mat[0] < 0; | |||
vertFlip = mat[3] < 0; | vertFlip = mat[3] < 0; | |||
if (horizFlip) { | ||||
getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); | ||||
} else { | ||||
getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); | ||||
} | ||||
if (vertFlip) { | if (vertFlip) { | |||
if (horizFlip) { // bottom-up, mirrored | getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); | |||
getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); | ||||
getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); | ||||
} else { // bottom-up | ||||
getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); | ||||
getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); | ||||
} | ||||
} else { | } else { | |||
if (horizFlip) { // top-down, mirrored | getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); | |||
getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); | } | |||
getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); | } else if (rot90Only) { | |||
} else { // top-down | horizFlip = mat[2] < 0; | |||
getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); | vertFlip = mat[1] < 0; | |||
getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); | if (horizFlip) { | |||
} | getImageBounds(mat[2] + mat[4], mat[4], &xMin, &xMax); | |||
} else { | ||||
getImageBounds(mat[4], mat[2] + mat[4], &xMin, &xMax); | ||||
} | ||||
if (vertFlip) { | ||||
getImageBounds(mat[1] + mat[5], mat[5], &yMin, &yMax); | ||||
} else { | ||||
getImageBounds(mat[5], mat[1] + mat[5], &yMin, &yMax); | ||||
} | } | |||
} else { | } else { | |||
int xx = splashRound(mat[4]); // (0,0) | int xx = splashRound(mat[4]); // (0,0) | |||
int yy = splashRound(mat[5]); | int yy = splashRound(mat[5]); | |||
xMin = xMax = xx; | xMin = xMax = xx; | |||
yMin = yMax = yy; | yMin = yMax = yy; | |||
xx = splashRound(mat[0] + mat[4]); // (1,0) | xx = splashRound(mat[0] + mat[4]); // (1,0) | |||
yy = splashRound(mat[1] + mat[5]); | yy = splashRound(mat[1] + mat[5]); | |||
if (xx < xMin) { | if (xx < xMin) { | |||
xMin = xx; | xMin = xx; | |||
skipping to change at line 5857 | skipping to change at line 6041 | |||
SplashDrawImageMaskRowData dd; | SplashDrawImageMaskRowData dd; | |||
pipeInit(&dd.pipe, state->fillPattern, | pipeInit(&dd.pipe, state->fillPattern, | |||
(Guchar)splashRound(state->fillAlpha * 255), | (Guchar)splashRound(state->fillAlpha * 255), | |||
gTrue, gFalse); | gTrue, gFalse); | |||
//--- choose the drawRow function | //--- choose the drawRow function | |||
SplashDrawImageMaskRowFunc drawRowFunc; | SplashDrawImageMaskRowFunc drawRowFunc; | |||
if (clipRes == splashClipAllInside) { | if (clipRes == splashClipAllInside) { | |||
drawRowFunc = &Splash::drawImageMaskRowNoClip; | drawRowFunc = &Splash::drawImageMaskRowNoClip; | |||
} else { | } else { | |||
if (vectorAntialias) { | if (antialias) { | |||
drawRowFunc = &Splash::drawImageMaskRowClipAA; | drawRowFunc = &Splash::drawImageMaskRowClipAA; | |||
} else { | } else { | |||
drawRowFunc = &Splash::drawImageMaskRowClipNoAA; | drawRowFunc = &Splash::drawImageMaskRowClipNoAA; | |||
} | } | |||
} | } | |||
//--- horizontal/vertical flips only | //--- horizontal/vertical flips only | |||
if (flipsOnly && !veryLarge) { | if (flipsOnly && !veryLarge) { | |||
if (clipRes != splashClipAllOutside) { | if (clipRes != splashClipAllOutside) { | |||
int scaledWidth = xMax - xMin; | int scaledWidth = xMax - xMin; | |||
int scaledHeight = yMax - yMin; | int scaledHeight = yMax - yMin; | |||
ImageMaskScaler scaler(src, srcData, w, h, | ImageMaskScaler scaler(src, srcData, w, h, | |||
scaledWidth, scaledHeight, interpolate); | scaledWidth, scaledHeight, interpolate, antialias); | |||
Guchar *tmpLine = NULL; | Guchar *tmpLine = NULL; | |||
if (horizFlip) { | if (horizFlip) { | |||
tmpLine = (Guchar *)gmalloc(scaledWidth); | tmpLine = (Guchar *)gmalloc(scaledWidth); | |||
} | } | |||
if (vertFlip) { | if (vertFlip) { | |||
if (horizFlip) { // bottom-up, mirrored | if (horizFlip) { // bottom-up, mirrored | |||
for (int y = 0; y < scaledHeight; ++y) { | for (int y = 0; y < scaledHeight; ++y) { | |||
scaler.nextLine(); | scaler.nextLine(); | |||
mirrorImageMaskRow(scaler.data(), tmpLine, scaledWidth); | mirrorImageMaskRow(scaler.data(), tmpLine, scaledWidth); | |||
(this->*drawRowFunc)(&dd, tmpLine, | (this->*drawRowFunc)(&dd, tmpLine, | |||
skipping to change at line 5909 | skipping to change at line 6093 | |||
for (int y = 0; y < scaledHeight; ++y) { | for (int y = 0; y < scaledHeight; ++y) { | |||
scaler.nextLine(); | scaler.nextLine(); | |||
(this->*drawRowFunc)(&dd, scaler.data(), | (this->*drawRowFunc)(&dd, scaler.data(), | |||
xMin, yMin + y, scaledWidth); | xMin, yMin + y, scaledWidth); | |||
} | } | |||
} | } | |||
} | } | |||
gfree(tmpLine); | gfree(tmpLine); | |||
} | } | |||
//--- 90/270 rotation | ||||
} else if (rot90Only && !veryLarge) { | ||||
if (clipRes != splashClipAllOutside) { | ||||
// scale the mask | ||||
int scaledWidth = yMax - yMin; | ||||
int scaledHeight = xMax - xMin; | ||||
ImageMaskScaler scaler(src, srcData, w, h, | ||||
scaledWidth, scaledHeight, interpolate, antialias); | ||||
Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth); | ||||
Guchar *ptr = scaledMask; | ||||
for (int y = 0; y < scaledHeight; ++y) { | ||||
scaler.nextLine(); | ||||
memcpy(ptr, scaler.data(), scaledWidth); | ||||
ptr += scaledWidth; | ||||
} | ||||
// draw it | ||||
Guchar *tmpLine = (Guchar *)gmalloc(scaledHeight); | ||||
for (int y = 0; y < scaledWidth; ++y) { | ||||
if (vertFlip) { | ||||
ptr = scaledMask + (scaledWidth - 1 - y); | ||||
} else { | ||||
ptr = scaledMask + y; | ||||
} | ||||
if (horizFlip) { | ||||
ptr += (scaledHeight - 1) * scaledWidth; | ||||
for (int x = 0; x < scaledHeight; ++x) { | ||||
tmpLine[x] = *ptr; | ||||
ptr -= scaledWidth; | ||||
} | ||||
} else { | ||||
for (int x = 0; x < scaledHeight; ++x) { | ||||
tmpLine[x] = *ptr; | ||||
ptr += scaledWidth; | ||||
} | ||||
} | ||||
(this->*drawRowFunc)(&dd, tmpLine, xMin, yMin + y, scaledHeight); | ||||
} | ||||
gfree(tmpLine); | ||||
gfree(scaledMask); | ||||
} | ||||
//--- arbitrary transform | //--- arbitrary transform | |||
} else { | } else { | |||
// estimate of size of scaled image | // estimate of size of scaled image | |||
int scaledWidth = splashRound(splashSqrt(mat[0] * mat[0] | int scaledWidth = splashRound(splashSqrt(mat[0] * mat[0] | |||
+ mat[1] * mat[1])); | + mat[1] * mat[1])); | |||
int scaledHeight = splashRound(splashSqrt(mat[2] * mat[2] | int scaledHeight = splashRound(splashSqrt(mat[2] * mat[2] | |||
+ mat[3] * mat[3])); | + mat[3] * mat[3])); | |||
if (scaledWidth < 1) { | if (scaledWidth < 1) { | |||
scaledWidth = 1; | scaledWidth = 1; | |||
} | } | |||
skipping to change at line 5960 | skipping to change at line 6188 | |||
invMat[4] = (mat1[2] * mat1[5] - mat1[3] * mat1[4]) / det | invMat[4] = (mat1[2] * mat1[5] - mat1[3] * mat1[4]) / det | |||
+ (invMat[0] + invMat[2]) * 0.5; | + (invMat[0] + invMat[2]) * 0.5; | |||
invMat[5] = (mat1[1] * mat1[4] - mat1[0] * mat1[5]) / det | invMat[5] = (mat1[1] * mat1[4] - mat1[0] * mat1[5]) / det | |||
+ (invMat[1] + invMat[3]) * 0.5; | + (invMat[1] + invMat[3]) * 0.5; | |||
// if downscaling: store the downscaled image mask | // if downscaling: store the downscaled image mask | |||
// if upscaling: store the unscaled image mask | // if upscaling: store the unscaled image mask | |||
Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth); | Guchar *scaledMask = (Guchar *)gmallocn(scaledHeight, scaledWidth); | |||
if (downscaling) { | if (downscaling) { | |||
ImageMaskScaler scaler(src, srcData, w, h, | ImageMaskScaler scaler(src, srcData, w, h, | |||
scaledWidth, scaledHeight, interpolate); | scaledWidth, scaledHeight, interpolate, antialias); | |||
Guchar *ptr = scaledMask; | Guchar *ptr = scaledMask; | |||
for (int y = 0; y < scaledHeight; ++y) { | for (int y = 0; y < scaledHeight; ++y) { | |||
scaler.nextLine(); | scaler.nextLine(); | |||
memcpy(ptr, scaler.data(), scaledWidth); | memcpy(ptr, scaler.data(), scaledWidth); | |||
ptr += scaledWidth; | ptr += scaledWidth; | |||
} | } | |||
} else { | } else { | |||
Guchar *ptr = scaledMask; | Guchar *ptr = scaledMask; | |||
for (int y = 0; y < scaledHeight; ++y) { | for (int y = 0; y < scaledHeight; ++y) { | |||
(*src)(srcData, ptr); | (*src)(srcData, ptr); | |||
for (int x = 0; x < scaledWidth; ++x) { | for (int x = 0; x < scaledWidth; ++x) { | |||
*ptr = (Guchar)(*ptr * 255); | *ptr = (Guchar)(*ptr * 255); | |||
++ptr; | ++ptr; | |||
} | } | |||
} | } | |||
} | } | |||
// draw it | // draw it | |||
if (interpolate) { | if (interpolate && antialias) { | |||
drawImageMaskArbitraryInterp(scaledMask, | drawImageMaskArbitraryInterp(scaledMask, | |||
&dd, drawRowFunc, invMat, | &dd, drawRowFunc, invMat, | |||
scaledWidth, scaledHeight, | scaledWidth, scaledHeight, | |||
xMin, yMin, xMax, yMax); | xMin, yMin, xMax, yMax); | |||
} else { | } else { | |||
drawImageMaskArbitraryNoInterp(scaledMask, | drawImageMaskArbitraryNoInterp(scaledMask, | |||
&dd, drawRowFunc, invMat, | &dd, drawRowFunc, invMat, | |||
scaledWidth, scaledHeight, | scaledWidth, scaledHeight, | |||
xMin, yMin, xMax, yMax); | xMin, yMin, xMax, yMax); | |||
} | } | |||
skipping to change at line 6256 | skipping to change at line 6484 | |||
return splashErrModeMismatch; | return splashErrModeMismatch; | |||
} | } | |||
//--- check for singular matrix | //--- check for singular matrix | |||
if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.000001)) { | if (!splashCheckDet(mat[0], mat[1], mat[2], mat[3], 0.000001)) { | |||
return splashErrSingularMatrix; | return splashErrSingularMatrix; | |||
} | } | |||
//--- compute image bbox, check clipping | //--- compute image bbox, check clipping | |||
GBool flipsOnly = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001; | GBool flipsOnly = splashAbs(mat[1]) <= 0.0001 && splashAbs(mat[2]) <= 0.0001; | |||
GBool rot90Only = splashAbs(mat[0]) <= 0.0001 && splashAbs(mat[3]) <= 0.0001; | ||||
GBool horizFlip = gFalse; | GBool horizFlip = gFalse; | |||
GBool vertFlip = gFalse; | GBool vertFlip = gFalse; | |||
int xMin, yMin, xMax, yMax; | int xMin, yMin, xMax, yMax; | |||
if (flipsOnly) { | if (flipsOnly) { | |||
horizFlip = mat[0] < 0; | horizFlip = mat[0] < 0; | |||
vertFlip = mat[3] < 0; | vertFlip = mat[3] < 0; | |||
if (horizFlip) { | ||||
getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); | ||||
} else { | ||||
getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); | ||||
} | ||||
if (vertFlip) { | if (vertFlip) { | |||
if (horizFlip) { // bottom-up, mirrored | getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); | |||
getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); | ||||
getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); | ||||
} else { // bottom-up | ||||
getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); | ||||
getImageBounds(mat[3] + mat[5], mat[5], &yMin, &yMax); | ||||
} | ||||
} else { | } else { | |||
if (horizFlip) { // top-down, mirrored | getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); | |||
getImageBounds(mat[0] + mat[4], mat[4], &xMin, &xMax); | } | |||
getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); | } else if (rot90Only) { | |||
} else { // top-down | horizFlip = mat[2] < 0; | |||
getImageBounds(mat[4], mat[0] + mat[4], &xMin, &xMax); | vertFlip = mat[1] < 0; | |||
getImageBounds(mat[5], mat[3] + mat[5], &yMin, &yMax); | if (horizFlip) { | |||
} | getImageBounds(mat[2] + mat[4], mat[4], &xMin, &xMax); | |||
} else { | ||||
getImageBounds(mat[4], mat[2] + mat[4], &xMin, &xMax); | ||||
} | ||||
if (vertFlip) { | ||||
getImageBounds(mat[1] + mat[5], mat[5], &yMin, &yMax); | ||||
} else { | ||||
getImageBounds(mat[5], mat[1] + mat[5], &yMin, &yMax); | ||||
} | } | |||
} else { | } else { | |||
int xx = splashRound(mat[4]); // (0,0) | int xx = splashRound(mat[4]); // (0,0) | |||
int yy = splashRound(mat[5]); | int yy = splashRound(mat[5]); | |||
xMin = xMax = xx; | xMin = xMax = xx; | |||
yMin = yMax = yy; | yMin = yMax = yy; | |||
xx = splashRound(mat[0] + mat[4]); // (1,0) | xx = splashRound(mat[0] + mat[4]); // (1,0) | |||
yy = splashRound(mat[1] + mat[5]); | yy = splashRound(mat[1] + mat[5]); | |||
if (xx < xMin) { | if (xx < xMin) { | |||
xMin = xx; | xMin = xx; | |||
skipping to change at line 6432 | skipping to change at line 6667 | |||
(this->*drawRowFunc)(&dd, scaler->colorData(), scaler->alphaData(), | (this->*drawRowFunc)(&dd, scaler->colorData(), scaler->alphaData(), | |||
xMin, yMin + y, scaledWidth); | xMin, yMin + y, scaledWidth); | |||
} | } | |||
} | } | |||
} | } | |||
gfree(tmpLine); | gfree(tmpLine); | |||
gfree(tmpAlphaLine); | gfree(tmpAlphaLine); | |||
delete scaler; | delete scaler; | |||
} | } | |||
//--- 90/270 rotation | ||||
} else if (rot90Only && !veryLarge) { | ||||
if (clipRes != splashClipAllOutside) { | ||||
// scale the image | ||||
int scaledWidth = yMax - yMin; | ||||
int scaledHeight = xMax - xMin; | ||||
Guchar *scaledColor, *scaledAlpha; | ||||
GBool freeScaledImage; | ||||
getScaledImage(imageTag, src, srcData, w, h, nComps, | ||||
scaledWidth, scaledHeight, srcMode, srcAlpha, interpolate, | ||||
&scaledColor, &scaledAlpha, &freeScaledImage); | ||||
// draw it | ||||
Guchar *tmpLine = (Guchar *)gmallocn(scaledHeight, nComps); | ||||
Guchar *tmpAlphaLine = NULL; | ||||
if (srcAlpha) { | ||||
tmpAlphaLine = (Guchar *)gmalloc(scaledHeight); | ||||
} | ||||
for (int y = 0; y < scaledWidth; ++y) { | ||||
Guchar *ptr, *alphaPtr; | ||||
if (vertFlip) { | ||||
ptr = scaledColor + (scaledWidth - 1 - y) * nComps; | ||||
if (srcAlpha) { | ||||
alphaPtr = scaledAlpha + (scaledWidth - 1 - y); | ||||
} | ||||
} else { | ||||
ptr = scaledColor + y * nComps; | ||||
if (srcAlpha) { | ||||
alphaPtr = scaledAlpha + y; | ||||
} | ||||
} | ||||
if (horizFlip) { | ||||
ptr += (scaledHeight - 1) * scaledWidth * nComps; | ||||
Guchar *q = tmpLine; | ||||
for (int x = 0; x < scaledHeight; ++x) { | ||||
for (int i = 0; i < nComps; ++i) { | ||||
*q++ = ptr[i]; | ||||
} | ||||
ptr -= scaledWidth * nComps; | ||||
} | ||||
if (srcAlpha) { | ||||
alphaPtr += (scaledHeight - 1) * scaledWidth; | ||||
q = tmpAlphaLine; | ||||
for (int x = 0; x < scaledHeight; ++x) { | ||||
*q++ = *alphaPtr; | ||||
alphaPtr -= scaledWidth; | ||||
} | ||||
} | ||||
} else { | ||||
Guchar *q = tmpLine; | ||||
for (int x = 0; x < scaledHeight; ++x) { | ||||
for (int i = 0; i < nComps; ++i) { | ||||
*q++ = ptr[i]; | ||||
} | ||||
ptr += scaledWidth * nComps; | ||||
} | ||||
if (srcAlpha) { | ||||
q = tmpAlphaLine; | ||||
for (int x = 0; x < scaledHeight; ++x) { | ||||
*q++ = *alphaPtr; | ||||
alphaPtr += scaledWidth; | ||||
} | ||||
} | ||||
} | ||||
(this->*drawRowFunc)(&dd, tmpLine, tmpAlphaLine, | ||||
xMin, yMin + y, scaledHeight); | ||||
} | ||||
gfree(tmpLine); | ||||
gfree(tmpAlphaLine); | ||||
if (freeScaledImage) { | ||||
gfree(scaledColor); | ||||
gfree(scaledAlpha); | ||||
} | ||||
} | ||||
//--- arbitrary transform | //--- arbitrary transform | |||
} else { | } else { | |||
// estimate of size of scaled image | // estimate of size of scaled image | |||
int scaledWidth = splashRound(splashSqrt(mat[0] * mat[0] | int scaledWidth = splashRound(splashSqrt(mat[0] * mat[0] | |||
+ mat[1] * mat[1])); | + mat[1] * mat[1])); | |||
int scaledHeight = splashRound(splashSqrt(mat[2] * mat[2] | int scaledHeight = splashRound(splashSqrt(mat[2] * mat[2] | |||
+ mat[3] * mat[3])); | + mat[3] * mat[3])); | |||
if (scaledWidth < 1) { | if (scaledWidth < 1) { | |||
scaledWidth = 1; | scaledWidth = 1; | |||
} | } | |||
skipping to change at line 6515 | skipping to change at line 6827 | |||
} | } | |||
ImageScaler *Splash::getImageScaler(GString *imageTag, | ImageScaler *Splash::getImageScaler(GString *imageTag, | |||
SplashImageSource src, void *srcData, | SplashImageSource src, void *srcData, | |||
int w, int h, int nComps, | int w, int h, int nComps, | |||
int scaledWidth, int scaledHeight, | int scaledWidth, int scaledHeight, | |||
SplashColorMode srcMode, | SplashColorMode srcMode, | |||
GBool srcAlpha, GBool interpolate) { | GBool srcAlpha, GBool interpolate) { | |||
// Notes: | // Notes: | |||
// | // | |||
// * If the scaled image width or height is greater than 2000, we | // * If the scaled image is more than 8 Mpixels, we don't cache it. | |||
// don't cache it. | ||||
// | // | |||
// * Caching is done on the third consecutive use (second | // * Caching is done on the third consecutive use (second | |||
// consecutive reuse) of an image; this avoids overhead on the | // consecutive reuse) of an image; this avoids overhead on the | |||
// common case of single-use images. | // common case of single-use images. | |||
if (scaledWidth < 2000 && scaledHeight < 2000 && | if (scaledWidth < 8000000 / scaledHeight && | |||
imageCache->match(imageTag, scaledWidth, scaledHeight, | imageCache->match(imageTag, scaledWidth, scaledHeight, | |||
srcMode, srcAlpha, interpolate)) { | srcMode, srcAlpha, interpolate)) { | |||
if (imageCache->colorData) { | if (imageCache->colorData) { | |||
return new ReplayImageScaler(nComps, srcAlpha, scaledWidth, | return new ReplayImageScaler(nComps, srcAlpha, scaledWidth, | |||
imageCache->colorData, | imageCache->colorData, | |||
imageCache->alphaData); | imageCache->alphaData); | |||
} else { | } else { | |||
int lineSize; | int lineSize; | |||
if (scaledWidth < INT_MAX / nComps) { | if (scaledWidth < INT_MAX / nComps) { | |||
lineSize = scaledWidth * nComps; | lineSize = scaledWidth * nComps; | |||
skipping to change at line 6567 | skipping to change at line 6878 | |||
void Splash::getScaledImage(GString *imageTag, | void Splash::getScaledImage(GString *imageTag, | |||
SplashImageSource src, void *srcData, | SplashImageSource src, void *srcData, | |||
int w, int h, int nComps, | int w, int h, int nComps, | |||
int scaledWidth, int scaledHeight, | int scaledWidth, int scaledHeight, | |||
SplashColorMode srcMode, | SplashColorMode srcMode, | |||
GBool srcAlpha, GBool interpolate, | GBool srcAlpha, GBool interpolate, | |||
Guchar **scaledColor, Guchar **scaledAlpha, | Guchar **scaledColor, Guchar **scaledAlpha, | |||
GBool *freeScaledImage) { | GBool *freeScaledImage) { | |||
// Notes: | // Notes: | |||
// | // | |||
// * If the scaled image width or height is greater than 2000, we | // * If the scaled image is more than 8 Mpixels, we don't cache it. | |||
// don't cache it. | ||||
// | // | |||
// * This buffers the whole image anyway, so there's no reason to | // * This buffers the whole image anyway, so there's no reason to | |||
// skip caching on the first reuse. | // skip caching on the first reuse. | |||
if (scaledWidth >= 2000 || scaledHeight >= 2000) { | if (scaledWidth >= 8000000 / scaledHeight) { | |||
int lineSize; | int lineSize; | |||
if (scaledWidth < INT_MAX / nComps) { | if (scaledWidth < INT_MAX / nComps) { | |||
lineSize = scaledWidth * nComps; | lineSize = scaledWidth * nComps; | |||
} else { | } else { | |||
lineSize = -1; | lineSize = -1; | |||
} | } | |||
*scaledColor = (Guchar *)gmallocn(scaledHeight, lineSize); | *scaledColor = (Guchar *)gmallocn(scaledHeight, lineSize); | |||
if (srcAlpha) { | if (srcAlpha) { | |||
*scaledAlpha = (Guchar *)gmallocn(scaledHeight, scaledWidth); | *scaledAlpha = (Guchar *)gmallocn(scaledHeight, scaledWidth); | |||
} else { | } else { | |||
End of changes. 35 change blocks. | ||||
48 lines changed or deleted | 358 lines changed or added |