"Fossies" - the Fresh Open Source Software Archive  

Source code changes of the file "splash/Splash.cc" between
xpdf-4.03.tar.gz and xpdf-4.04.tar.gz

About: Xpdf is a PDF viewer for X.

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

Home  |  About  |  Features  |  All  |  Newest  |  Dox  |  Diffs  |  RSS Feeds  |  Screenshots  |  Comments  |  Imprint  |  Privacy  |  HTTP(S)