summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/splash/Splash.cc')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/Splash.cc1957
1 files changed, 1282 insertions, 675 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc b/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
index d9035b37aa9..0810fbc3bd2 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
@@ -15,7 +15,9 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <math.h>
#include "gmem.h"
+#include "gmempp.h"
#include "SplashErrorCodes.h"
#include "SplashMath.h"
#include "SplashBitmap.h"
@@ -29,9 +31,12 @@
#include "SplashGlyphBitmap.h"
#include "Splash.h"
-//------------------------------------------------------------------------
+// the MSVC math.h doesn't define this
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
-#define splashAAGamma 0.67
+//------------------------------------------------------------------------
// distance of Bezier control point from center for circle approximation
// = (4 * (sqrt(2) - 1) / 3) * r
@@ -123,17 +128,6 @@ SplashPipeResultColorCtrl Splash::pipeResultColorAlphaBlend[] = {
};
//------------------------------------------------------------------------
-
-static void blendXor(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = src[i] ^ dest[i];
- }
-}
-
-//------------------------------------------------------------------------
// modified region
//------------------------------------------------------------------------
@@ -269,7 +263,7 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
Guchar shape, aSrc, aDest, alphaI, alphaIm1, alpha0, aResult;
SplashColor cSrc, cDest, cBlend;
Guchar shapeVal, cResult0, cResult1, cResult2, cResult3;
- int cSrcStride, shapeStride, x, lastX, t, i;
+ int cSrcStride, shapeStride, x, lastX, t;
SplashColorPtr destColorPtr;
Guchar destColorMask;
Guchar *destAlphaPtr;
@@ -396,49 +390,33 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
pipe->pattern->getColor(x, y, pipe->cSrcVal);
}
+ cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy
+
if (pipe->noTransparency && !state->blendFunc) {
- //----- write destination pixel
+ //----- result color
switch (bitmap->mode) {
case splashModeMono1:
- cResult0 = state->grayTransfer[cSrcPtr[0]];
- if (state->screen->test(x, y, cResult0)) {
- *destColorPtr |= destColorMask;
- } else {
- *destColorPtr &= ~destColorMask;
- }
- destColorPtr += destColorMask & 1;
- destColorMask = (destColorMask << 7) | (destColorMask >> 1);
- break;
case splashModeMono8:
- *destColorPtr++ = state->grayTransfer[cSrcPtr[0]];
+ cResult0 = state->grayTransfer[cSrcPtr[0]];
break;
case splashModeRGB8:
- destColorPtr[0] = state->rgbTransferR[cSrcPtr[0]];
- destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]];
- destColorPtr[2] = state->rgbTransferB[cSrcPtr[2]];
- destColorPtr += 3;
- break;
case splashModeBGR8:
- destColorPtr[0] = state->rgbTransferB[cSrcPtr[2]];
- destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]];
- destColorPtr[2] = state->rgbTransferR[cSrcPtr[0]];
- destColorPtr += 3;
+ cResult0 = state->rgbTransferR[cSrcPtr[0]];
+ cResult1 = state->rgbTransferG[cSrcPtr[1]];
+ cResult2 = state->rgbTransferB[cSrcPtr[2]];
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- destColorPtr[0] = state->cmykTransferC[cSrcPtr[0]];
- destColorPtr[1] = state->cmykTransferM[cSrcPtr[1]];
- destColorPtr[2] = state->cmykTransferY[cSrcPtr[2]];
- destColorPtr[3] = state->cmykTransferK[cSrcPtr[3]];
- destColorPtr += 4;
+ cResult0 = state->cmykTransferC[cSrcPtr[0]];
+ cResult1 = state->cmykTransferM[cSrcPtr[1]];
+ cResult2 = state->cmykTransferY[cSrcPtr[2]];
+ cResult3 = state->cmykTransferK[cSrcPtr[3]];
break;
#endif
}
- if (destAlphaPtr) {
- *destAlphaPtr++ = 255;
- }
+ aResult = 255;
} else { // if (noTransparency && !blendFunc)
@@ -516,17 +494,42 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
aDest = 0xff;
}
- //----- overprint
+ //----- read source color; handle overprint
- for (i = 0; i < bitmapComps; ++i) {
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ case splashModeMono8:
+ cSrc[0] = state->grayTransfer[cSrcPtr[0]];
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ cSrc[0] = state->rgbTransferR[cSrcPtr[0]];
+ cSrc[1] = state->rgbTransferG[cSrcPtr[1]];
+ cSrc[2] = state->rgbTransferB[cSrcPtr[2]];
+ break;
#if SPLASH_CMYK
- if (state->overprintMask & (1 << i)) {
- cSrc[i] = cSrcPtr[i];
+ case splashModeCMYK8:
+ if (state->overprintMask & 0x01) {
+ cSrc[0] = state->cmykTransferC[cSrcPtr[0]];
} else {
- cSrc[i] = div255(aDest * cDest[i]);
+ cSrc[0] = div255(aDest * cDest[0]);
}
-#else
- cSrc[i] = cSrcPtr[i];
+ if (state->overprintMask & 0x02) {
+ cSrc[1] = state->cmykTransferM[cSrcPtr[1]];
+ } else {
+ cSrc[1] = div255(aDest * cDest[1]);
+ }
+ if (state->overprintMask & 0x04) {
+ cSrc[2] = state->cmykTransferY[cSrcPtr[2]];
+ } else {
+ cSrc[2] = div255(aDest * cDest[2]);
+ }
+ if (state->overprintMask & 0x08) {
+ cSrc[3] = state->cmykTransferK[cSrcPtr[3]];
+ } else {
+ cSrc[3] = div255(aDest * cDest[3]);
+ }
+ break;
#endif
}
@@ -629,32 +632,22 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
//----- result color
- cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy
-
switch (pipe->resultColorCtrl) {
case splashPipeResultColorNoAlphaBlendMono:
- cResult0 = state->grayTransfer[div255((255 - aDest) * cSrc[0] +
- aDest * cBlend[0])];
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
break;
case splashPipeResultColorNoAlphaBlendRGB:
- cResult0 = state->rgbTransferR[div255((255 - aDest) * cSrc[0] +
- aDest * cBlend[0])];
- cResult1 = state->rgbTransferG[div255((255 - aDest) * cSrc[1] +
- aDest * cBlend[1])];
- cResult2 = state->rgbTransferB[div255((255 - aDest) * cSrc[2] +
- aDest * cBlend[2])];
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
+ cResult1 = div255((255 - aDest) * cSrc[1] + aDest * cBlend[1]);
+ cResult2 = div255((255 - aDest) * cSrc[2] + aDest * cBlend[2]);
break;
#if SPLASH_CMYK
case splashPipeResultColorNoAlphaBlendCMYK:
- cResult0 = state->cmykTransferC[div255((255 - aDest) * cSrc[0] +
- aDest * cBlend[0])];
- cResult1 = state->cmykTransferM[div255((255 - aDest) * cSrc[1] +
- aDest * cBlend[1])];
- cResult2 = state->cmykTransferY[div255((255 - aDest) * cSrc[2] +
- aDest * cBlend[2])];
- cResult3 = state->cmykTransferK[div255((255 - aDest) * cSrc[3] +
- aDest * cBlend[3])];
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
+ cResult1 = div255((255 - aDest) * cSrc[1] + aDest * cBlend[1]);
+ cResult2 = div255((255 - aDest) * cSrc[2] + aDest * cBlend[2]);
+ cResult3 = div255((255 - aDest) * cSrc[3] + aDest * cBlend[3]);
break;
#endif
@@ -662,8 +655,7 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
if (alphaI == 0) {
cResult0 = 0;
} else {
- cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] +
- aSrc * cSrc[0]) / alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) / alphaI;
}
break;
case splashPipeResultColorAlphaNoBlendRGB:
@@ -672,12 +664,9 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] +
- aSrc * cSrc[0]) / alphaI];
- cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] +
- aSrc * cSrc[1]) / alphaI];
- cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] +
- aSrc * cSrc[2]) / alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) / alphaI;
+ cResult1 = ((alphaI - aSrc) * cDest[1] + aSrc * cSrc[1]) / alphaI;
+ cResult2 = ((alphaI - aSrc) * cDest[2] + aSrc * cSrc[2]) / alphaI;
}
break;
#if SPLASH_CMYK
@@ -688,14 +677,10 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 = state->cmykTransferC[((alphaI - aSrc) * cDest[0] +
- aSrc * cSrc[0]) / alphaI];
- cResult1 = state->cmykTransferM[((alphaI - aSrc) * cDest[1] +
- aSrc * cSrc[1]) / alphaI];
- cResult2 = state->cmykTransferY[((alphaI - aSrc) * cDest[2] +
- aSrc * cSrc[2]) / alphaI];
- cResult3 = state->cmykTransferK[((alphaI - aSrc) * cDest[3] +
- aSrc * cSrc[3]) / alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) / alphaI;
+ cResult1 = ((alphaI - aSrc) * cDest[1] + aSrc * cSrc[1]) / alphaI;
+ cResult2 = ((alphaI - aSrc) * cDest[2] + aSrc * cSrc[2]) / alphaI;
+ cResult3 = ((alphaI - aSrc) * cDest[3] + aSrc * cSrc[3]) / alphaI;
}
break;
#endif
@@ -704,10 +689,10 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
if (alphaI == 0) {
cResult0 = 0;
} else {
- cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] +
- aSrc * ((255 - alphaIm1) * cSrc[0] +
- alphaIm1 * cBlend[0]) / 255) /
- alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI;
}
break;
case splashPipeResultColorAlphaBlendRGB:
@@ -716,18 +701,18 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] +
- aSrc * ((255 - alphaIm1) * cSrc[0] +
- alphaIm1 * cBlend[0]) / 255) /
- alphaI];
- cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] +
- aSrc * ((255 - alphaIm1) * cSrc[1] +
- alphaIm1 * cBlend[1]) / 255) /
- alphaI];
- cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] +
- aSrc * ((255 - alphaIm1) * cSrc[2] +
- alphaIm1 * cBlend[2]) / 255) /
- alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI;
+ cResult1 = ((alphaI - aSrc) * cDest[1] +
+ aSrc * ((255 - alphaIm1) * cSrc[1] +
+ alphaIm1 * cBlend[1]) / 255)
+ / alphaI;
+ cResult2 = ((alphaI - aSrc) * cDest[2] +
+ aSrc * ((255 - alphaIm1) * cSrc[2] +
+ alphaIm1 * cBlend[2]) / 255)
+ / alphaI;
}
break;
#if SPLASH_CMYK
@@ -738,73 +723,69 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 =
- state->cmykTransferC[((alphaI - aSrc) * cDest[0] +
- aSrc * ((255 - alphaIm1) * cSrc[0] +
- alphaIm1 * cBlend[0]) / 255) /
- alphaI];
- cResult1 =
- state->cmykTransferM[((alphaI - aSrc) * cDest[1] +
- aSrc * ((255 - alphaIm1) * cSrc[1] +
- alphaIm1 * cBlend[1]) / 255) /
- alphaI];
- cResult2 =
- state->cmykTransferY[((alphaI - aSrc) * cDest[2] +
- aSrc * ((255 - alphaIm1) * cSrc[2] +
- alphaIm1 * cBlend[2]) / 255) /
- alphaI];
- cResult3 =
- state->cmykTransferK[((alphaI - aSrc) * cDest[3] +
- aSrc * ((255 - alphaIm1) * cSrc[3] +
- alphaIm1 * cBlend[3]) / 255) /
- alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI;
+ cResult1 = ((alphaI - aSrc) * cDest[1] +
+ aSrc * ((255 - alphaIm1) * cSrc[1] +
+ alphaIm1 * cBlend[1]) / 255)
+ / alphaI;
+ cResult2 = ((alphaI - aSrc) * cDest[2] +
+ aSrc * ((255 - alphaIm1) * cSrc[2] +
+ alphaIm1 * cBlend[2]) / 255)
+ / alphaI;
+ cResult3 = ((alphaI - aSrc) * cDest[3] +
+ aSrc * ((255 - alphaIm1) * cSrc[3] +
+ alphaIm1 * cBlend[3]) / 255)
+ / alphaI;
}
break;
#endif
}
- //----- write destination pixel
+ } // if (noTransparency && !blendFunc)
- switch (bitmap->mode) {
- case splashModeMono1:
- if (state->screen->test(x, y, cResult0)) {
- *destColorPtr |= destColorMask;
- } else {
- *destColorPtr &= ~destColorMask;
- }
- destColorPtr += destColorMask & 1;
- destColorMask = (destColorMask << 7) | (destColorMask >> 1);
- break;
- case splashModeMono8:
- *destColorPtr++ = cResult0;
- break;
- case splashModeRGB8:
- destColorPtr[0] = cResult0;
- destColorPtr[1] = cResult1;
- destColorPtr[2] = cResult2;
- destColorPtr += 3;
- break;
- case splashModeBGR8:
- destColorPtr[0] = cResult2;
- destColorPtr[1] = cResult1;
- destColorPtr[2] = cResult0;
- destColorPtr += 3;
- break;
+ //----- write destination pixel
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ if (state->screen->test(x, y, cResult0)) {
+ *destColorPtr |= destColorMask;
+ } else {
+ *destColorPtr &= ~destColorMask;
+ }
+ destColorPtr += destColorMask & 1;
+ destColorMask = (destColorMask << 7) | (destColorMask >> 1);
+ break;
+ case splashModeMono8:
+ *destColorPtr++ = cResult0;
+ break;
+ case splashModeRGB8:
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr += 3;
+ break;
+ case splashModeBGR8:
+ destColorPtr[0] = cResult2;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult0;
+ destColorPtr += 3;
+ break;
#if SPLASH_CMYK
- case splashModeCMYK8:
- destColorPtr[0] = cResult0;
- destColorPtr[1] = cResult1;
- destColorPtr[2] = cResult2;
- destColorPtr[3] = cResult3;
- destColorPtr += 4;
- break;
+ case splashModeCMYK8:
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr[3] = cResult3;
+ destColorPtr += 4;
+ break;
#endif
- }
- if (destAlphaPtr) {
- *destAlphaPtr++ = aResult;
- }
-
- } // if (noTransparency && !blendFunc)
+ }
+ if (destAlphaPtr) {
+ *destAlphaPtr++ = aResult;
+ }
cSrcPtr += cSrcStride;
shapePtr2 += shapeStride;
@@ -821,6 +802,7 @@ void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y,
Guchar cResult0;
SplashColorPtr destColorPtr;
Guchar destColorMask;
+ SplashScreenCursor screenCursor;
int cSrcStride, x;
if (cSrcPtr) {
@@ -839,11 +821,13 @@ void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y,
destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
destColorMask = 0x80 >> (x0 & 7);
+ screenCursor = state->screen->getTestCursor(y);
+
for (x = x0; x <= x1; ++x) {
//----- write destination pixel
cResult0 = state->grayTransfer[cSrcPtr[0]];
- if (state->screen->test(x, y, cResult0)) {
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
*destColorPtr |= destColorMask;
} else {
*destColorPtr &= ~destColorMask;
@@ -1013,9 +997,10 @@ void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y,
// bitmap->mode == splashModeMono1 && !bitmap->alpha
void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
- Guchar shape, aSrc, cDest0, cResult0;
+ Guchar shape, aSrc, cSrc0, cDest0, cResult0;
SplashColorPtr destColorPtr;
Guchar destColorMask;
+ SplashScreenCursor screenCursor;
int cSrcStride, x, lastX;
if (cSrcPtr) {
@@ -1041,6 +1026,8 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
destColorMask = 0x80 >> (x0 & 7);
+ screenCursor = state->screen->getTestCursor(y);
+
for (x = x0; x <= x1; ++x) {
//----- shape
@@ -1054,19 +1041,27 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
}
lastX = x;
- //----- read destination pixel
- cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
//----- source alpha
aSrc = shape;
- //----- result color
- // note: aDest = alphaI = aResult = 0xff
- cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest0 +
- aSrc * cSrcPtr[0])];
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+
+ //----- result color
+ // note: aDest = alphaI = aResult = 0xff
+ cResult0 = (Guchar)div255((0xff - aSrc) * cDest0 + aSrc * cSrc0);
+ }
//----- write destination pixel
- if (state->screen->test(x, y, cResult0)) {
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
*destColorPtr |= destColorMask;
} else {
*destColorPtr &= ~destColorMask;
@@ -1086,7 +1081,7 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
// bitmap->mode == splashModeMono8 && bitmap->alpha
void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
- Guchar shape, aSrc, aDest, alphaI, aResult, cDest0, cResult0;
+ Guchar shape, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0;
SplashColorPtr destColorPtr;
Guchar *destAlphaPtr;
int cSrcStride, x, lastX;
@@ -1127,23 +1122,37 @@ void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y,
}
lastX = x;
- //----- read destination pixel
- cDest0 = *destColorPtr;
- aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
//----- source alpha
aSrc = shape;
- //----- result alpha and non-isolated group element correction
- aResult = aSrc + aDest - div255(aSrc * aDest);
- alphaI = aResult;
-
- //----- result color
- if (alphaI == 0) {
- cResult0 = 0;
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
} else {
- cResult0 = state->grayTransfer[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = *destColorPtr;
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ }
}
//----- write destination pixel
@@ -1163,6 +1172,7 @@ void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y,
void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
Guchar cDest0, cDest1, cDest2;
Guchar cResult0, cResult1, cResult2;
SplashColorPtr destColorPtr;
@@ -1205,31 +1215,47 @@ void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y,
}
lastX = x;
- //----- read destination pixel
- cDest0 = destColorPtr[0];
- cDest1 = destColorPtr[1];
- cDest2 = destColorPtr[2];
- aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
//----- source alpha
aSrc = shape;
- //----- result alpha and non-isolated group element correction
- aResult = aSrc + aDest - div255(aSrc * aDest);
- alphaI = aResult;
-
- //----- result color
- if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
} else {
- cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
- cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrcPtr[1]) / alphaI)];
- cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrcPtr[2]) / alphaI)];
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
}
//----- write destination pixel
@@ -1252,6 +1278,7 @@ void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y,
void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
Guchar cDest0, cDest1, cDest2;
Guchar cResult0, cResult1, cResult2;
SplashColorPtr destColorPtr;
@@ -1294,31 +1321,47 @@ void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y,
}
lastX = x;
- //----- read destination pixel
- cDest0 = destColorPtr[2];
- cDest1 = destColorPtr[1];
- cDest2 = destColorPtr[0];
- aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
//----- source alpha
aSrc = shape;
- //----- result alpha and non-isolated group element correction
- aResult = aSrc + aDest - div255(aSrc * aDest);
- alphaI = aResult;
-
- //----- result color
- if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
} else {
- cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
- cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrcPtr[1]) / alphaI)];
- cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrcPtr[2]) / alphaI)];
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[2];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[0];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
}
//----- write destination pixel
@@ -1394,22 +1437,22 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y,
//----- overprint
if (state->overprintMask & 1) {
- cSrc0 = cSrcPtr[0];
+ cSrc0 = state->cmykTransferC[cSrcPtr[0]];
} else {
cSrc0 = div255(aDest * cDest0);
}
if (state->overprintMask & 2) {
- cSrc1 = cSrcPtr[1];
+ cSrc1 = state->cmykTransferM[cSrcPtr[1]];
} else {
cSrc1 = div255(aDest * cDest1);
}
if (state->overprintMask & 4) {
- cSrc2 = cSrcPtr[2];
+ cSrc2 = state->cmykTransferY[cSrcPtr[2]];
} else {
cSrc2 = div255(aDest * cDest2);
}
if (state->overprintMask & 8) {
- cSrc3 = cSrcPtr[3];
+ cSrc3 = state->cmykTransferK[cSrcPtr[3]];
} else {
cSrc3 = div255(aDest * cDest3);
}
@@ -1417,25 +1460,34 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y,
//----- source alpha
aSrc = shape;
- //----- result alpha and non-isolated group element correction
- aResult = aSrc + aDest - div255(aSrc * aDest);
- alphaI = aResult;
-
- //----- result color
- if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
- cResult3 = 0;
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ cResult3 = cSrc3;
} else {
- cResult0 = state->cmykTransferC[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrc0) / alphaI)];
- cResult1 = state->cmykTransferM[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrc1) / alphaI)];
- cResult2 = state->cmykTransferY[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrc2) / alphaI)];
- cResult3 = state->cmykTransferK[(Guchar)(((alphaI - aSrc) * cDest3 +
- aSrc * cSrc3) / alphaI)];
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ cResult3 = cSrc3;
+ } else {
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest3 + aSrc * cSrc3) / alphaI);
+ }
}
//----- write destination pixel
@@ -1462,9 +1514,10 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y,
// bitmap->mode == splashModeMono1 && !bitmap->alpha
void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
- Guchar shape, aSrc, cDest0, cResult0;
+ Guchar shape, aSrc, cSrc0, cDest0, cResult0;
SplashColorPtr destColorPtr;
Guchar destColorMask;
+ SplashScreenCursor screenCursor;
int cSrcStride, x, lastX;
if (cSrcPtr) {
@@ -1490,6 +1543,8 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
destColorMask = 0x80 >> (x0 & 7);
+ screenCursor = state->screen->getTestCursor(y);
+
for (x = x0; x <= x1; ++x) {
//----- shape
@@ -1506,16 +1561,18 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
//----- read destination pixel
cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
//----- source alpha
aSrc = div255(pipe->aInput * shape);
//----- result color
// note: aDest = alphaI = aResult = 0xff
- cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest0 +
- aSrc * cSrcPtr[0])];
+ cResult0 = (Guchar)div255((0xff - aSrc) * cDest0 + aSrc * cSrc0);
//----- write destination pixel
- if (state->screen->test(x, y, cResult0)) {
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
*destColorPtr |= destColorMask;
} else {
*destColorPtr &= ~destColorMask;
@@ -1537,7 +1594,7 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
// bitmap->mode == splashModeMono8 && bitmap->alpha
void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
- Guchar shape, aSrc, aDest, alphaI, aResult, cDest0, cResult0;
+ Guchar shape, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0;
SplashColorPtr destColorPtr;
Guchar *destAlphaPtr;
int cSrcStride, x, lastX;
@@ -1582,6 +1639,9 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
cDest0 = *destColorPtr;
aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
//----- source alpha
aSrc = div255(pipe->aInput * shape);
@@ -1593,8 +1653,7 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
if (alphaI == 0) {
cResult0 = 0;
} else {
- cResult0 = state->grayTransfer[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
}
//----- write destination pixel
@@ -1616,6 +1675,7 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
Guchar cDest0, cDest1, cDest2;
Guchar cResult0, cResult1, cResult2;
SplashColorPtr destColorPtr;
@@ -1664,6 +1724,11 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
cDest2 = destColorPtr[2];
aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
//----- source alpha
aSrc = div255(pipe->aInput * shape);
@@ -1677,12 +1742,9 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
- cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrcPtr[1]) / alphaI)];
- cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrcPtr[2]) / alphaI)];
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
}
//----- write destination pixel
@@ -1707,6 +1769,7 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
Guchar cDest0, cDest1, cDest2;
Guchar cResult0, cResult1, cResult2;
SplashColorPtr destColorPtr;
@@ -1755,6 +1818,11 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y,
cDest2 = destColorPtr[0];
aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
//----- source alpha
aSrc = div255(pipe->aInput * shape);
@@ -1768,12 +1836,9 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y,
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
- cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrcPtr[1]) / alphaI)];
- cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrcPtr[2]) / alphaI)];
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
}
//----- write destination pixel
@@ -1851,22 +1916,22 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y,
//----- overprint
if (state->overprintMask & 1) {
- cSrc0 = cSrcPtr[0];
+ cSrc0 = state->cmykTransferC[cSrcPtr[0]];
} else {
cSrc0 = div255(aDest * cDest0);
}
if (state->overprintMask & 2) {
- cSrc1 = cSrcPtr[1];
+ cSrc1 = state->cmykTransferM[cSrcPtr[1]];
} else {
cSrc1 = div255(aDest * cDest1);
}
if (state->overprintMask & 4) {
- cSrc2 = cSrcPtr[2];
+ cSrc2 = state->cmykTransferY[cSrcPtr[2]];
} else {
cSrc2 = div255(aDest * cDest2);
}
if (state->overprintMask & 8) {
- cSrc3 = cSrcPtr[3];
+ cSrc3 = state->cmykTransferK[cSrcPtr[3]];
} else {
cSrc3 = div255(aDest * cDest3);
}
@@ -1885,14 +1950,10 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y,
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 = state->cmykTransferC[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrc0) / alphaI)];
- cResult1 = state->cmykTransferM[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrc1) / alphaI)];
- cResult2 = state->cmykTransferY[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrc2) / alphaI)];
- cResult3 = state->cmykTransferK[(Guchar)(((alphaI - aSrc) * cDest3 +
- aSrc * cSrc3) / alphaI)];
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest3 + aSrc * cSrc3) / alphaI);
}
//----- write destination pixel
@@ -1931,8 +1992,6 @@ inline void Splash::transform(SplashCoord *matrix,
Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
SplashScreenParams *screenParams) {
- int i;
-
bitmap = bitmapA;
bitmapComps = splashColorModeNComps[bitmap->mode];
vectorAntialias = vectorAntialiasA;
@@ -1940,13 +1999,12 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
screenParams);
scanBuf = (Guchar *)gmalloc(bitmap->width);
- if (vectorAntialias) {
- for (i = 0; i <= 255; ++i) {
- aaGamma[i] = (Guchar)splashRound(
- splashPow((SplashCoord)i / (SplashCoord)255,
- splashAAGamma) * 255);
- }
+ if (bitmap->mode == splashModeMono1) {
+ scanBuf2 = (Guchar *)gmalloc(bitmap->width);
+ } else {
+ scanBuf2 = NULL;
}
+ groupBackBitmap = NULL;
minLineWidth = 0;
clearModRegion();
debugMode = gFalse;
@@ -1954,8 +2012,6 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
SplashScreen *screenA) {
- int i;
-
bitmap = bitmapA;
bitmapComps = splashColorModeNComps[bitmap->mode];
vectorAntialias = vectorAntialiasA;
@@ -1963,13 +2019,12 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
screenA);
scanBuf = (Guchar *)gmalloc(bitmap->width);
- if (vectorAntialias) {
- for (i = 0; i <= 255; ++i) {
- aaGamma[i] = (Guchar)splashRound(
- splashPow((SplashCoord)i / (SplashCoord)255,
- splashAAGamma) * 255);
- }
+ if (bitmap->mode == splashModeMono1) {
+ scanBuf2 = (Guchar *)gmalloc(bitmap->width);
+ } else {
+ scanBuf2 = NULL;
}
+ groupBackBitmap = NULL;
minLineWidth = 0;
clearModRegion();
debugMode = gFalse;
@@ -1981,6 +2036,7 @@ Splash::~Splash() {
}
delete state;
gfree(scanBuf);
+ gfree(scanBuf2);
}
//------------------------------------------------------------------------
@@ -2047,7 +2103,7 @@ SplashCoord Splash::getLineDashPhase() {
return state->lineDashPhase;
}
-GBool Splash::getStrokeAdjust() {
+SplashStrokeAdjustMode Splash::getStrokeAdjust() {
return state->strokeAdjust;
}
@@ -2128,7 +2184,7 @@ void Splash::setLineDash(SplashCoord *lineDash, int lineDashLength,
state->setLineDash(lineDash, lineDashLength, lineDashPhase);
}
-void Splash::setStrokeAdjust(GBool strokeAdjust) {
+void Splash::setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust) {
state->strokeAdjust = strokeAdjust;
}
@@ -2169,6 +2225,10 @@ void Splash::setOverprintMask(Guint overprintMask) {
state->overprintMask = overprintMask;
}
+void Splash::setEnablePathSimplification(GBool en) {
+ state->enablePathSimplification = en;
+}
+
//------------------------------------------------------------------------
// state save/restore
//------------------------------------------------------------------------
@@ -2300,7 +2360,8 @@ void Splash::clear(SplashColorPtr color, Guchar alpha) {
SplashError Splash::stroke(SplashPath *path) {
SplashPath *path2, *dPath;
- SplashCoord t0, t1, t2, t3, w, w2;
+ SplashCoord t0, t1, t2, t3, w, w2, lineDashMax, lineDashTotal;
+ int lineCap, lineJoin, i;
if (debugMode) {
printf("stroke [dash:%d] [width:%.2f]:\n",
@@ -2312,15 +2373,6 @@ SplashError Splash::stroke(SplashPath *path) {
return splashErrEmptyPath;
}
path2 = flattenPath(path, state->matrix, state->flatness);
- if (state->lineDashLength > 0) {
- dPath = makeDashedPath(path2);
- delete path2;
- path2 = dPath;
- if (path2->length == 0) {
- delete path2;
- return splashErrEmptyPath;
- }
- }
// Compute an approximation of the transformed line width.
// Given a CTM of [m0 m1],
@@ -2341,10 +2393,62 @@ SplashError Splash::stroke(SplashPath *path) {
w = (t1 < t2) ? t1 : t2;
}
w2 = w * state->lineWidth;
+
+ // construct the dashed path
+ if (state->lineDashLength > 0) {
+
+ // check the maximum transformed dash element length (using the
+ // same approximation as for line width) -- if it's less than 0.1
+ // pixel, don't apply the dash pattern; this avoids a huge
+ // performance/memory hit with PDF files that use absurd dash
+ // patterns like [0.0007 0.0003]
+ lineDashTotal = 0;
+ lineDashMax = 0;
+ for (i = 0; i < state->lineDashLength; ++i) {
+ lineDashTotal += state->lineDash[i];
+ if (state->lineDash[i] > lineDashMax) {
+ lineDashMax = state->lineDash[i];
+ }
+ }
+ // Acrobat simply draws nothing if the dash array is [0]
+ if (lineDashTotal == 0) {
+ delete path2;
+ return splashOk;
+ }
+ if (w * lineDashMax > 0.1) {
+
+ dPath = makeDashedPath(path2);
+ delete path2;
+ path2 = dPath;
+ if (path2->length == 0) {
+ delete path2;
+ return splashErrEmptyPath;
+ }
+ }
+ }
+
+ // round caps on narrow lines look bad, and can't be
+ // stroke-adjusted, so use projecting caps instead (but we can't do
+ // this if there are zero-length dashes or segments, because those
+ // turn into round dots)
+ lineCap = state->lineCap;
+ lineJoin = state->lineJoin;
+ if (state->strokeAdjust == splashStrokeAdjustCAD &&
+ w2 < 3.5) {
+ if (lineCap == splashLineCapRound &&
+ !state->lineDashContainsZeroLengthDashes() &&
+ !path->containsZeroLengthSubpaths()) {
+ lineCap = splashLineCapProjecting;
+ }
+ if (lineJoin == splashLineJoinRound) {
+ lineJoin = splashLineJoinBevel;
+ }
+ }
+
// if there is a min line width set, and the transformed line width
// is smaller, use the min line width
if (w > 0 && w2 < minLineWidth) {
- strokeWide(path2, minLineWidth / w);
+ strokeWide(path2, minLineWidth / w, splashLineCapButt, splashLineJoinBevel);
} else if (bitmap->mode == splashModeMono1) {
// in monochrome mode, use 0-width lines for any transformed line
// width <= 1 -- lines less than 1 pixel wide look too fat without
@@ -2352,7 +2456,7 @@ SplashError Splash::stroke(SplashPath *path) {
if (w2 < 1.001) {
strokeNarrow(path2);
} else {
- strokeWide(path2, state->lineWidth);
+ strokeWide(path2, state->lineWidth, lineCap, lineJoin);
}
} else {
// in gray and color modes, only use 0-width lines if the line
@@ -2360,7 +2464,7 @@ SplashError Splash::stroke(SplashPath *path) {
if (state->lineWidth == 0) {
strokeNarrow(path2);
} else {
- strokeWide(path2, state->lineWidth);
+ strokeWide(path2, state->lineWidth, lineCap, lineJoin);
}
}
@@ -2380,7 +2484,9 @@ void Splash::strokeNarrow(SplashPath *path) {
nClipRes[0] = nClipRes[1] = nClipRes[2] = 0;
- xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse);
+ xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse,
+ state->enablePathSimplification,
+ state->strokeAdjust);
pipeInit(&pipe, state->strokePattern,
(Guchar)splashRound(state->strokeAlpha * 255),
@@ -2497,10 +2603,11 @@ void Splash::drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y,
(this->*pipe->run)(pipe, x0, x1, y, scanBuf + x0, NULL);
}
-void Splash::strokeWide(SplashPath *path, SplashCoord w) {
+void Splash::strokeWide(SplashPath *path, SplashCoord w,
+ int lineCap, int lineJoin) {
SplashPath *path2;
- path2 = makeStrokePath(path, w, gFalse);
+ path2 = makeStrokePath(path, w, lineCap, lineJoin, gFalse);
fillWithPattern(path2, gFalse, state->strokePattern, state->strokeAlpha);
delete path2;
}
@@ -2636,8 +2743,8 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
SplashCoord lineDashTotal;
SplashCoord lineDashStartPhase, lineDashDist, segLen;
SplashCoord x0, y0, x1, y1, xa, ya;
- GBool lineDashStartOn, lineDashOn, newPath;
- int lineDashStartIdx, lineDashIdx;
+ GBool lineDashStartOn, lineDashEndOn, lineDashOn, newPath;
+ int lineDashStartIdx, lineDashIdx, subpathStart, nDashes;
int i, j, k;
lineDashTotal = 0;
@@ -2649,6 +2756,13 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
return new SplashPath();
}
lineDashStartPhase = state->lineDashPhase;
+ if (lineDashStartPhase > lineDashTotal * 2) {
+ i = splashFloor(lineDashStartPhase / (lineDashTotal * 2));
+ lineDashStartPhase -= lineDashTotal * i * 2;
+ } else if (lineDashStartPhase < 0) {
+ i = splashCeil(-lineDashStartPhase / (lineDashTotal * 2));
+ lineDashStartPhase += lineDashTotal * i * 2;
+ }
i = splashFloor(lineDashStartPhase / lineDashTotal);
lineDashStartPhase -= (SplashCoord)i * lineDashTotal;
lineDashStartOn = gTrue;
@@ -2657,7 +2771,9 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {
lineDashStartOn = !lineDashStartOn;
lineDashStartPhase -= state->lineDash[lineDashStartIdx];
- ++lineDashStartIdx;
+ if (++lineDashStartIdx == state->lineDashLength) {
+ lineDashStartIdx = 0;
+ }
}
}
@@ -2674,8 +2790,11 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
// initialize the dash parameters
lineDashOn = lineDashStartOn;
+ lineDashEndOn = lineDashStartOn;
lineDashIdx = lineDashStartIdx;
lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase;
+ subpathStart = dPath->length;
+ nDashes = 0;
// process each segment of the subpath
newPath = gTrue;
@@ -2691,11 +2810,31 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
// process the segment
while (segLen > 0) {
- if (lineDashDist >= segLen) {
+ // Special case for zero-length dash segments: draw a very
+ // short -- but not zero-length -- segment. This ensures that
+ // we get the correct behavior with butt and projecting line
+ // caps. The PS/PDF specs imply that zero-length segments are
+ // not drawn unless the line cap is round, but Acrobat and
+ // Ghostscript both draw very short segments (for butt caps)
+ // and squares (for projecting caps).
+ if (lineDashDist == 0) {
if (lineDashOn) {
if (newPath) {
dPath->moveTo(x0, y0);
newPath = gFalse;
+ ++nDashes;
+ }
+ xa = x0 + ((SplashCoord)0.001 / segLen) * (x1 - x0);
+ ya = y0 + ((SplashCoord)0.001 / segLen) * (y1 - y0);
+ dPath->lineTo(xa, ya);
+ }
+
+ } else if (lineDashDist >= segLen) {
+ if (lineDashOn) {
+ if (newPath) {
+ dPath->moveTo(x0, y0);
+ newPath = gFalse;
+ ++nDashes;
}
dPath->lineTo(x1, y1);
}
@@ -2709,6 +2848,7 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
if (newPath) {
dPath->moveTo(x0, y0);
newPath = gFalse;
+ ++nDashes;
}
dPath->lineTo(xa, ya);
}
@@ -2718,6 +2858,8 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
lineDashDist = 0;
}
+ lineDashEndOn = lineDashOn;
+
// get the next entry in the dash array
if (lineDashDist <= 0) {
lineDashOn = !lineDashOn;
@@ -2729,6 +2871,31 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
}
}
}
+
+ // in a closed subpath, where the dash pattern is "on" at both the
+ // start and end of the subpath, we need to merge the start and
+ // end to get a proper line join
+ if ((path->flags[j] & splashPathClosed) &&
+ lineDashStartOn &&
+ lineDashEndOn) {
+ if (nDashes == 1) {
+ dPath->close();
+ } else if (nDashes > 1) {
+ k = subpathStart;
+ do {
+ ++k;
+ dPath->lineTo(dPath->pts[k].x, dPath->pts[k].y);
+ } while (!(dPath->flags[k] & splashPathLast));
+ ++k;
+ memmove(&dPath->pts[subpathStart], &dPath->pts[k],
+ (dPath->length - k) * sizeof(SplashPathPoint));
+ memmove(&dPath->flags[subpathStart], &dPath->flags[k],
+ (dPath->length - k) * sizeof(Guchar));
+ dPath->length -= k - subpathStart;
+ dPath->curSubpath -= k - subpathStart;
+ }
+ }
+
i = j + 1;
}
@@ -2750,7 +2917,7 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
SplashPath *path2;
SplashXPath *xPath;
SplashXPathScanner *scanner;
- int xMin, yMin, xMax, yMax, x, y, t;
+ int xMin, yMin, xMax, xMin2, xMax2, yMax, y, t;
SplashClipResult clipRes;
if (path->length == 0) {
@@ -2763,7 +2930,9 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
path2 = tweakFillPath(path);
- xPath = new SplashXPath(path2, state->matrix, state->flatness, gTrue);
+ xPath = new SplashXPath(path2, state->matrix, state->flatness, gTrue,
+ state->enablePathSimplification,
+ state->strokeAdjust);
if (path2 != path) {
delete path2;
}
@@ -2806,23 +2975,25 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
// draw the spans
if (vectorAntialias && !inShading) {
for (y = yMin; y <= yMax; ++y) {
- scanner->getSpan(scanBuf, y, xMin, xMax);
- if (clipRes != splashClipAllInside) {
- state->clip->clipSpan(scanBuf, y, xMin, xMax, state->strokeAdjust);
- }
- for (x = xMin; x <= xMax; ++x) {
- scanBuf[x] = aaGamma[scanBuf[x]];
+ scanner->getSpan(scanBuf, y, xMin, xMax, &xMin2, &xMax2);
+ if (xMin2 <= xMax2) {
+ if (clipRes != splashClipAllInside) {
+ state->clip->clipSpan(scanBuf, y, xMin2, xMax2,
+ state->strokeAdjust);
+ }
+ (this->*pipe.run)(&pipe, xMin2, xMax2, y, scanBuf + xMin2, NULL);
}
- (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
}
} else {
for (y = yMin; y <= yMax; ++y) {
- scanner->getSpanBinary(scanBuf, y, xMin, xMax);
- if (clipRes != splashClipAllInside) {
- state->clip->clipSpanBinary(scanBuf, y, xMin, xMax,
- state->strokeAdjust);
+ scanner->getSpanBinary(scanBuf, y, xMin, xMax, &xMin2, &xMax2);
+ if (xMin2 <= xMax2) {
+ if (clipRes != splashClipAllInside) {
+ state->clip->clipSpanBinary(scanBuf, y, xMin2, xMax2,
+ state->strokeAdjust);
+ }
+ (this->*pipe.run)(&pipe, xMin2, xMax2, y, scanBuf + xMin2, NULL);
}
- (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
}
}
}
@@ -2849,7 +3020,7 @@ SplashPath *Splash::tweakFillPath(SplashPath *path) {
SplashCoord xx0, yy0, xx1, yy1, dx, dy, d, wx, wy, w;
int n;
- if (!state->strokeAdjust || path->hints) {
+ if (state->strokeAdjust == splashStrokeAdjustOff || path->hints) {
return path;
}
@@ -2887,7 +3058,7 @@ SplashPath *Splash::tweakFillPath(SplashPath *path) {
splashAbs(path->pts[1].y - path->pts[2].y) < 0.001)))) {
wx = state->matrix[0] + state->matrix[2];
wy = state->matrix[1] + state->matrix[3];
- w = sqrt(wx*wx + wy*wy);
+ w = splashSqrt(wx*wx + wy*wy);
if (w < 0.001) {
w = 0;
} else {
@@ -2905,7 +3076,7 @@ SplashPath *Splash::tweakFillPath(SplashPath *path) {
}
dx = xx1 - xx0;
dy = yy1 - yy0;
- d = sqrt(dx * dx + dy * dy);
+ d = splashSqrt(dx * dx + dy * dy);
if (d < 0.001) {
d = 0;
} else {
@@ -2995,6 +3166,10 @@ GBool Splash::pathAllOutside(SplashPath *path) {
} else if (y > yMax2) {
yMax2 = y;
}
+ // sanity-check the coordinates - xMinI/yMinI/xMaxI/yMaxI are
+ // 32-bit integers, so coords need to be < 2^31
+ SplashXPath::clampCoords(&xMin2, &yMin2);
+ SplashXPath::clampCoords(&xMax2, &yMax2);
xMinI = splashFloor(xMin2);
yMinI = splashFloor(yMin2);
xMaxI = splashFloor(xMax2);
@@ -3005,77 +3180,6 @@ GBool Splash::pathAllOutside(SplashPath *path) {
splashClipAllOutside;
}
-SplashError Splash::xorFill(SplashPath *path, GBool eo) {
- SplashPipe pipe;
- SplashXPath *xPath;
- SplashXPathScanner *scanner;
- int xMin, yMin, xMax, yMax, y, t;
- SplashClipResult clipRes;
- SplashBlendFunc origBlendFunc;
-
- if (path->length == 0) {
- return splashErrEmptyPath;
- }
- if (pathAllOutside(path)) {
- opClipRes = splashClipAllOutside;
- return splashOk;
- }
- xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
- xMin = xPath->getXMin();
- yMin = xPath->getYMin();
- xMax = xPath->getXMax();
- yMax = xPath->getYMax();
- if (xMin > xMax || yMin > yMax) {
- delete xPath;
- return splashOk;
- }
- scanner = new SplashXPathScanner(xPath, eo, yMin, yMax);
-
- // check clipping
- if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax,
- state->strokeAdjust))
- != splashClipAllOutside) {
-
- if ((t = state->clip->getXMinI(state->strokeAdjust)) > xMin) {
- xMin = t;
- }
- if ((t = state->clip->getXMaxI(state->strokeAdjust)) < xMax) {
- xMax = t;
- }
- if ((t = state->clip->getYMinI(state->strokeAdjust)) > yMin) {
- yMin = t;
- }
- if ((t = state->clip->getYMaxI(state->strokeAdjust)) < yMax) {
- yMax = t;
- }
- if (xMin > xMax || yMin > yMax) {
- delete scanner;
- delete xPath;
- return splashOk;
- }
-
- origBlendFunc = state->blendFunc;
- state->blendFunc = &blendXor;
- pipeInit(&pipe, state->fillPattern, 255, gTrue, gFalse);
-
- // draw the spans
- for (y = yMin; y <= yMax; ++y) {
- scanner->getSpanBinary(scanBuf, y, xMin, xMax);
- if (clipRes != splashClipAllInside) {
- state->clip->clipSpanBinary(scanBuf, y, xMin, xMax,
- state->strokeAdjust);
- }
- (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
- }
- state->blendFunc = origBlendFunc;
- }
- opClipRes = clipRes;
-
- delete scanner;
- delete xPath;
- return splashOk;
-}
-
SplashError Splash::fillChar(SplashCoord x, SplashCoord y,
int c, SplashFont *font) {
SplashGlyphBitmap glyph;
@@ -3208,14 +3312,14 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
void Splash::getImageBounds(SplashCoord xyMin, SplashCoord xyMax,
int *xyMinI, int *xyMaxI) {
- if (state->strokeAdjust) {
- splashStrokeAdjust(xyMin, xyMax, xyMinI, xyMaxI);
- } else {
+ if (state->strokeAdjust == splashStrokeAdjustOff) {
*xyMinI = splashFloor(xyMin);
*xyMaxI = splashFloor(xyMax);
if (*xyMaxI <= *xyMinI) {
*xyMaxI = *xyMinI + 1;
}
+ } else {
+ splashStrokeAdjust(xyMin, xyMax, xyMinI, xyMaxI, state->strokeAdjust);
}
}
@@ -3254,8 +3358,14 @@ SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
// stream-mode upscaling -- this is slower, so we only use it if the
// upscaled mask is large (in which case clipping should remove many
// pixels)
- if (wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) {
+#if USE_FIXEDPOINT
+ if ((wSize > 2 * w && hSize > 2 * h && (int)wSize > 1000000 / (int)hSize) ||
+ (wSize > w && hSize > h && (int)wSize > 10000000 / (int)hSize)) {
+#else
+ if ((wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) ||
+ (wSize > w && hSize > h && wSize * hSize > 10000000)) {
upscaleMask(src, srcData, w, h, mat, glyphMode, interpolate);
+#endif
// scaling only
} else if (mat[0] > 0 && minorAxisZero && mat[3] > 0) {
@@ -3462,10 +3572,12 @@ void Splash::upscaleMask(SplashImageMaskSource src, void *srcData,
if (y1 >= srcHeight) {
y1 = srcHeight - 1;
}
- pix0 = ((SplashCoord)1 - sx) * unscaledImage[y0 * srcWidth + x0]
- + sx * unscaledImage[y0 * srcWidth + x1];
- pix1 = ((SplashCoord)1 - sx) * unscaledImage[y1 * srcWidth + x0]
- + sx * unscaledImage[y1 * srcWidth + x1];
+ pix0 = ((SplashCoord)1 - sx)
+ * (SplashCoord)unscaledImage[y0 * srcWidth + x0]
+ + sx * (SplashCoord)unscaledImage[y0 * srcWidth + x1];
+ pix1 = ((SplashCoord)1 - sx)
+ * (SplashCoord)unscaledImage[y1 * srcWidth + x0]
+ + sx * (SplashCoord)unscaledImage[y1 * srcWidth + x1];
scanBuf[x] = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0
+ sy * pix1);
} else {
@@ -4041,10 +4153,10 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
int scaledWidth, int scaledHeight,
SplashBitmap *dest) {
Guchar *lineBuf;
- Guint pix;
- Guchar *destPtr0, *destPtr;
- int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx;
- int i, j;
+ Guchar pix;
+ Guchar *srcPtr, *destPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep;
+ int i;
// Bresenham parameters for y scale
yp = scaledHeight / srcHeight;
@@ -4060,7 +4172,7 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
// init y scale Bresenham
yt = 0;
- destPtr0 = dest->data;
+ destPtr = dest->data;
for (y = 0; y < srcHeight; ++y) {
// y scale Bresenham
@@ -4077,7 +4189,8 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
// init x scale Bresenham
xt = 0;
- xx = 0;
+ // generate one row
+ srcPtr = lineBuf;
for (x = 0; x < srcWidth; ++x) {
// x scale Bresenham
@@ -4089,20 +4202,20 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
}
// compute the final pixel
- pix = lineBuf[x] ? 255 : 0;
+ pix = *srcPtr ? 255 : 0;
+ ++srcPtr;
- // store the pixel
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destPtr = destPtr0 + i * scaledWidth + xx + j;
- *destPtr++ = (Guchar)pix;
- }
+ // duplicate the pixel horizontally
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = pix;
}
-
- xx += xStep;
}
- destPtr0 += yStep * scaledWidth;
+ // duplicate the row vertically
+ for (i = 1 ; i < yStep; ++i) {
+ memcpy(destPtr, destPtr - scaledWidth, scaledWidth);
+ destPtr += scaledWidth;
+ }
}
gfree(lineBuf);
@@ -4149,11 +4262,11 @@ void Splash::scaleMaskYuXuI(SplashImageMaskSource src, void *srcData,
xSrc1 = srcWidth - 1;
}
lineBuf0[x] = (Guchar)(int)
- ((xs * lineBuf0[xSrc0] +
- ((SplashCoord)1 - xs) * lineBuf0[xSrc1]) * 255);
+ ((xs * (int)lineBuf0[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)lineBuf0[xSrc1]) * 255);
lineBuf1[x] = (Guchar)(int)
- ((xs * lineBuf1[xSrc0] +
- ((SplashCoord)1 - xs) * lineBuf1[xSrc1]) * 255);
+ ((xs * (int)lineBuf1[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)lineBuf1[xSrc1]) * 255);
}
destPtr = dest->data;
@@ -4193,8 +4306,8 @@ void Splash::scaleMaskYuXuI(SplashImageMaskSource src, void *srcData,
xSrc1 = srcWidth - 1;
}
lineBuf1[x] = (Guchar)(int)
- ((xs * lineBuf1[xSrc0] +
- ((SplashCoord)1 - xs) * lineBuf1[xSrc1]) * 255);
+ ((xs * (int)lineBuf1[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)lineBuf1[xSrc1]) * 255);
}
++yBuf;
@@ -4203,8 +4316,8 @@ void Splash::scaleMaskYuXuI(SplashImageMaskSource src, void *srcData,
// do the vertical interpolation
for (x = 0; x < scaledWidth; ++x) {
- pix = (Guchar)(int)(ys * lineBuf0[x] +
- ((SplashCoord)1 - ys) * lineBuf1[x]);
+ pix = (Guchar)(int)(ys * (int)lineBuf0[x] +
+ ((SplashCoord)1 - ys) * (int)lineBuf1[x]);
// store the pixel
*destPtr++ = pix;
@@ -4329,7 +4442,13 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData,
// stream-mode upscaling -- this is slower, so we only use it if the
// upscaled image is large (in which case clipping should remove
// many pixels)
- if (wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) {
+#if USE_FIXEDPOINT
+ if ((wSize > 2 * w && hSize > 2 * h && (int)wSize > 1000000 / (int)hSize) ||
+ (wSize > w && hSize > h && (int)wSize > 10000000 / (int)hSize)) {
+#else
+ if ((wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) ||
+ (wSize > w && hSize > h && wSize * hSize > 10000000)) {
+#endif
upscaleImage(src, srcData, srcMode, nComps, srcAlpha,
w, h, mat, interpolate);
@@ -4367,7 +4486,7 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData,
}
// scaling plus horizontal flip
- } else if (mat[0] > 0 && minorAxisZero && mat[3] > 0) {
+ } else if (mat[0] < 0 && minorAxisZero && mat[3] > 0) {
getImageBounds(mat[0] + mat[4], mat[4], &x0, &x1);
getImageBounds(mat[5], mat[3] + mat[5], &y0, &y1);
clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1,
@@ -4384,7 +4503,7 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData,
}
// scaling plus horizontal and vertical flips
- } else if (mat[0] > 0 && minorAxisZero && mat[3] < 0) {
+ } else if (mat[0] < 0 && minorAxisZero && mat[3] < 0) {
getImageBounds(mat[0] + mat[4], mat[4], &x0, &x1);
getImageBounds(mat[3] + mat[5], mat[5], &y0, &y1);
clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1,
@@ -4557,16 +4676,18 @@ void Splash::upscaleImage(SplashImageSource src, void *srcData,
q10 = &unscaledImage[(y1 * srcWidth + x0) * nComps];
q11 = &unscaledImage[(y1 * srcWidth + x1) * nComps];
for (i = 0; i < nComps; ++i) {
- pix0 = ((SplashCoord)1 - sx) * *q00++ + sx * *q01++;
- pix1 = ((SplashCoord)1 - sx) * *q10++ + sx * *q11++;
+ pix0 = ((SplashCoord)1 - sx) * (int)*q00++ + sx * (int)*q01++;
+ pix1 = ((SplashCoord)1 - sx) * (int)*q10++ + sx * (int)*q11++;
*p++ = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0
+ sy * pix1);
}
if (srcAlpha) {
- pix0 = ((SplashCoord)1 - sx) * unscaledAlpha[y0 * srcWidth + x0]
- + sx * unscaledAlpha[y0 * srcWidth + x1];
- pix1 = ((SplashCoord)1 - sx) * unscaledAlpha[y1 * srcWidth + x0]
- + sx * unscaledAlpha[y1 * srcWidth + x1];
+ pix0 = ((SplashCoord)1 - sx)
+ * (SplashCoord)unscaledAlpha[y0 * srcWidth + x0]
+ + sx * (SplashCoord)unscaledAlpha[y0 * srcWidth + x1];
+ pix1 = ((SplashCoord)1 - sx)
+ * (SplashCoord)unscaledAlpha[y1 * srcWidth + x0]
+ + sx * (SplashCoord)unscaledAlpha[y1 * srcWidth + x1];
scanBuf[x] = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0
+ sy * pix1);
} else {
@@ -5139,6 +5260,12 @@ void Splash::scaleImageYdXu(SplashImageSource src, void *srcData,
alphaPixBuf = NULL;
}
+ // make gcc happy
+ pix[0] = pix[1] = pix[2] = 0;
+#if SPLASH_CMYK
+ pix[3] = 0;
+#endif
+
// init y scale Bresenham
yt = 0;
@@ -5266,6 +5393,12 @@ void Splash::scaleImageYuXd(SplashImageSource src, void *srcData,
alphaLineBuf = NULL;
}
+ // make gcc happy
+ pix[0] = pix[1] = pix[2] = 0;
+#if SPLASH_CMYK
+ pix[3] = 0;
+#endif
+
// init y scale Bresenham
yt = 0;
@@ -5380,11 +5513,15 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
int scaledWidth, int scaledHeight,
SplashBitmap *dest) {
Guchar *lineBuf, *alphaLineBuf;
- Guint pix[splashMaxColorComps];
+ Guchar pix0, pix1, pix2;
+#if SPLASH_CMYK
+ Guchar pix3;
+#endif
Guint alpha;
- Guchar *destPtr0, *destPtr, *destAlphaPtr0, *destAlphaPtr;
- int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx;
- int i, j;
+ Guchar *srcPtr, *srcAlphaPtr;
+ Guchar *destPtr, *destAlphaPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep;
+ int i;
// Bresenham parameters for y scale
yp = scaledHeight / srcHeight;
@@ -5405,8 +5542,8 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
// init y scale Bresenham
yt = 0;
- destPtr0 = dest->data;
- destAlphaPtr0 = dest->alpha;
+ destPtr = dest->data;
+ destAlphaPtr = dest->alpha;
for (y = 0; y < srcHeight; ++y) {
// y scale Bresenham
@@ -5423,7 +5560,9 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
// init x scale Bresenham
xt = 0;
- xx = 0;
+ // generate one row
+ srcPtr = lineBuf;
+ srcAlphaPtr = alphaLineBuf;
for (x = 0; x < srcWidth; ++x) {
// x scale Bresenham
@@ -5434,41 +5573,35 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
xStep = xp;
}
- // compute the final pixel
- for (i = 0; i < nComps; ++i) {
- pix[i] = lineBuf[x * nComps + i];
- }
-
- // store the pixel
+ // duplicate the pixel horizontally
switch (srcMode) {
case splashModeMono8:
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
- *destPtr++ = (Guchar)pix[0];
- }
+ pix0 = *srcPtr++;
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = pix0;
}
break;
case splashModeRGB8:
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
- *destPtr++ = (Guchar)pix[0];
- *destPtr++ = (Guchar)pix[1];
- *destPtr++ = (Guchar)pix[2];
- }
+ pix0 = *srcPtr++;
+ pix1 = *srcPtr++;
+ pix2 = *srcPtr++;
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = pix0;
+ *destPtr++ = pix1;
+ *destPtr++ = pix2;
}
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
- *destPtr++ = (Guchar)pix[0];
- *destPtr++ = (Guchar)pix[1];
- *destPtr++ = (Guchar)pix[2];
- *destPtr++ = (Guchar)pix[3];
- }
+ pix0 = *srcPtr++;
+ pix1 = *srcPtr++;
+ pix2 = *srcPtr++;
+ pix3 = *srcPtr++;
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = pix0;
+ *destPtr++ = pix1;
+ *destPtr++ = pix2;
+ *destPtr++ = pix3;
}
break;
#endif
@@ -5478,23 +5611,26 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
break;
}
- // process alpha
+ // duplicate the alpha value horizontally
if (srcAlpha) {
- alpha = alphaLineBuf[x];
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destAlphaPtr = destAlphaPtr0 + i * scaledWidth + xx + j;
- *destAlphaPtr = (Guchar)alpha;
- }
+ alpha = *srcAlphaPtr++;
+ for (i = 0; i < xStep; ++i) {
+ *destAlphaPtr++ = alpha;
}
}
-
- xx += xStep;
}
- destPtr0 += yStep * scaledWidth * nComps;
+ // duplicate the row vertically
+ for (i = 1; i < yStep; ++i) {
+ memcpy(destPtr, destPtr - scaledWidth * nComps,
+ scaledWidth * nComps);
+ destPtr += scaledWidth * nComps;
+ }
if (srcAlpha) {
- destAlphaPtr0 += yStep * scaledWidth;
+ for (i = 1; i < yStep; ++i) {
+ memcpy(destAlphaPtr, destAlphaPtr - scaledWidth, scaledWidth);
+ destAlphaPtr += scaledWidth;
+ }
}
}
@@ -5555,22 +5691,28 @@ void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData,
}
for (i = 0; i < nComps; ++i) {
lineBuf0[x*nComps+i] = (Guchar)(int)
- (xs * lineBuf0[xSrc0*nComps+i] +
- ((SplashCoord)1 - xs) * lineBuf0[xSrc1*nComps+i]);
+ (xs * (int)lineBuf0[xSrc0*nComps+i] +
+ ((SplashCoord)1 - xs) * (int)lineBuf0[xSrc1*nComps+i]);
lineBuf1[x*nComps+i] = (Guchar)(int)
- (xs * lineBuf1[xSrc0*nComps+i] +
- ((SplashCoord)1 - xs) * lineBuf1[xSrc1*nComps+i]);
+ (xs * (int)lineBuf1[xSrc0*nComps+i] +
+ ((SplashCoord)1 - xs) * (int)lineBuf1[xSrc1*nComps+i]);
}
if (srcAlpha) {
alphaLineBuf0[x] = (Guchar)(int)
- (xs * alphaLineBuf0[xSrc0] +
- ((SplashCoord)1 - xs) * alphaLineBuf0[xSrc1]);
+ (xs * (int)alphaLineBuf0[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)alphaLineBuf0[xSrc1]);
alphaLineBuf1[x] = (Guchar)(int)
- (xs * alphaLineBuf1[xSrc0] +
- ((SplashCoord)1 - xs) * alphaLineBuf1[xSrc1]);
+ (xs * (int)alphaLineBuf1[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)alphaLineBuf1[xSrc1]);
}
}
+ // make gcc happy
+ pix[0] = pix[1] = pix[2] = 0;
+#if SPLASH_CMYK
+ pix[3] = 0;
+#endif
+
destPtr = dest->data;
destAlphaPtr = dest->alpha;
for (y = 0; y < scaledHeight; ++y) {
@@ -5612,14 +5754,14 @@ void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData,
xSrc1 = srcWidth - 1;
}
for (i = 0; i < nComps; ++i) {
- lineBuf1[x*nComps+i] =
- (Guchar)(int)(xs * lineBuf1[xSrc0*nComps+i] +
- ((SplashCoord)1 - xs) * lineBuf1[xSrc1*nComps+i]);
+ lineBuf1[x*nComps+i] = (Guchar)(int)
+ (xs * (int)lineBuf1[xSrc0*nComps+i] +
+ ((SplashCoord)1 - xs) * (int)lineBuf1[xSrc1*nComps+i]);
}
if (srcAlpha) {
- alphaLineBuf1[x] =
- (Guchar)(int)(xs * alphaLineBuf1[xSrc0] +
- ((SplashCoord)1 - xs) * alphaLineBuf1[xSrc1]);
+ alphaLineBuf1[x] = (Guchar)(int)
+ (xs * (int)alphaLineBuf1[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)alphaLineBuf1[xSrc1]);
}
}
@@ -5630,8 +5772,9 @@ void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData,
for (x = 0; x < scaledWidth; ++x) {
for (i = 0; i < nComps; ++i) {
- pix[i] = (Guchar)(int)(ys * lineBuf0[x*nComps+i] +
- ((SplashCoord)1 - ys) * lineBuf1[x*nComps+i]);
+ pix[i] = (Guchar)(int)
+ (ys * (int)lineBuf0[x*nComps+i] +
+ ((SplashCoord)1 - ys) * (int)lineBuf1[x*nComps+i]);
}
// store the pixel
@@ -5661,8 +5804,8 @@ void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData,
// process alpha
if (srcAlpha) {
*destAlphaPtr++ = (Guchar)(int)
- (ys * alphaLineBuf0[x] +
- ((SplashCoord)1 - ys) * alphaLineBuf1[x]);
+ (ys * (int)alphaLineBuf0[x] +
+ ((SplashCoord)1 - ys) * (int)alphaLineBuf1[x]);
}
}
}
@@ -5878,82 +6021,287 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc,
int xDest, int yDest, int w, int h,
GBool noClip, GBool nonIsolated) {
SplashPipe pipe;
- int x0, x1, y0, y1, y, t;
+ Guchar *mono1Ptr, *lineBuf, *linePtr;
+ Guchar mono1Mask, b;
+ int x0, x1, x, y0, y1, y, t;
- if (src->mode != bitmap->mode) {
+ if (!(src->mode == bitmap->mode ||
+ (src->mode == splashModeMono8 && bitmap->mode == splashModeMono1) ||
+ (src->mode == splashModeRGB8 && bitmap->mode == splashModeBGR8))) {
return splashErrModeMismatch;
}
pipeInit(&pipe, NULL,
(Guchar)splashRound(state->fillAlpha * 255),
!noClip || src->alpha != NULL, nonIsolated);
- if (noClip) {
- if (src->alpha) {
- for (y = 0; y < h; ++y) {
- // this uses shape instead of alpha, which isn't technically
- // correct, but works out the same
- (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
- src->getAlphaPtr() +
- (ySrc + y) * src->getWidth() + xSrc,
- src->getDataPtr() + (ySrc + y) * src->getRowSize() +
- xSrc * bitmapComps);
+ if (src->mode == splashModeMono1) {
+ // in mono1 mode, pipeRun expects the source to be in mono8
+ // format, so we need to extract the source color values into
+ // scanBuf, expanding them from mono1 to mono8
+ if (noClip) {
+ if (src->alpha) {
+ for (y = 0; y < h; ++y) {
+ mono1Ptr = src->getDataPtr()
+ + (ySrc + y) * src->rowSize + (xSrc >> 3);
+ mono1Mask = 0x80 >> (xSrc & 7);
+ for (x = 0; x < w; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (mono1Mask << 7) | (mono1Mask >> 1);
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->getAlphaPtr() +
+ (ySrc + y) * src->getWidth() + xSrc,
+ scanBuf);
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ mono1Ptr = src->getDataPtr()
+ + (ySrc + y) * src->rowSize + (xSrc >> 3);
+ mono1Mask = 0x80 >> (xSrc & 7);
+ for (x = 0; x < w; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (mono1Mask << 7) | (mono1Mask >> 1);
+ }
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ NULL,
+ scanBuf);
+ }
}
} else {
- for (y = 0; y < h; ++y) {
- (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
- NULL,
- src->getDataPtr() + (ySrc + y) * src->getRowSize() +
- xSrc * bitmapComps);
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ mono1Ptr = src->getDataPtr()
+ + (ySrc + y - yDest) * src->rowSize
+ + ((xSrc + x0 - xDest) >> 3);
+ mono1Mask = 0x80 >> ((xSrc + x0 - xDest) & 7);
+ for (x = x0; x < x1; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (mono1Mask << 7) | (mono1Mask >> 1);
+ }
+ memcpy(scanBuf2 + x0,
+ src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ if (!state->clip->clipSpanBinary(scanBuf2, y, x0, x1 - 1,
+ state->strokeAdjust)) {
+ continue;
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf2 + x0,
+ scanBuf + x0);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ mono1Ptr = src->getDataPtr()
+ + (ySrc + y - yDest) * src->rowSize
+ + ((xSrc + x0 - xDest) >> 3);
+ mono1Mask = 0x80 >> ((xSrc + x0 - xDest) & 7);
+ for (x = x0; x < x1; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (mono1Mask << 7) | (mono1Mask >> 1);
+ }
+ memset(scanBuf2 + x0, 0xff, x1 - x0);
+ if (!state->clip->clipSpanBinary(scanBuf2, y, x0, x1 - 1,
+ state->strokeAdjust)) {
+ continue;
+ }
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf2 + x0,
+ scanBuf + x0);
+ }
+ }
}
}
- } else {
- x0 = xDest;
- if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
- x0 = t;
- }
- x1 = xDest + w;
- if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
- x1 = t;
- }
- y0 = yDest;
- if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
- y0 = t;
- }
- y1 = yDest + h;
- if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
- y1 = t;
- }
- if (x0 < x1 && y0 < y1) {
+
+ } else if (src->mode == splashModeBGR8) {
+ // in BGR8 mode, pipeRun expects the source to be in RGB8 format,
+ // so we need to swap bytes
+ lineBuf = (Guchar *)gmallocn(w, 3);
+ if (noClip) {
if (src->alpha) {
- for (y = y0; y < y1; ++y) {
- memcpy(scanBuf + x0,
- src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() +
- (xSrc + x0 - xDest),
- x1 - x0);
- if (!state->clip->clipSpanBinary(scanBuf, y, x0, x1 - 1,
- state->strokeAdjust)) {
- continue;
+ for (y = 0; y < h; ++y) {
+ memcpy(lineBuf,
+ src->getDataPtr() + (ySrc + y) * src->rowSize + xSrc * 3,
+ w * 3);
+ for (x = 0, linePtr = lineBuf; x < w; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
}
// this uses shape instead of alpha, which isn't technically
// correct, but works out the same
- (this->*pipe.run)(&pipe, x0, x1 - 1, y,
- scanBuf + x0,
- src->getDataPtr() +
- (ySrc + y - yDest) * src->getRowSize() +
- (xSrc + x0 - xDest) * bitmapComps);
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->getAlphaPtr() +
+ (ySrc + y) * src->getWidth() + xSrc,
+ lineBuf);
}
} else {
- for (y = y0; y < y1; ++y) {
- memset(scanBuf + x0, 0xff, x1 - x0);
- if (!state->clip->clipSpanBinary(scanBuf, y, x0, x1 - 1,
- state->strokeAdjust)) {
- continue;
+ for (y = 0; y < h; ++y) {
+ memcpy(lineBuf,
+ src->getDataPtr() + (ySrc + y) * src->rowSize + xSrc * 3,
+ w * 3);
+ for (x = 0, linePtr = lineBuf; x < w; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
}
(this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
- scanBuf + x0,
- src->getDataPtr() +
- (ySrc + y - yDest) * src->getRowSize() +
- (xSrc - xDest) * bitmapComps);
+ NULL, lineBuf);
+ }
+ }
+ } else {
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ memcpy(scanBuf + x0,
+ src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ memcpy(lineBuf,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * 3,
+ (x1 - x0) * 3);
+ for (x = 0, linePtr = lineBuf; x < x1 - x0; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf + x0, lineBuf);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ memset(scanBuf + x0, 0xff, x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ memcpy(lineBuf,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * 3,
+ (x1 - x0) * 3);
+ for (x = 0, linePtr = lineBuf; x < x1 - x0; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
+ }
+ (this->*pipe.run)(&pipe, x0, x1 - 1, yDest + y,
+ scanBuf + x0,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ }
+ }
+ }
+ gfree(lineBuf);
+
+ } else { // src->mode not mono1 or BGR8
+ if (noClip) {
+ if (src->alpha) {
+ for (y = 0; y < h; ++y) {
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->getAlphaPtr() +
+ (ySrc + y) * src->getWidth() + xSrc,
+ src->getDataPtr() + (ySrc + y) * src->rowSize +
+ xSrc * bitmapComps);
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ NULL,
+ src->getDataPtr() + (ySrc + y) * src->rowSize +
+ xSrc * bitmapComps);
+ }
+ }
+ } else {
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ memcpy(scanBuf + x0,
+ src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf + x0,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ memset(scanBuf + x0, 0xff, x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ (this->*pipe.run)(&pipe, x0, x1 - 1, yDest + y,
+ scanBuf + x0,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
}
}
}
@@ -5980,13 +6328,21 @@ void Splash::compositeBackground(SplashColorPtr color) {
mask = 0x80;
for (x = 0; x < bitmap->width; ++x) {
alpha = *q++;
- alpha1 = 255 - alpha;
- c = (*p & mask) ? 0xff : 0x00;
- c = div255(alpha1 * color0 + alpha * c);
- if (c & 0x80) {
- *p |= mask;
- } else {
- *p &= ~mask;
+ if (alpha == 0) {
+ if (color0 & 0x80) {
+ *p |= mask;
+ } else {
+ *p &= ~mask;
+ }
+ } else if (alpha != 255) {
+ alpha1 = 255 - alpha;
+ c = (*p & mask) ? 0xff : 0x00;
+ c = div255(alpha1 * color0 + alpha * c);
+ if (c & 0x80) {
+ *p |= mask;
+ } else {
+ *p &= ~mask;
+ }
}
if (!(mask >>= 1)) {
mask = 0x80;
@@ -6002,8 +6358,12 @@ void Splash::compositeBackground(SplashColorPtr color) {
q = &bitmap->alpha[y * bitmap->width];
for (x = 0; x < bitmap->width; ++x) {
alpha = *q++;
- alpha1 = 255 - alpha;
- p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ if (alpha == 0) {
+ p[0] = color0;
+ } else if (alpha != 255) {
+ alpha1 = 255 - alpha;
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ }
++p;
}
}
@@ -6018,10 +6378,16 @@ void Splash::compositeBackground(SplashColorPtr color) {
q = &bitmap->alpha[y * bitmap->width];
for (x = 0; x < bitmap->width; ++x) {
alpha = *q++;
- alpha1 = 255 - alpha;
- p[0] = div255(alpha1 * color0 + alpha * p[0]);
- p[1] = div255(alpha1 * color1 + alpha * p[1]);
- p[2] = div255(alpha1 * color2 + alpha * p[2]);
+ if (alpha == 0) {
+ p[0] = color0;
+ p[1] = color1;
+ p[2] = color2;
+ } else if (alpha != 255) {
+ alpha1 = 255 - alpha;
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ p[1] = div255(alpha1 * color1 + alpha * p[1]);
+ p[2] = div255(alpha1 * color2 + alpha * p[2]);
+ }
p += 3;
}
}
@@ -6037,11 +6403,18 @@ void Splash::compositeBackground(SplashColorPtr color) {
q = &bitmap->alpha[y * bitmap->width];
for (x = 0; x < bitmap->width; ++x) {
alpha = *q++;
- alpha1 = 255 - alpha;
- p[0] = div255(alpha1 * color0 + alpha * p[0]);
- p[1] = div255(alpha1 * color1 + alpha * p[1]);
- p[2] = div255(alpha1 * color2 + alpha * p[2]);
- p[3] = div255(alpha1 * color3 + alpha * p[3]);
+ if (alpha == 0) {
+ p[0] = color0;
+ p[1] = color1;
+ p[2] = color2;
+ p[3] = color3;
+ } else if (alpha != 255) {
+ alpha1 = 255 - alpha;
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ p[1] = div255(alpha1 * color1 + alpha * p[1]);
+ p[2] = div255(alpha1 * color2 + alpha * p[2]);
+ p[3] = div255(alpha1 * color3 + alpha * p[3]);
+ }
p += 4;
}
}
@@ -6120,11 +6493,95 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
return splashOk;
}
+SplashError Splash::blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h) {
+ SplashColorPtr p, q;
+ Guchar *alpha0Ptr;
+ Guchar alpha0, aSrc;
+ int x, y, mask, srcMask;
+
+ if (bitmap->mode != dest->mode ||
+ !bitmap->alpha ||
+ !dest->alpha ||
+ !groupBackBitmap) {
+ return splashErrModeMismatch;
+ }
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + (xDest >> 3)];
+ mask = 0x80 >> (xDest & 7);
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + (xSrc >> 3)];
+ srcMask = 0x80 >> (xSrc & 7);
+ for (x = 0; x < w; ++x) {
+ if (*q & srcMask) {
+ *p |= mask;
+ } else {
+ *p &= ~mask;
+ }
+ if (!(mask >>= 1)) {
+ mask = 0x80;
+ ++p;
+ }
+ if (!(srcMask >>= 1)) {
+ srcMask = 0x80;
+ ++q;
+ }
+ }
+ }
+ break;
+ case splashModeMono8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + xSrc];
+ memcpy(p, q, w);
+ }
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + 3 * xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + 3 * xSrc];
+ memcpy(p, q, 3 * w);
+ }
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + 4 * xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + 4 * xSrc];
+ memcpy(p, q, 4 * w);
+ }
+ break;
+#endif
+ }
+
+ for (y = 0; y < h; ++y) {
+ p = &dest->alpha[(yDest + y) * dest->width + xDest];
+ q = &bitmap->alpha[(ySrc + y) * bitmap->width + xSrc];
+ alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + ySrc + y)
+ * groupBackBitmap->width +
+ (groupBackX + xSrc)];
+ for (x = 0; x < w; ++x) {
+ alpha0 = *alpha0Ptr++;
+ aSrc = *q++;
+ *p++ = alpha0 + aSrc - div255(alpha0 * aSrc);
+ }
+ }
+
+ return splashOk;
+}
+
SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
- GBool flatten) {
+ int lineCap, int lineJoin,
+ GBool flatten) {
SplashPath *pathIn, *dashPath, *pathOut;
SplashCoord d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext;
SplashCoord crossprod, dotprod, miter, m;
+ SplashCoord angle, angleNext, dAngle, xc, yc;
+ SplashCoord dxJoin, dyJoin, dJoin, kappa;
+ SplashCoord cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
GBool first, last, closed;
int subpathStart0, subpathStart1, seg, i0, i1, j0, j1, k0, k1;
int left0, left1, left2, right0, right1, right2, join0, join1, join2;
@@ -6184,7 +6641,7 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
j1 = j0;
}
if (pathIn->flags[i1] & splashPathLast) {
- if (first && state->lineCap == splashLineCapRound) {
+ if (first && lineCap == splashLineCapRound) {
// special case: zero-length subpath with round line caps -->
// draw a circle
pathOut->moveTo(pathIn->pts[i0].x + (SplashCoord)0.5 * w,
@@ -6250,16 +6707,17 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
wdy = (SplashCoord)0.5 * w * dy;
// draw the start cap
- pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
if (i0 == subpathStart0) {
- firstPt = pathOut->length - 1;
+ firstPt = pathOut->length;
}
if (first && !closed) {
- switch (state->lineCap) {
+ switch (lineCap) {
case splashLineCapButt:
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
break;
case splashLineCapRound:
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
pathOut->curveTo(pathIn->pts[i0].x - wdy - bezierCircle * wdx,
pathIn->pts[i0].y + wdx - bezierCircle * wdy,
pathIn->pts[i0].x - wdx - bezierCircle * wdy,
@@ -6274,29 +6732,27 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
pathIn->pts[i0].y - wdx);
break;
case splashLineCapProjecting:
- pathOut->lineTo(pathIn->pts[i0].x - wdx - wdy,
+ pathOut->moveTo(pathIn->pts[i0].x - wdx - wdy,
pathIn->pts[i0].y + wdx - wdy);
pathOut->lineTo(pathIn->pts[i0].x - wdx + wdy,
pathIn->pts[i0].y - wdx - wdy);
- pathOut->lineTo(pathIn->pts[i0].x + wdy,
- pathIn->pts[i0].y - wdx);
break;
}
} else {
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
}
- // draw the left side of the segment rectangle
+ // draw the left side of the segment rectangle and the end cap
left2 = pathOut->length - 1;
- pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
-
- // draw the end cap
if (last && !closed) {
- switch (state->lineCap) {
+ switch (lineCap) {
case splashLineCapButt:
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
break;
case splashLineCapRound:
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
pathOut->curveTo(pathIn->pts[j0].x + wdy + bezierCircle * wdx,
pathIn->pts[j0].y - wdx + bezierCircle * wdy,
pathIn->pts[j0].x + wdx + bezierCircle * wdy,
@@ -6315,11 +6771,10 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
pathIn->pts[j0].y - wdx + wdy);
pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx,
pathIn->pts[j0].y + wdx + wdy);
- pathOut->lineTo(pathIn->pts[j0].x - wdy,
- pathIn->pts[j0].y + wdx);
break;
}
} else {
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
}
@@ -6327,7 +6782,7 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
// (NB: if stroke adjustment is enabled, the closepath operation MUST
// add a segment because this segment is used for a hint)
right2 = pathOut->length - 1;
- pathOut->close(state->strokeAdjust);
+ pathOut->close(state->strokeAdjust != splashStrokeAdjustOff);
// draw the join
join2 = pathOut->length;
@@ -6372,43 +6827,121 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
}
// round join
- if (state->lineJoin == splashLineJoinRound) {
- pathOut->moveTo(pathIn->pts[j0].x + (SplashCoord)0.5 * w,
- pathIn->pts[j0].y);
- pathOut->curveTo(pathIn->pts[j0].x + (SplashCoord)0.5 * w,
- pathIn->pts[j0].y + bezierCircle2 * w,
- pathIn->pts[j0].x + bezierCircle2 * w,
- pathIn->pts[j0].y + (SplashCoord)0.5 * w,
- pathIn->pts[j0].x,
- pathIn->pts[j0].y + (SplashCoord)0.5 * w);
- pathOut->curveTo(pathIn->pts[j0].x - bezierCircle2 * w,
- pathIn->pts[j0].y + (SplashCoord)0.5 * w,
- pathIn->pts[j0].x - (SplashCoord)0.5 * w,
- pathIn->pts[j0].y + bezierCircle2 * w,
- pathIn->pts[j0].x - (SplashCoord)0.5 * w,
- pathIn->pts[j0].y);
- pathOut->curveTo(pathIn->pts[j0].x - (SplashCoord)0.5 * w,
- pathIn->pts[j0].y - bezierCircle2 * w,
- pathIn->pts[j0].x - bezierCircle2 * w,
- pathIn->pts[j0].y - (SplashCoord)0.5 * w,
- pathIn->pts[j0].x,
- pathIn->pts[j0].y - (SplashCoord)0.5 * w);
- pathOut->curveTo(pathIn->pts[j0].x + bezierCircle2 * w,
- pathIn->pts[j0].y - (SplashCoord)0.5 * w,
- pathIn->pts[j0].x + (SplashCoord)0.5 * w,
- pathIn->pts[j0].y - bezierCircle2 * w,
- pathIn->pts[j0].x + (SplashCoord)0.5 * w,
- pathIn->pts[j0].y);
+ if (lineJoin == splashLineJoinRound) {
+ // join angle < 180
+ if (crossprod < 0) {
+ angle = atan2((double)dx, (double)-dy);
+ angleNext = atan2((double)dxNext, (double)-dyNext);
+ if (angle < angleNext) {
+ angle += 2 * M_PI;
+ }
+ dAngle = (angle - angleNext) / M_PI;
+ if (dAngle < 0.501) {
+ // span angle is <= 90 degrees -> draw a single arc
+ kappa = dAngle * bezierCircle * w;
+ cx1 = pathIn->pts[j0].x - wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y + wdx + kappa * dy;
+ cx2 = pathIn->pts[j0].x - wdyNext - kappa * dxNext;
+ cy2 = pathIn->pts[j0].y + wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
+ pathIn->pts[j0].y + wdxNext);
+ pathOut->curveTo(cx2, cy2, cx1, cy1,
+ pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ } else {
+ // span angle is > 90 degrees -> split into two arcs
+ dJoin = splashDist(-wdy, wdx, -wdyNext, wdxNext);
+ if (dJoin > 0) {
+ dxJoin = (-wdyNext + wdy) / dJoin;
+ dyJoin = (wdxNext - wdx) / dJoin;
+ xc = pathIn->pts[j0].x
+ + (SplashCoord)0.5 * w
+ * cos((double)((SplashCoord)0.5 * (angle + angleNext)));
+ yc = pathIn->pts[j0].y
+ + (SplashCoord)0.5 * w
+ * sin((double)((SplashCoord)0.5 * (angle + angleNext)));
+ kappa = dAngle * bezierCircle2 * w;
+ cx1 = pathIn->pts[j0].x - wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y + wdx + kappa * dy;
+ cx2 = xc - kappa * dxJoin;
+ cy2 = yc - kappa * dyJoin;
+ cx3 = xc + kappa * dxJoin;
+ cy3 = yc + kappa * dyJoin;
+ cx4 = pathIn->pts[j0].x - wdyNext - kappa * dxNext;
+ cy4 = pathIn->pts[j0].y + wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
+ pathIn->pts[j0].y + wdxNext);
+ pathOut->curveTo(cx4, cy4, cx3, cy3, xc, yc);
+ pathOut->curveTo(cx2, cy2, cx1, cy1,
+ pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ }
+ }
+
+ // join angle >= 180
+ } else {
+ angle = atan2((double)-dx, (double)dy);
+ angleNext = atan2((double)-dxNext, (double)dyNext);
+ if (angleNext < angle) {
+ angleNext += 2 * M_PI;
+ }
+ dAngle = (angleNext - angle) / M_PI;
+ if (dAngle < 0.501) {
+ // span angle is <= 90 degrees -> draw a single arc
+ kappa = dAngle * bezierCircle * w;
+ cx1 = pathIn->pts[j0].x + wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y - wdx + kappa * dy;
+ cx2 = pathIn->pts[j0].x + wdyNext - kappa * dxNext;
+ cy2 = pathIn->pts[j0].y - wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
+ pathIn->pts[j0].y - wdx);
+ pathOut->curveTo(cx1, cy1, cx2, cy2,
+ pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
+ } else {
+ // span angle is > 90 degrees -> split into two arcs
+ dJoin = splashDist(wdy, -wdx, wdyNext, -wdxNext);
+ if (dJoin > 0) {
+ dxJoin = (wdyNext - wdy) / dJoin;
+ dyJoin = (-wdxNext + wdx) / dJoin;
+ xc = pathIn->pts[j0].x
+ + (SplashCoord)0.5 * w
+ * cos((double)((SplashCoord)0.5 * (angle + angleNext)));
+ yc = pathIn->pts[j0].y
+ + (SplashCoord)0.5 * w
+ * sin((double)((SplashCoord)0.5 * (angle + angleNext)));
+ kappa = dAngle * bezierCircle2 * w;
+ cx1 = pathIn->pts[j0].x + wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y - wdx + kappa * dy;
+ cx2 = xc - kappa * dxJoin;
+ cy2 = yc - kappa * dyJoin;
+ cx3 = xc + kappa * dxJoin;
+ cy3 = yc + kappa * dyJoin;
+ cx4 = pathIn->pts[j0].x + wdyNext - kappa * dxNext;
+ cy4 = pathIn->pts[j0].y - wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
+ pathIn->pts[j0].y - wdx);
+ pathOut->curveTo(cx1, cy1, cx2, cy2, xc, yc);
+ pathOut->curveTo(cx3, cy3, cx4, cy4,
+ pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
+ }
+ }
+ }
} else {
pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
- // angle < 180
+ // join angle < 180
if (crossprod < 0) {
pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
pathIn->pts[j0].y + wdxNext);
// miter join inside limit
- if (state->lineJoin == splashLineJoinMiter &&
+ if (lineJoin == splashLineJoinMiter &&
splashSqrt(miter) <= state->miterLimit) {
pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx * m,
pathIn->pts[j0].y + wdx + wdy * m);
@@ -6420,12 +6953,12 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
pathIn->pts[j0].y + wdx);
}
- // angle >= 180
+ // join angle >= 180
} else {
pathOut->lineTo(pathIn->pts[j0].x + wdy,
pathIn->pts[j0].y - wdx);
// miter join inside limit
- if (state->lineJoin == splashLineJoinMiter &&
+ if (lineJoin == splashLineJoinMiter &&
splashSqrt(miter) <= state->miterLimit) {
pathOut->lineTo(pathIn->pts[j0].x + wdy + wdx * m,
pathIn->pts[j0].y - wdx + wdy * m);
@@ -6443,36 +6976,106 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
}
// add stroke adjustment hints
- if (state->strokeAdjust) {
- if (seg == 0 && !closed) {
- if (state->lineCap == splashLineCapButt) {
+ if (state->strokeAdjust != splashStrokeAdjustOff) {
+
+ // subpath with one segment
+ if (seg == 0 && last) {
+ switch (lineCap) {
+ case splashLineCapButt:
pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
- firstPt, firstPt + 1);
- if (last) {
- pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
- left2 + 1, left2 + 2);
- }
- } else if (state->lineCap == splashLineCapProjecting) {
- if (last) {
- pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 2,
- firstPt + 1, firstPt + 2);
- pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 2,
- left2 + 2, left2 + 3);
- } else {
- pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 1,
- firstPt + 1, firstPt + 2);
+ firstPt, pathOut->length - 1);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
+ firstPt, pathOut->length - 1, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
+ pathOut->addStrokeAdjustHint(left2, right2,
+ firstPt, pathOut->length - 1);
+ } else {
+
+ // start of subpath
+ if (seg == 1) {
+
+ // start cap
+ if (!closed) {
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ firstPt, firstPt + 1);
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ right1 + 1, right1 + 1);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ firstPt, firstPt + 1, gTrue);
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ right1 + 1, right1 + 1, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
}
+
+ // first segment
+ pathOut->addStrokeAdjustHint(left1, right1, firstPt, left2);
+ pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1);
}
- }
- if (seg >= 1) {
- if (seg >= 2) {
+
+ // middle of subpath
+ if (seg > 1) {
pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
pathOut->addStrokeAdjustHint(left1, right1, join0, left2);
- } else {
- pathOut->addStrokeAdjustHint(left1, right1, firstPt, left2);
+ pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1);
+ }
+
+ // end of subpath
+ if (last) {
+
+ if (closed) {
+ // first segment
+ pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
+ left2 + 1, right2);
+ pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
+ join2, pathOut->length - 1);
+
+ // last segment
+ pathOut->addStrokeAdjustHint(left2, right2,
+ left1 + 1, right1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ join1, pathOut->length - 1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ leftFirst - 1, leftFirst);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ rightFirst + 1, rightFirst + 1);
+
+ } else {
+
+ // last segment
+ pathOut->addStrokeAdjustHint(left2, right2,
+ left1 + 1, right1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ join1, pathOut->length - 1);
+
+ // end cap
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->addStrokeAdjustHint(left2 - 1, left2 + 1,
+ left2 + 1, left2 + 2);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(left2 - 1, left2 + 1,
+ left2 + 1, left2 + 2, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
+ }
}
- pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1);
}
+
left0 = left1;
left1 = left2;
right0 = right1;
@@ -6483,34 +7086,6 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
leftFirst = left2;
rightFirst = right2;
}
- if (last) {
- if (seg >= 2) {
- pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
- pathOut->addStrokeAdjustHint(left1, right1,
- join0, pathOut->length - 1);
- } else {
- pathOut->addStrokeAdjustHint(left1, right1,
- firstPt, pathOut->length - 1);
- }
- if (closed) {
- pathOut->addStrokeAdjustHint(left1, right1, firstPt, leftFirst);
- pathOut->addStrokeAdjustHint(left1, right1,
- rightFirst + 1, rightFirst + 1);
- pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
- left1 + 1, right1);
- pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
- join1, pathOut->length - 1);
- }
- if (!closed && seg > 0) {
- if (state->lineCap == splashLineCapButt) {
- pathOut->addStrokeAdjustHint(left1 - 1, left1 + 1,
- left1 + 1, left1 + 2);
- } else if (state->lineCap == splashLineCapProjecting) {
- pathOut->addStrokeAdjustHint(left1 - 1, left1 + 2,
- left1 + 2, left1 + 3);
- }
- }
- }
}
i0 = j0;
@@ -6525,6 +7100,29 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
return pathOut;
}
+SplashClipResult Splash::limitRectToClipRect(int *xMin, int *yMin,
+ int *xMax, int *yMax) {
+ int t;
+
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > *xMin) {
+ *xMin = t;
+ }
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < *xMax) {
+ *xMax = t;
+ }
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > *yMin) {
+ *yMin = t;
+ }
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < *yMax) {
+ *yMax = t;
+ }
+ if (*xMin >= *xMax || *yMin >= *yMax) {
+ return splashClipAllOutside;
+ }
+ return state->clip->testRect(*xMin, *yMin, *xMax - 1, *yMax - 1,
+ state->strokeAdjust);
+}
+
void Splash::dumpPath(SplashPath *path) {
int i;
@@ -6536,6 +7134,15 @@ void Splash::dumpPath(SplashPath *path) {
(path->flags[i] & splashPathClosed) ? " closed" : "",
(path->flags[i] & splashPathCurve) ? " curve" : "");
}
+ if (path->hintsLength == 0) {
+ printf(" no hints\n");
+ } else {
+ for (i = 0; i < path->hintsLength; ++i) {
+ printf(" hint %3d: ctrl0=%d ctrl1=%d pts=%d..%d\n",
+ i, path->hints[i].ctrl0, path->hints[i].ctrl1,
+ path->hints[i].firstPt, path->hints[i].lastPt);
+ }
+ }
}
void Splash::dumpXPath(SplashXPath *path) {