summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlbert Astals Cid <aacid@kde.org>2012-01-07 17:14:51 +0100
committerAlbert Astals Cid <aacid@kde.org>2012-01-07 17:14:51 +0100
commit0666d0a46fb65ac1bd56dd345e2ce47bcb51b5c6 (patch)
tree09e89c793a6752cbc861e7324ac560ff5db58c4b
parentc11c53037d4ae53f9062249da0eba680f2a70fed (diff)
xpdf303: Merge some stuff in Splash [Thomas Freitag]
1. merge the complete pipe changes a) including the overprint implementation from Derek used by pipe b) including the transfer function implementation 2. Two changes (not really a merge) to get it compiled under windows (in GlobalParams.cc & PDFDoc.cc) 3. merge fill and stroke changes a) including merge of SplashClip.cc b) including merge of SplashXPathScanner.cc
-rw-r--r--ALL_DIFF3562
1 files changed, 9 insertions, 3553 deletions
diff --git a/ALL_DIFF b/ALL_DIFF
index 5e964a4..afe4e00 100644
--- a/ALL_DIFF
+++ b/ALL_DIFF
@@ -15,23 +15,11 @@ diff -ru xpdf-3.02/doc/pdftotext.1 xpdf-3.03/doc/pdftotext.1
diff -ru xpdf-3.02/splash/Splash.cc xpdf-3.03/splash/Splash.cc
--- xpdf-3.02/splash/Splash.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/splash/Splash.cc 2011-08-15 23:08:53.000000000 +0200
-@@ -28,6 +29,8 @@
-
- //------------------------------------------------------------------------
-
-+#define splashAAGamma 1.5
-+
- // distance of Bezier control point from center for circle approximation
- // = (4 * (sqrt(2) - 1) / 3) * r
- #define bezierCircle ((SplashCoord)0.55228475)
@@ -38,6 +41,52 @@
- return (Guchar)((x + (x >> 8) + 0x80) >> 8);
+ // Clip x to lie in [0, 255].
+ static inline Guchar clip255(int x) {
+ return x < 0 ? 0 : x > 255 ? 255 : x;
}
-
-+// Clip x to lie in [0, 255].
-+static inline Guchar clip255(int x) {
-+ return x < 0 ? 0 : x > 255 ? 255 : x;
-+}
+
+// The PDF spec says that all pixels whose *centers* lie within the
+// image target region get painted, so we want to round n+0.5 down to
@@ -77,1461 +65,6 @@ diff -ru xpdf-3.02/splash/Splash.cc xpdf-3.03/splash/Splash.cc
//------------------------------------------------------------------------
// SplashPipe
//------------------------------------------------------------------------
-@@ -52,9 +101,8 @@
- SplashPattern *pattern;
-
- // source alpha and color
-- SplashCoord aInput;
-+ Guchar aInput;
- GBool usesShape;
-- Guchar aSrc;
- SplashColorPtr cSrc;
- SplashColor cSrcVal;
-
-@@ -70,14 +118,17 @@
- Guchar *destAlphaPtr;
-
- // shape
-- SplashCoord shape;
-+ Guchar shape;
-
- // result alpha and color
- GBool noTransparency;
- SplashPipeResultColorCtrl resultColorCtrl;
-
- // non-isolated group correction
-- int nonIsolatedGroup;
-+ GBool nonIsolatedGroup;
-+
-+ // the "run" function
-+ void (Splash::*run)(SplashPipe *pipe);
- };
-
- SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = {
-@@ -159,7 +210,7 @@
-
- inline void Splash::pipeInit(SplashPipe *pipe, int x, int y,
- SplashPattern *pattern, SplashColorPtr cSrc,
-- SplashCoord aInput, GBool usesShape,
-+ Guchar aInput, GBool usesShape,
- GBool nonIsolatedGroup) {
- pipeSetXY(pipe, x, y);
- pipe->pattern = NULL;
-@@ -178,18 +229,11 @@
-
- // source alpha
- pipe->aInput = aInput;
-- if (!state->softMask) {
-- if (usesShape) {
-- pipe->aInput *= 255;
-- } else {
-- pipe->aSrc = (Guchar)splashRound(pipe->aInput * 255);
-- }
-- }
- pipe->usesShape = usesShape;
-
- // result alpha
-- if (aInput == 1 && !state->softMask && !usesShape &&
-- !state->inNonIsolatedGroup) {
-+ if (aInput == 255 && !state->softMask && !usesShape &&
-+ !state->inNonIsolatedGroup && !nonIsolatedGroup) {
- pipe->noTransparency = gTrue;
- } else {
- pipe->noTransparency = gFalse;
-@@ -206,17 +250,54 @@
- }
-
- // non-isolated group correction
-- if (nonIsolatedGroup) {
-- pipe->nonIsolatedGroup = splashColorModeNComps[bitmap->mode];
-- } else {
-- pipe->nonIsolatedGroup = 0;
-+ pipe->nonIsolatedGroup = nonIsolatedGroup;
-+
-+ // select the 'run' function
-+ pipe->run = &Splash::pipeRun;
-+ if (!pipe->pattern && pipe->noTransparency && !state->blendFunc) {
-+ if (bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunSimpleMono1;
-+ } else if (bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunSimpleMono8;
-+ } else if (bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunSimpleRGB8;
-+ } else if (bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunSimpleBGR8;
-+#if SPLASH_CMYK
-+ } else if (bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunSimpleCMYK8;
-+#endif
-+ }
-+ } else if (!pipe->pattern && !pipe->noTransparency && !state->softMask &&
-+ pipe->usesShape &&
-+ !(state->inNonIsolatedGroup && alpha0Bitmap->alpha) &&
-+ !state->blendFunc && !pipe->nonIsolatedGroup) {
-+ if (bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunAAMono1;
-+ } else if (bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunAAMono8;
-+ } else if (bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunAARGB8;
-+ } else if (bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunAABGR8;
-+#if SPLASH_CMYK
-+ } else if (bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) {
-+ pipe->run = &Splash::pipeRunAACMYK8;
-+#endif
-+ }
- }
- }
-
--inline void Splash::pipeRun(SplashPipe *pipe) {
-- Guchar aSrc, aDest, alpha2, alpha0, aResult;
-- SplashColor cDest, cBlend;
-+// general case
-+void Splash::pipeRun(SplashPipe *pipe) {
-+ Guchar aSrc, aDest, alphaI, alphaIm1, alpha0, aResult;
-+ SplashColor cSrcNonIso, cDest, cBlend;
-+ SplashColorPtr cSrc;
- Guchar cResult0, cResult1, cResult2, cResult3;
-+ int t;
-+#if SPLASH_CMYK
-+ SplashColor cSrc2, cDest2;
-+#endif
-
- //----- source color
-
-@@ -234,7 +315,7 @@
-
- switch (bitmap->mode) {
- case splashModeMono1:
-- cResult0 = pipe->cSrc[0];
-+ cResult0 = state->grayTransfer[pipe->cSrc[0]];
- if (state->screen->test(pipe->x, pipe->y, cResult0)) {
- *pipe->destColorPtr |= pipe->destColorMask;
- } else {
-@@ -246,24 +327,33 @@
- }
- break;
- case splashModeMono8:
-- *pipe->destColorPtr++ = pipe->cSrc[0];
-+ *pipe->destColorPtr++ = state->grayTransfer[pipe->cSrc[0]];
- break;
- case splashModeRGB8:
-- *pipe->destColorPtr++ = pipe->cSrc[0];
-- *pipe->destColorPtr++ = pipe->cSrc[1];
-- *pipe->destColorPtr++ = pipe->cSrc[2];
-+ *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]];
-+ *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]];
-+ *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]];
- break;
- case splashModeBGR8:
-- *pipe->destColorPtr++ = pipe->cSrc[2];
-- *pipe->destColorPtr++ = pipe->cSrc[1];
-- *pipe->destColorPtr++ = pipe->cSrc[0];
-+ *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]];
-+ *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]];
-+ *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]];
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- *pipe->destColorPtr++ = pipe->cSrc[0];
-- *pipe->destColorPtr++ = pipe->cSrc[1];
-- *pipe->destColorPtr++ = pipe->cSrc[2];
-- *pipe->destColorPtr++ = pipe->cSrc[3];
-+ if (state->overprintMask & 1) {
-+ pipe->destColorPtr[0] = state->cmykTransferC[pipe->cSrc[0]];
-+ }
-+ if (state->overprintMask & 2) {
-+ pipe->destColorPtr[1] = state->cmykTransferM[pipe->cSrc[1]];
-+ }
-+ if (state->overprintMask & 4) {
-+ pipe->destColorPtr[2] = state->cmykTransferY[pipe->cSrc[2]];
-+ }
-+ if (state->overprintMask & 8) {
-+ pipe->destColorPtr[3] = state->cmykTransferK[pipe->cSrc[3]];
-+ }
-+ pipe->destColorPtr += 4;
- break;
- #endif
- }
-@@ -307,41 +397,98 @@
- aDest = 0xff;
- }
-
-- //----- blend function
--
-- if (state->blendFunc) {
-- (*state->blendFunc)(pipe->cSrc, cDest, cBlend, bitmap->mode);
-- }
--
- //----- source alpha
-
- if (state->softMask) {
- if (pipe->usesShape) {
-- aSrc = (Guchar)splashRound(pipe->aInput * *pipe->softMaskPtr++
-- * pipe->shape);
-+ aSrc = div255(div255(pipe->aInput * *pipe->softMaskPtr++) *
-+ pipe->shape);
- } else {
-- aSrc = (Guchar)splashRound(pipe->aInput * *pipe->softMaskPtr++);
-+ aSrc = div255(pipe->aInput * *pipe->softMaskPtr++);
- }
- } else if (pipe->usesShape) {
-- // pipe->aInput is premultiplied by 255 in pipeInit
-- aSrc = (Guchar)splashRound(pipe->aInput * pipe->shape);
-+ aSrc = div255(pipe->aInput * pipe->shape);
-+ } else {
-+ aSrc = pipe->aInput;
-+ }
-+
-+ //----- non-isolated group correction
-+
-+ if (pipe->nonIsolatedGroup) {
-+ // This path is only used when Splash::composite() is called to
-+ // composite a non-isolated group onto the backdrop. In this
-+ // case, pipe->shape is the source (group) alpha.
-+ if (pipe->shape == 0) {
-+ // this value will be multiplied by zero later, so it doesn't
-+ // matter what we use
-+ cSrc = pipe->cSrc;
-+ } else {
-+ t = (aDest * 255) / pipe->shape - aDest;
-+ switch (bitmap->mode) {
-+#if SPLASH_CMYK
-+ case splashModeCMYK8:
-+ cSrcNonIso[3] = clip255(pipe->cSrc[3] +
-+ ((pipe->cSrc[3] - cDest[3]) * t) / 255);
-+#endif
-+ case splashModeRGB8:
-+ case splashModeBGR8:
-+ cSrcNonIso[2] = clip255(pipe->cSrc[2] +
-+ ((pipe->cSrc[2] - cDest[2]) * t) / 255);
-+ cSrcNonIso[1] = clip255(pipe->cSrc[1] +
-+ ((pipe->cSrc[1] - cDest[1]) * t) / 255);
-+ case splashModeMono1:
-+ case splashModeMono8:
-+ cSrcNonIso[0] = clip255(pipe->cSrc[0] +
-+ ((pipe->cSrc[0] - cDest[0]) * t) / 255);
-+ break;
-+ }
-+ cSrc = cSrcNonIso;
-+ }
- } else {
-- // precomputed in pipeInit
-- aSrc = pipe->aSrc;
-+ cSrc = pipe->cSrc;
-+ }
-+
-+ //----- blend function
-+
-+ if (state->blendFunc) {
-+#if SPLASH_CMYK
-+ if (bitmap->mode == splashModeCMYK8) {
-+ // convert colors to additive
-+ cSrc2[0] = 0xff - cSrc[0];
-+ cSrc2[1] = 0xff - cSrc[1];
-+ cSrc2[2] = 0xff - cSrc[2];
-+ cSrc2[3] = 0xff - cSrc[3];
-+ cDest2[0] = 0xff - cDest[0];
-+ cDest2[1] = 0xff - cDest[1];
-+ cDest2[2] = 0xff - cDest[2];
-+ cDest2[3] = 0xff - cDest[3];
-+ (*state->blendFunc)(cSrc2, cDest2, cBlend, bitmap->mode);
-+ // convert result back to subtractive
-+ cBlend[0] = 0xff - cBlend[0];
-+ cBlend[1] = 0xff - cBlend[1];
-+ cBlend[2] = 0xff - cBlend[2];
-+ cBlend[3] = 0xff - cBlend[3];
-+ } else
-+#endif
-+ (*state->blendFunc)(cSrc, cDest, cBlend, bitmap->mode);
- }
-
- //----- result alpha and non-isolated group element correction
-
- if (pipe->noTransparency) {
-- alpha2 = aResult = 255;
-+ alphaI = alphaIm1 = aResult = 255;
- } else {
- aResult = aSrc + aDest - div255(aSrc * aDest);
-
-+ // alphaI = alpha_i
-+ // alphaIm1 = alpha_(i-1)
- if (pipe->alpha0Ptr) {
- alpha0 = *pipe->alpha0Ptr++;
-- alpha2 = aResult + alpha0 - div255(aResult * alpha0);
-+ alphaI = aResult + alpha0 - div255(aResult * alpha0);
-+ alphaIm1 = alpha0 + aDest - div255(alpha0 * aDest);
- } else {
-- alpha2 = aResult;
-+ alphaI = aResult;
-+ alphaIm1 = aDest;
- }
- }
-
-@@ -351,140 +498,132 @@
-
- switch (pipe->resultColorCtrl) {
-
-+ case splashPipeResultColorNoAlphaBlendMono:
-+ cResult0 = state->grayTransfer[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])];
-+ break;
- #if SPLASH_CMYK
- case splashPipeResultColorNoAlphaBlendCMYK:
-- cResult3 = div255((255 - aDest) * pipe->cSrc[3] + aDest * cBlend[3]);
--#endif
-- case splashPipeResultColorNoAlphaBlendRGB:
-- cResult2 = div255((255 - aDest) * pipe->cSrc[2] + aDest * cBlend[2]);
-- cResult1 = div255((255 - aDest) * pipe->cSrc[1] + aDest * cBlend[1]);
-- case splashPipeResultColorNoAlphaBlendMono:
-- cResult0 = div255((255 - aDest) * pipe->cSrc[0] + aDest * cBlend[0]);
-+ 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])];
- break;
-+#endif
-
- case splashPipeResultColorAlphaNoBlendMono:
-- if (alpha2 == 0) {
-+ if (alphaI == 0) {
- cResult0 = 0;
- } else {
-- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
-- aSrc * pipe->cSrc[0]) / alpha2);
-+ cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] +
-+ aSrc * cSrc[0]) / alphaI];
- }
- break;
- case splashPipeResultColorAlphaNoBlendRGB:
-- if (alpha2 == 0) {
-+ if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
- } else {
-- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
-- aSrc * pipe->cSrc[0]) / alpha2);
-- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
-- aSrc * pipe->cSrc[1]) / alpha2);
-- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
-- aSrc * pipe->cSrc[2]) / alpha2);
-+ 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];
- }
- break;
- #if SPLASH_CMYK
- case splashPipeResultColorAlphaNoBlendCMYK:
-- if (alpha2 == 0) {
-+ if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
- cResult3 = 0;
- } else {
-- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
-- aSrc * pipe->cSrc[0]) / alpha2);
-- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
-- aSrc * pipe->cSrc[1]) / alpha2);
-- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
-- aSrc * pipe->cSrc[2]) / alpha2);
-- cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] +
-- aSrc * pipe->cSrc[3]) / alpha2);
-+ 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];
- }
- break;
- #endif
-
- case splashPipeResultColorAlphaBlendMono:
-- if (alpha2 == 0) {
-+ if (alphaI == 0) {
- cResult0 = 0;
- } else {
-- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
-- aSrc * ((255 - aDest) * pipe->cSrc[0] +
-- aDest * cBlend[0]) / 255) /
-- alpha2);
-+ cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] +
-+ aSrc * ((255 - alphaIm1) * cSrc[0] +
-+ alphaIm1 * cBlend[0]) / 255) /
-+ alphaI];
- }
- break;
- case splashPipeResultColorAlphaBlendRGB:
-- if (alpha2 == 0) {
-+ if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
- } else {
-- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
-- aSrc * ((255 - aDest) * pipe->cSrc[0] +
-- aDest * cBlend[0]) / 255) /
-- alpha2);
-- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
-- aSrc * ((255 - aDest) * pipe->cSrc[1] +
-- aDest * cBlend[1]) / 255) /
-- alpha2);
-- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
-- aSrc * ((255 - aDest) * pipe->cSrc[2] +
-- aDest * cBlend[2]) / 255) /
-- alpha2);
-+ 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];
- }
- break;
- #if SPLASH_CMYK
- case splashPipeResultColorAlphaBlendCMYK:
-- if (alpha2 == 0) {
-+ if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
- cResult3 = 0;
- } else {
-- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
-- aSrc * ((255 - aDest) * pipe->cSrc[0] +
-- aDest * cBlend[0]) / 255) /
-- alpha2);
-- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
-- aSrc * ((255 - aDest) * pipe->cSrc[1] +
-- aDest * cBlend[1]) / 255) /
-- alpha2);
-- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
-- aSrc * ((255 - aDest) * pipe->cSrc[2] +
-- aDest * cBlend[2]) / 255) /
-- alpha2);
-- cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] +
-- aSrc * ((255 - aDest) * pipe->cSrc[3] +
-- aDest * cBlend[3]) / 255) /
-- alpha2);
-+ 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];
- }
- break;
- #endif
- }
-
-- //----- non-isolated group correction
--
-- if (aResult != 0) {
-- switch (pipe->nonIsolatedGroup) {
--#if SPLASH_CMYK
-- case 4:
-- cResult3 += (cResult3 - cDest[3]) * aDest *
-- (255 - aResult) / (255 * aResult);
--#endif
-- case 3:
-- cResult2 += (cResult2 - cDest[2]) * aDest *
-- (255 - aResult) / (255 * aResult);
-- cResult1 += (cResult1 - cDest[1]) * aDest *
-- (255 - aResult) / (255 * aResult);
-- case 1:
-- cResult0 += (cResult0 - cDest[0]) * aDest *
-- (255 - aResult) / (255 * aResult);
-- case 0:
-- break;
-- }
-- }
--
- //----- write destination pixel
-
- switch (bitmap->mode) {
-@@ -514,10 +653,19 @@
- break;
- #if SPLASH_CMYK
- case splashModeCMYK8:
-- *pipe->destColorPtr++ = cResult0;
-- *pipe->destColorPtr++ = cResult1;
-- *pipe->destColorPtr++ = cResult2;
-- *pipe->destColorPtr++ = cResult3;
-+ if (state->overprintMask & 1) {
-+ pipe->destColorPtr[0] = cResult0;
-+ }
-+ if (state->overprintMask & 2) {
-+ pipe->destColorPtr[1] = cResult1;
-+ }
-+ if (state->overprintMask & 4) {
-+ pipe->destColorPtr[2] = cResult2;
-+ }
-+ if (state->overprintMask & 8) {
-+ pipe->destColorPtr[3] = cResult3;
-+ }
-+ pipe->destColorPtr += 4;
- break;
- #endif
- }
-@@ -530,6 +678,316 @@
- ++pipe->x;
- }
-
-+// special case:
-+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
-+// bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr) {
-+void Splash::pipeRunSimpleMono1(SplashPipe *pipe) {
-+ Guchar cResult0;
-+
-+ //----- write destination pixel
-+ cResult0 = state->grayTransfer[pipe->cSrc[0]];
-+ if (state->screen->test(pipe->x, pipe->y, cResult0)) {
-+ *pipe->destColorPtr |= pipe->destColorMask;
-+ } else {
-+ *pipe->destColorPtr &= ~pipe->destColorMask;
-+ }
-+ if (!(pipe->destColorMask >>= 1)) {
-+ pipe->destColorMask = 0x80;
-+ ++pipe->destColorPtr;
-+ }
-+
-+ ++pipe->x;
-+}
-+
-+// special case:
-+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
-+// bitmap->mode == splashModeMono8 && pipe->destAlphaPtr) {
-+void Splash::pipeRunSimpleMono8(SplashPipe *pipe) {
-+ //----- write destination pixel
-+ *pipe->destColorPtr++ = state->grayTransfer[pipe->cSrc[0]];
-+ *pipe->destAlphaPtr++ = 255;
-+
-+ ++pipe->x;
-+}
-+
-+// special case:
-+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
-+// bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr) {
-+void Splash::pipeRunSimpleRGB8(SplashPipe *pipe) {
-+ //----- write destination pixel
-+ *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]];
-+ *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]];
-+ *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]];
-+ *pipe->destAlphaPtr++ = 255;
-+
-+ ++pipe->x;
-+}
-+
-+// special case:
-+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
-+// bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr) {
-+void Splash::pipeRunSimpleBGR8(SplashPipe *pipe) {
-+ //----- write destination pixel
-+ *pipe->destColorPtr++ = state->rgbTransferB[pipe->cSrc[2]];
-+ *pipe->destColorPtr++ = state->rgbTransferG[pipe->cSrc[1]];
-+ *pipe->destColorPtr++ = state->rgbTransferR[pipe->cSrc[0]];
-+ *pipe->destAlphaPtr++ = 255;
-+
-+ ++pipe->x;
-+}
-+
-+#if SPLASH_CMYK
-+// special case:
-+// !pipe->pattern && pipe->noTransparency && !state->blendFunc &&
-+// bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr) {
-+void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe) {
-+ //----- write destination pixel
-+ if (state->overprintMask & 1) {
-+ pipe->destColorPtr[0] = state->cmykTransferC[pipe->cSrc[0]];
-+ }
-+ if (state->overprintMask & 2) {
-+ pipe->destColorPtr[1] = state->cmykTransferM[pipe->cSrc[1]];
-+ }
-+ if (state->overprintMask & 4) {
-+ pipe->destColorPtr[2] = state->cmykTransferY[pipe->cSrc[2]];
-+ }
-+ if (state->overprintMask & 8) {
-+ pipe->destColorPtr[3] = state->cmykTransferK[pipe->cSrc[3]];
-+ }
-+ pipe->destColorPtr += 4;
-+ *pipe->destAlphaPtr++ = 255;
-+
-+ ++pipe->x;
-+}
-+#endif
-+
-+
-+// special case:
-+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
-+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
-+// !pipe->nonIsolatedGroup &&
-+// bitmap->mode == splashModeMono1 && !pipe->destAlphaPtr
-+void Splash::pipeRunAAMono1(SplashPipe *pipe) {
-+ Guchar aSrc;
-+ SplashColor cDest;
-+ Guchar cResult0;
-+
-+ //----- read destination pixel
-+ cDest[0] = (*pipe->destColorPtr & pipe->destColorMask) ? 0xff : 0x00;
-+
-+ //----- source alpha
-+ aSrc = div255(pipe->aInput * pipe->shape);
-+
-+ //----- result color
-+ // note: aDest = alpha2 = aResult = 0xff
-+ cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest[0] +
-+ aSrc * pipe->cSrc[0])];
-+
-+ //----- write destination pixel
-+ if (state->screen->test(pipe->x, pipe->y, cResult0)) {
-+ *pipe->destColorPtr |= pipe->destColorMask;
-+ } else {
-+ *pipe->destColorPtr &= ~pipe->destColorMask;
-+ }
-+ if (!(pipe->destColorMask >>= 1)) {
-+ pipe->destColorMask = 0x80;
-+ ++pipe->destColorPtr;
-+ }
-+
-+ ++pipe->x;
-+}
-+
-+// special case:
-+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
-+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
-+// !pipe->nonIsolatedGroup &&
-+// bitmap->mode == splashModeMono8 && pipe->destAlphaPtr
-+void Splash::pipeRunAAMono8(SplashPipe *pipe) {
-+ Guchar aSrc, aDest, alpha2, aResult;
-+ SplashColor cDest;
-+ Guchar cResult0;
-+
-+ //----- read destination pixel
-+ cDest[0] = *pipe->destColorPtr;
-+ aDest = *pipe->destAlphaPtr;
-+
-+ //----- source alpha
-+ aSrc = div255(pipe->aInput * pipe->shape);
-+
-+ //----- result alpha and non-isolated group element correction
-+ aResult = aSrc + aDest - div255(aSrc * aDest);
-+ alpha2 = aResult;
-+
-+ //----- result color
-+ if (alpha2 == 0) {
-+ cResult0 = 0;
-+ } else {
-+ cResult0 = state->grayTransfer[(Guchar)(((alpha2 - aSrc) * cDest[0] +
-+ aSrc * pipe->cSrc[0]) / alpha2)];
-+ }
-+
-+ //----- write destination pixel
-+ *pipe->destColorPtr++ = cResult0;
-+ *pipe->destAlphaPtr++ = aResult;
-+
-+ ++pipe->x;
-+}
-+
-+// special case:
-+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
-+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
-+// !pipe->nonIsolatedGroup &&
-+// bitmap->mode == splashModeRGB8 && pipe->destAlphaPtr
-+void Splash::pipeRunAARGB8(SplashPipe *pipe) {
-+ Guchar aSrc, aDest, alpha2, aResult;
-+ SplashColor cDest;
-+ Guchar cResult0, cResult1, cResult2;
-+
-+ //----- read destination pixel
-+ cDest[0] = pipe->destColorPtr[0];
-+ cDest[1] = pipe->destColorPtr[1];
-+ cDest[2] = pipe->destColorPtr[2];
-+ aDest = *pipe->destAlphaPtr;
-+
-+ //----- source alpha
-+ aSrc = div255(pipe->aInput * pipe->shape);
-+
-+ //----- result alpha and non-isolated group element correction
-+ aResult = aSrc + aDest - div255(aSrc * aDest);
-+ alpha2 = aResult;
-+
-+ //----- result color
-+ if (alpha2 == 0) {
-+ cResult0 = 0;
-+ cResult1 = 0;
-+ cResult2 = 0;
-+ } else {
-+ cResult0 = state->rgbTransferR[(Guchar)(((alpha2 - aSrc) * cDest[0] +
-+ aSrc * pipe->cSrc[0]) / alpha2)];
-+ cResult1 = state->rgbTransferG[(Guchar)(((alpha2 - aSrc) * cDest[1] +
-+ aSrc * pipe->cSrc[1]) / alpha2)];
-+ cResult2 = state->rgbTransferB[(Guchar)(((alpha2 - aSrc) * cDest[2] +
-+ aSrc * pipe->cSrc[2]) / alpha2)];
-+ }
-+
-+ //----- write destination pixel
-+ *pipe->destColorPtr++ = cResult0;
-+ *pipe->destColorPtr++ = cResult1;
-+ *pipe->destColorPtr++ = cResult2;
-+ *pipe->destAlphaPtr++ = aResult;
-+
-+ ++pipe->x;
-+}
-+
-+// special case:
-+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
-+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
-+// !pipe->nonIsolatedGroup &&
-+// bitmap->mode == splashModeBGR8 && pipe->destAlphaPtr
-+void Splash::pipeRunAABGR8(SplashPipe *pipe) {
-+ Guchar aSrc, aDest, alpha2, aResult;
-+ SplashColor cDest;
-+ Guchar cResult0, cResult1, cResult2;
-+
-+ //----- read destination pixel
-+ cDest[0] = pipe->destColorPtr[2];
-+ cDest[1] = pipe->destColorPtr[1];
-+ cDest[2] = pipe->destColorPtr[0];
-+ aDest = *pipe->destAlphaPtr;
-+
-+ //----- source alpha
-+ aSrc = div255(pipe->aInput * pipe->shape);
-+
-+ //----- result alpha and non-isolated group element correction
-+ aResult = aSrc + aDest - div255(aSrc * aDest);
-+ alpha2 = aResult;
-+
-+ //----- result color
-+ if (alpha2 == 0) {
-+ cResult0 = 0;
-+ cResult1 = 0;
-+ cResult2 = 0;
-+ } else {
-+ cResult0 = state->rgbTransferR[(Guchar)(((alpha2 - aSrc) * cDest[0] +
-+ aSrc * pipe->cSrc[0]) / alpha2)];
-+ cResult1 = state->rgbTransferG[(Guchar)(((alpha2 - aSrc) * cDest[1] +
-+ aSrc * pipe->cSrc[1]) / alpha2)];
-+ cResult2 = state->rgbTransferB[(Guchar)(((alpha2 - aSrc) * cDest[2] +
-+ aSrc * pipe->cSrc[2]) / alpha2)];
-+ }
-+
-+ //----- write destination pixel
-+ *pipe->destColorPtr++ = cResult2;
-+ *pipe->destColorPtr++ = cResult1;
-+ *pipe->destColorPtr++ = cResult0;
-+ *pipe->destAlphaPtr++ = aResult;
-+
-+ ++pipe->x;
-+}
-+
-+#if SPLASH_CMYK
-+// special case:
-+// !pipe->pattern && !pipe->noTransparency && !state->softMask &&
-+// pipe->usesShape && !pipe->alpha0Ptr && !state->blendFunc &&
-+// !pipe->nonIsolatedGroup &&
-+// bitmap->mode == splashModeCMYK8 && pipe->destAlphaPtr
-+void Splash::pipeRunAACMYK8(SplashPipe *pipe) {
-+ Guchar aSrc, aDest, alpha2, aResult;
-+ SplashColor cDest;
-+ Guchar cResult0, cResult1, cResult2, cResult3;
-+
-+ //----- read destination pixel
-+ cDest[0] = pipe->destColorPtr[0];
-+ cDest[1] = pipe->destColorPtr[1];
-+ cDest[2] = pipe->destColorPtr[2];
-+ cDest[3] = pipe->destColorPtr[3];
-+ aDest = *pipe->destAlphaPtr;
-+
-+ //----- source alpha
-+ aSrc = div255(pipe->aInput * pipe->shape);
-+
-+ //----- result alpha and non-isolated group element correction
-+ aResult = aSrc + aDest - div255(aSrc * aDest);
-+ alpha2 = aResult;
-+
-+ //----- result color
-+ if (alpha2 == 0) {
-+ cResult0 = 0;
-+ cResult1 = 0;
-+ cResult2 = 0;
-+ cResult3 = 0;
-+ } else {
-+ cResult0 = state->cmykTransferC[(Guchar)(((alpha2 - aSrc) * cDest[0] +
-+ aSrc * pipe->cSrc[0]) / alpha2)];
-+ cResult1 = state->cmykTransferM[(Guchar)(((alpha2 - aSrc) * cDest[1] +
-+ aSrc * pipe->cSrc[1]) / alpha2)];
-+ cResult2 = state->cmykTransferY[(Guchar)(((alpha2 - aSrc) * cDest[2] +
-+ aSrc * pipe->cSrc[2]) / alpha2)];
-+ cResult3 = state->cmykTransferK[(Guchar)(((alpha2 - aSrc) * cDest[3] +
-+ aSrc * pipe->cSrc[3]) / alpha2)];
-+ }
-+
-+ //----- write destination pixel
-+ if (state->overprintMask & 1) {
-+ pipe->destColorPtr[0] = cResult0;
-+ }
-+ if (state->overprintMask & 2) {
-+ pipe->destColorPtr[1] = cResult1;
-+ }
-+ if (state->overprintMask & 4) {
-+ pipe->destColorPtr[2] = cResult2;
-+ }
-+ if (state->overprintMask & 8) {
-+ pipe->destColorPtr[3] = cResult3;
-+ }
-+ pipe->destColorPtr += 4;
-+ *pipe->destAlphaPtr++ = aResult;
-+
-+ ++pipe->x;
-+}
-+#endif
-+
-+
- inline void Splash::pipeSetXY(SplashPipe *pipe, int x, int y) {
- pipe->x = x;
- pipe->y = y;
-@@ -605,7 +1063,7 @@
- inline void Splash::drawPixel(SplashPipe *pipe, int x, int y, GBool noClip) {
- if (noClip || state->clip->test(x, y)) {
- pipeSetXY(pipe, x, y);
-- pipeRun(pipe);
-+ (this->*pipe->run)(pipe);
- updateModX(x);
- updateModY(y);
- }
-@@ -666,8 +1124,8 @@
- // draw the pixel
- if (t != 0) {
- pipeSetXY(pipe, x, y);
-- pipe->shape *= aaGamma[t];
-- pipeRun(pipe);
-+ pipe->shape = div255(aaGamma[t] * pipe->shape);
-+ (this->*pipe->run)(pipe);
- updateModX(x);
- updateModY(y);
- }
-@@ -677,18 +1135,25 @@
- GBool noClip) {
- int x;
-
-- pipeSetXY(pipe, x0, y);
- if (noClip) {
-+ pipeSetXY(pipe, x0, y);
- for (x = x0; x <= x1; ++x) {
-- pipeRun(pipe);
-+ (this->*pipe->run)(pipe);
- }
- updateModX(x0);
- updateModX(x1);
- updateModY(y);
- } else {
-+ if (x0 < state->clip->getXMinI()) {
-+ x0 = state->clip->getXMinI();
-+ }
-+ if (x1 > state->clip->getXMaxI()) {
-+ x1 = state->clip->getXMaxI();
-+ }
-+ pipeSetXY(pipe, x0, y);
- for (x = x0; x <= x1; ++x) {
- if (state->clip->test(x, y)) {
-- pipeRun(pipe);
-+ (this->*pipe->run)(pipe);
- updateModX(x);
- updateModY(y);
- } else {
-@@ -742,7 +1207,7 @@
-
- if (t != 0) {
- pipe->shape = aaGamma[t];
-- pipeRun(pipe);
-+ (this->*pipe->run)(pipe);
- updateModX(x);
- updateModY(y);
- } else {
-@@ -774,19 +1239,22 @@
-
- bitmap = bitmapA;
- vectorAntialias = vectorAntialiasA;
-+ inShading = gFalse;
- state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
- screenParams);
- if (vectorAntialias) {
- aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize,
- 1, splashModeMono1, gFalse);
- for (i = 0; i <= splashAASize * splashAASize; ++i) {
-- aaGamma[i] = splashPow((SplashCoord)i /
-- (SplashCoord)(splashAASize * splashAASize),
-- 1.5);
-+ aaGamma[i] = (Guchar)splashRound(
-+ splashPow((SplashCoord)i /
-+ (SplashCoord)(splashAASize * splashAASize),
-+ splashAAGamma) * 255);
- }
- } else {
- aaBuf = NULL;
- }
-+ minLineWidth = 0;
- clearModRegion();
- debugMode = gFalse;
- }
-@@ -797,19 +1265,22 @@
-
- bitmap = bitmapA;
- vectorAntialias = vectorAntialiasA;
-+ inShading = gFalse;
- state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
- screenA);
- if (vectorAntialias) {
- aaBuf = new SplashBitmap(splashAASize * bitmap->width, splashAASize,
- 1, splashModeMono1, gFalse);
- for (i = 0; i <= splashAASize * splashAASize; ++i) {
-- aaGamma[i] = splashPow((SplashCoord)i /
-- (SplashCoord)(splashAASize * splashAASize),
-- 1.5);
-+ aaGamma[i] = (Guchar)splashRound(
-+ splashPow((SplashCoord)i /
-+ (SplashCoord)(splashAASize * splashAASize),
-+ splashAAGamma) * 255);
- }
- } else {
- aaBuf = NULL;
- }
-+ minLineWidth = 0;
- clearModRegion();
- debugMode = gFalse;
- }
-@@ -888,6 +1359,10 @@
- return state->lineDashPhase;
- }
-
-+GBool Splash::getStrokeAdjust() {
-+ return state->strokeAdjust;
-+}
-+
- SplashClip *Splash::getClip() {
- return state->clip;
- }
-@@ -991,6 +1466,15 @@
- state->inNonIsolatedGroup = gTrue;
- }
-
-+void Splash::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
-+ Guchar *gray) {
-+ state->setTransfer(red, green, blue, gray);
-+}
-+
-+void Splash::setOverprintMask(Guint overprintMask) {
-+ state->overprintMask = overprintMask;
-+}
-+
- //------------------------------------------------------------------------
- // state save/restore
- //------------------------------------------------------------------------
-@@ -1122,6 +1606,7 @@
-
- SplashError Splash::stroke(SplashPath *path) {
- SplashPath *path2, *dPath;
-+ SplashCoord d1, d2, t1, t2, w;
-
- if (debugMode) {
- printf("stroke [dash:%d] [width:%.2f]:\n",
-@@ -1137,12 +1622,44 @@
- dPath = makeDashedPath(path2);
- delete path2;
- path2 = dPath;
-+ if (path2->length == 0) {
-+ delete path2;
-+ return splashErrEmptyPath;
-+ }
- }
-- if (state->lineWidth == 0) {
-- strokeNarrow(path2);
-+
-+ // transform a unit square, and take the half the max of the two
-+ // diagonals; the product of this number and the line width is the
-+ // (approximate) transformed line width
-+ t1 = state->matrix[0] + state->matrix[2];
-+ t2 = state->matrix[1] + state->matrix[3];
-+ d1 = t1 * t1 + t2 * t2;
-+ t1 = state->matrix[0] - state->matrix[2];
-+ t2 = state->matrix[1] - state->matrix[3];
-+ d2 = t1 * t1 + t2 * t2;
-+ if (d2 > d1) {
-+ d1 = d2;
-+ }
-+ d1 *= 0.5;
-+ if (d1 > 0 &&
-+ d1 * state->lineWidth * state->lineWidth < minLineWidth * minLineWidth) {
-+ w = minLineWidth / splashSqrt(d1);
-+ strokeWide(path2, w);
-+ } else if (bitmap->mode == splashModeMono1) {
-+ // this gets close to Adobe's behavior in mono mode
-+ if (d1 <= 2) {
-+ strokeNarrow(path2);
-+ } else {
-+ strokeWide(path2, state->lineWidth);
-+ }
- } else {
-- strokeWide(path2);
-+ if (state->lineWidth == 0) {
-+ strokeNarrow(path2);
-+ } else {
-+ strokeWide(path2, state->lineWidth);
-+ }
- }
-+
- delete path2;
- return splashOk;
- }
-@@ -1151,8 +1668,8 @@
- SplashPipe pipe;
- SplashXPath *xPath;
- SplashXPathSeg *seg;
-- int x0, x1, x2, x3, y0, y1, x, y, t;
-- SplashCoord dx, dy, dxdy;
-+ int x0, x1, y0, y1, xa, xb, y;
-+ SplashCoord dxdy;
- SplashClipResult clipRes;
- int nClipRes[3];
- int i;
-@@ -1161,85 +1678,74 @@
-
- xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse);
-
-- pipeInit(&pipe, 0, 0, state->strokePattern, NULL, state->strokeAlpha,
-+ pipeInit(&pipe, 0, 0, state->strokePattern, NULL,
-+ (Guchar)splashRound(state->strokeAlpha * 255),
- gFalse, gFalse);
-
- for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) {
--
-- x0 = splashFloor(seg->x0);
-- x1 = splashFloor(seg->x1);
-- y0 = splashFloor(seg->y0);
-- y1 = splashFloor(seg->y1);
--
-- // horizontal segment
-- if (y0 == y1) {
-- if (x0 > x1) {
-- t = x0; x0 = x1; x1 = t;
-- }
-- if ((clipRes = state->clip->testSpan(x0, x1, y0))
-- != splashClipAllOutside) {
-- drawSpan(&pipe, x0, x1, y0, clipRes == splashClipAllInside);
-- }
--
-- // segment with |dx| > |dy|
-- } else if (splashAbs(seg->dxdy) > 1) {
-- dx = seg->x1 - seg->x0;
-- dy = seg->y1 - seg->y0;
-- dxdy = seg->dxdy;
-- if (y0 > y1) {
-- t = y0; y0 = y1; y1 = t;
-- t = x0; x0 = x1; x1 = t;
-- dx = -dx;
-- dy = -dy;
-- }
-- if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
-- x0 <= x1 ? x1 : x0, y1))
-- != splashClipAllOutside) {
-- if (dx > 0) {
-- x2 = x0;
-- x3 = splashFloor(seg->x0 + ((SplashCoord)y0 + 1 - seg->y0) * dxdy);
-- drawSpan(&pipe, x2, (x2 <= x3 - 1) ? x3 - 1 : x2, y0,
-- clipRes == splashClipAllInside);
-- x2 = x3;
-- for (y = y0 + 1; y <= y1 - 1; ++y) {
-- x3 = splashFloor(seg->x0 + ((SplashCoord)y + 1 - seg->y0) * dxdy);
-- drawSpan(&pipe, x2, x3 - 1, y, clipRes == splashClipAllInside);
-- x2 = x3;
-- }
-- drawSpan(&pipe, x2, x2 <= x1 ? x1 : x2, y1,
-- clipRes == splashClipAllInside);
-+ if (seg->y0 <= seg->y1) {
-+ y0 = splashFloor(seg->y0);
-+ y1 = splashFloor(seg->y1);
-+ x0 = splashFloor(seg->x0);
-+ x1 = splashFloor(seg->x1);
-+ } else {
-+ y0 = splashFloor(seg->y1);
-+ y1 = splashFloor(seg->y0);
-+ x0 = splashFloor(seg->x1);
-+ x1 = splashFloor(seg->x0);
-+ }
-+ if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
-+ x0 <= x1 ? x1 : x0, y1))
-+ != splashClipAllOutside) {
-+ if (y0 == y1) {
-+ if (x0 <= x1) {
-+ drawSpan(&pipe, x0, x1, y0, clipRes == splashClipAllInside);
- } else {
-- x2 = x0;
-- x3 = splashFloor(seg->x0 + ((SplashCoord)y0 + 1 - seg->y0) * dxdy);
-- drawSpan(&pipe, (x3 + 1 <= x2) ? x3 + 1 : x2, x2, y0,
-- clipRes == splashClipAllInside);
-- x2 = x3;
-- for (y = y0 + 1; y <= y1 - 1; ++y) {
-- x3 = splashFloor(seg->x0 + ((SplashCoord)y + 1 - seg->y0) * dxdy);
-- drawSpan(&pipe, x3 + 1, x2, y, clipRes == splashClipAllInside);
-- x2 = x3;
-- }
-- drawSpan(&pipe, x1, (x1 <= x2) ? x2 : x1, y1,
-- clipRes == splashClipAllInside);
-+ drawSpan(&pipe, x1, x0, y0, clipRes == splashClipAllInside);
- }
-- }
--
-- // segment with |dy| > |dx|
-- } else {
-- dxdy = seg->dxdy;
-- if (y0 > y1) {
-- t = x0; x0 = x1; x1 = t;
-- t = y0; y0 = y1; y1 = t;
-- }
-- if ((clipRes = state->clip->testRect(x0 <= x1 ? x0 : x1, y0,
-- x0 <= x1 ? x1 : x0, y1))
-- != splashClipAllOutside) {
-- drawPixel(&pipe, x0, y0, clipRes == splashClipAllInside);
-- for (y = y0 + 1; y <= y1 - 1; ++y) {
-- x = splashFloor(seg->x0 + ((SplashCoord)y - seg->y0) * dxdy);
-- drawPixel(&pipe, x, y, clipRes == splashClipAllInside);
-+ } else {
-+ dxdy = seg->dxdy;
-+ if (y0 < state->clip->getYMinI()) {
-+ y0 = state->clip->getYMinI();
-+ x0 = splashFloor(seg->x0 + ((SplashCoord)y0 - seg->y0) * dxdy);
-+ }
-+ if (y1 > state->clip->getYMaxI()) {
-+ y1 = state->clip->getYMaxI();
-+ x1 = splashFloor(seg->x0 + ((SplashCoord)y1 - seg->y0) * dxdy);
-+ }
-+ if (x0 <= x1) {
-+ xa = x0;
-+ for (y = y0; y <= y1; ++y) {
-+ if (y < y1) {
-+ xb = splashFloor(seg->x0 +
-+ ((SplashCoord)y + 1 - seg->y0) * dxdy);
-+ } else {
-+ xb = x1 + 1;
-+ }
-+ if (xa == xb) {
-+ drawPixel(&pipe, xa, y, clipRes == splashClipAllInside);
-+ } else {
-+ drawSpan(&pipe, xa, xb - 1, y, clipRes == splashClipAllInside);
-+ }
-+ xa = xb;
-+ }
-+ } else {
-+ xa = x0;
-+ for (y = y0; y <= y1; ++y) {
-+ if (y < y1) {
-+ xb = splashFloor(seg->x0 +
-+ ((SplashCoord)y + 1 - seg->y0) * dxdy);
-+ } else {
-+ xb = x1 - 1;
-+ }
-+ if (xa == xb) {
-+ drawPixel(&pipe, xa, y, clipRes == splashClipAllInside);
-+ } else {
-+ drawSpan(&pipe, xb + 1, xa, y, clipRes == splashClipAllInside);
-+ }
-+ xa = xb;
-+ }
- }
-- drawPixel(&pipe, x1, y1, clipRes == splashClipAllInside);
- }
- }
- ++nClipRes[clipRes];
-@@ -1256,10 +1762,10 @@
- delete xPath;
- }
-
--void Splash::strokeWide(SplashPath *path) {
-+void Splash::strokeWide(SplashPath *path, SplashCoord w) {
- SplashPath *path2;
-
-- path2 = makeStrokePath(path, gFalse);
-+ path2 = makeStrokePath(path, w, gFalse);
- fillWithPattern(path2, gFalse, state->strokePattern, state->strokeAlpha);
- delete path2;
- }
-@@ -1353,18 +1871,18 @@
-
- // otherwise, subdivide the curve
- } else {
-- xl1 = (xl0 + xx1) * 0.5;
-- yl1 = (yl0 + yy1) * 0.5;
-- xh = (xx1 + xx2) * 0.5;
-- yh = (yy1 + yy2) * 0.5;
-- xl2 = (xl1 + xh) * 0.5;
-- yl2 = (yl1 + yh) * 0.5;
-- xr2 = (xx2 + xr3) * 0.5;
-- yr2 = (yy2 + yr3) * 0.5;
-- xr1 = (xh + xr2) * 0.5;
-- yr1 = (yh + yr2) * 0.5;
-- xr0 = (xl2 + xr1) * 0.5;
-- yr0 = (yl2 + yr1) * 0.5;
-+ xl1 = splashAvg(xl0, xx1);
-+ yl1 = splashAvg(yl0, yy1);
-+ xh = splashAvg(xx1, xx2);
-+ yh = splashAvg(yy1, yy2);
-+ xl2 = splashAvg(xl1, xh);
-+ yl2 = splashAvg(yl1, yh);
-+ xr2 = splashAvg(xx2, xr3);
-+ yr2 = splashAvg(yy2, yr3);
-+ xr1 = splashAvg(xh, xr2);
-+ yr1 = splashAvg(yh, yr2);
-+ xr0 = splashAvg(xl2, xr1);
-+ yr0 = splashAvg(yl2, yr1);
- // add the new subdivision points
- p3 = (p1 + p2) / 2;
- cx[p1][1] = xl1; cy[p1][1] = yl1;
-@@ -1391,15 +1909,21 @@
- for (i = 0; i < state->lineDashLength; ++i) {
- lineDashTotal += state->lineDash[i];
- }
-+ // Acrobat simply draws nothing if the dash array is [0]
-+ if (lineDashTotal == 0) {
-+ return new SplashPath();
-+ }
- lineDashStartPhase = state->lineDashPhase;
- i = splashFloor(lineDashStartPhase / lineDashTotal);
- lineDashStartPhase -= (SplashCoord)i * lineDashTotal;
- lineDashStartOn = gTrue;
- lineDashStartIdx = 0;
-- while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {
-- lineDashStartOn = !lineDashStartOn;
-- lineDashStartPhase -= state->lineDash[lineDashStartIdx];
-- ++lineDashStartIdx;
-+ if (lineDashStartPhase > 0) {
-+ while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {
-+ lineDashStartOn = !lineDashStartOn;
-+ lineDashStartPhase -= state->lineDash[lineDashStartIdx];
-+ ++lineDashStartIdx;
-+ }
- }
-
- dPath = new SplashPath();
-@@ -1496,15 +2020,49 @@
- if (path->length == 0) {
- return splashErrEmptyPath;
- }
-+ if (pathAllOutside(path)) {
-+ opClipRes = splashClipAllOutside;
-+ return splashOk;
-+ }
-+
-+ // add stroke adjustment hints for filled rectangles -- this only
-+ // applies to paths that consist of a single subpath
-+ // (this appears to match Acrobat's behavior)
-+ if (state->strokeAdjust && !path->hints) {
-+ int n;
-+ n = path->getLength();
-+ if (n == 4 &&
-+ !(path->flags[0] & splashPathClosed) &&
-+ !(path->flags[1] & splashPathLast) &&
-+ !(path->flags[2] & splashPathLast)) {
-+ path->close(gTrue);
-+ path->addStrokeAdjustHint(0, 2, 0, 4);
-+ path->addStrokeAdjustHint(1, 3, 0, 4);
-+ } else if (n == 5 &&
-+ (path->flags[0] & splashPathClosed) &&
-+ !(path->flags[1] & splashPathLast) &&
-+ !(path->flags[2] & splashPathLast) &&
-+ !(path->flags[3] & splashPathLast)) {
-+ path->addStrokeAdjustHint(0, 2, 0, 4);
-+ path->addStrokeAdjustHint(1, 3, 0, 4);
-+ }
-+ }
-+
- xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
-- if (vectorAntialias) {
-+ if (vectorAntialias && !inShading) {
- xPath->aaScale();
- }
- xPath->sort();
-- scanner = new SplashXPathScanner(xPath, eo);
-+ yMinI = state->clip->getYMinI();
-+ yMaxI = state->clip->getYMaxI();
-+ if (vectorAntialias && !inShading) {
-+ yMinI = yMinI * splashAASize;
-+ yMaxI = (yMaxI + 1) * splashAASize - 1;
-+ }
-+ scanner = new SplashXPathScanner(xPath, eo, yMinI, yMaxI);
-
- // get the min and max x and y values
-- if (vectorAntialias) {
-+ if (vectorAntialias && !inShading) {
- scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI);
- } else {
- scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
-@@ -1513,19 +2071,15 @@
- // check clipping
- if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))
- != splashClipAllOutside) {
--
-- // limit the y range
-- if (yMinI < state->clip->getYMinI()) {
-- yMinI = state->clip->getYMinI();
-- }
-- if (yMaxI > state->clip->getYMaxI()) {
-- yMaxI = state->clip->getYMaxI();
-+ if (scanner->hasPartialClip()) {
-+ clipRes = splashClipPartial;
- }
-
-- pipeInit(&pipe, 0, yMinI, pattern, NULL, alpha, vectorAntialias, gFalse);
-+ pipeInit(&pipe, 0, yMinI, pattern, NULL, (Guchar)splashRound(alpha * 255),
-+ vectorAntialias && !inShading, gFalse);
-
- // draw the spans
-- if (vectorAntialias) {
-+ if (vectorAntialias && !inShading) {
- for (y = yMinI; y <= yMaxI; ++y) {
- scanner->renderAALine(aaBuf, &x0, &x1, y);
- if (clipRes != splashClipAllInside) {
-@@ -1560,6 +2114,73 @@
- return splashOk;
- }
-
-+GBool Splash::pathAllOutside(SplashPath *path) {
-+ SplashCoord xMin1, yMin1, xMax1, yMax1;
-+ SplashCoord xMin2, yMin2, xMax2, yMax2;
-+ SplashCoord x, y;
-+ int xMinI, yMinI, xMaxI, yMaxI;
-+ int i;
-+
-+ xMin1 = xMax1 = path->pts[0].x;
-+ yMin1 = yMax1 = path->pts[0].y;
-+ for (i = 1; i < path->length; ++i) {
-+ if (path->pts[i].x < xMin1) {
-+ xMin1 = path->pts[i].x;
-+ } else if (path->pts[i].x > xMax1) {
-+ xMax1 = path->pts[i].x;
-+ }
-+ if (path->pts[i].y < yMin1) {
-+ yMin1 = path->pts[i].y;
-+ } else if (path->pts[i].y > yMax1) {
-+ yMax1 = path->pts[i].y;
-+ }
-+ }
-+
-+ transform(state->matrix, xMin1, yMin1, &x, &y);
-+ xMin2 = xMax2 = x;
-+ yMin2 = yMax2 = y;
-+ transform(state->matrix, xMin1, yMax1, &x, &y);
-+ if (x < xMin2) {
-+ xMin2 = x;
-+ } else if (x > xMax2) {
-+ xMax2 = x;
-+ }
-+ if (y < yMin2) {
-+ yMin2 = y;
-+ } else if (y > yMax2) {
-+ yMax2 = y;
-+ }
-+ transform(state->matrix, xMax1, yMin1, &x, &y);
-+ if (x < xMin2) {
-+ xMin2 = x;
-+ } else if (x > xMax2) {
-+ xMax2 = x;
-+ }
-+ if (y < yMin2) {
-+ yMin2 = y;
-+ } else if (y > yMax2) {
-+ yMax2 = y;
-+ }
-+ transform(state->matrix, xMax1, yMax1, &x, &y);
-+ if (x < xMin2) {
-+ xMin2 = x;
-+ } else if (x > xMax2) {
-+ xMax2 = x;
-+ }
-+ if (y < yMin2) {
-+ yMin2 = y;
-+ } else if (y > yMax2) {
-+ yMax2 = y;
-+ }
-+ xMinI = splashFloor(xMin2);
-+ yMinI = splashFloor(yMin2);
-+ xMaxI = splashFloor(xMax2);
-+ yMaxI = splashFloor(yMax2);
-+
-+ return state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI) ==
-+ splashClipAllOutside;
-+}
-+
- SplashError Splash::xorFill(SplashPath *path, GBool eo) {
- SplashPipe pipe;
- SplashXPath *xPath;
-@@ -1573,7 +2194,8 @@
- }
- xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
- xPath->sort();
-- scanner = new SplashXPathScanner(xPath, eo);
-+ scanner = new SplashXPathScanner(xPath, eo, state->clip->getYMinI(),
-+ state->clip->getYMaxI());
-
- // get the min and max x and y values
- scanner->getBBox(&xMinI, &yMinI, &xMaxI, &yMaxI);
-@@ -1581,18 +2203,13 @@
- // check clipping
- if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI))
- != splashClipAllOutside) {
--
-- // limit the y range
-- if (yMinI < state->clip->getYMinI()) {
-- yMinI = state->clip->getYMinI();
-- }
-- if (yMaxI > state->clip->getYMaxI()) {
-- yMaxI = state->clip->getYMaxI();
-+ if (scanner->hasPartialClip()) {
-+ clipRes = splashClipPartial;
- }
-
- origBlendFunc = state->blendFunc;
- state->blendFunc = &blendXor;
-- pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 1, gFalse, gFalse);
-+ pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 255, gFalse, gFalse);
-
- // draw the spans
- for (y = yMinI; y <= yMaxI; ++y) {
@@ -1662,7 +2279,8 @@
SplashPipe pipe;
SplashClipResult clipRes;
@@ -1542,89 +75,6 @@ diff -ru xpdf-3.02/splash/Splash.cc xpdf-3.03/splash/Splash.cc
Guchar *p;
int x1, y1, xx, xx1, yy;
-@@ -1675,16 +2293,16 @@
-
- if (noClip) {
- if (glyph->aa) {
-- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
-- state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
-+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL,
-+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse);
- p = glyph->data;
- for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
- pipeSetXY(&pipe, x0 - glyph->x, y1);
- for (xx = 0, x1 = x0 - glyph->x; xx < glyph->w; ++xx, ++x1) {
- alpha = *p++;
- if (alpha != 0) {
-- pipe.shape = (SplashCoord)(alpha / 255.0);
-- pipeRun(&pipe);
-+ pipe.shape = alpha;
-+ (this->*pipe.run)(&pipe);
- updateModX(x1);
- updateModY(y1);
- } else {
-@@ -1693,8 +2311,8 @@
- }
- }
- } else {
-- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
-- state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
-+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL,
-+ (Guchar)splashRound(state->fillAlpha * 255), gFalse, gFalse);
- p = glyph->data;
- for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
- pipeSetXY(&pipe, x0 - glyph->x, y1);
-@@ -1702,7 +2320,7 @@
- alpha0 = *p++;
- for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
- if (alpha0 & 0x80) {
-- pipeRun(&pipe);
-+ (this->*pipe.run)(&pipe);
- updateModX(x1);
- updateModY(y1);
- } else {
-@@ -1715,8 +2333,8 @@
- }
- } else {
- if (glyph->aa) {
-- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
-- state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
-+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL,
-+ (Guchar)splashRound(state->fillAlpha * 255), gTrue, gFalse);
- p = glyph->data;
- for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
- pipeSetXY(&pipe, x0 - glyph->x, y1);
-@@ -1724,8 +2342,8 @@
- if (state->clip->test(x1, y1)) {
- alpha = *p++;
- if (alpha != 0) {
-- pipe.shape = (SplashCoord)(alpha / 255.0);
-- pipeRun(&pipe);
-+ pipe.shape = alpha;
-+ (this->*pipe.run)(&pipe);
- updateModX(x1);
- updateModY(y1);
- } else {
-@@ -1738,8 +2356,8 @@
- }
- }
- } else {
-- pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y,
-- state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
-+ pipeInit(&pipe, x0 - glyph->x, y0 - glyph->y, state->fillPattern, NULL,
-+ (Guchar)splashRound(state->fillAlpha * 255), gFalse, gFalse);
- p = glyph->data;
- for (yy = 0, y1 = y0 - glyph->y; yy < glyph->h; ++yy, ++y1) {
- pipeSetXY(&pipe, x0 - glyph->x, y1);
-@@ -1748,7 +2366,7 @@
- for (xx1 = 0; xx1 < 8 && xx + xx1 < glyph->w; ++xx1, ++x1) {
- if (state->clip->test(x1, y1)) {
- if (alpha0 & 0x80) {
-- pipeRun(&pipe);
-+ (this->*pipe.run)(&pipe);
- updateModX(x1);
- updateModY(y1);
- } else {
@@ -1772,22 +2390,10 @@
SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
int w, int h, SplashCoord *mat,
@@ -4537,677 +2987,6 @@ diff -ru xpdf-3.02/splash/Splash.cc xpdf-3.03/splash/Splash.cc
}
}
break;
-@@ -2988,166 +4580,246 @@
- return splashOk;
- }
-
--SplashPath *Splash::makeStrokePath(SplashPath *path, GBool flatten) {
-- SplashPath *pathIn, *pathOut;
-- SplashCoord w, d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext;
-+SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
-+ GBool flatten) {
-+ SplashPath *pathIn, *dashPath, *pathOut;
-+ SplashCoord d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext;
- SplashCoord crossprod, dotprod, miter, m;
- GBool first, last, closed;
-- int subpathStart, next, i;
-+ int subpathStart0, subpathStart1, seg, i0, i1, j0, j1, k0, k1;
- int left0, left1, left2, right0, right1, right2, join0, join1, join2;
- int leftFirst, rightFirst, firstPt;
-
-+ pathOut = new SplashPath();
-+
-+ if (path->length == 0) {
-+ return pathOut;
-+ }
-+
- if (flatten) {
- pathIn = flattenPath(path, state->matrix, state->flatness);
- if (state->lineDashLength > 0) {
-- pathOut = makeDashedPath(pathIn);
-+ dashPath = makeDashedPath(pathIn);
- delete pathIn;
-- pathIn = pathOut;
-+ pathIn = dashPath;
-+ if (pathIn->length == 0) {
-+ delete pathIn;
-+ return pathOut;
-+ }
- }
- } else {
- pathIn = path;
- }
-
-- subpathStart = 0; // make gcc happy
-+ subpathStart0 = subpathStart1 = 0; // make gcc happy
-+ seg = 0; // make gcc happy
- closed = gFalse; // make gcc happy
- left0 = left1 = right0 = right1 = join0 = join1 = 0; // make gcc happy
- leftFirst = rightFirst = firstPt = 0; // make gcc happy
-
-- pathOut = new SplashPath();
-- w = state->lineWidth;
--
-- for (i = 0; i < pathIn->length - 1; ++i) {
-- if (pathIn->flags[i] & splashPathLast) {
-+ i0 = 0;
-+ for (i1 = i0;
-+ !(pathIn->flags[i1] & splashPathLast) &&
-+ i1 + 1 < pathIn->length &&
-+ pathIn->pts[i1+1].x == pathIn->pts[i1].x &&
-+ pathIn->pts[i1+1].y == pathIn->pts[i1].y;
-+ ++i1) ;
-+
-+ while (i1 < pathIn->length) {
-+ if ((first = pathIn->flags[i0] & splashPathFirst)) {
-+ subpathStart0 = i0;
-+ subpathStart1 = i1;
-+ seg = 0;
-+ closed = pathIn->flags[i0] & splashPathClosed;
-+ }
-+ j0 = i1 + 1;
-+ if (j0 < pathIn->length) {
-+ for (j1 = j0;
-+ !(pathIn->flags[j1] & splashPathLast) &&
-+ j1 + 1 < pathIn->length &&
-+ pathIn->pts[j1+1].x == pathIn->pts[j1].x &&
-+ pathIn->pts[j1+1].y == pathIn->pts[j1].y;
-+ ++j1) ;
-+ } else {
-+ j1 = j0;
-+ }
-+ if (pathIn->flags[i1] & splashPathLast) {
-+ if (first && state->lineCap == splashLineCapRound) {
-+ // special case: zero-length subpath with round line caps -->
-+ // draw a circle
-+ pathOut->moveTo(pathIn->pts[i0].x + (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].y);
-+ pathOut->curveTo(pathIn->pts[i0].x + (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].y + bezierCircle2 * w,
-+ pathIn->pts[i0].x + bezierCircle2 * w,
-+ pathIn->pts[i0].y + (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].x,
-+ pathIn->pts[i0].y + (SplashCoord)0.5 * w);
-+ pathOut->curveTo(pathIn->pts[i0].x - bezierCircle2 * w,
-+ pathIn->pts[i0].y + (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].x - (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].y + bezierCircle2 * w,
-+ pathIn->pts[i0].x - (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].y);
-+ pathOut->curveTo(pathIn->pts[i0].x - (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].y - bezierCircle2 * w,
-+ pathIn->pts[i0].x - bezierCircle2 * w,
-+ pathIn->pts[i0].y - (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].x,
-+ pathIn->pts[i0].y - (SplashCoord)0.5 * w);
-+ pathOut->curveTo(pathIn->pts[i0].x + bezierCircle2 * w,
-+ pathIn->pts[i0].y - (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].x + (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].y - bezierCircle2 * w,
-+ pathIn->pts[i0].x + (SplashCoord)0.5 * w,
-+ pathIn->pts[i0].y);
-+ pathOut->close();
-+ }
-+ i0 = j0;
-+ i1 = j1;
- continue;
- }
-- if ((first = pathIn->flags[i] & splashPathFirst)) {
-- subpathStart = i;
-- closed = pathIn->flags[i] & splashPathClosed;
-- }
-- last = pathIn->flags[i+1] & splashPathLast;
--
-- // compute the deltas for segment (i, i+1)
-- d = splashDist(pathIn->pts[i].x, pathIn->pts[i].y,
-- pathIn->pts[i+1].x, pathIn->pts[i+1].y);
-- if (d == 0) {
-- // we need to draw end caps on zero-length lines
-- //~ not clear what the behavior should be for splashLineCapButt
-- //~ with d==0
-- dx = 0;
-- dy = 1;
-- } else {
-- d = (SplashCoord)1 / d;
-- dx = d * (pathIn->pts[i+1].x - pathIn->pts[i].x);
-- dy = d * (pathIn->pts[i+1].y - pathIn->pts[i].y);
-+ last = pathIn->flags[j1] & splashPathLast;
-+ if (last) {
-+ k0 = subpathStart1 + 1;
-+ } else {
-+ k0 = j1 + 1;
- }
-+ for (k1 = k0;
-+ !(pathIn->flags[k1] & splashPathLast) &&
-+ k1 + 1 < pathIn->length &&
-+ pathIn->pts[k1+1].x == pathIn->pts[k1].x &&
-+ pathIn->pts[k1+1].y == pathIn->pts[k1].y;
-+ ++k1) ;
-+
-+ // compute the deltas for segment (i1, j0)
-+#if USE_FIXEDPOINT
-+ // the 1/d value can be small, which introduces significant
-+ // inaccuracies in fixed point mode
-+ d = splashDist(pathIn->pts[i1].x, pathIn->pts[i1].y,
-+ pathIn->pts[j0].x, pathIn->pts[j0].y);
-+ dx = (pathIn->pts[j0].x - pathIn->pts[i1].x) / d;
-+ dy = (pathIn->pts[j0].y - pathIn->pts[i1].y) / d;
-+#else
-+ d = (SplashCoord)1 / splashDist(pathIn->pts[i1].x, pathIn->pts[i1].y,
-+ pathIn->pts[j0].x, pathIn->pts[j0].y);
-+ dx = d * (pathIn->pts[j0].x - pathIn->pts[i1].x);
-+ dy = d * (pathIn->pts[j0].y - pathIn->pts[i1].y);
-+#endif
- wdx = (SplashCoord)0.5 * w * dx;
- wdy = (SplashCoord)0.5 * w * dy;
-
-- // compute the deltas for segment (i+1, next)
-- next = last ? subpathStart + 1 : i + 2;
-- d = splashDist(pathIn->pts[i+1].x, pathIn->pts[i+1].y,
-- pathIn->pts[next].x, pathIn->pts[next].y);
-- if (d == 0) {
-- // we need to draw end caps on zero-length lines
-- //~ not clear what the behavior should be for splashLineCapButt
-- //~ with d==0
-- dxNext = 0;
-- dyNext = 1;
-- } else {
-- d = (SplashCoord)1 / d;
-- dxNext = d * (pathIn->pts[next].x - pathIn->pts[i+1].x);
-- dyNext = d * (pathIn->pts[next].y - pathIn->pts[i+1].y);
-- }
-- wdxNext = (SplashCoord)0.5 * w * dxNext;
-- wdyNext = (SplashCoord)0.5 * w * dyNext;
--
- // draw the start cap
-- pathOut->moveTo(pathIn->pts[i].x - wdy, pathIn->pts[i].y + wdx);
-- if (i == subpathStart) {
-+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
-+ if (i0 == subpathStart0) {
- firstPt = pathOut->length - 1;
- }
- if (first && !closed) {
- switch (state->lineCap) {
- case splashLineCapButt:
-- pathOut->lineTo(pathIn->pts[i].x + wdy, pathIn->pts[i].y - wdx);
-+ pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
- break;
- case splashLineCapRound:
-- pathOut->curveTo(pathIn->pts[i].x - wdy - bezierCircle * wdx,
-- pathIn->pts[i].y + wdx - bezierCircle * wdy,
-- pathIn->pts[i].x - wdx - bezierCircle * wdy,
-- pathIn->pts[i].y - wdy + bezierCircle * wdx,
-- pathIn->pts[i].x - wdx,
-- pathIn->pts[i].y - wdy);
-- pathOut->curveTo(pathIn->pts[i].x - wdx + bezierCircle * wdy,
-- pathIn->pts[i].y - wdy - bezierCircle * wdx,
-- pathIn->pts[i].x + wdy - bezierCircle * wdx,
-- pathIn->pts[i].y - wdx - bezierCircle * wdy,
-- pathIn->pts[i].x + wdy,
-- pathIn->pts[i].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,
-+ pathIn->pts[i0].y - wdy + bezierCircle * wdx,
-+ pathIn->pts[i0].x - wdx,
-+ pathIn->pts[i0].y - wdy);
-+ pathOut->curveTo(pathIn->pts[i0].x - wdx + bezierCircle * wdy,
-+ pathIn->pts[i0].y - wdy - bezierCircle * wdx,
-+ pathIn->pts[i0].x + wdy - bezierCircle * wdx,
-+ pathIn->pts[i0].y - wdx - bezierCircle * wdy,
-+ pathIn->pts[i0].x + wdy,
-+ pathIn->pts[i0].y - wdx);
- break;
- case splashLineCapProjecting:
-- pathOut->lineTo(pathIn->pts[i].x - wdx - wdy,
-- pathIn->pts[i].y + wdx - wdy);
-- pathOut->lineTo(pathIn->pts[i].x - wdx + wdy,
-- pathIn->pts[i].y - wdx - wdy);
-- pathOut->lineTo(pathIn->pts[i].x + wdy,
-- pathIn->pts[i].y - wdx);
-+ pathOut->lineTo(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->lineTo(pathIn->pts[i].x + wdy, pathIn->pts[i].y - wdx);
-+ pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
- }
-
- // draw the left side of the segment rectangle
- left2 = pathOut->length - 1;
-- pathOut->lineTo(pathIn->pts[i+1].x + wdy, pathIn->pts[i+1].y - wdx);
-+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
-
- // draw the end cap
- if (last && !closed) {
- switch (state->lineCap) {
- case splashLineCapButt:
-- pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx);
-+ pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
- break;
- case splashLineCapRound:
-- pathOut->curveTo(pathIn->pts[i+1].x + wdy + bezierCircle * wdx,
-- pathIn->pts[i+1].y - wdx + bezierCircle * wdy,
-- pathIn->pts[i+1].x + wdx + bezierCircle * wdy,
-- pathIn->pts[i+1].y + wdy - bezierCircle * wdx,
-- pathIn->pts[i+1].x + wdx,
-- pathIn->pts[i+1].y + wdy);
-- pathOut->curveTo(pathIn->pts[i+1].x + wdx - bezierCircle * wdy,
-- pathIn->pts[i+1].y + wdy + bezierCircle * wdx,
-- pathIn->pts[i+1].x - wdy + bezierCircle * wdx,
-- pathIn->pts[i+1].y + wdx + bezierCircle * wdy,
-- pathIn->pts[i+1].x - wdy,
-- pathIn->pts[i+1].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,
-+ pathIn->pts[j0].y + wdy - bezierCircle * wdx,
-+ pathIn->pts[j0].x + wdx,
-+ pathIn->pts[j0].y + wdy);
-+ pathOut->curveTo(pathIn->pts[j0].x + wdx - bezierCircle * wdy,
-+ pathIn->pts[j0].y + wdy + bezierCircle * wdx,
-+ pathIn->pts[j0].x - wdy + bezierCircle * wdx,
-+ pathIn->pts[j0].y + wdx + bezierCircle * wdy,
-+ pathIn->pts[j0].x - wdy,
-+ pathIn->pts[j0].y + wdx);
- break;
- case splashLineCapProjecting:
-- pathOut->lineTo(pathIn->pts[i+1].x + wdy + wdx,
-- pathIn->pts[i+1].y - wdx + wdy);
-- pathOut->lineTo(pathIn->pts[i+1].x - wdy + wdx,
-- pathIn->pts[i+1].y + wdx + wdy);
-- pathOut->lineTo(pathIn->pts[i+1].x - wdy,
-- pathIn->pts[i+1].y + wdx);
-+ pathOut->lineTo(pathIn->pts[j0].x + wdy + wdx,
-+ 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[i+1].x - wdy, pathIn->pts[i+1].y + wdx);
-+ pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
- }
-
- // draw the right side of the segment rectangle
-+ // (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();
-+ pathOut->close(state->strokeAdjust);
-
- // draw the join
- join2 = pathOut->length;
- if (!last || closed) {
-+
-+ // compute the deltas for segment (j1, k0)
-+#if USE_FIXEDPOINT
-+ // the 1/d value can be small, which introduces significant
-+ // inaccuracies in fixed point mode
-+ d = splashDist(pathIn->pts[j1].x, pathIn->pts[j1].y,
-+ pathIn->pts[k0].x, pathIn->pts[k0].y);
-+ dxNext = (pathIn->pts[k0].x - pathIn->pts[j1].x) / d;
-+ dyNext = (pathIn->pts[k0].y - pathIn->pts[j1].y) / d;
-+#else
-+ d = (SplashCoord)1 / splashDist(pathIn->pts[j1].x, pathIn->pts[j1].y,
-+ pathIn->pts[k0].x, pathIn->pts[k0].y);
-+ dxNext = d * (pathIn->pts[k0].x - pathIn->pts[j1].x);
-+ dyNext = d * (pathIn->pts[k0].y - pathIn->pts[j1].y);
-+#endif
-+ wdxNext = (SplashCoord)0.5 * w * dxNext;
-+ wdyNext = (SplashCoord)0.5 * w * dyNext;
-+
-+ // compute the join parameters
- crossprod = dx * dyNext - dy * dxNext;
- dotprod = -(dx * dxNext + dy * dyNext);
-- if (dotprod > 0.99999) {
-+ if (dotprod > 0.9999) {
- // avoid a divide-by-zero -- set miter to something arbitrary
- // such that sqrt(miter) will exceed miterLimit (and m is never
- // used in that situation)
-+ // (note: the comparison value (0.9999) has to be less than
-+ // 1-epsilon, where epsilon is the smallest value
-+ // representable in the fixed point format)
- miter = (state->miterLimit + 1) * (state->miterLimit + 1);
- m = 0;
- } else {
-@@ -3161,67 +4833,68 @@
-
- // round join
- if (state->lineJoin == splashLineJoinRound) {
-- pathOut->moveTo(pathIn->pts[i+1].x + (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].y);
-- pathOut->curveTo(pathIn->pts[i+1].x + (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].y + bezierCircle2 * w,
-- pathIn->pts[i+1].x + bezierCircle2 * w,
-- pathIn->pts[i+1].y + (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].x,
-- pathIn->pts[i+1].y + (SplashCoord)0.5 * w);
-- pathOut->curveTo(pathIn->pts[i+1].x - bezierCircle2 * w,
-- pathIn->pts[i+1].y + (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].x - (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].y + bezierCircle2 * w,
-- pathIn->pts[i+1].x - (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].y);
-- pathOut->curveTo(pathIn->pts[i+1].x - (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].y - bezierCircle2 * w,
-- pathIn->pts[i+1].x - bezierCircle2 * w,
-- pathIn->pts[i+1].y - (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].x,
-- pathIn->pts[i+1].y - (SplashCoord)0.5 * w);
-- pathOut->curveTo(pathIn->pts[i+1].x + bezierCircle2 * w,
-- pathIn->pts[i+1].y - (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].x + (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].y - bezierCircle2 * w,
-- pathIn->pts[i+1].x + (SplashCoord)0.5 * w,
-- pathIn->pts[i+1].y);
-+ 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);
-
- } else {
-- pathOut->moveTo(pathIn->pts[i+1].x, pathIn->pts[i+1].y);
-+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
-
- // angle < 180
- if (crossprod < 0) {
-- pathOut->lineTo(pathIn->pts[i+1].x - wdyNext,
-- pathIn->pts[i+1].y + wdxNext);
-+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
-+ pathIn->pts[j0].y + wdxNext);
- // miter join inside limit
- if (state->lineJoin == splashLineJoinMiter &&
- splashSqrt(miter) <= state->miterLimit) {
-- pathOut->lineTo(pathIn->pts[i+1].x - wdy + wdx * m,
-- pathIn->pts[i+1].y + wdx + wdy * m);
-- pathOut->lineTo(pathIn->pts[i+1].x - wdy,
-- pathIn->pts[i+1].y + wdx);
-+ pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx * m,
-+ pathIn->pts[j0].y + wdx + wdy * m);
-+ pathOut->lineTo(pathIn->pts[j0].x - wdy,
-+ pathIn->pts[j0].y + wdx);
- // bevel join or miter join outside limit
- } else {
-- pathOut->lineTo(pathIn->pts[i+1].x - wdy, pathIn->pts[i+1].y + wdx);
-+ pathOut->lineTo(pathIn->pts[j0].x - wdy,
-+ pathIn->pts[j0].y + wdx);
- }
-
- // angle >= 180
- } else {
-- pathOut->lineTo(pathIn->pts[i+1].x + wdy,
-- pathIn->pts[i+1].y - wdx);
-+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
-+ pathIn->pts[j0].y - wdx);
- // miter join inside limit
- if (state->lineJoin == splashLineJoinMiter &&
- splashSqrt(miter) <= state->miterLimit) {
-- pathOut->lineTo(pathIn->pts[i+1].x + wdy + wdx * m,
-- pathIn->pts[i+1].y - wdx + wdy * m);
-- pathOut->lineTo(pathIn->pts[i+1].x + wdyNext,
-- pathIn->pts[i+1].y - wdxNext);
-+ pathOut->lineTo(pathIn->pts[j0].x + wdy + wdx * m,
-+ pathIn->pts[j0].y - wdx + wdy * m);
-+ pathOut->lineTo(pathIn->pts[j0].x + wdyNext,
-+ pathIn->pts[j0].y - wdxNext);
- // bevel join or miter join outside limit
- } else {
-- pathOut->lineTo(pathIn->pts[i+1].x + wdyNext,
-- pathIn->pts[i+1].y - wdxNext);
-+ pathOut->lineTo(pathIn->pts[j0].x + wdyNext,
-+ pathIn->pts[j0].y - wdxNext);
- }
- }
- }
-@@ -3231,8 +4904,28 @@
-
- // add stroke adjustment hints
- if (state->strokeAdjust) {
-- if (i >= subpathStart + 1) {
-- if (i >= subpathStart + 2) {
-+ if (seg == 0 && !closed) {
-+ if (state->lineCap == 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);
-+ }
-+ }
-+ }
-+ if (seg >= 1) {
-+ if (seg >= 2) {
- pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
- pathOut->addStrokeAdjustHint(left1, right1, join0, left2);
- } else {
-@@ -3246,12 +4939,12 @@
- right1 = right2;
- join0 = join1;
- join1 = join2;
-- if (i == subpathStart) {
-+ if (seg == 0) {
- leftFirst = left2;
- rightFirst = right2;
- }
- if (last) {
-- if (i >= subpathStart + 2) {
-+ if (seg >= 2) {
- pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
- pathOut->addStrokeAdjustHint(left1, right1,
- join0, pathOut->length - 1);
-@@ -3268,8 +4961,21 @@
- 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;
-+ i1 = j1;
-+ ++seg;
- }
-
- if (pathIn != path) {
-diff -ru xpdf-3.02/splash/SplashClip.cc xpdf-3.03/splash/SplashClip.cc
---- xpdf-3.02/splash/SplashClip.cc 2007-02-27 23:05:52.000000000 +0100
-+++ xpdf-3.03/splash/SplashClip.cc 2011-08-15 23:08:53.000000000 +0200
-@@ -50,8 +50,8 @@
- }
- xMinI = splashFloor(xMin);
- yMinI = splashFloor(yMin);
-- xMaxI = splashFloor(xMax);
-- yMaxI = splashFloor(yMax);
-+ xMaxI = splashCeil(xMax) - 1;
-+ yMaxI = splashCeil(yMax) - 1;
- paths = NULL;
- flags = NULL;
- scanners = NULL;
-@@ -59,6 +59,7 @@
- }
-
- SplashClip::SplashClip(SplashClip *clip) {
-+ int yMinAA, yMaxAA;
- int i;
-
- antialias = clip->antialias;
-@@ -79,7 +80,15 @@
- for (i = 0; i < length; ++i) {
- paths[i] = clip->paths[i]->copy();
- flags[i] = clip->flags[i];
-- scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO);
-+ if (antialias) {
-+ yMinAA = yMinI * splashAASize;
-+ yMaxAA = (yMaxI + 1) * splashAASize - 1;
-+ } else {
-+ yMinAA = yMinI;
-+ yMaxAA = yMaxI;
-+ }
-+ scanners[i] = new SplashXPathScanner(paths[i], flags[i] & splashClipEO,
-+ yMinAA, yMaxAA);
- }
- }
-
-@@ -142,8 +151,8 @@
- }
- xMinI = splashFloor(xMin);
- yMinI = splashFloor(yMin);
-- xMaxI = splashFloor(xMax);
-- yMaxI = splashFloor(yMax);
-+ xMaxI = splashCeil(xMax) - 1;
-+ yMaxI = splashCeil(yMax) - 1;
- }
-
- SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
-@@ -155,7 +164,7 @@
- }
- if (x1 < xMax) {
- xMax = x1;
-- xMaxI = splashFloor(xMax);
-+ xMaxI = splashCeil(xMax) - 1;
- }
- } else {
- if (x1 > xMin) {
-@@ -164,7 +173,7 @@
- }
- if (x0 < xMax) {
- xMax = x0;
-- xMaxI = splashFloor(xMax);
-+ xMaxI = splashCeil(xMax) - 1;
- }
- }
- if (y0 < y1) {
-@@ -174,7 +183,7 @@
- }
- if (y1 < yMax) {
- yMax = y1;
-- yMaxI = splashFloor(yMax);
-+ yMaxI = splashCeil(yMax) - 1;
- }
- } else {
- if (y1 > yMin) {
-@@ -183,7 +192,7 @@
- }
- if (y0 < yMax) {
- yMax = y0;
-- yMaxI = splashFloor(yMax);
-+ yMaxI = splashCeil(yMax) - 1;
- }
- }
- return splashOk;
-@@ -192,6 +201,7 @@
- SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
- SplashCoord flatness, GBool eo) {
- SplashXPath *xPath;
-+ int yMinAA, yMaxAA;
-
- xPath = new SplashXPath(path, matrix, flatness, gTrue);
-
-@@ -199,8 +209,8 @@
- if (xPath->length == 0) {
- xMax = xMin - 1;
- yMax = yMin - 1;
-- xMaxI = splashFloor(xMax);
-- yMaxI = splashFloor(yMax);
-+ xMaxI = splashCeil(xMax) - 1;
-+ yMaxI = splashCeil(yMax) - 1;
- delete xPath;
-
- // check for a rectangle
-@@ -241,7 +251,14 @@
- xPath->sort();
- paths[length] = xPath;
- flags[length] = eo ? splashClipEO : 0;
-- scanners[length] = new SplashXPathScanner(xPath, eo);
-+ if (antialias) {
-+ yMinAA = yMinI * splashAASize;
-+ yMaxAA = (yMaxI + 1) * splashAASize - 1;
-+ } else {
-+ yMinAA = yMinI;
-+ yMaxAA = yMaxI;
-+ }
-+ scanners[length] = new SplashXPathScanner(xPath, eo, yMinAA, yMaxAA);
- ++length;
- }
-
-@@ -280,10 +297,10 @@
- // x = [rectXMin, rectXMax + 1) (note: rect coords are ints)
- // y = [rectYMin, rectYMax + 1)
- // against the clipping region:
-- // x = [xMin, xMax] (note: clipping coords are fp)
-- // y = [yMin, yMax]
-- if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin > xMax ||
-- (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin > yMax) {
-+ // x = [xMin, xMax) (note: clipping coords are fp)
-+ // y = [yMin, yMax)
-+ if ((SplashCoord)(rectXMax + 1) <= xMin || (SplashCoord)rectXMin >= xMax ||
-+ (SplashCoord)(rectYMax + 1) <= yMin || (SplashCoord)rectYMin >= yMax) {
- return splashClipAllOutside;
- }
- if ((SplashCoord)rectXMin >= xMin && (SplashCoord)(rectXMax + 1) <= xMax &&
-@@ -301,10 +318,10 @@
- // x = [spanXMin, spanXMax + 1) (note: span coords are ints)
- // y = [spanY, spanY + 1)
- // against the clipping region:
-- // x = [xMin, xMax] (note: clipping coords are fp)
-- // y = [yMin, yMax]
-- if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin > xMax ||
-- (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY > yMax) {
-+ // x = [xMin, xMax) (note: clipping coords are fp)
-+ // y = [yMin, yMax)
-+ if ((SplashCoord)(spanXMax + 1) <= xMin || (SplashCoord)spanXMin >= xMax ||
-+ (SplashCoord)(spanY + 1) <= yMin || (SplashCoord)spanY >= yMax) {
- return splashClipAllOutside;
- }
- if (!((SplashCoord)spanXMin >= xMin && (SplashCoord)(spanXMax + 1) <= xMax &&
diff -ru xpdf-3.02/splash/SplashFTFont.cc xpdf-3.03/splash/SplashFTFont.cc
--- xpdf-3.02/splash/SplashFTFont.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/splash/SplashFTFont.cc 2011-08-15 23:08:53.000000000 +0200
@@ -5308,95 +3087,18 @@ diff -ru xpdf-3.02/splash/Splash.h xpdf-3.03/splash/Splash.h
splashPipeResultColorAlphaNoBlendMono,
splashPipeResultColorAlphaNoBlendRGB,
#if SPLASH_CMYK
-@@ -93,6 +93,7 @@
- SplashCoord *getLineDash();
- int getLineDashLength();
- SplashCoord getLineDashPhase();
-+ GBool getStrokeAdjust();
- SplashClip *getClip();
- SplashBitmap *getSoftMask();
- GBool getInNonIsolatedGroup();
-@@ -126,6 +127,8 @@
- void setSoftMask(SplashBitmap *softMask);
- void setInNonIsolatedGroup(SplashBitmap *alpha0BitmapA,
- int alpha0XA, int alpha0YA);
-+ void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
-+ void setOverprintMask(Guint overprintMask);
-
- //----- state save/restore
-
-@@ -208,14 +211,19 @@
-
- //----- misc
-
-- // Construct a path for a stroke, given the path to be stroked, and
-- // using the current line parameters. If <flatten> is true, this
-- // function will first flatten the path and handle the linedash.
-- SplashPath *makeStrokePath(SplashPath *path, GBool flatten = gTrue);
-+ // Construct a path for a stroke, given the path to be stroked and
-+ // the line width <w>. All other stroke parameters are taken from
-+ // the current state. If <flatten> is true, this function will
-+ // first flatten the path and handle the linedash.
-+ SplashPath *makeStrokePath(SplashPath *path, SplashCoord w,
-+ GBool flatten = gTrue);
-
- // Return the associated bitmap.
- SplashBitmap *getBitmap() { return bitmap; }
-
-+ // Set the minimum line width.
-+ void setMinLineWidth(SplashCoord w) { minLineWidth = w; }
-+
- // Get a bounding box which includes all modifications since the
- // last call to clearModRegion.
- void getModRegion(int *xMin, int *yMin, int *xMax, int *yMax)
@@ -232,17 +240,30 @@
void setDebugMode(GBool debugModeA) { debugMode = debugModeA; }
#if 1 //~tmp: turn off anti-aliasing temporarily
- GBool getVectorAntialias() { return vectorAntialias; }
- void setVectorAntialias(GBool vaa) { vectorAntialias = vaa; }
-+ void setInShading(GBool sh) { inShading = sh; }
+ void setInShading(GBool sh) { inShading = sh; }
#endif
private:
- void pipeInit(SplashPipe *pipe, int x, int y,
- SplashPattern *pattern, SplashColorPtr cSrc,
-- SplashCoord aInput, GBool usesShape,
-+ Guchar aInput, GBool usesShape,
- GBool nonIsolatedGroup);
- void pipeRun(SplashPipe *pipe);
-+ void pipeRunSimpleMono1(SplashPipe *pipe);
-+ void pipeRunSimpleMono8(SplashPipe *pipe);
-+ void pipeRunSimpleRGB8(SplashPipe *pipe);
-+ void pipeRunSimpleBGR8(SplashPipe *pipe);
-+#if SPLASH_CMYK
-+ void pipeRunSimpleCMYK8(SplashPipe *pipe);
-+#endif
-+ void pipeRunAAMono1(SplashPipe *pipe);
-+ void pipeRunAAMono8(SplashPipe *pipe);
-+ void pipeRunAARGB8(SplashPipe *pipe);
-+ void pipeRunAABGR8(SplashPipe *pipe);
-+#if SPLASH_CMYK
-+ void pipeRunAACMYK8(SplashPipe *pipe);
-+#endif
- void pipeSetXY(SplashPipe *pipe, int x, int y);
- void pipeIncX(SplashPipe *pipe);
- void drawPixel(SplashPipe *pipe, int x, int y, GBool noClip);
-@@ -255,7 +276,7 @@
- void updateModX(int x);
- void updateModY(int y);
- void strokeNarrow(SplashPath *path);
-- void strokeWide(SplashPath *path);
-+ void strokeWide(SplashPath *path, SplashCoord w);
- SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix,
- SplashCoord flatness);
- void flattenCurve(SplashCoord x0, SplashCoord y0,
@@ -267,7 +288,68 @@
- SplashPath *makeDashedPath(SplashPath *xPath);
- SplashError fillWithPattern(SplashPath *path, GBool eo,
- SplashPattern *pattern, SplashCoord alpha);
-+ GBool pathAllOutside(SplashPath *path);
SplashError fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph);
+ void arbitraryTransformMask(SplashImageMaskSource src, void *srcData,
+ int srcWidth, int srcHeight,
@@ -5467,34 +3169,10 @@ diff -ru xpdf-3.02/splash/Splash.h xpdf-3.03/splash/Splash.h
int alpha0X, alpha0Y; // offset within alpha0Bitmap
- SplashCoord aaGamma[splashAASize * splashAASize + 1];
+ Guchar aaGamma[splashAASize * splashAASize + 1];
-+ SplashCoord minLineWidth;
- int modXMin, modYMin, modXMax, modYMax;
- SplashClipResult opClipRes;
- GBool vectorAntialias;
-+ GBool inShading;
- GBool debugMode;
- };
-
+ SplashCoord minLineWidth;
diff -ru xpdf-3.02/splash/SplashState.cc xpdf-3.03/splash/SplashState.cc
--- xpdf-3.02/splash/SplashState.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/splash/SplashState.cc 2011-08-15 23:08:53.000000000 +0200
-@@ -24,15 +24,16 @@
-
- // number of components in each color mode
- int splashColorModeNComps[] = {
- 1, 1, 3, 3
-#if SPLASH_CMYK
- , 4
-#endif
- };
-
- SplashState::SplashState(int width, int height, GBool vectorAntialias,
- SplashScreenParams *screenParams) {
- SplashColor color;
-+ int i;
-
- matrix[0] = 1; matrix[1] = 0;
- matrix[2] = 0; matrix[3] = 1;
@@ -50,16 +54,28 @@
lineDashLength = 0;
lineDashPhase = 0;
@@ -5504,27 +3182,6 @@ diff -ru xpdf-3.02/splash/SplashState.cc xpdf-3.03/splash/SplashState.cc
softMask = NULL;
deleteSoftMask = gFalse;
inNonIsolatedGroup = gFalse;
-+ for (i = 0; i < 256; ++i) {
-+ rgbTransferR[i] = (Guchar)i;
-+ rgbTransferG[i] = (Guchar)i;
-+ rgbTransferB[i] = (Guchar)i;
-+ grayTransfer[i] = (Guchar)i;
-+ cmykTransferC[i] = (Guchar)i;
-+ cmykTransferM[i] = (Guchar)i;
-+ cmykTransferY[i] = (Guchar)i;
-+ cmykTransferK[i] = (Guchar)i;
-+ }
-+ overprintMask = 0xffffffff;
- next = NULL;
- }
-
- SplashState::SplashState(int width, int height, GBool vectorAntialias,
- SplashScreen *screenA) {
- SplashColor color;
-+ int i;
-
- matrix[0] = 1; matrix[1] = 0;
- matrix[2] = 0; matrix[3] = 1;
@@ -80,10 +96,21 @@
lineDashLength = 0;
lineDashPhase = 0;
@@ -5534,85 +3191,6 @@ diff -ru xpdf-3.02/splash/SplashState.cc xpdf-3.03/splash/SplashState.cc
softMask = NULL;
deleteSoftMask = gFalse;
inNonIsolatedGroup = gFalse;
-+ for (i = 0; i < 256; ++i) {
-+ rgbTransferR[i] = (Guchar)i;
-+ rgbTransferG[i] = (Guchar)i;
-+ rgbTransferB[i] = (Guchar)i;
-+ grayTransfer[i] = (Guchar)i;
-+ cmykTransferC[i] = (Guchar)i;
-+ cmykTransferM[i] = (Guchar)i;
-+ cmykTransferY[i] = (Guchar)i;
-+ cmykTransferK[i] = (Guchar)i;
-+ }
-+ overprintMask = 0xffffffff;
- next = NULL;
- }
-
-@@ -114,6 +141,15 @@
- softMask = state->softMask;
- deleteSoftMask = gFalse;
- inNonIsolatedGroup = state->inNonIsolatedGroup;
-+ memcpy(rgbTransferR, state->rgbTransferR, 256);
-+ memcpy(rgbTransferG, state->rgbTransferG, 256);
-+ memcpy(rgbTransferB, state->rgbTransferB, 256);
-+ memcpy(grayTransfer, state->grayTransfer, 256);
-+ memcpy(cmykTransferC, state->cmykTransferC, 256);
-+ memcpy(cmykTransferM, state->cmykTransferM, 256);
-+ memcpy(cmykTransferY, state->cmykTransferY, 256);
-+ memcpy(cmykTransferK, state->cmykTransferK, 256);
-+ overprintMask = state->overprintMask;
- next = NULL;
- }
-
-@@ -163,3 +199,19 @@
- softMask = softMaskA;
- deleteSoftMask = gTrue;
- }
-+
-+void SplashState::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
-+ Guchar *gray) {
-+ int i;
-+
-+ memcpy(rgbTransferR, red, 256);
-+ memcpy(rgbTransferG, green, 256);
-+ memcpy(rgbTransferB, blue, 256);
-+ memcpy(grayTransfer, gray, 256);
-+ for (i = 0; i < 256; ++i) {
-+ cmykTransferC[i] = 255 - rgbTransferR[255 - i];
-+ cmykTransferM[i] = 255 - rgbTransferG[255 - i];
-+ cmykTransferY[i] = 255 - rgbTransferB[255 - i];
-+ cmykTransferK[i] = 255 - grayTransfer[255 - i];
-+ }
-+}
-diff -ru xpdf-3.02/splash/SplashState.h xpdf-3.03/splash/SplashState.h
---- xpdf-3.02/splash/SplashState.h 2007-02-27 23:05:52.000000000 +0100
-+++ xpdf-3.03/splash/SplashState.h 2011-08-15 23:08:53.000000000 +0200
-@@ -70,6 +70,9 @@
- // Set the soft mask bitmap.
- void setSoftMask(SplashBitmap *softMaskA);
-
-+ // Set the transfer function.
-+ void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
-+
- private:
-
- SplashState(SplashState *state);
-@@ -94,6 +97,15 @@
- SplashBitmap *softMask;
- GBool deleteSoftMask;
- GBool inNonIsolatedGroup;
-+ Guchar rgbTransferR[256],
-+ rgbTransferG[256],
-+ rgbTransferB[256];
-+ Guchar grayTransfer[256];
-+ Guchar cmykTransferC[256],
-+ cmykTransferM[256],
-+ cmykTransferY[256],
-+ cmykTransferK[256];
-+ Guint overprintMask;
-
- SplashState *next; // used by Splash class
-
diff -ru xpdf-3.02/splash/SplashXPath.cc xpdf-3.03/splash/SplashXPath.cc
--- xpdf-3.02/splash/SplashXPath.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/splash/SplashXPath.cc 2011-08-15 23:08:53.000000000 +0200
@@ -5664,734 +3242,6 @@ diff -ru xpdf-3.02/splash/SplashXPath.cc xpdf-3.03/splash/SplashXPath.cc
adjusts[i].xm = (SplashCoord)0.5 * (adjusts[i].x0 + adjusts[i].x1);
adjusts[i].firstPt = hint->firstPt;
adjusts[i].lastPt = hint->lastPt;
-diff -ru xpdf-3.02/splash/SplashXPathScanner.cc xpdf-3.03/splash/SplashXPathScanner.cc
---- xpdf-3.02/splash/SplashXPathScanner.cc 2007-02-27 23:05:52.000000000 +0100
-+++ xpdf-3.03/splash/SplashXPathScanner.cc 2011-08-15 23:08:53.000000000 +0200
-@@ -12,6 +12,9 @@
-
- #include <stdlib.h>
- #include <string.h>
-+#if HAVE_STD_SORT
-+#include <algorithm>
-+#endif
- #include "gmem.h"
- #include "SplashMath.h"
- #include "SplashXPath.h"
-@@ -21,25 +24,47 @@
- //------------------------------------------------------------------------
-
- struct SplashIntersect {
-+ int y;
- int x0, x1; // intersection of segment with [y, y+1)
- int count; // EO/NZWN counter increment
- };
-
-+#if HAVE_STD_SORT
-+
-+struct cmpIntersectFunctor {
-+ bool operator()(const SplashIntersect &i0, const SplashIntersect &i1) {
-+ return (i0.y != i1.y) ? (i0.y < i1.y) : (i0.x0 < i1.x0);
-+ }
-+};
-+
-+#else // HAVE_STD_SORT
-+
- static int cmpIntersect(const void *p0, const void *p1) {
-- return ((SplashIntersect *)p0)->x0 - ((SplashIntersect *)p1)->x0;
-+ SplashIntersect *i0 = (SplashIntersect *)p0;
-+ SplashIntersect *i1 = (SplashIntersect *)p1;
-+ int cmp;
-+
-+ if ((cmp = i0->y - i1->y) == 0) {
-+ cmp = i0->x0 - i1->x0;
-+ }
-+ return cmp;
- }
-
-+#endif // HAVE_STD_SORT
-+
- //------------------------------------------------------------------------
- // SplashXPathScanner
- //------------------------------------------------------------------------
-
--SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA) {
-+SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA,
-+ int clipYMin, int clipYMax) {
- SplashXPathSeg *seg;
- SplashCoord xMinFP, yMinFP, xMaxFP, yMaxFP;
- int i;
-
- xPath = xPathA;
- eo = eoA;
-+ partialClip = gFalse;
-
- // compute the bbox
- if (xPath->length == 0) {
-@@ -87,16 +112,25 @@
- xMax = splashFloor(xMaxFP);
- yMin = splashFloor(yMinFP);
- yMax = splashFloor(yMaxFP);
-+ if (clipYMin > yMin) {
-+ yMin = clipYMin;
-+ partialClip = gTrue;
-+ }
-+ if (clipYMax < yMax) {
-+ yMax = clipYMax;
-+ partialClip = gTrue;
-+ }
- }
-
-- interY = yMin - 1;
-- xPathIdx = 0;
-+ allInter = NULL;
- inter = NULL;
-- interLen = interSize = 0;
-+ computeIntersections();
-+ interY = yMin - 1;
- }
-
- SplashXPathScanner::~SplashXPathScanner() {
- gfree(inter);
-+ gfree(allInter);
- }
-
- void SplashXPathScanner::getBBoxAA(int *xMinA, int *yMinA,
-@@ -108,12 +142,23 @@
- }
-
- void SplashXPathScanner::getSpanBounds(int y, int *spanXMin, int *spanXMax) {
-- if (interY != y) {
-- computeIntersections(y);
-+ int interBegin, interEnd, xx, i;
-+
-+ if (y < yMin || y > yMax) {
-+ interBegin = interEnd = 0;
-+ } else {
-+ interBegin = inter[y - yMin];
-+ interEnd = inter[y - yMin + 1];
- }
-- if (interLen > 0) {
-- *spanXMin = inter[0].x0;
-- *spanXMax = inter[interLen - 1].x1;
-+ if (interBegin < interEnd) {
-+ *spanXMin = allInter[interBegin].x0;
-+ xx = allInter[interBegin].x1;
-+ for (i = interBegin + 1; i < interEnd; ++i) {
-+ if (allInter[i].x1 > xx) {
-+ xx = allInter[i].x1;
-+ }
-+ }
-+ *spanXMax = xx;
- } else {
- *spanXMin = xMax + 1;
- *spanXMax = xMax;
-@@ -121,47 +166,50 @@
- }
-
- GBool SplashXPathScanner::test(int x, int y) {
-- int count, i;
-+ int interBegin, interEnd, count, i;
-
-- if (interY != y) {
-- computeIntersections(y);
-+ if (y < yMin || y > yMax) {
-+ return gFalse;
- }
-+ interBegin = inter[y - yMin];
-+ interEnd = inter[y - yMin + 1];
- count = 0;
-- for (i = 0; i < interLen && inter[i].x0 <= x; ++i) {
-- if (x <= inter[i].x1) {
-+ for (i = interBegin; i < interEnd && allInter[i].x0 <= x; ++i) {
-+ if (x <= allInter[i].x1) {
- return gTrue;
- }
-- count += inter[i].count;
-+ count += allInter[i].count;
- }
- return eo ? (count & 1) : (count != 0);
- }
-
- GBool SplashXPathScanner::testSpan(int x0, int x1, int y) {
-- int count, xx1, i;
-+ int interBegin, interEnd, count, xx1, i;
-
-- if (interY != y) {
-- computeIntersections(y);
-+ if (y < yMin || y > yMax) {
-+ return gFalse;
- }
--
-+ interBegin = inter[y - yMin];
-+ interEnd = inter[y - yMin + 1];
- count = 0;
-- for (i = 0; i < interLen && inter[i].x1 < x0; ++i) {
-- count += inter[i].count;
-+ for (i = interBegin; i < interEnd && allInter[i].x1 < x0; ++i) {
-+ count += allInter[i].count;
- }
-
- // invariant: the subspan [x0,xx1] is inside the path
- xx1 = x0 - 1;
- while (xx1 < x1) {
-- if (i >= interLen) {
-+ if (i >= interEnd) {
- return gFalse;
- }
-- if (inter[i].x0 > xx1 + 1 &&
-+ if (allInter[i].x0 > xx1 + 1 &&
- !(eo ? (count & 1) : (count != 0))) {
- return gFalse;
- }
-- if (inter[i].x1 > xx1) {
-- xx1 = inter[i].x1;
-+ if (allInter[i].x1 > xx1) {
-+ xx1 = allInter[i].x1;
- }
-- count += inter[i].count;
-+ count += allInter[i].count;
- ++i;
- }
-
-@@ -169,25 +217,31 @@
- }
-
- GBool SplashXPathScanner::getNextSpan(int y, int *x0, int *x1) {
-- int xx0, xx1;
-+ int interEnd, xx0, xx1;
-
-+ if (y < yMin || y > yMax) {
-+ return gFalse;
-+ }
- if (interY != y) {
-- computeIntersections(y);
-+ interY = y;
-+ interIdx = inter[y - yMin];
-+ interCount = 0;
- }
-- if (interIdx >= interLen) {
-+ interEnd = inter[y - yMin + 1];
-+ if (interIdx >= interEnd) {
- return gFalse;
- }
-- xx0 = inter[interIdx].x0;
-- xx1 = inter[interIdx].x1;
-- interCount += inter[interIdx].count;
-+ xx0 = allInter[interIdx].x0;
-+ xx1 = allInter[interIdx].x1;
-+ interCount += allInter[interIdx].count;
- ++interIdx;
-- while (interIdx < interLen &&
-- (inter[interIdx].x0 <= xx1 ||
-+ while (interIdx < interEnd &&
-+ (allInter[interIdx].x0 <= xx1 ||
- (eo ? (interCount & 1) : (interCount != 0)))) {
-- if (inter[interIdx].x1 > xx1) {
-- xx1 = inter[interIdx].x1;
-+ if (allInter[interIdx].x1 > xx1) {
-+ xx1 = allInter[interIdx].x1;
- }
-- interCount += inter[interIdx].count;
-+ interCount += allInter[interIdx].count;
- ++interIdx;
- }
- *x0 = xx0;
-@@ -195,161 +249,203 @@
- return gTrue;
- }
-
--void SplashXPathScanner::computeIntersections(int y) {
-- SplashCoord xSegMin, xSegMax, ySegMin, ySegMax, xx0, xx1;
-+void SplashXPathScanner::computeIntersections() {
- SplashXPathSeg *seg;
-- int i, j;
-+ SplashCoord segXMin, segXMax, segYMin, segYMax, xx0, xx1;
-+ int x, y, y0, y1, i;
-
-- // find the first segment that intersects [y, y+1)
-- i = (y >= interY) ? xPathIdx : 0;
-- while (i < xPath->length &&
-- xPath->segs[i].y0 < y && xPath->segs[i].y1 < y) {
-- ++i;
-+ if (yMin > yMax) {
-+ return;
- }
-- xPathIdx = i;
-
-- // find all of the segments that intersect [y, y+1) and create an
-- // Intersect element for each one
-- interLen = 0;
-- for (j = i; j < xPath->length; ++j) {
-- seg = &xPath->segs[j];
-+ // build the list of all intersections
-+ allInterLen = 0;
-+ allInterSize = 16;
-+ allInter = (SplashIntersect *)gmallocn(allInterSize,
-+ sizeof(SplashIntersect));
-+ for (i = 0; i < xPath->length; ++i) {
-+ seg = &xPath->segs[i];
- if (seg->flags & splashXPathFlip) {
-- ySegMin = seg->y1;
-- ySegMax = seg->y0;
-+ segYMin = seg->y1;
-+ segYMax = seg->y0;
- } else {
-- ySegMin = seg->y0;
-- ySegMax = seg->y1;
-- }
--
-- // ensure that: ySegMin < y+1
-- // y <= ySegMax
-- if (ySegMin >= y + 1) {
-- break;
-+ segYMin = seg->y0;
-+ segYMax = seg->y1;
- }
-- if (ySegMax < y) {
-- continue;
-- }
--
-- if (interLen == interSize) {
-- if (interSize == 0) {
-- interSize = 16;
-- } else {
-- interSize *= 2;
-- }
-- inter = (SplashIntersect *)greallocn(inter, interSize,
-- sizeof(SplashIntersect));
-- }
--
- if (seg->flags & splashXPathHoriz) {
-- xx0 = seg->x0;
-- xx1 = seg->x1;
-+ y = splashFloor(seg->y0);
-+ if (y >= yMin && y <= yMax) {
-+ addIntersection(segYMin, segYMax, seg->flags,
-+ y, splashFloor(seg->x0), splashFloor(seg->x1));
-+ }
- } else if (seg->flags & splashXPathVert) {
-- xx0 = xx1 = seg->x0;
-+ y0 = splashFloor(segYMin);
-+ if (y0 < yMin) {
-+ y0 = yMin;
-+ }
-+ y1 = splashFloor(segYMax);
-+ if (y1 > yMax) {
-+ y1 = yMax;
-+ }
-+ x = splashFloor(seg->x0);
-+ for (y = y0; y <= y1; ++y) {
-+ addIntersection(segYMin, segYMax, seg->flags, y, x, x);
-+ }
- } else {
- if (seg->x0 < seg->x1) {
-- xSegMin = seg->x0;
-- xSegMax = seg->x1;
-+ segXMin = seg->x0;
-+ segXMax = seg->x1;
- } else {
-- xSegMin = seg->x1;
-- xSegMax = seg->x0;
-+ segXMin = seg->x1;
-+ segXMax = seg->x0;
-+ }
-+ y0 = splashFloor(segYMin);
-+ if (y0 < yMin) {
-+ y0 = yMin;
-+ }
-+ y1 = splashFloor(segYMax);
-+ if (y1 > yMax) {
-+ y1 = yMax;
-+ }
-+ // this loop could just add seg->dxdy to xx1 on each iteration,
-+ // but that introduces numerical accuracy problems
-+ xx1 = seg->x0 + ((SplashCoord)y0 - seg->y0) * seg->dxdy;
-+ for (y = y0; y <= y1; ++y) {
-+ xx0 = xx1;
-+ xx1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy;
-+ // the segment may not actually extend to the top and/or bottom edges
-+ if (xx0 < segXMin) {
-+ xx0 = segXMin;
-+ } else if (xx0 > segXMax) {
-+ xx0 = segXMax;
-+ }
-+ if (xx1 < segXMin) {
-+ xx1 = segXMin;
-+ } else if (xx1 > segXMax) {
-+ xx1 = segXMax;
-+ }
-+ addIntersection(segYMin, segYMax, seg->flags, y,
-+ splashFloor(xx0), splashFloor(xx1));
- }
-- // intersection with top edge
-- xx0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy;
-- // intersection with bottom edge
-- xx1 = seg->x0 + ((SplashCoord)y + 1 - seg->y0) * seg->dxdy;
-- // the segment may not actually extend to the top and/or bottom edges
-- if (xx0 < xSegMin) {
-- xx0 = xSegMin;
-- } else if (xx0 > xSegMax) {
-- xx0 = xSegMax;
-- }
-- if (xx1 < xSegMin) {
-- xx1 = xSegMin;
-- } else if (xx1 > xSegMax) {
-- xx1 = xSegMax;
-- }
-- }
-- if (xx0 < xx1) {
-- inter[interLen].x0 = splashFloor(xx0);
-- inter[interLen].x1 = splashFloor(xx1);
-- } else {
-- inter[interLen].x0 = splashFloor(xx1);
-- inter[interLen].x1 = splashFloor(xx0);
- }
-- if (ySegMin <= y &&
-- (SplashCoord)y < ySegMax &&
-- !(seg->flags & splashXPathHoriz)) {
-- inter[interLen].count = eo ? 1
-- : (seg->flags & splashXPathFlip) ? 1 : -1;
-- } else {
-- inter[interLen].count = 0;
-+ }
-+#if HAVE_STD_SORT
-+ std::sort(allInter, allInter + allInterLen, cmpIntersectFunctor());
-+#else
-+ qsort(allInter, allInterLen, sizeof(SplashIntersect), cmpIntersect);
-+#endif
-+
-+ // build the list of y pointers
-+ inter = (int *)gmallocn(yMax - yMin + 2, sizeof(int));
-+ i = 0;
-+ for (y = yMin; y <= yMax; ++y) {
-+ inter[y - yMin] = i;
-+ while (i < allInterLen && allInter[i].y <= y) {
-+ ++i;
- }
-- ++interLen;
- }
-+ inter[yMax - yMin + 1] = i;
-+}
-
-- qsort(inter, interLen, sizeof(SplashIntersect), &cmpIntersect);
--
-- interY = y;
-- interIdx = 0;
-- interCount = 0;
-+void SplashXPathScanner::addIntersection(double segYMin, double segYMax,
-+ Guint segFlags,
-+ int y, int x0, int x1) {
-+ if (allInterLen == allInterSize) {
-+ allInterSize *= 2;
-+ allInter = (SplashIntersect *)greallocn(allInter, allInterSize,
-+ sizeof(SplashIntersect));
-+ }
-+ allInter[allInterLen].y = y;
-+ if (x0 < x1) {
-+ allInter[allInterLen].x0 = x0;
-+ allInter[allInterLen].x1 = x1;
-+ } else {
-+ allInter[allInterLen].x0 = x1;
-+ allInter[allInterLen].x1 = x0;
-+ }
-+ if (segYMin <= y &&
-+ (SplashCoord)y < segYMax &&
-+ !(segFlags & splashXPathHoriz)) {
-+ allInter[allInterLen].count = eo ? 1
-+ : (segFlags & splashXPathFlip) ? 1 : -1;
-+ } else {
-+ allInter[allInterLen].count = 0;
-+ }
-+ ++allInterLen;
- }
-
- void SplashXPathScanner::renderAALine(SplashBitmap *aaBuf,
- int *x0, int *x1, int y) {
-- int xx0, xx1, xx, xxMin, xxMax, yy;
-+ int xx0, xx1, xx, xxMin, xxMax, yy, interEnd;
- Guchar mask;
- SplashColorPtr p;
-
- memset(aaBuf->getDataPtr(), 0, aaBuf->getRowSize() * aaBuf->getHeight());
- xxMin = aaBuf->getWidth();
- xxMax = -1;
-- for (yy = 0; yy < splashAASize; ++yy) {
-- computeIntersections(splashAASize * y + yy);
-- while (interIdx < interLen) {
-- xx0 = inter[interIdx].x0;
-- xx1 = inter[interIdx].x1;
-- interCount += inter[interIdx].count;
-- ++interIdx;
-- while (interIdx < interLen &&
-- (inter[interIdx].x0 <= xx1 ||
-- (eo ? (interCount & 1) : (interCount != 0)))) {
-- if (inter[interIdx].x1 > xx1) {
-- xx1 = inter[interIdx].x1;
-- }
-- interCount += inter[interIdx].count;
-- ++interIdx;
-- }
-- if (xx0 < 0) {
-- xx0 = 0;
-+ if (yMin <= yMax) {
-+ if (splashAASize * y < yMin) {
-+ interIdx = inter[0];
-+ } else if (splashAASize * y > yMax) {
-+ interIdx = inter[yMax - yMin + 1];
-+ } else {
-+ interIdx = inter[splashAASize * y - yMin];
-+ }
-+ for (yy = 0; yy < splashAASize; ++yy) {
-+ if (splashAASize * y + yy < yMin) {
-+ interEnd = inter[0];
-+ } else if (splashAASize * y + yy > yMax) {
-+ interEnd = inter[yMax - yMin + 1];
-+ } else {
-+ interEnd = inter[splashAASize * y + yy - yMin + 1];
- }
-- ++xx1;
-- if (xx1 > aaBuf->getWidth()) {
-- xx1 = aaBuf->getWidth();
-- }
-- // set [xx0, xx1) to 1
-- if (xx0 < xx1) {
-- xx = xx0;
-- p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
-- if (xx & 7) {
-- mask = 0xff >> (xx & 7);
-- if ((xx & ~7) == (xx1 & ~7)) {
-- mask &= (Guchar)(0xff00 >> (xx1 & 7));
-+ interCount = 0;
-+ while (interIdx < interEnd) {
-+ xx0 = allInter[interIdx].x0;
-+ xx1 = allInter[interIdx].x1;
-+ interCount += allInter[interIdx].count;
-+ ++interIdx;
-+ while (interIdx < interEnd &&
-+ (allInter[interIdx].x0 <= xx1 ||
-+ (eo ? (interCount & 1) : (interCount != 0)))) {
-+ if (allInter[interIdx].x1 > xx1) {
-+ xx1 = allInter[interIdx].x1;
- }
-- *p++ |= mask;
-- xx = (xx & ~7) + 8;
-+ interCount += allInter[interIdx].count;
-+ ++interIdx;
- }
-- for (; xx + 7 < xx1; xx += 8) {
-- *p++ |= 0xff;
-+ if (xx0 < 0) {
-+ xx0 = 0;
- }
-- if (xx < xx1) {
-- *p |= (Guchar)(0xff00 >> (xx1 & 7));
-+ ++xx1;
-+ if (xx1 > aaBuf->getWidth()) {
-+ xx1 = aaBuf->getWidth();
-+ }
-+ // set [xx0, xx1) to 1
-+ if (xx0 < xx1) {
-+ xx = xx0;
-+ p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
-+ if (xx & 7) {
-+ mask = 0xff >> (xx & 7);
-+ if ((xx & ~7) == (xx1 & ~7)) {
-+ mask &= (Guchar)(0xff00 >> (xx1 & 7));
-+ }
-+ *p++ |= mask;
-+ xx = (xx & ~7) + 8;
-+ }
-+ for (; xx + 7 < xx1; xx += 8) {
-+ *p++ |= 0xff;
-+ }
-+ if (xx < xx1) {
-+ *p |= (Guchar)(0xff00 >> (xx1 & 7));
-+ }
-+ }
-+ if (xx0 < xxMin) {
-+ xxMin = xx0;
-+ }
-+ if (xx1 > xxMax) {
-+ xxMax = xx1;
- }
-- }
-- if (xx0 < xxMin) {
-- xxMin = xx0;
-- }
-- if (xx1 > xxMax) {
-- xxMax = xx1;
- }
- }
- }
-@@ -359,51 +455,65 @@
-
- void SplashXPathScanner::clipAALine(SplashBitmap *aaBuf,
- int *x0, int *x1, int y) {
-- int xx0, xx1, xx, yy;
-+ int xx0, xx1, xx, yy, interEnd;
- Guchar mask;
- SplashColorPtr p;
-
- for (yy = 0; yy < splashAASize; ++yy) {
- xx = *x0 * splashAASize;
-- computeIntersections(splashAASize * y + yy);
-- while (interIdx < interLen && xx < (*x1 + 1) * splashAASize) {
-- xx0 = inter[interIdx].x0;
-- xx1 = inter[interIdx].x1;
-- interCount += inter[interIdx].count;
-- ++interIdx;
-- while (interIdx < interLen &&
-- (inter[interIdx].x0 <= xx1 ||
-- (eo ? (interCount & 1) : (interCount != 0)))) {
-- if (inter[interIdx].x1 > xx1) {
-- xx1 = inter[interIdx].x1;
-+ if (yMin <= yMax) {
-+ if (splashAASize * y + yy < yMin) {
-+ interIdx = interEnd = inter[0];
-+ } else if (splashAASize * y + yy > yMax) {
-+ interIdx = interEnd = inter[yMax - yMin + 1];
-+ } else {
-+ interIdx = inter[splashAASize * y + yy - yMin];
-+ if (splashAASize * y + yy > yMax) {
-+ interEnd = inter[yMax - yMin + 1];
-+ } else {
-+ interEnd = inter[splashAASize * y + yy - yMin + 1];
- }
-- interCount += inter[interIdx].count;
-- ++interIdx;
-- }
-- if (xx0 > aaBuf->getWidth()) {
-- xx0 = aaBuf->getWidth();
- }
-- // set [xx, xx0) to 0
-- if (xx < xx0) {
-- p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
-- if (xx & 7) {
-- mask = (Guchar)(0xff00 >> (xx & 7));
-- if ((xx & ~7) == (xx0 & ~7)) {
-- mask |= 0xff >> (xx0 & 7);
-+ interCount = 0;
-+ while (interIdx < interEnd && xx < (*x1 + 1) * splashAASize) {
-+ xx0 = allInter[interIdx].x0;
-+ xx1 = allInter[interIdx].x1;
-+ interCount += allInter[interIdx].count;
-+ ++interIdx;
-+ while (interIdx < interEnd &&
-+ (allInter[interIdx].x0 <= xx1 ||
-+ (eo ? (interCount & 1) : (interCount != 0)))) {
-+ if (allInter[interIdx].x1 > xx1) {
-+ xx1 = allInter[interIdx].x1;
- }
-- *p++ &= mask;
-- xx = (xx & ~7) + 8;
-+ interCount += allInter[interIdx].count;
-+ ++interIdx;
- }
-- for (; xx + 7 <= xx0; xx += 8) {
-- *p++ = 0x00;
-+ if (xx0 > aaBuf->getWidth()) {
-+ xx0 = aaBuf->getWidth();
-+ }
-+ // set [xx, xx0) to 0
-+ if (xx < xx0) {
-+ p = aaBuf->getDataPtr() + yy * aaBuf->getRowSize() + (xx >> 3);
-+ if (xx & 7) {
-+ mask = (Guchar)(0xff00 >> (xx & 7));
-+ if ((xx & ~7) == (xx0 & ~7)) {
-+ mask |= 0xff >> (xx0 & 7);
-+ }
-+ *p++ &= mask;
-+ xx = (xx & ~7) + 8;
-+ }
-+ for (; xx + 7 < xx0; xx += 8) {
-+ *p++ = 0x00;
-+ }
-+ if (xx < xx0) {
-+ *p &= 0xff >> (xx0 & 7);
-+ }
- }
-- if (xx <= xx0) {
-- *p &= 0xff >> (xx0 & 7);
-+ if (xx1 >= xx) {
-+ xx = xx1 + 1;
- }
- }
-- if (xx1 >= xx) {
-- xx = xx1 + 1;
-- }
- }
- xx0 = (*x1 + 1) * splashAASize;
- // set [xx, xx0) to 0
-@@ -417,10 +527,10 @@
- *p++ &= mask;
- xx = (xx & ~7) + 8;
- }
-- for (; xx + 7 <= xx0; xx += 8) {
-+ for (; xx + 7 < xx0; xx += 8) {
- *p++ = 0x00;
- }
-- if (xx <= xx0) {
-+ if (xx < xx0) {
- *p &= 0xff >> (xx0 & 7);
- }
- }
-diff -ru xpdf-3.02/splash/SplashXPathScanner.h xpdf-3.03/splash/SplashXPathScanner.h
---- xpdf-3.02/splash/SplashXPathScanner.h 2007-02-27 23:05:52.000000000 +0100
-+++ xpdf-3.03/splash/SplashXPathScanner.h 2011-08-15 23:08:53.000000000 +0200
-@@ -27,7 +27,8 @@
- public:
-
- // Create a new SplashXPathScanner object. <xPathA> must be sorted.
-- SplashXPathScanner(SplashXPath *xPathA, GBool eoA);
-+ SplashXPathScanner(SplashXPath *xPathA, GBool eoA,
-+ int clipYMin, int clipYMax);
-
- ~SplashXPathScanner();
-
-@@ -38,6 +39,10 @@
- // Return the path's bounding box.
- void getBBoxAA(int *xMinA, int *yMinA, int *xMaxA, int *yMaxA);
-
-+ // Returns true if at least part of the path was outside the
-+ // clipYMin/clipYMax bounds passed to the constructor.
-+ GBool hasPartialClip() { return partialClip; }
-+
- // Return the min/max x values for the span at <y>.
- void getSpanBounds(int y, int *spanXMin, int *spanXMax);
-
-@@ -66,22 +71,25 @@
-
- private:
-
-- void computeIntersections(int y);
-+ void computeIntersections();
-+ void addIntersection(double segYMin, double segYMax,
-+ Guint segFlags,
-+ int y, int x0, int x1);
-
- SplashXPath *xPath;
- GBool eo;
- int xMin, yMin, xMax, yMax;
-+ GBool partialClip;
-
-- int interY; // current y value
-+ SplashIntersect *allInter; // array of intersections
-+ int allInterLen; // number of intersections in <allInter>
-+ int allInterSize; // size of the <allInter> array
-+ int *inter; // indexes into <allInter> for each y value
-+ int interY; // current y value - used by getNextSpan
- int interIdx; // current index into <inter> - used by
- // getNextSpan
- int interCount; // current EO/NZWN counter - used by
- // getNextSpan
-- int xPathIdx; // current index into <xPath> - used by
-- // computeIntersections
-- SplashIntersect *inter; // intersections array for <interY>
-- int interLen; // number of intersections in <inter>
-- int interSize; // size of the <inter> array
- };
-
- #endif
diff -ru xpdf-3.02/xpdf/Annot.cc xpdf-3.03/xpdf/Annot.cc
--- xpdf-3.02/xpdf/Annot.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/Annot.cc 2011-08-15 23:08:53.000000000 +0200
@@ -10404,22 +7254,6 @@ diff -ru xpdf-3.02/xpdf/Gfx.h xpdf-3.03/xpdf/Gfx.h
diff -ru xpdf-3.02/xpdf/GfxState.cc xpdf-3.03/xpdf/GfxState.cc
--- xpdf-3.02/xpdf/GfxState.cc 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/GfxState.cc 2011-08-15 23:08:53.000000000 +0200
-@@ -82,20 +89,26 @@
-
- #define nGfxColorSpaceModes ((sizeof(gfxColorSpaceModeNames) / sizeof(char *)))
-
-+
- //------------------------------------------------------------------------
- // GfxColorSpace
- //------------------------------------------------------------------------
-
- GfxColorSpace::GfxColorSpace() {
-+ overprintMask = 0x0f;
- }
-
- GfxColorSpace::~GfxColorSpace() {
- }
-
@@ -819,26 +854,27 @@
obj1.free();
arr->get(1, &obj1);
@@ -10448,14 +7282,6 @@ diff -ru xpdf-3.02/xpdf/GfxState.cc xpdf-3.03/xpdf/GfxState.cc
+ nCompsA = 4;
}
if (dict->lookup("Alternate", &obj2)->isNull() ||
-@@ -927,6 +964,7 @@
- indexHigh = indexHighA;
- lookup = (Guchar *)gmallocn((indexHigh + 1) * base->getNComps(),
- sizeof(Guchar));
-+ overprintMask = base->getOverprintMask();
- }
-
- GfxIndexedColorSpace::~GfxIndexedColorSpace() {
@@ -986,8 +1025,9 @@
for (i = 0; i <= indexHighA; ++i) {
for (j = 0; j < n; ++j) {
@@ -10480,120 +7306,11 @@ diff -ru xpdf-3.02/xpdf/GfxState.cc xpdf-3.03/xpdf/GfxState.cc
}
s = obj1.getString()->getCString();
for (i = 0; i <= indexHighA; ++i) {
-@@ -1074,6 +1116,27 @@
- alt = altA;
- func = funcA;
- nonMarking = !name->cmp("None");
-+ if (!name->cmp("Cyan")) {
-+ overprintMask = 0x01;
-+ } else if (!name->cmp("Magenta")) {
-+ overprintMask = 0x02;
-+ } else if (!name->cmp("Yellow")) {
-+ overprintMask = 0x04;
-+ } else if (!name->cmp("Black")) {
-+ overprintMask = 0x08;
-+ }
-+}
-+
-+GfxSeparationColorSpace::GfxSeparationColorSpace(GString *nameA,
-+ GfxColorSpace *altA,
-+ Function *funcA,
-+ GBool nonMarkingA,
-+ Guint overprintMaskA) {
-+ name = nameA;
-+ alt = altA;
-+ func = funcA;
-+ nonMarking = nonMarkingA;
-+ overprintMask = overprintMaskA;
- }
-
- GfxSeparationColorSpace::~GfxSeparationColorSpace() {
-@@ -1083,11 +1146,12 @@
- }
-
- GfxColorSpace *GfxSeparationColorSpace::copy() {
-- return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy());
-+ return new GfxSeparationColorSpace(name->copy(), alt->copy(), func->copy(),
-+ nonMarking, overprintMask);
- }
-
- //~ handle the 'All' and 'None' colorants
-@@ -1179,12 +1245,51 @@
- //------------------------------------------------------------------------
-
- GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
-+ GString **namesA,
- GfxColorSpace *altA,
- Function *funcA) {
-+ int i;
-+
-+ nComps = nCompsA;
-+ alt = altA;
-+ func = funcA;
-+ nonMarking = gTrue;
-+ overprintMask = 0;
-+ for (i = 0; i < nComps; ++i) {
-+ names[i] = namesA[i];
-+ if (names[i]->cmp("None")) {
-+ nonMarking = gFalse;
-+ }
-+ if (!names[i]->cmp("Cyan")) {
-+ overprintMask |= 0x01;
-+ } else if (!names[i]->cmp("Magenta")) {
-+ overprintMask |= 0x02;
-+ } else if (!names[i]->cmp("Yellow")) {
-+ overprintMask |= 0x04;
-+ } else if (!names[i]->cmp("Black")) {
-+ overprintMask |= 0x08;
-+ } else {
-+ overprintMask = 0x0f;
-+ }
-+ }
-+}
-+
-+GfxDeviceNColorSpace::GfxDeviceNColorSpace(int nCompsA,
-+ GString **namesA,
-+ GfxColorSpace *altA,
-+ Function *funcA,
-+ GBool nonMarkingA,
-+ Guint overprintMaskA) {
-+ int i;
-+
- nComps = nCompsA;
- alt = altA;
- func = funcA;
-- nonMarking = gFalse;
-+ nonMarking = nonMarkingA;
-+ overprintMask = overprintMaskA;
-+ for (i = 0; i < nComps; ++i) {
-+ names[i] = namesA[i]->copy();
-+ }
- }
-
- GfxDeviceNColorSpace::~GfxDeviceNColorSpace() {
-@@ -1198,19 +1303,12 @@
- }
-
- GfxColorSpace *GfxDeviceNColorSpace::copy() {
-- GfxDeviceNColorSpace *cs;
-- int i;
--
-- cs = new GfxDeviceNColorSpace(nComps, alt->copy(), func->copy());
-- for (i = 0; i < nComps; ++i) {
-- cs->names[i] = names[i]->copy();
-- }
-- cs->nonMarking = nonMarking;
-- return cs;
-+ return new GfxDeviceNColorSpace(nComps, names, alt->copy(), func->copy(),
-+ nonMarking, overprintMask);
- }
-
- //~ handle the 'None' colorant
@@ -1254,14 +1354,7 @@
goto err4;
}
obj1.free();
-- cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
+ cs = new GfxDeviceNColorSpace(nCompsA, altA, funcA);
- cs->nonMarking = gTrue;
- for (i = 0; i < nCompsA; ++i) {
- cs->names[i] = namesA[i];
@@ -10601,7 +7318,6 @@ diff -ru xpdf-3.02/xpdf/GfxState.cc xpdf-3.03/xpdf/GfxState.cc
- cs->nonMarking = gFalse;
- }
- }
-+ cs = new GfxDeviceNColorSpace(nCompsA, namesA, altA, funcA);
return cs;
err4:
@@ -11005,64 +7721,6 @@ diff -ru xpdf-3.02/xpdf/GfxState.cc xpdf-3.03/xpdf/GfxState.cc
diff -ru xpdf-3.02/xpdf/GfxState.h xpdf-3.03/xpdf/GfxState.h
--- xpdf-3.02/xpdf/GfxState.h 2007-02-27 23:05:52.000000000 +0100
+++ xpdf-3.03/xpdf/GfxState.h 2011-08-15 23:08:53.000000000 +0200
-@@ -160,13 +162,18 @@
- // mark the page (e.g., the "None" colorant).
- virtual GBool isNonMarking() { return gFalse; }
-
-+ // Return the color space's overprint mask.
-+ Guint getOverprintMask() { return overprintMask; }
-+
- // Return the number of color space modes
- static int getNumColorSpaceModes();
-
- // Return the name of the <idx>th color space mode.
- static const char *getColorSpaceModeName(int idx);
-
--private:
-+protected:
-+
-+ Guint overprintMask;
- };
-
- //------------------------------------------------------------------------
-@@ -468,6 +475,10 @@
-
- private:
-
-+ GfxSeparationColorSpace(GString *nameA, GfxColorSpace *altA,
-+ Function *funcA, GBool nonMarkingA,
-+ Guint overprintMaskA);
-+
- GString *name; // colorant name
- GfxColorSpace *alt; // alternate color space
- Function *func; // tint transform (into alternate color space)
-@@ -481,13 +492,14 @@
- class GfxDeviceNColorSpace: public GfxColorSpace {
- public:
-
-- GfxDeviceNColorSpace(int nCompsA, GfxColorSpace *alt, Function *func);
-+ GfxDeviceNColorSpace(int nCompsA, GString **namesA,
-+ GfxColorSpace *alt, Function *func);
- virtual ~GfxDeviceNColorSpace();
- virtual GfxColorSpace *copy();
- virtual GfxColorSpaceMode getMode() { return csDeviceN; }
-
- // Construct a DeviceN color space. Returns NULL if unsuccessful.
- static GfxColorSpace *parse(Array *arr, int recursion);
-
- virtual void getGray(GfxColor *color, GfxGray *gray);
- virtual void getRGB(GfxColor *color, GfxRGB *rgb);
-@@ -505,6 +517,10 @@
-
- private:
-
-+ GfxDeviceNColorSpace(int nCompsA, GString **namesA,
-+ GfxColorSpace *alt, Function *func,
-+ GBool nonMarkingA, Guint overprintMaskA);
-+
- int nComps; // number of components
- GString // colorant names
- *names[gfxColorMaxComps];
@@ -878,6 +894,11 @@
void getCMYK(Guchar *x, GfxCMYK *cmyk);
void getColor(Guchar *x, GfxColor *color);
@@ -11730,7 +8388,7 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.cc xpdf-3.03/xpdf/GlobalParams.cc
screenBlackThreshold = 0.0;
screenWhiteThreshold = 1.0;
+ minLineWidth = 0.0;
-+ overprintPreview = gFalse;
+ overprintPreview = gFalse;
urlCommand = NULL;
movieCommand = NULL;
mapNumericCharNames = gTrue;
@@ -12326,7 +8984,7 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.h xpdf-3.03/xpdf/GlobalParams.h
double getScreenWhiteThreshold();
+ double getMinLineWidth();
+ GBool getDrawAnnotations();
-+ GBool getOverprintPreview() { return overprintPreview; }
+ GBool getOverprintPreview() { return overprintPreview; }
GString *getURLCommand() { return urlCommand; }
GString *getMovieCommand() { return movieCommand; }
GBool getMapNumericCharNames();
@@ -12423,7 +9081,7 @@ diff -ru xpdf-3.02/xpdf/GlobalParams.h xpdf-3.03/xpdf/GlobalParams.h
double screenBlackThreshold; // screen black clamping threshold
double screenWhiteThreshold; // screen white clamping threshold
+ double minLineWidth; // minimum line width
-+ GBool overprintPreview; // enable overprint preview
+ GBool overprintPreview; // enable overprint preview
GString *urlCommand; // command executed for URL links
GString *movieCommand; // command executed for movie annotations
GBool mapNumericCharNames; // map numeric char names (from font subsets)?
@@ -16777,92 +13435,10 @@ diff -ru xpdf-3.02/xpdf/SplashOutputDev.cc xpdf-3.03/xpdf/SplashOutputDev.cc
- }
- return pattern;
-+
-+void SplashOutputDev::setOverprintMask(GfxColorSpace *colorSpace,
-+ GBool overprintFlag,
-+ int overprintMode,
-+ GfxColor *singleColor) {
-+#if SPLASH_CMYK
-+ Guint mask;
-+ GfxCMYK cmyk;
-+
-+ if (overprintFlag && globalParams->getOverprintPreview()) {
-+ mask = colorSpace->getOverprintMask();
-+ if (singleColor && overprintMode &&
-+ (colorSpace->getMode() == csDeviceCMYK ||
-+ (colorSpace->getMode() == csICCBased &&
-+ colorSpace->getNComps() == 4))) {
-+ colorSpace->getCMYK(singleColor, &cmyk);
-+ if (cmyk.c == 0) {
-+ mask &= ~1;
-+ }
-+ if (cmyk.m == 0) {
-+ mask &= ~2;
-+ }
-+ if (cmyk.y == 0) {
-+ mask &= ~4;
-+ }
-+ if (cmyk.k == 0) {
-+ mask &= ~8;
-+ }
-+ }
-+ } else {
-+ mask = 0xffffffff;
-+ }
-+ splash->setOverprintMask(mask);
-+#endif
}
void SplashOutputDev::updateBlendMode(GfxState *state) {
@@ -956,35 +1013,82 @@
- splash->setStrokeAlpha((SplashCoord)state->getStrokeOpacity());
- }
-
-+void SplashOutputDev::updateTransfer(GfxState *state) {
-+ Function **transfer;
-+ Guchar red[256], green[256], blue[256], gray[256];
-+ double x, y;
-+ int i;
-+
-+ transfer = state->getTransfer();
-+ if (transfer[0] &&
-+ transfer[0]->getInputSize() == 1 &&
-+ transfer[0]->getOutputSize() == 1) {
-+ if (transfer[1] &&
-+ transfer[1]->getInputSize() == 1 &&
-+ transfer[1]->getOutputSize() == 1 &&
-+ transfer[2] &&
-+ transfer[2]->getInputSize() == 1 &&
-+ transfer[2]->getOutputSize() == 1 &&
-+ transfer[3] &&
-+ transfer[3]->getInputSize() == 1 &&
-+ transfer[3]->getOutputSize() == 1) {
-+ for (i = 0; i < 256; ++i) {
-+ x = i / 255.0;
-+ transfer[0]->transform(&x, &y);
-+ red[i] = (Guchar)(y * 255.0 + 0.5);
-+ transfer[1]->transform(&x, &y);
-+ green[i] = (Guchar)(y * 255.0 + 0.5);
-+ transfer[2]->transform(&x, &y);
-+ blue[i] = (Guchar)(y * 255.0 + 0.5);
-+ transfer[3]->transform(&x, &y);
-+ gray[i] = (Guchar)(y * 255.0 + 0.5);
-+ }
-+ } else {
-+ for (i = 0; i < 256; ++i) {
-+ x = i / 255.0;
-+ transfer[0]->transform(&x, &y);
-+ red[i] = green[i] = blue[i] = gray[i] = (Guchar)(y * 255.0 + 0.5);
-+ }
-+ }
-+ } else {
-+ for (i = 0; i < 256; ++i) {
-+ red[i] = green[i] = blue[i] = gray[i] = (Guchar)i;
-+ }
-+ }
-+ splash->setTransfer(red, green, blue, gray);
-+}
-+
void SplashOutputDev::updateFont(GfxState *state) {
needFontUpdate = gTrue;
}
@@ -17279,36 +13855,7 @@ diff -ru xpdf-3.02/xpdf/SplashOutputDev.cc xpdf-3.03/xpdf/SplashOutputDev.cc
}
}
}
-@@ -1280,7 +1414,9 @@
- if (state->getStrokeColorSpace()->isNonMarking()) {
- return;
- }
-- path = convertPath(state, state->getPath());
-+ setOverprintMask(state->getStrokeColorSpace(), state->getStrokeOverprint(),
-+ state->getOverprintMode(), state->getStrokeColor());
-+ path = convertPath(state, state->getPath(), gFalse);
- splash->stroke(path);
- delete path;
- }
-@@ -1291,7 +1427,9 @@
- if (state->getFillColorSpace()->isNonMarking()) {
- return;
- }
-- path = convertPath(state, state->getPath());
-+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
-+ state->getOverprintMode(), state->getFillColor());
-+ path = convertPath(state, state->getPath(), gTrue);
- splash->fill(path, gFalse);
- delete path;
- }
@@ -1302,15 +1440,155 @@
- if (state->getFillColorSpace()->isNonMarking()) {
- return;
- }
-- path = convertPath(state, state->getPath());
-+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
-+ state->getOverprintMode(), state->getFillColor());
-+ path = convertPath(state, state->getPath(), gTrue);
splash->fill(path, gTrue);
delete path;
}
@@ -17454,50 +14001,6 @@ diff -ru xpdf-3.02/xpdf/SplashOutputDev.cc xpdf-3.03/xpdf/SplashOutputDev.cc
void SplashOutputDev::clip(GfxState *state) {
SplashPath *path;
-- path = convertPath(state, state->getPath());
-+ path = convertPath(state, state->getPath(), gTrue);
- splash->clipToPath(path, gFalse);
- delete path;
- }
-@@ -1318,7 +1596,7 @@
- void SplashOutputDev::eoClip(GfxState *state) {
- SplashPath *path;
-
-- path = convertPath(state, state->getPath());
-+ path = convertPath(state, state->getPath(), gTrue);
- splash->clipToPath(path, gTrue);
- delete path;
- }
-@@ -1326,22 +1604,24 @@
- void SplashOutputDev::clipToStrokePath(GfxState *state) {
- SplashPath *path, *path2;
-
-- path = convertPath(state, state->getPath());
-- path2 = splash->makeStrokePath(path);
-+ path = convertPath(state, state->getPath(), gFalse);
-+ path2 = splash->makeStrokePath(path, state->getLineWidth());
- delete path;
- splash->clipToPath(path2, gFalse);
- delete path2;
- }
-
--SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path) {
-+SplashPath *SplashOutputDev::convertPath(GfxState *state, GfxPath *path,
-+ GBool dropEmptySubpaths) {
- SplashPath *sPath;
- GfxSubpath *subpath;
-- int i, j;
-+ int n, i, j;
-
-+ n = dropEmptySubpaths ? 1 : 0;
- sPath = new SplashPath();
- for (i = 0; i < path->getNumSubpaths(); ++i) {
- subpath = path->getSubpath(i);
-- if (subpath->getNumPoints() > 0) {
-+ if (subpath->getNumPoints() > n) {
- sPath->moveTo((SplashCoord)subpath->getX(0),
- (SplashCoord)subpath->getY(0));
- j = 1;
@@ -1375,6 +1655,18 @@
Unicode *u, int uLen) {
SplashPath *path;
@@ -17645,15 +14148,6 @@ diff -ru xpdf-3.02/xpdf/SplashOutputDev.cc xpdf-3.03/xpdf/SplashOutputDev.cc
validBBox,
colorMode != splashModeMono1);
}
-@@ -1532,7 +1875,7 @@
- for (j = 0; j < t3Font->cacheAssoc; ++j) {
- if ((t3Font->cacheTags[i+j].mru & 0x8000) &&
- t3Font->cacheTags[i+j].code == code) {
-- drawType3Glyph(t3Font, &t3Font->cacheTags[i+j],
-+ drawType3Glyph(state, t3Font, &t3Font->cacheTags[i+j],
- t3Font->cacheData + (i+j) * t3Font->glyphSize);
- return gTrue;
- }
@@ -1547,6 +1890,8 @@
t3GlyphStack->cacheTag = NULL;
t3GlyphStack->cacheData = NULL;
@@ -17671,15 +14165,6 @@ diff -ru xpdf-3.02/xpdf/SplashOutputDev.cc xpdf-3.03/xpdf/SplashOutputDev.cc
memcpy(t3GlyphStack->cacheData, bitmap->getDataPtr(),
t3GlyphStack->cache->glyphSize);
delete bitmap;
-@@ -1565,7 +1911,7 @@
- state->setCTM(ctm[0], ctm[1], ctm[2], ctm[3],
- t3GlyphStack->origCTM4, t3GlyphStack->origCTM5);
- updateCTM(state, 0, 0, 0, 0, 0, 0);
-- drawType3Glyph(t3GlyphStack->cache,
-+ drawType3Glyph(state, t3GlyphStack->cache,
- t3GlyphStack->cacheTag, t3GlyphStack->cacheData);
- }
- t3gs = t3GlyphStack;
@@ -1574,6 +1920,7 @@
}
@@ -17725,16 +14210,6 @@ diff -ru xpdf-3.02/xpdf/SplashOutputDev.cc xpdf-3.03/xpdf/SplashOutputDev.cc
+ ++nestCount;
}
--void SplashOutputDev::drawType3Glyph(T3FontCache *t3Font,
-+void SplashOutputDev::drawType3Glyph(GfxState *state, T3FontCache *t3Font,
- T3FontCacheTag *tag, Guchar *data) {
- SplashGlyphBitmap glyph;
-
-+ setOverprintMask(state->getFillColorSpace(), state->getFillOverprint(),
-+ state->getOverprintMode(), state->getFillColor());
- glyph.x = -t3Font->glyphX;
- glyph.y = -t3Font->glyphY;
- glyph.w = t3Font->glyphW;
@@ -1717,9 +2075,10 @@
if (imgMaskData->y == imgMaskData->height) {
return gFalse;
@@ -18486,14 +14961,6 @@ diff -ru xpdf-3.02/xpdf/SplashOutputDev.h xpdf-3.03/xpdf/SplashOutputDev.h
//----- initialization and control
// Start a page.
-@@ -95,6 +101,7 @@
- virtual void updateBlendMode(GfxState *state);
- virtual void updateFillOpacity(GfxState *state);
- virtual void updateStrokeOpacity(GfxState *state);
-+ virtual void updateTransfer(GfxState *state);
-
- //----- update text state
- virtual void updateFont(GfxState *state);
@@ -103,6 +110,11 @@
virtual void stroke(GfxState *state);
virtual void fill(GfxState *state);
@@ -18562,17 +15029,6 @@ diff -ru xpdf-3.02/xpdf/SplashOutputDev.h xpdf-3.03/xpdf/SplashOutputDev.h
- SplashPattern *getColor(GfxGray gray, GfxRGB *rgb);
+ SplashPattern *getColor(GfxCMYK *cmyk);
#endif
-- SplashPath *convertPath(GfxState *state, GfxPath *path);
-+ void setOverprintMask(GfxColorSpace *colorSpace, GBool overprintFlag,
-+ int overprintMode, GfxColor *singleColor);
-+ SplashPath *convertPath(GfxState *state, GfxPath *path,
-+ GBool dropEmptySubpaths);
- void doUpdateFont(GfxState *state);
-- void drawType3Glyph(T3FontCache *t3Font,
-+ void drawType3Glyph(GfxState *state, T3FontCache *t3Font,
- T3FontCacheTag *tag, Guchar *data);
- static GBool imageMaskSrc(void *data, SplashColorPtr line);
- static GBool imageSrc(void *data, SplashColorPtr colorLine,
@@ -219,11 +249,14 @@
SplashColorMode colorMode;
int bitmapRowPad;