summaryrefslogtreecommitdiff
path: root/Build/source/libs/xpdf/xpdf-src/splash
diff options
context:
space:
mode:
authorAkira Kakuto <kakuto@fuk.kindai.ac.jp>2017-08-13 07:14:48 +0000
committerAkira Kakuto <kakuto@fuk.kindai.ac.jp>2017-08-13 07:14:48 +0000
commit4b4995cda35627e06c43e25ecbe07c1bc1859bb5 (patch)
tree143ed02a389bab62f44043a54cbc70f69e312e2f /Build/source/libs/xpdf/xpdf-src/splash
parent00d00899c484b81967558f43c4fe4a896ffdf610 (diff)
xpdf 4.00
git-svn-id: svn://tug.org/texlive/trunk@45031 c570f23f-e606-0410-a88d-b1316a301751
Diffstat (limited to 'Build/source/libs/xpdf/xpdf-src/splash')
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt47
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/Makefile.dep0
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/Makefile.in93
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/Splash.cc1957
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/Splash.h26
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashBitmap.cc14
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc153
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashClip.h24
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.cc45
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.h4
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.cc53
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.h10
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.cc36
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.h16
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFont.cc9
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFont.h13
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.cc32
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.h12
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.cc16
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.h24
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashFontFileID.cc1
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashMath.h194
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashPath.cc27
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashPath.h10
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashPattern.cc1
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.cc1
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.h16
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc47
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashState.h9
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashTypes.h10
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.cc377
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.h54
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc929
-rw-r--r--Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.h61
34 files changed, 2736 insertions, 1585 deletions
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt b/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt
new file mode 100644
index 00000000000..f84968cfb2a
--- /dev/null
+++ b/Build/source/libs/xpdf/xpdf-src/splash/CMakeLists.txt
@@ -0,0 +1,47 @@
+#========================================================================
+#
+# splash/CMakeLists.txt
+#
+# CMake script for the splash library.
+#
+# Copyright 2015 Glyph & Cog, LLC
+#
+#========================================================================
+
+if (HAVE_SPLASH)
+ include_directories("${PROJECT_SOURCE_DIR}")
+ include_directories("${PROJECT_BINARY_DIR}")
+ include_directories("${PROJECT_SOURCE_DIR}/goo")
+ include_directories("${PROJECT_SOURCE_DIR}/fofi")
+ include_directories("${FREETYPE_INCLUDE_DIRS}")
+
+ if (HAVE_DTYPE4_H)
+ include_directories("${DTYPE_INCLUDE_DIR}")
+ set(DTYPE_SRCS
+ SplashDT4Font.cc SplashDT4FontEngine.cc SplashDT4FontFile.cc)
+ endif ()
+
+ add_library(splash_objs OBJECT
+ Splash.cc
+ SplashBitmap.cc
+ SplashClip.cc
+ SplashFTFont.cc
+ SplashFTFontEngine.cc
+ SplashFTFontFile.cc
+ SplashFont.cc
+ SplashFontEngine.cc
+ SplashFontFile.cc
+ SplashFontFileID.cc
+ SplashPath.cc
+ SplashPattern.cc
+ SplashScreen.cc
+ SplashState.cc
+ SplashXPath.cc
+ SplashXPathScanner.cc
+ ${DTYPE_SRCS}
+ )
+
+ add_library(splash
+ $<TARGET_OBJECTS:splash_objs>
+ )
+endif ()
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/Makefile.dep b/Build/source/libs/xpdf/xpdf-src/splash/Makefile.dep
deleted file mode 100644
index e69de29bb2d..00000000000
--- a/Build/source/libs/xpdf/xpdf-src/splash/Makefile.dep
+++ /dev/null
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/Makefile.in b/Build/source/libs/xpdf/xpdf-src/splash/Makefile.in
deleted file mode 100644
index 6479b1543ee..00000000000
--- a/Build/source/libs/xpdf/xpdf-src/splash/Makefile.in
+++ /dev/null
@@ -1,93 +0,0 @@
-#========================================================================
-#
-# Splash library Makefile
-#
-# Copyright 2003 Glyph & Cog, LLC
-#
-#========================================================================
-
-SHELL = /bin/sh
-
-srcdir = @srcdir@
-VPATH = @srcdir@
-
-GOOSRCDIR = $(srcdir)/../goo
-GOOLIBDIR = ../goo
-FOFISRCDIR = $(srcdir)/../fofi
-FOFILIBDIR = ../fofi
-
-CXXFLAGS = @CXXFLAGS@ @DEFS@ -I.. -I$(srcdir)/.. -I$(GOOSRCDIR) -I$(FOFISRCDIR) -I$(srcdir) @freetype2_CFLAGS@
-
-CXX = @CXX@
-AR = @AR@
-RANLIB = @RANLIB@
-
-LIBPREFIX = @LIBPREFIX@
-
-#------------------------------------------------------------------------
-
-.SUFFIXES: .cc
-
-.cc.o:
- $(CXX) $(CXXFLAGS) -c $<
-
-#------------------------------------------------------------------------
-
-CXX_SRC = \
- $(srcdir)/Splash.cc \
- $(srcdir)/SplashBitmap.cc \
- $(srcdir)/SplashClip.cc \
- $(srcdir)/SplashFTFont.cc \
- $(srcdir)/SplashFTFontEngine.cc \
- $(srcdir)/SplashFTFontFile.cc \
- $(srcdir)/SplashFont.cc \
- $(srcdir)/SplashFontEngine.cc \
- $(srcdir)/SplashFontFile.cc \
- $(srcdir)/SplashFontFileID.cc \
- $(srcdir)/SplashPath.cc \
- $(srcdir)/SplashPattern.cc \
- $(srcdir)/SplashScreen.cc \
- $(srcdir)/SplashState.cc \
- $(srcdir)/SplashXPath.cc \
- $(srcdir)/SplashXPathScanner.cc
-
-#------------------------------------------------------------------------
-
-all: $(LIBPREFIX)splash.a
-
-#------------------------------------------------------------------------
-
-SPLASH_OBJS = \
- Splash.o \
- SplashBitmap.o \
- SplashClip.o \
- SplashFTFont.o \
- SplashFTFontEngine.o \
- SplashFTFontFile.o \
- SplashFont.o \
- SplashFontEngine.o \
- SplashFontFile.o \
- SplashFontFileID.o \
- SplashPath.o \
- SplashPattern.o \
- SplashScreen.o \
- SplashState.o \
- SplashXPath.o \
- SplashXPathScanner.o
-
-$(LIBPREFIX)splash.a: $(SPLASH_OBJS)
- rm -f $(LIBPREFIX)splash.a
- $(AR) $(LIBPREFIX)splash.a $(SPLASH_OBJS)
- $(RANLIB) $(LIBPREFIX)splash.a
-
-#------------------------------------------------------------------------
-
-clean:
- rm -f $(SPLASH_OBJS) $(LIBPREFIX)splash.a
-
-#------------------------------------------------------------------------
-
-depend:
- $(CXX) $(CXXFLAGS) -MM $(CXX_SRC) >Makefile.dep
-
--include Makefile.dep
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc b/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
index d9035b37aa9..0810fbc3bd2 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/Splash.cc
@@ -15,7 +15,9 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <math.h>
#include "gmem.h"
+#include "gmempp.h"
#include "SplashErrorCodes.h"
#include "SplashMath.h"
#include "SplashBitmap.h"
@@ -29,9 +31,12 @@
#include "SplashGlyphBitmap.h"
#include "Splash.h"
-//------------------------------------------------------------------------
+// the MSVC math.h doesn't define this
+#ifndef M_PI
+#define M_PI 3.14159265358979323846
+#endif
-#define splashAAGamma 0.67
+//------------------------------------------------------------------------
// distance of Bezier control point from center for circle approximation
// = (4 * (sqrt(2) - 1) / 3) * r
@@ -123,17 +128,6 @@ SplashPipeResultColorCtrl Splash::pipeResultColorAlphaBlend[] = {
};
//------------------------------------------------------------------------
-
-static void blendXor(SplashColorPtr src, SplashColorPtr dest,
- SplashColorPtr blend, SplashColorMode cm) {
- int i;
-
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = src[i] ^ dest[i];
- }
-}
-
-//------------------------------------------------------------------------
// modified region
//------------------------------------------------------------------------
@@ -269,7 +263,7 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
Guchar shape, aSrc, aDest, alphaI, alphaIm1, alpha0, aResult;
SplashColor cSrc, cDest, cBlend;
Guchar shapeVal, cResult0, cResult1, cResult2, cResult3;
- int cSrcStride, shapeStride, x, lastX, t, i;
+ int cSrcStride, shapeStride, x, lastX, t;
SplashColorPtr destColorPtr;
Guchar destColorMask;
Guchar *destAlphaPtr;
@@ -396,49 +390,33 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
pipe->pattern->getColor(x, y, pipe->cSrcVal);
}
+ cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy
+
if (pipe->noTransparency && !state->blendFunc) {
- //----- write destination pixel
+ //----- result color
switch (bitmap->mode) {
case splashModeMono1:
- cResult0 = state->grayTransfer[cSrcPtr[0]];
- if (state->screen->test(x, y, cResult0)) {
- *destColorPtr |= destColorMask;
- } else {
- *destColorPtr &= ~destColorMask;
- }
- destColorPtr += destColorMask & 1;
- destColorMask = (destColorMask << 7) | (destColorMask >> 1);
- break;
case splashModeMono8:
- *destColorPtr++ = state->grayTransfer[cSrcPtr[0]];
+ cResult0 = state->grayTransfer[cSrcPtr[0]];
break;
case splashModeRGB8:
- destColorPtr[0] = state->rgbTransferR[cSrcPtr[0]];
- destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]];
- destColorPtr[2] = state->rgbTransferB[cSrcPtr[2]];
- destColorPtr += 3;
- break;
case splashModeBGR8:
- destColorPtr[0] = state->rgbTransferB[cSrcPtr[2]];
- destColorPtr[1] = state->rgbTransferG[cSrcPtr[1]];
- destColorPtr[2] = state->rgbTransferR[cSrcPtr[0]];
- destColorPtr += 3;
+ cResult0 = state->rgbTransferR[cSrcPtr[0]];
+ cResult1 = state->rgbTransferG[cSrcPtr[1]];
+ cResult2 = state->rgbTransferB[cSrcPtr[2]];
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- destColorPtr[0] = state->cmykTransferC[cSrcPtr[0]];
- destColorPtr[1] = state->cmykTransferM[cSrcPtr[1]];
- destColorPtr[2] = state->cmykTransferY[cSrcPtr[2]];
- destColorPtr[3] = state->cmykTransferK[cSrcPtr[3]];
- destColorPtr += 4;
+ cResult0 = state->cmykTransferC[cSrcPtr[0]];
+ cResult1 = state->cmykTransferM[cSrcPtr[1]];
+ cResult2 = state->cmykTransferY[cSrcPtr[2]];
+ cResult3 = state->cmykTransferK[cSrcPtr[3]];
break;
#endif
}
- if (destAlphaPtr) {
- *destAlphaPtr++ = 255;
- }
+ aResult = 255;
} else { // if (noTransparency && !blendFunc)
@@ -516,17 +494,42 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
aDest = 0xff;
}
- //----- overprint
+ //----- read source color; handle overprint
- for (i = 0; i < bitmapComps; ++i) {
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ case splashModeMono8:
+ cSrc[0] = state->grayTransfer[cSrcPtr[0]];
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ cSrc[0] = state->rgbTransferR[cSrcPtr[0]];
+ cSrc[1] = state->rgbTransferG[cSrcPtr[1]];
+ cSrc[2] = state->rgbTransferB[cSrcPtr[2]];
+ break;
#if SPLASH_CMYK
- if (state->overprintMask & (1 << i)) {
- cSrc[i] = cSrcPtr[i];
+ case splashModeCMYK8:
+ if (state->overprintMask & 0x01) {
+ cSrc[0] = state->cmykTransferC[cSrcPtr[0]];
} else {
- cSrc[i] = div255(aDest * cDest[i]);
+ cSrc[0] = div255(aDest * cDest[0]);
}
-#else
- cSrc[i] = cSrcPtr[i];
+ if (state->overprintMask & 0x02) {
+ cSrc[1] = state->cmykTransferM[cSrcPtr[1]];
+ } else {
+ cSrc[1] = div255(aDest * cDest[1]);
+ }
+ if (state->overprintMask & 0x04) {
+ cSrc[2] = state->cmykTransferY[cSrcPtr[2]];
+ } else {
+ cSrc[2] = div255(aDest * cDest[2]);
+ }
+ if (state->overprintMask & 0x08) {
+ cSrc[3] = state->cmykTransferK[cSrcPtr[3]];
+ } else {
+ cSrc[3] = div255(aDest * cDest[3]);
+ }
+ break;
#endif
}
@@ -629,32 +632,22 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
//----- result color
- cResult0 = cResult1 = cResult2 = cResult3 = 0; // make gcc happy
-
switch (pipe->resultColorCtrl) {
case splashPipeResultColorNoAlphaBlendMono:
- cResult0 = state->grayTransfer[div255((255 - aDest) * cSrc[0] +
- aDest * cBlend[0])];
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
break;
case splashPipeResultColorNoAlphaBlendRGB:
- cResult0 = state->rgbTransferR[div255((255 - aDest) * cSrc[0] +
- aDest * cBlend[0])];
- cResult1 = state->rgbTransferG[div255((255 - aDest) * cSrc[1] +
- aDest * cBlend[1])];
- cResult2 = state->rgbTransferB[div255((255 - aDest) * cSrc[2] +
- aDest * cBlend[2])];
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
+ cResult1 = div255((255 - aDest) * cSrc[1] + aDest * cBlend[1]);
+ cResult2 = div255((255 - aDest) * cSrc[2] + aDest * cBlend[2]);
break;
#if SPLASH_CMYK
case splashPipeResultColorNoAlphaBlendCMYK:
- cResult0 = state->cmykTransferC[div255((255 - aDest) * cSrc[0] +
- aDest * cBlend[0])];
- cResult1 = state->cmykTransferM[div255((255 - aDest) * cSrc[1] +
- aDest * cBlend[1])];
- cResult2 = state->cmykTransferY[div255((255 - aDest) * cSrc[2] +
- aDest * cBlend[2])];
- cResult3 = state->cmykTransferK[div255((255 - aDest) * cSrc[3] +
- aDest * cBlend[3])];
+ cResult0 = div255((255 - aDest) * cSrc[0] + aDest * cBlend[0]);
+ cResult1 = div255((255 - aDest) * cSrc[1] + aDest * cBlend[1]);
+ cResult2 = div255((255 - aDest) * cSrc[2] + aDest * cBlend[2]);
+ cResult3 = div255((255 - aDest) * cSrc[3] + aDest * cBlend[3]);
break;
#endif
@@ -662,8 +655,7 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
if (alphaI == 0) {
cResult0 = 0;
} else {
- cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] +
- aSrc * cSrc[0]) / alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) / alphaI;
}
break;
case splashPipeResultColorAlphaNoBlendRGB:
@@ -672,12 +664,9 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] +
- aSrc * cSrc[0]) / alphaI];
- cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] +
- aSrc * cSrc[1]) / alphaI];
- cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] +
- aSrc * cSrc[2]) / alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) / alphaI;
+ cResult1 = ((alphaI - aSrc) * cDest[1] + aSrc * cSrc[1]) / alphaI;
+ cResult2 = ((alphaI - aSrc) * cDest[2] + aSrc * cSrc[2]) / alphaI;
}
break;
#if SPLASH_CMYK
@@ -688,14 +677,10 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 = state->cmykTransferC[((alphaI - aSrc) * cDest[0] +
- aSrc * cSrc[0]) / alphaI];
- cResult1 = state->cmykTransferM[((alphaI - aSrc) * cDest[1] +
- aSrc * cSrc[1]) / alphaI];
- cResult2 = state->cmykTransferY[((alphaI - aSrc) * cDest[2] +
- aSrc * cSrc[2]) / alphaI];
- cResult3 = state->cmykTransferK[((alphaI - aSrc) * cDest[3] +
- aSrc * cSrc[3]) / alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] + aSrc * cSrc[0]) / alphaI;
+ cResult1 = ((alphaI - aSrc) * cDest[1] + aSrc * cSrc[1]) / alphaI;
+ cResult2 = ((alphaI - aSrc) * cDest[2] + aSrc * cSrc[2]) / alphaI;
+ cResult3 = ((alphaI - aSrc) * cDest[3] + aSrc * cSrc[3]) / alphaI;
}
break;
#endif
@@ -704,10 +689,10 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
if (alphaI == 0) {
cResult0 = 0;
} else {
- cResult0 = state->grayTransfer[((alphaI - aSrc) * cDest[0] +
- aSrc * ((255 - alphaIm1) * cSrc[0] +
- alphaIm1 * cBlend[0]) / 255) /
- alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI;
}
break;
case splashPipeResultColorAlphaBlendRGB:
@@ -716,18 +701,18 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = state->rgbTransferR[((alphaI - aSrc) * cDest[0] +
- aSrc * ((255 - alphaIm1) * cSrc[0] +
- alphaIm1 * cBlend[0]) / 255) /
- alphaI];
- cResult1 = state->rgbTransferG[((alphaI - aSrc) * cDest[1] +
- aSrc * ((255 - alphaIm1) * cSrc[1] +
- alphaIm1 * cBlend[1]) / 255) /
- alphaI];
- cResult2 = state->rgbTransferB[((alphaI - aSrc) * cDest[2] +
- aSrc * ((255 - alphaIm1) * cSrc[2] +
- alphaIm1 * cBlend[2]) / 255) /
- alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI;
+ cResult1 = ((alphaI - aSrc) * cDest[1] +
+ aSrc * ((255 - alphaIm1) * cSrc[1] +
+ alphaIm1 * cBlend[1]) / 255)
+ / alphaI;
+ cResult2 = ((alphaI - aSrc) * cDest[2] +
+ aSrc * ((255 - alphaIm1) * cSrc[2] +
+ alphaIm1 * cBlend[2]) / 255)
+ / alphaI;
}
break;
#if SPLASH_CMYK
@@ -738,73 +723,69 @@ void Splash::pipeRun(SplashPipe *pipe, int x0, int x1, int y,
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 =
- state->cmykTransferC[((alphaI - aSrc) * cDest[0] +
- aSrc * ((255 - alphaIm1) * cSrc[0] +
- alphaIm1 * cBlend[0]) / 255) /
- alphaI];
- cResult1 =
- state->cmykTransferM[((alphaI - aSrc) * cDest[1] +
- aSrc * ((255 - alphaIm1) * cSrc[1] +
- alphaIm1 * cBlend[1]) / 255) /
- alphaI];
- cResult2 =
- state->cmykTransferY[((alphaI - aSrc) * cDest[2] +
- aSrc * ((255 - alphaIm1) * cSrc[2] +
- alphaIm1 * cBlend[2]) / 255) /
- alphaI];
- cResult3 =
- state->cmykTransferK[((alphaI - aSrc) * cDest[3] +
- aSrc * ((255 - alphaIm1) * cSrc[3] +
- alphaIm1 * cBlend[3]) / 255) /
- alphaI];
+ cResult0 = ((alphaI - aSrc) * cDest[0] +
+ aSrc * ((255 - alphaIm1) * cSrc[0] +
+ alphaIm1 * cBlend[0]) / 255)
+ / alphaI;
+ cResult1 = ((alphaI - aSrc) * cDest[1] +
+ aSrc * ((255 - alphaIm1) * cSrc[1] +
+ alphaIm1 * cBlend[1]) / 255)
+ / alphaI;
+ cResult2 = ((alphaI - aSrc) * cDest[2] +
+ aSrc * ((255 - alphaIm1) * cSrc[2] +
+ alphaIm1 * cBlend[2]) / 255)
+ / alphaI;
+ cResult3 = ((alphaI - aSrc) * cDest[3] +
+ aSrc * ((255 - alphaIm1) * cSrc[3] +
+ alphaIm1 * cBlend[3]) / 255)
+ / alphaI;
}
break;
#endif
}
- //----- write destination pixel
+ } // if (noTransparency && !blendFunc)
- switch (bitmap->mode) {
- case splashModeMono1:
- if (state->screen->test(x, y, cResult0)) {
- *destColorPtr |= destColorMask;
- } else {
- *destColorPtr &= ~destColorMask;
- }
- destColorPtr += destColorMask & 1;
- destColorMask = (destColorMask << 7) | (destColorMask >> 1);
- break;
- case splashModeMono8:
- *destColorPtr++ = cResult0;
- break;
- case splashModeRGB8:
- destColorPtr[0] = cResult0;
- destColorPtr[1] = cResult1;
- destColorPtr[2] = cResult2;
- destColorPtr += 3;
- break;
- case splashModeBGR8:
- destColorPtr[0] = cResult2;
- destColorPtr[1] = cResult1;
- destColorPtr[2] = cResult0;
- destColorPtr += 3;
- break;
+ //----- write destination pixel
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ if (state->screen->test(x, y, cResult0)) {
+ *destColorPtr |= destColorMask;
+ } else {
+ *destColorPtr &= ~destColorMask;
+ }
+ destColorPtr += destColorMask & 1;
+ destColorMask = (destColorMask << 7) | (destColorMask >> 1);
+ break;
+ case splashModeMono8:
+ *destColorPtr++ = cResult0;
+ break;
+ case splashModeRGB8:
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr += 3;
+ break;
+ case splashModeBGR8:
+ destColorPtr[0] = cResult2;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult0;
+ destColorPtr += 3;
+ break;
#if SPLASH_CMYK
- case splashModeCMYK8:
- destColorPtr[0] = cResult0;
- destColorPtr[1] = cResult1;
- destColorPtr[2] = cResult2;
- destColorPtr[3] = cResult3;
- destColorPtr += 4;
- break;
+ case splashModeCMYK8:
+ destColorPtr[0] = cResult0;
+ destColorPtr[1] = cResult1;
+ destColorPtr[2] = cResult2;
+ destColorPtr[3] = cResult3;
+ destColorPtr += 4;
+ break;
#endif
- }
- if (destAlphaPtr) {
- *destAlphaPtr++ = aResult;
- }
-
- } // if (noTransparency && !blendFunc)
+ }
+ if (destAlphaPtr) {
+ *destAlphaPtr++ = aResult;
+ }
cSrcPtr += cSrcStride;
shapePtr2 += shapeStride;
@@ -821,6 +802,7 @@ void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y,
Guchar cResult0;
SplashColorPtr destColorPtr;
Guchar destColorMask;
+ SplashScreenCursor screenCursor;
int cSrcStride, x;
if (cSrcPtr) {
@@ -839,11 +821,13 @@ void Splash::pipeRunSimpleMono1(SplashPipe *pipe, int x0, int x1, int y,
destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
destColorMask = 0x80 >> (x0 & 7);
+ screenCursor = state->screen->getTestCursor(y);
+
for (x = x0; x <= x1; ++x) {
//----- write destination pixel
cResult0 = state->grayTransfer[cSrcPtr[0]];
- if (state->screen->test(x, y, cResult0)) {
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
*destColorPtr |= destColorMask;
} else {
*destColorPtr &= ~destColorMask;
@@ -1013,9 +997,10 @@ void Splash::pipeRunSimpleCMYK8(SplashPipe *pipe, int x0, int x1, int y,
// bitmap->mode == splashModeMono1 && !bitmap->alpha
void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
- Guchar shape, aSrc, cDest0, cResult0;
+ Guchar shape, aSrc, cSrc0, cDest0, cResult0;
SplashColorPtr destColorPtr;
Guchar destColorMask;
+ SplashScreenCursor screenCursor;
int cSrcStride, x, lastX;
if (cSrcPtr) {
@@ -1041,6 +1026,8 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
destColorMask = 0x80 >> (x0 & 7);
+ screenCursor = state->screen->getTestCursor(y);
+
for (x = x0; x <= x1; ++x) {
//----- shape
@@ -1054,19 +1041,27 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
}
lastX = x;
- //----- read destination pixel
- cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
//----- source alpha
aSrc = shape;
- //----- result color
- // note: aDest = alphaI = aResult = 0xff
- cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest0 +
- aSrc * cSrcPtr[0])];
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+
+ //----- result color
+ // note: aDest = alphaI = aResult = 0xff
+ cResult0 = (Guchar)div255((0xff - aSrc) * cDest0 + aSrc * cSrc0);
+ }
//----- write destination pixel
- if (state->screen->test(x, y, cResult0)) {
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
*destColorPtr |= destColorMask;
} else {
*destColorPtr &= ~destColorMask;
@@ -1086,7 +1081,7 @@ void Splash::pipeRunShapeMono1(SplashPipe *pipe, int x0, int x1, int y,
// bitmap->mode == splashModeMono8 && bitmap->alpha
void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
- Guchar shape, aSrc, aDest, alphaI, aResult, cDest0, cResult0;
+ Guchar shape, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0;
SplashColorPtr destColorPtr;
Guchar *destAlphaPtr;
int cSrcStride, x, lastX;
@@ -1127,23 +1122,37 @@ void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y,
}
lastX = x;
- //----- read destination pixel
- cDest0 = *destColorPtr;
- aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
//----- source alpha
aSrc = shape;
- //----- result alpha and non-isolated group element correction
- aResult = aSrc + aDest - div255(aSrc * aDest);
- alphaI = aResult;
-
- //----- result color
- if (alphaI == 0) {
- cResult0 = 0;
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
} else {
- cResult0 = state->grayTransfer[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = *destColorPtr;
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ }
}
//----- write destination pixel
@@ -1163,6 +1172,7 @@ void Splash::pipeRunShapeMono8(SplashPipe *pipe, int x0, int x1, int y,
void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
Guchar cDest0, cDest1, cDest2;
Guchar cResult0, cResult1, cResult2;
SplashColorPtr destColorPtr;
@@ -1205,31 +1215,47 @@ void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y,
}
lastX = x;
- //----- read destination pixel
- cDest0 = destColorPtr[0];
- cDest1 = destColorPtr[1];
- cDest2 = destColorPtr[2];
- aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
//----- source alpha
aSrc = shape;
- //----- result alpha and non-isolated group element correction
- aResult = aSrc + aDest - div255(aSrc * aDest);
- alphaI = aResult;
-
- //----- result color
- if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
} else {
- cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
- cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrcPtr[1]) / alphaI)];
- cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrcPtr[2]) / alphaI)];
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[0];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[2];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
}
//----- write destination pixel
@@ -1252,6 +1278,7 @@ void Splash::pipeRunShapeRGB8(SplashPipe *pipe, int x0, int x1, int y,
void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
Guchar cDest0, cDest1, cDest2;
Guchar cResult0, cResult1, cResult2;
SplashColorPtr destColorPtr;
@@ -1294,31 +1321,47 @@ void Splash::pipeRunShapeBGR8(SplashPipe *pipe, int x0, int x1, int y,
}
lastX = x;
- //----- read destination pixel
- cDest0 = destColorPtr[2];
- cDest1 = destColorPtr[1];
- cDest2 = destColorPtr[0];
- aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
//----- source alpha
aSrc = shape;
- //----- result alpha and non-isolated group element correction
- aResult = aSrc + aDest - div255(aSrc * aDest);
- alphaI = aResult;
-
- //----- result color
- if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
} else {
- cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
- cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrcPtr[1]) / alphaI)];
- cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrcPtr[2]) / alphaI)];
+
+ //----- read destination alpha
+ aDest = *destAlphaPtr;
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ } else {
+
+ //----- read destination pixel
+ cDest0 = destColorPtr[2];
+ cDest1 = destColorPtr[1];
+ cDest2 = destColorPtr[0];
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ }
}
//----- write destination pixel
@@ -1394,22 +1437,22 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y,
//----- overprint
if (state->overprintMask & 1) {
- cSrc0 = cSrcPtr[0];
+ cSrc0 = state->cmykTransferC[cSrcPtr[0]];
} else {
cSrc0 = div255(aDest * cDest0);
}
if (state->overprintMask & 2) {
- cSrc1 = cSrcPtr[1];
+ cSrc1 = state->cmykTransferM[cSrcPtr[1]];
} else {
cSrc1 = div255(aDest * cDest1);
}
if (state->overprintMask & 4) {
- cSrc2 = cSrcPtr[2];
+ cSrc2 = state->cmykTransferY[cSrcPtr[2]];
} else {
cSrc2 = div255(aDest * cDest2);
}
if (state->overprintMask & 8) {
- cSrc3 = cSrcPtr[3];
+ cSrc3 = state->cmykTransferK[cSrcPtr[3]];
} else {
cSrc3 = div255(aDest * cDest3);
}
@@ -1417,25 +1460,34 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y,
//----- source alpha
aSrc = shape;
- //----- result alpha and non-isolated group element correction
- aResult = aSrc + aDest - div255(aSrc * aDest);
- alphaI = aResult;
-
- //----- result color
- if (alphaI == 0) {
- cResult0 = 0;
- cResult1 = 0;
- cResult2 = 0;
- cResult3 = 0;
+ //----- special case for aSrc = 255
+ if (aSrc == 255) {
+ aResult = 255;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ cResult3 = cSrc3;
} else {
- cResult0 = state->cmykTransferC[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrc0) / alphaI)];
- cResult1 = state->cmykTransferM[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrc1) / alphaI)];
- cResult2 = state->cmykTransferY[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrc2) / alphaI)];
- cResult3 = state->cmykTransferK[(Guchar)(((alphaI - aSrc) * cDest3 +
- aSrc * cSrc3) / alphaI)];
+
+ //----- special case for aDest = 0
+ if (aDest == 0) {
+ aResult = aSrc;
+ cResult0 = cSrc0;
+ cResult1 = cSrc1;
+ cResult2 = cSrc2;
+ cResult3 = cSrc3;
+ } else {
+
+ //----- result alpha and non-isolated group element correction
+ aResult = aSrc + aDest - div255(aSrc * aDest);
+ alphaI = aResult;
+
+ //----- result color
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest3 + aSrc * cSrc3) / alphaI);
+ }
}
//----- write destination pixel
@@ -1462,9 +1514,10 @@ void Splash::pipeRunShapeCMYK8(SplashPipe *pipe, int x0, int x1, int y,
// bitmap->mode == splashModeMono1 && !bitmap->alpha
void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
- Guchar shape, aSrc, cDest0, cResult0;
+ Guchar shape, aSrc, cSrc0, cDest0, cResult0;
SplashColorPtr destColorPtr;
Guchar destColorMask;
+ SplashScreenCursor screenCursor;
int cSrcStride, x, lastX;
if (cSrcPtr) {
@@ -1490,6 +1543,8 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
destColorPtr = &bitmap->data[y * bitmap->rowSize + (x0 >> 3)];
destColorMask = 0x80 >> (x0 & 7);
+ screenCursor = state->screen->getTestCursor(y);
+
for (x = x0; x <= x1; ++x) {
//----- shape
@@ -1506,16 +1561,18 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
//----- read destination pixel
cDest0 = (*destColorPtr & destColorMask) ? 0xff : 0x00;
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
//----- source alpha
aSrc = div255(pipe->aInput * shape);
//----- result color
// note: aDest = alphaI = aResult = 0xff
- cResult0 = state->grayTransfer[(Guchar)div255((0xff - aSrc) * cDest0 +
- aSrc * cSrcPtr[0])];
+ cResult0 = (Guchar)div255((0xff - aSrc) * cDest0 + aSrc * cSrc0);
//----- write destination pixel
- if (state->screen->test(x, y, cResult0)) {
+ if (state->screen->testWithCursor(screenCursor, x, cResult0)) {
*destColorPtr |= destColorMask;
} else {
*destColorPtr &= ~destColorMask;
@@ -1537,7 +1594,7 @@ void Splash::pipeRunAAMono1(SplashPipe *pipe, int x0, int x1, int y,
// bitmap->mode == splashModeMono8 && bitmap->alpha
void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
- Guchar shape, aSrc, aDest, alphaI, aResult, cDest0, cResult0;
+ Guchar shape, aSrc, aDest, alphaI, aResult, cSrc0, cDest0, cResult0;
SplashColorPtr destColorPtr;
Guchar *destAlphaPtr;
int cSrcStride, x, lastX;
@@ -1582,6 +1639,9 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
cDest0 = *destColorPtr;
aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->grayTransfer[cSrcPtr[0]];
+
//----- source alpha
aSrc = div255(pipe->aInput * shape);
@@ -1593,8 +1653,7 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
if (alphaI == 0) {
cResult0 = 0;
} else {
- cResult0 = state->grayTransfer[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
}
//----- write destination pixel
@@ -1616,6 +1675,7 @@ void Splash::pipeRunAAMono8(SplashPipe *pipe, int x0, int x1, int y,
void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
Guchar cDest0, cDest1, cDest2;
Guchar cResult0, cResult1, cResult2;
SplashColorPtr destColorPtr;
@@ -1664,6 +1724,11 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
cDest2 = destColorPtr[2];
aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
//----- source alpha
aSrc = div255(pipe->aInput * shape);
@@ -1677,12 +1742,9 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
- cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrcPtr[1]) / alphaI)];
- cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrcPtr[2]) / alphaI)];
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
}
//----- write destination pixel
@@ -1707,6 +1769,7 @@ void Splash::pipeRunAARGB8(SplashPipe *pipe, int x0, int x1, int y,
void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y,
Guchar *shapePtr, SplashColorPtr cSrcPtr) {
Guchar shape, aSrc, aDest, alphaI, aResult;
+ Guchar cSrc0, cSrc1, cSrc2;
Guchar cDest0, cDest1, cDest2;
Guchar cResult0, cResult1, cResult2;
SplashColorPtr destColorPtr;
@@ -1755,6 +1818,11 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y,
cDest2 = destColorPtr[0];
aDest = *destAlphaPtr;
+ //----- source color
+ cSrc0 = state->rgbTransferR[cSrcPtr[0]];
+ cSrc1 = state->rgbTransferG[cSrcPtr[1]];
+ cSrc2 = state->rgbTransferB[cSrcPtr[2]];
+
//----- source alpha
aSrc = div255(pipe->aInput * shape);
@@ -1768,12 +1836,9 @@ void Splash::pipeRunAABGR8(SplashPipe *pipe, int x0, int x1, int y,
cResult1 = 0;
cResult2 = 0;
} else {
- cResult0 = state->rgbTransferR[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrcPtr[0]) / alphaI)];
- cResult1 = state->rgbTransferG[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrcPtr[1]) / alphaI)];
- cResult2 = state->rgbTransferB[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrcPtr[2]) / alphaI)];
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
}
//----- write destination pixel
@@ -1851,22 +1916,22 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y,
//----- overprint
if (state->overprintMask & 1) {
- cSrc0 = cSrcPtr[0];
+ cSrc0 = state->cmykTransferC[cSrcPtr[0]];
} else {
cSrc0 = div255(aDest * cDest0);
}
if (state->overprintMask & 2) {
- cSrc1 = cSrcPtr[1];
+ cSrc1 = state->cmykTransferM[cSrcPtr[1]];
} else {
cSrc1 = div255(aDest * cDest1);
}
if (state->overprintMask & 4) {
- cSrc2 = cSrcPtr[2];
+ cSrc2 = state->cmykTransferY[cSrcPtr[2]];
} else {
cSrc2 = div255(aDest * cDest2);
}
if (state->overprintMask & 8) {
- cSrc3 = cSrcPtr[3];
+ cSrc3 = state->cmykTransferK[cSrcPtr[3]];
} else {
cSrc3 = div255(aDest * cDest3);
}
@@ -1885,14 +1950,10 @@ void Splash::pipeRunAACMYK8(SplashPipe *pipe, int x0, int x1, int y,
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 = state->cmykTransferC[(Guchar)(((alphaI - aSrc) * cDest0 +
- aSrc * cSrc0) / alphaI)];
- cResult1 = state->cmykTransferM[(Guchar)(((alphaI - aSrc) * cDest1 +
- aSrc * cSrc1) / alphaI)];
- cResult2 = state->cmykTransferY[(Guchar)(((alphaI - aSrc) * cDest2 +
- aSrc * cSrc2) / alphaI)];
- cResult3 = state->cmykTransferK[(Guchar)(((alphaI - aSrc) * cDest3 +
- aSrc * cSrc3) / alphaI)];
+ cResult0 = (Guchar)(((alphaI - aSrc) * cDest0 + aSrc * cSrc0) / alphaI);
+ cResult1 = (Guchar)(((alphaI - aSrc) * cDest1 + aSrc * cSrc1) / alphaI);
+ cResult2 = (Guchar)(((alphaI - aSrc) * cDest2 + aSrc * cSrc2) / alphaI);
+ cResult3 = (Guchar)(((alphaI - aSrc) * cDest3 + aSrc * cSrc3) / alphaI);
}
//----- write destination pixel
@@ -1931,8 +1992,6 @@ inline void Splash::transform(SplashCoord *matrix,
Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
SplashScreenParams *screenParams) {
- int i;
-
bitmap = bitmapA;
bitmapComps = splashColorModeNComps[bitmap->mode];
vectorAntialias = vectorAntialiasA;
@@ -1940,13 +1999,12 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
screenParams);
scanBuf = (Guchar *)gmalloc(bitmap->width);
- if (vectorAntialias) {
- for (i = 0; i <= 255; ++i) {
- aaGamma[i] = (Guchar)splashRound(
- splashPow((SplashCoord)i / (SplashCoord)255,
- splashAAGamma) * 255);
- }
+ if (bitmap->mode == splashModeMono1) {
+ scanBuf2 = (Guchar *)gmalloc(bitmap->width);
+ } else {
+ scanBuf2 = NULL;
}
+ groupBackBitmap = NULL;
minLineWidth = 0;
clearModRegion();
debugMode = gFalse;
@@ -1954,8 +2012,6 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
SplashScreen *screenA) {
- int i;
-
bitmap = bitmapA;
bitmapComps = splashColorModeNComps[bitmap->mode];
vectorAntialias = vectorAntialiasA;
@@ -1963,13 +2019,12 @@ Splash::Splash(SplashBitmap *bitmapA, GBool vectorAntialiasA,
state = new SplashState(bitmap->width, bitmap->height, vectorAntialias,
screenA);
scanBuf = (Guchar *)gmalloc(bitmap->width);
- if (vectorAntialias) {
- for (i = 0; i <= 255; ++i) {
- aaGamma[i] = (Guchar)splashRound(
- splashPow((SplashCoord)i / (SplashCoord)255,
- splashAAGamma) * 255);
- }
+ if (bitmap->mode == splashModeMono1) {
+ scanBuf2 = (Guchar *)gmalloc(bitmap->width);
+ } else {
+ scanBuf2 = NULL;
}
+ groupBackBitmap = NULL;
minLineWidth = 0;
clearModRegion();
debugMode = gFalse;
@@ -1981,6 +2036,7 @@ Splash::~Splash() {
}
delete state;
gfree(scanBuf);
+ gfree(scanBuf2);
}
//------------------------------------------------------------------------
@@ -2047,7 +2103,7 @@ SplashCoord Splash::getLineDashPhase() {
return state->lineDashPhase;
}
-GBool Splash::getStrokeAdjust() {
+SplashStrokeAdjustMode Splash::getStrokeAdjust() {
return state->strokeAdjust;
}
@@ -2128,7 +2184,7 @@ void Splash::setLineDash(SplashCoord *lineDash, int lineDashLength,
state->setLineDash(lineDash, lineDashLength, lineDashPhase);
}
-void Splash::setStrokeAdjust(GBool strokeAdjust) {
+void Splash::setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust) {
state->strokeAdjust = strokeAdjust;
}
@@ -2169,6 +2225,10 @@ void Splash::setOverprintMask(Guint overprintMask) {
state->overprintMask = overprintMask;
}
+void Splash::setEnablePathSimplification(GBool en) {
+ state->enablePathSimplification = en;
+}
+
//------------------------------------------------------------------------
// state save/restore
//------------------------------------------------------------------------
@@ -2300,7 +2360,8 @@ void Splash::clear(SplashColorPtr color, Guchar alpha) {
SplashError Splash::stroke(SplashPath *path) {
SplashPath *path2, *dPath;
- SplashCoord t0, t1, t2, t3, w, w2;
+ SplashCoord t0, t1, t2, t3, w, w2, lineDashMax, lineDashTotal;
+ int lineCap, lineJoin, i;
if (debugMode) {
printf("stroke [dash:%d] [width:%.2f]:\n",
@@ -2312,15 +2373,6 @@ SplashError Splash::stroke(SplashPath *path) {
return splashErrEmptyPath;
}
path2 = flattenPath(path, state->matrix, state->flatness);
- if (state->lineDashLength > 0) {
- dPath = makeDashedPath(path2);
- delete path2;
- path2 = dPath;
- if (path2->length == 0) {
- delete path2;
- return splashErrEmptyPath;
- }
- }
// Compute an approximation of the transformed line width.
// Given a CTM of [m0 m1],
@@ -2341,10 +2393,62 @@ SplashError Splash::stroke(SplashPath *path) {
w = (t1 < t2) ? t1 : t2;
}
w2 = w * state->lineWidth;
+
+ // construct the dashed path
+ if (state->lineDashLength > 0) {
+
+ // check the maximum transformed dash element length (using the
+ // same approximation as for line width) -- if it's less than 0.1
+ // pixel, don't apply the dash pattern; this avoids a huge
+ // performance/memory hit with PDF files that use absurd dash
+ // patterns like [0.0007 0.0003]
+ lineDashTotal = 0;
+ lineDashMax = 0;
+ for (i = 0; i < state->lineDashLength; ++i) {
+ lineDashTotal += state->lineDash[i];
+ if (state->lineDash[i] > lineDashMax) {
+ lineDashMax = state->lineDash[i];
+ }
+ }
+ // Acrobat simply draws nothing if the dash array is [0]
+ if (lineDashTotal == 0) {
+ delete path2;
+ return splashOk;
+ }
+ if (w * lineDashMax > 0.1) {
+
+ dPath = makeDashedPath(path2);
+ delete path2;
+ path2 = dPath;
+ if (path2->length == 0) {
+ delete path2;
+ return splashErrEmptyPath;
+ }
+ }
+ }
+
+ // round caps on narrow lines look bad, and can't be
+ // stroke-adjusted, so use projecting caps instead (but we can't do
+ // this if there are zero-length dashes or segments, because those
+ // turn into round dots)
+ lineCap = state->lineCap;
+ lineJoin = state->lineJoin;
+ if (state->strokeAdjust == splashStrokeAdjustCAD &&
+ w2 < 3.5) {
+ if (lineCap == splashLineCapRound &&
+ !state->lineDashContainsZeroLengthDashes() &&
+ !path->containsZeroLengthSubpaths()) {
+ lineCap = splashLineCapProjecting;
+ }
+ if (lineJoin == splashLineJoinRound) {
+ lineJoin = splashLineJoinBevel;
+ }
+ }
+
// if there is a min line width set, and the transformed line width
// is smaller, use the min line width
if (w > 0 && w2 < minLineWidth) {
- strokeWide(path2, minLineWidth / w);
+ strokeWide(path2, minLineWidth / w, splashLineCapButt, splashLineJoinBevel);
} else if (bitmap->mode == splashModeMono1) {
// in monochrome mode, use 0-width lines for any transformed line
// width <= 1 -- lines less than 1 pixel wide look too fat without
@@ -2352,7 +2456,7 @@ SplashError Splash::stroke(SplashPath *path) {
if (w2 < 1.001) {
strokeNarrow(path2);
} else {
- strokeWide(path2, state->lineWidth);
+ strokeWide(path2, state->lineWidth, lineCap, lineJoin);
}
} else {
// in gray and color modes, only use 0-width lines if the line
@@ -2360,7 +2464,7 @@ SplashError Splash::stroke(SplashPath *path) {
if (state->lineWidth == 0) {
strokeNarrow(path2);
} else {
- strokeWide(path2, state->lineWidth);
+ strokeWide(path2, state->lineWidth, lineCap, lineJoin);
}
}
@@ -2380,7 +2484,9 @@ void Splash::strokeNarrow(SplashPath *path) {
nClipRes[0] = nClipRes[1] = nClipRes[2] = 0;
- xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse);
+ xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse,
+ state->enablePathSimplification,
+ state->strokeAdjust);
pipeInit(&pipe, state->strokePattern,
(Guchar)splashRound(state->strokeAlpha * 255),
@@ -2497,10 +2603,11 @@ void Splash::drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y,
(this->*pipe->run)(pipe, x0, x1, y, scanBuf + x0, NULL);
}
-void Splash::strokeWide(SplashPath *path, SplashCoord w) {
+void Splash::strokeWide(SplashPath *path, SplashCoord w,
+ int lineCap, int lineJoin) {
SplashPath *path2;
- path2 = makeStrokePath(path, w, gFalse);
+ path2 = makeStrokePath(path, w, lineCap, lineJoin, gFalse);
fillWithPattern(path2, gFalse, state->strokePattern, state->strokeAlpha);
delete path2;
}
@@ -2636,8 +2743,8 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
SplashCoord lineDashTotal;
SplashCoord lineDashStartPhase, lineDashDist, segLen;
SplashCoord x0, y0, x1, y1, xa, ya;
- GBool lineDashStartOn, lineDashOn, newPath;
- int lineDashStartIdx, lineDashIdx;
+ GBool lineDashStartOn, lineDashEndOn, lineDashOn, newPath;
+ int lineDashStartIdx, lineDashIdx, subpathStart, nDashes;
int i, j, k;
lineDashTotal = 0;
@@ -2649,6 +2756,13 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
return new SplashPath();
}
lineDashStartPhase = state->lineDashPhase;
+ if (lineDashStartPhase > lineDashTotal * 2) {
+ i = splashFloor(lineDashStartPhase / (lineDashTotal * 2));
+ lineDashStartPhase -= lineDashTotal * i * 2;
+ } else if (lineDashStartPhase < 0) {
+ i = splashCeil(-lineDashStartPhase / (lineDashTotal * 2));
+ lineDashStartPhase += lineDashTotal * i * 2;
+ }
i = splashFloor(lineDashStartPhase / lineDashTotal);
lineDashStartPhase -= (SplashCoord)i * lineDashTotal;
lineDashStartOn = gTrue;
@@ -2657,7 +2771,9 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
while (lineDashStartPhase >= state->lineDash[lineDashStartIdx]) {
lineDashStartOn = !lineDashStartOn;
lineDashStartPhase -= state->lineDash[lineDashStartIdx];
- ++lineDashStartIdx;
+ if (++lineDashStartIdx == state->lineDashLength) {
+ lineDashStartIdx = 0;
+ }
}
}
@@ -2674,8 +2790,11 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
// initialize the dash parameters
lineDashOn = lineDashStartOn;
+ lineDashEndOn = lineDashStartOn;
lineDashIdx = lineDashStartIdx;
lineDashDist = state->lineDash[lineDashIdx] - lineDashStartPhase;
+ subpathStart = dPath->length;
+ nDashes = 0;
// process each segment of the subpath
newPath = gTrue;
@@ -2691,11 +2810,31 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
// process the segment
while (segLen > 0) {
- if (lineDashDist >= segLen) {
+ // Special case for zero-length dash segments: draw a very
+ // short -- but not zero-length -- segment. This ensures that
+ // we get the correct behavior with butt and projecting line
+ // caps. The PS/PDF specs imply that zero-length segments are
+ // not drawn unless the line cap is round, but Acrobat and
+ // Ghostscript both draw very short segments (for butt caps)
+ // and squares (for projecting caps).
+ if (lineDashDist == 0) {
if (lineDashOn) {
if (newPath) {
dPath->moveTo(x0, y0);
newPath = gFalse;
+ ++nDashes;
+ }
+ xa = x0 + ((SplashCoord)0.001 / segLen) * (x1 - x0);
+ ya = y0 + ((SplashCoord)0.001 / segLen) * (y1 - y0);
+ dPath->lineTo(xa, ya);
+ }
+
+ } else if (lineDashDist >= segLen) {
+ if (lineDashOn) {
+ if (newPath) {
+ dPath->moveTo(x0, y0);
+ newPath = gFalse;
+ ++nDashes;
}
dPath->lineTo(x1, y1);
}
@@ -2709,6 +2848,7 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
if (newPath) {
dPath->moveTo(x0, y0);
newPath = gFalse;
+ ++nDashes;
}
dPath->lineTo(xa, ya);
}
@@ -2718,6 +2858,8 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
lineDashDist = 0;
}
+ lineDashEndOn = lineDashOn;
+
// get the next entry in the dash array
if (lineDashDist <= 0) {
lineDashOn = !lineDashOn;
@@ -2729,6 +2871,31 @@ SplashPath *Splash::makeDashedPath(SplashPath *path) {
}
}
}
+
+ // in a closed subpath, where the dash pattern is "on" at both the
+ // start and end of the subpath, we need to merge the start and
+ // end to get a proper line join
+ if ((path->flags[j] & splashPathClosed) &&
+ lineDashStartOn &&
+ lineDashEndOn) {
+ if (nDashes == 1) {
+ dPath->close();
+ } else if (nDashes > 1) {
+ k = subpathStart;
+ do {
+ ++k;
+ dPath->lineTo(dPath->pts[k].x, dPath->pts[k].y);
+ } while (!(dPath->flags[k] & splashPathLast));
+ ++k;
+ memmove(&dPath->pts[subpathStart], &dPath->pts[k],
+ (dPath->length - k) * sizeof(SplashPathPoint));
+ memmove(&dPath->flags[subpathStart], &dPath->flags[k],
+ (dPath->length - k) * sizeof(Guchar));
+ dPath->length -= k - subpathStart;
+ dPath->curSubpath -= k - subpathStart;
+ }
+ }
+
i = j + 1;
}
@@ -2750,7 +2917,7 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
SplashPath *path2;
SplashXPath *xPath;
SplashXPathScanner *scanner;
- int xMin, yMin, xMax, yMax, x, y, t;
+ int xMin, yMin, xMax, xMin2, xMax2, yMax, y, t;
SplashClipResult clipRes;
if (path->length == 0) {
@@ -2763,7 +2930,9 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
path2 = tweakFillPath(path);
- xPath = new SplashXPath(path2, state->matrix, state->flatness, gTrue);
+ xPath = new SplashXPath(path2, state->matrix, state->flatness, gTrue,
+ state->enablePathSimplification,
+ state->strokeAdjust);
if (path2 != path) {
delete path2;
}
@@ -2806,23 +2975,25 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
// draw the spans
if (vectorAntialias && !inShading) {
for (y = yMin; y <= yMax; ++y) {
- scanner->getSpan(scanBuf, y, xMin, xMax);
- if (clipRes != splashClipAllInside) {
- state->clip->clipSpan(scanBuf, y, xMin, xMax, state->strokeAdjust);
- }
- for (x = xMin; x <= xMax; ++x) {
- scanBuf[x] = aaGamma[scanBuf[x]];
+ scanner->getSpan(scanBuf, y, xMin, xMax, &xMin2, &xMax2);
+ if (xMin2 <= xMax2) {
+ if (clipRes != splashClipAllInside) {
+ state->clip->clipSpan(scanBuf, y, xMin2, xMax2,
+ state->strokeAdjust);
+ }
+ (this->*pipe.run)(&pipe, xMin2, xMax2, y, scanBuf + xMin2, NULL);
}
- (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
}
} else {
for (y = yMin; y <= yMax; ++y) {
- scanner->getSpanBinary(scanBuf, y, xMin, xMax);
- if (clipRes != splashClipAllInside) {
- state->clip->clipSpanBinary(scanBuf, y, xMin, xMax,
- state->strokeAdjust);
+ scanner->getSpanBinary(scanBuf, y, xMin, xMax, &xMin2, &xMax2);
+ if (xMin2 <= xMax2) {
+ if (clipRes != splashClipAllInside) {
+ state->clip->clipSpanBinary(scanBuf, y, xMin2, xMax2,
+ state->strokeAdjust);
+ }
+ (this->*pipe.run)(&pipe, xMin2, xMax2, y, scanBuf + xMin2, NULL);
}
- (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
}
}
}
@@ -2849,7 +3020,7 @@ SplashPath *Splash::tweakFillPath(SplashPath *path) {
SplashCoord xx0, yy0, xx1, yy1, dx, dy, d, wx, wy, w;
int n;
- if (!state->strokeAdjust || path->hints) {
+ if (state->strokeAdjust == splashStrokeAdjustOff || path->hints) {
return path;
}
@@ -2887,7 +3058,7 @@ SplashPath *Splash::tweakFillPath(SplashPath *path) {
splashAbs(path->pts[1].y - path->pts[2].y) < 0.001)))) {
wx = state->matrix[0] + state->matrix[2];
wy = state->matrix[1] + state->matrix[3];
- w = sqrt(wx*wx + wy*wy);
+ w = splashSqrt(wx*wx + wy*wy);
if (w < 0.001) {
w = 0;
} else {
@@ -2905,7 +3076,7 @@ SplashPath *Splash::tweakFillPath(SplashPath *path) {
}
dx = xx1 - xx0;
dy = yy1 - yy0;
- d = sqrt(dx * dx + dy * dy);
+ d = splashSqrt(dx * dx + dy * dy);
if (d < 0.001) {
d = 0;
} else {
@@ -2995,6 +3166,10 @@ GBool Splash::pathAllOutside(SplashPath *path) {
} else if (y > yMax2) {
yMax2 = y;
}
+ // sanity-check the coordinates - xMinI/yMinI/xMaxI/yMaxI are
+ // 32-bit integers, so coords need to be < 2^31
+ SplashXPath::clampCoords(&xMin2, &yMin2);
+ SplashXPath::clampCoords(&xMax2, &yMax2);
xMinI = splashFloor(xMin2);
yMinI = splashFloor(yMin2);
xMaxI = splashFloor(xMax2);
@@ -3005,77 +3180,6 @@ GBool Splash::pathAllOutside(SplashPath *path) {
splashClipAllOutside;
}
-SplashError Splash::xorFill(SplashPath *path, GBool eo) {
- SplashPipe pipe;
- SplashXPath *xPath;
- SplashXPathScanner *scanner;
- int xMin, yMin, xMax, yMax, y, t;
- SplashClipResult clipRes;
- SplashBlendFunc origBlendFunc;
-
- if (path->length == 0) {
- return splashErrEmptyPath;
- }
- if (pathAllOutside(path)) {
- opClipRes = splashClipAllOutside;
- return splashOk;
- }
- xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue);
- xMin = xPath->getXMin();
- yMin = xPath->getYMin();
- xMax = xPath->getXMax();
- yMax = xPath->getYMax();
- if (xMin > xMax || yMin > yMax) {
- delete xPath;
- return splashOk;
- }
- scanner = new SplashXPathScanner(xPath, eo, yMin, yMax);
-
- // check clipping
- if ((clipRes = state->clip->testRect(xMin, yMin, xMax, yMax,
- state->strokeAdjust))
- != splashClipAllOutside) {
-
- if ((t = state->clip->getXMinI(state->strokeAdjust)) > xMin) {
- xMin = t;
- }
- if ((t = state->clip->getXMaxI(state->strokeAdjust)) < xMax) {
- xMax = t;
- }
- if ((t = state->clip->getYMinI(state->strokeAdjust)) > yMin) {
- yMin = t;
- }
- if ((t = state->clip->getYMaxI(state->strokeAdjust)) < yMax) {
- yMax = t;
- }
- if (xMin > xMax || yMin > yMax) {
- delete scanner;
- delete xPath;
- return splashOk;
- }
-
- origBlendFunc = state->blendFunc;
- state->blendFunc = &blendXor;
- pipeInit(&pipe, state->fillPattern, 255, gTrue, gFalse);
-
- // draw the spans
- for (y = yMin; y <= yMax; ++y) {
- scanner->getSpanBinary(scanBuf, y, xMin, xMax);
- if (clipRes != splashClipAllInside) {
- state->clip->clipSpanBinary(scanBuf, y, xMin, xMax,
- state->strokeAdjust);
- }
- (this->*pipe.run)(&pipe, xMin, xMax, y, scanBuf + xMin, NULL);
- }
- state->blendFunc = origBlendFunc;
- }
- opClipRes = clipRes;
-
- delete scanner;
- delete xPath;
- return splashOk;
-}
-
SplashError Splash::fillChar(SplashCoord x, SplashCoord y,
int c, SplashFont *font) {
SplashGlyphBitmap glyph;
@@ -3208,14 +3312,14 @@ SplashError Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph) {
void Splash::getImageBounds(SplashCoord xyMin, SplashCoord xyMax,
int *xyMinI, int *xyMaxI) {
- if (state->strokeAdjust) {
- splashStrokeAdjust(xyMin, xyMax, xyMinI, xyMaxI);
- } else {
+ if (state->strokeAdjust == splashStrokeAdjustOff) {
*xyMinI = splashFloor(xyMin);
*xyMaxI = splashFloor(xyMax);
if (*xyMaxI <= *xyMinI) {
*xyMaxI = *xyMinI + 1;
}
+ } else {
+ splashStrokeAdjust(xyMin, xyMax, xyMinI, xyMaxI, state->strokeAdjust);
}
}
@@ -3254,8 +3358,14 @@ SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
// stream-mode upscaling -- this is slower, so we only use it if the
// upscaled mask is large (in which case clipping should remove many
// pixels)
- if (wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) {
+#if USE_FIXEDPOINT
+ if ((wSize > 2 * w && hSize > 2 * h && (int)wSize > 1000000 / (int)hSize) ||
+ (wSize > w && hSize > h && (int)wSize > 10000000 / (int)hSize)) {
+#else
+ if ((wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) ||
+ (wSize > w && hSize > h && wSize * hSize > 10000000)) {
upscaleMask(src, srcData, w, h, mat, glyphMode, interpolate);
+#endif
// scaling only
} else if (mat[0] > 0 && minorAxisZero && mat[3] > 0) {
@@ -3462,10 +3572,12 @@ void Splash::upscaleMask(SplashImageMaskSource src, void *srcData,
if (y1 >= srcHeight) {
y1 = srcHeight - 1;
}
- pix0 = ((SplashCoord)1 - sx) * unscaledImage[y0 * srcWidth + x0]
- + sx * unscaledImage[y0 * srcWidth + x1];
- pix1 = ((SplashCoord)1 - sx) * unscaledImage[y1 * srcWidth + x0]
- + sx * unscaledImage[y1 * srcWidth + x1];
+ pix0 = ((SplashCoord)1 - sx)
+ * (SplashCoord)unscaledImage[y0 * srcWidth + x0]
+ + sx * (SplashCoord)unscaledImage[y0 * srcWidth + x1];
+ pix1 = ((SplashCoord)1 - sx)
+ * (SplashCoord)unscaledImage[y1 * srcWidth + x0]
+ + sx * (SplashCoord)unscaledImage[y1 * srcWidth + x1];
scanBuf[x] = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0
+ sy * pix1);
} else {
@@ -4041,10 +4153,10 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
int scaledWidth, int scaledHeight,
SplashBitmap *dest) {
Guchar *lineBuf;
- Guint pix;
- Guchar *destPtr0, *destPtr;
- int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx;
- int i, j;
+ Guchar pix;
+ Guchar *srcPtr, *destPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep;
+ int i;
// Bresenham parameters for y scale
yp = scaledHeight / srcHeight;
@@ -4060,7 +4172,7 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
// init y scale Bresenham
yt = 0;
- destPtr0 = dest->data;
+ destPtr = dest->data;
for (y = 0; y < srcHeight; ++y) {
// y scale Bresenham
@@ -4077,7 +4189,8 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
// init x scale Bresenham
xt = 0;
- xx = 0;
+ // generate one row
+ srcPtr = lineBuf;
for (x = 0; x < srcWidth; ++x) {
// x scale Bresenham
@@ -4089,20 +4202,20 @@ void Splash::scaleMaskYuXu(SplashImageMaskSource src, void *srcData,
}
// compute the final pixel
- pix = lineBuf[x] ? 255 : 0;
+ pix = *srcPtr ? 255 : 0;
+ ++srcPtr;
- // store the pixel
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destPtr = destPtr0 + i * scaledWidth + xx + j;
- *destPtr++ = (Guchar)pix;
- }
+ // duplicate the pixel horizontally
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = pix;
}
-
- xx += xStep;
}
- destPtr0 += yStep * scaledWidth;
+ // duplicate the row vertically
+ for (i = 1 ; i < yStep; ++i) {
+ memcpy(destPtr, destPtr - scaledWidth, scaledWidth);
+ destPtr += scaledWidth;
+ }
}
gfree(lineBuf);
@@ -4149,11 +4262,11 @@ void Splash::scaleMaskYuXuI(SplashImageMaskSource src, void *srcData,
xSrc1 = srcWidth - 1;
}
lineBuf0[x] = (Guchar)(int)
- ((xs * lineBuf0[xSrc0] +
- ((SplashCoord)1 - xs) * lineBuf0[xSrc1]) * 255);
+ ((xs * (int)lineBuf0[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)lineBuf0[xSrc1]) * 255);
lineBuf1[x] = (Guchar)(int)
- ((xs * lineBuf1[xSrc0] +
- ((SplashCoord)1 - xs) * lineBuf1[xSrc1]) * 255);
+ ((xs * (int)lineBuf1[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)lineBuf1[xSrc1]) * 255);
}
destPtr = dest->data;
@@ -4193,8 +4306,8 @@ void Splash::scaleMaskYuXuI(SplashImageMaskSource src, void *srcData,
xSrc1 = srcWidth - 1;
}
lineBuf1[x] = (Guchar)(int)
- ((xs * lineBuf1[xSrc0] +
- ((SplashCoord)1 - xs) * lineBuf1[xSrc1]) * 255);
+ ((xs * (int)lineBuf1[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)lineBuf1[xSrc1]) * 255);
}
++yBuf;
@@ -4203,8 +4316,8 @@ void Splash::scaleMaskYuXuI(SplashImageMaskSource src, void *srcData,
// do the vertical interpolation
for (x = 0; x < scaledWidth; ++x) {
- pix = (Guchar)(int)(ys * lineBuf0[x] +
- ((SplashCoord)1 - ys) * lineBuf1[x]);
+ pix = (Guchar)(int)(ys * (int)lineBuf0[x] +
+ ((SplashCoord)1 - ys) * (int)lineBuf1[x]);
// store the pixel
*destPtr++ = pix;
@@ -4329,7 +4442,13 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData,
// stream-mode upscaling -- this is slower, so we only use it if the
// upscaled image is large (in which case clipping should remove
// many pixels)
- if (wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) {
+#if USE_FIXEDPOINT
+ if ((wSize > 2 * w && hSize > 2 * h && (int)wSize > 1000000 / (int)hSize) ||
+ (wSize > w && hSize > h && (int)wSize > 10000000 / (int)hSize)) {
+#else
+ if ((wSize > 2 * w && hSize > 2 * h && wSize * hSize > 1000000) ||
+ (wSize > w && hSize > h && wSize * hSize > 10000000)) {
+#endif
upscaleImage(src, srcData, srcMode, nComps, srcAlpha,
w, h, mat, interpolate);
@@ -4367,7 +4486,7 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData,
}
// scaling plus horizontal flip
- } else if (mat[0] > 0 && minorAxisZero && mat[3] > 0) {
+ } else if (mat[0] < 0 && minorAxisZero && mat[3] > 0) {
getImageBounds(mat[0] + mat[4], mat[4], &x0, &x1);
getImageBounds(mat[5], mat[3] + mat[5], &y0, &y1);
clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1,
@@ -4384,7 +4503,7 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData,
}
// scaling plus horizontal and vertical flips
- } else if (mat[0] > 0 && minorAxisZero && mat[3] < 0) {
+ } else if (mat[0] < 0 && minorAxisZero && mat[3] < 0) {
getImageBounds(mat[0] + mat[4], mat[4], &x0, &x1);
getImageBounds(mat[3] + mat[5], mat[5], &y0, &y1);
clipRes = state->clip->testRect(x0, y0, x1 - 1, y1 - 1,
@@ -4557,16 +4676,18 @@ void Splash::upscaleImage(SplashImageSource src, void *srcData,
q10 = &unscaledImage[(y1 * srcWidth + x0) * nComps];
q11 = &unscaledImage[(y1 * srcWidth + x1) * nComps];
for (i = 0; i < nComps; ++i) {
- pix0 = ((SplashCoord)1 - sx) * *q00++ + sx * *q01++;
- pix1 = ((SplashCoord)1 - sx) * *q10++ + sx * *q11++;
+ pix0 = ((SplashCoord)1 - sx) * (int)*q00++ + sx * (int)*q01++;
+ pix1 = ((SplashCoord)1 - sx) * (int)*q10++ + sx * (int)*q11++;
*p++ = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0
+ sy * pix1);
}
if (srcAlpha) {
- pix0 = ((SplashCoord)1 - sx) * unscaledAlpha[y0 * srcWidth + x0]
- + sx * unscaledAlpha[y0 * srcWidth + x1];
- pix1 = ((SplashCoord)1 - sx) * unscaledAlpha[y1 * srcWidth + x0]
- + sx * unscaledAlpha[y1 * srcWidth + x1];
+ pix0 = ((SplashCoord)1 - sx)
+ * (SplashCoord)unscaledAlpha[y0 * srcWidth + x0]
+ + sx * (SplashCoord)unscaledAlpha[y0 * srcWidth + x1];
+ pix1 = ((SplashCoord)1 - sx)
+ * (SplashCoord)unscaledAlpha[y1 * srcWidth + x0]
+ + sx * (SplashCoord)unscaledAlpha[y1 * srcWidth + x1];
scanBuf[x] = (Guchar)splashRound(((SplashCoord)1 - sy) * pix0
+ sy * pix1);
} else {
@@ -5139,6 +5260,12 @@ void Splash::scaleImageYdXu(SplashImageSource src, void *srcData,
alphaPixBuf = NULL;
}
+ // make gcc happy
+ pix[0] = pix[1] = pix[2] = 0;
+#if SPLASH_CMYK
+ pix[3] = 0;
+#endif
+
// init y scale Bresenham
yt = 0;
@@ -5266,6 +5393,12 @@ void Splash::scaleImageYuXd(SplashImageSource src, void *srcData,
alphaLineBuf = NULL;
}
+ // make gcc happy
+ pix[0] = pix[1] = pix[2] = 0;
+#if SPLASH_CMYK
+ pix[3] = 0;
+#endif
+
// init y scale Bresenham
yt = 0;
@@ -5380,11 +5513,15 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
int scaledWidth, int scaledHeight,
SplashBitmap *dest) {
Guchar *lineBuf, *alphaLineBuf;
- Guint pix[splashMaxColorComps];
+ Guchar pix0, pix1, pix2;
+#if SPLASH_CMYK
+ Guchar pix3;
+#endif
Guint alpha;
- Guchar *destPtr0, *destPtr, *destAlphaPtr0, *destAlphaPtr;
- int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep, xx;
- int i, j;
+ Guchar *srcPtr, *srcAlphaPtr;
+ Guchar *destPtr, *destAlphaPtr;
+ int yp, yq, xp, xq, yt, y, yStep, xt, x, xStep;
+ int i;
// Bresenham parameters for y scale
yp = scaledHeight / srcHeight;
@@ -5405,8 +5542,8 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
// init y scale Bresenham
yt = 0;
- destPtr0 = dest->data;
- destAlphaPtr0 = dest->alpha;
+ destPtr = dest->data;
+ destAlphaPtr = dest->alpha;
for (y = 0; y < srcHeight; ++y) {
// y scale Bresenham
@@ -5423,7 +5560,9 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
// init x scale Bresenham
xt = 0;
- xx = 0;
+ // generate one row
+ srcPtr = lineBuf;
+ srcAlphaPtr = alphaLineBuf;
for (x = 0; x < srcWidth; ++x) {
// x scale Bresenham
@@ -5434,41 +5573,35 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
xStep = xp;
}
- // compute the final pixel
- for (i = 0; i < nComps; ++i) {
- pix[i] = lineBuf[x * nComps + i];
- }
-
- // store the pixel
+ // duplicate the pixel horizontally
switch (srcMode) {
case splashModeMono8:
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
- *destPtr++ = (Guchar)pix[0];
- }
+ pix0 = *srcPtr++;
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = pix0;
}
break;
case splashModeRGB8:
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
- *destPtr++ = (Guchar)pix[0];
- *destPtr++ = (Guchar)pix[1];
- *destPtr++ = (Guchar)pix[2];
- }
+ pix0 = *srcPtr++;
+ pix1 = *srcPtr++;
+ pix2 = *srcPtr++;
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = pix0;
+ *destPtr++ = pix1;
+ *destPtr++ = pix2;
}
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destPtr = destPtr0 + (i * scaledWidth + xx + j) * nComps;
- *destPtr++ = (Guchar)pix[0];
- *destPtr++ = (Guchar)pix[1];
- *destPtr++ = (Guchar)pix[2];
- *destPtr++ = (Guchar)pix[3];
- }
+ pix0 = *srcPtr++;
+ pix1 = *srcPtr++;
+ pix2 = *srcPtr++;
+ pix3 = *srcPtr++;
+ for (i = 0; i < xStep; ++i) {
+ *destPtr++ = pix0;
+ *destPtr++ = pix1;
+ *destPtr++ = pix2;
+ *destPtr++ = pix3;
}
break;
#endif
@@ -5478,23 +5611,26 @@ void Splash::scaleImageYuXu(SplashImageSource src, void *srcData,
break;
}
- // process alpha
+ // duplicate the alpha value horizontally
if (srcAlpha) {
- alpha = alphaLineBuf[x];
- for (i = 0; i < yStep; ++i) {
- for (j = 0; j < xStep; ++j) {
- destAlphaPtr = destAlphaPtr0 + i * scaledWidth + xx + j;
- *destAlphaPtr = (Guchar)alpha;
- }
+ alpha = *srcAlphaPtr++;
+ for (i = 0; i < xStep; ++i) {
+ *destAlphaPtr++ = alpha;
}
}
-
- xx += xStep;
}
- destPtr0 += yStep * scaledWidth * nComps;
+ // duplicate the row vertically
+ for (i = 1; i < yStep; ++i) {
+ memcpy(destPtr, destPtr - scaledWidth * nComps,
+ scaledWidth * nComps);
+ destPtr += scaledWidth * nComps;
+ }
if (srcAlpha) {
- destAlphaPtr0 += yStep * scaledWidth;
+ for (i = 1; i < yStep; ++i) {
+ memcpy(destAlphaPtr, destAlphaPtr - scaledWidth, scaledWidth);
+ destAlphaPtr += scaledWidth;
+ }
}
}
@@ -5555,22 +5691,28 @@ void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData,
}
for (i = 0; i < nComps; ++i) {
lineBuf0[x*nComps+i] = (Guchar)(int)
- (xs * lineBuf0[xSrc0*nComps+i] +
- ((SplashCoord)1 - xs) * lineBuf0[xSrc1*nComps+i]);
+ (xs * (int)lineBuf0[xSrc0*nComps+i] +
+ ((SplashCoord)1 - xs) * (int)lineBuf0[xSrc1*nComps+i]);
lineBuf1[x*nComps+i] = (Guchar)(int)
- (xs * lineBuf1[xSrc0*nComps+i] +
- ((SplashCoord)1 - xs) * lineBuf1[xSrc1*nComps+i]);
+ (xs * (int)lineBuf1[xSrc0*nComps+i] +
+ ((SplashCoord)1 - xs) * (int)lineBuf1[xSrc1*nComps+i]);
}
if (srcAlpha) {
alphaLineBuf0[x] = (Guchar)(int)
- (xs * alphaLineBuf0[xSrc0] +
- ((SplashCoord)1 - xs) * alphaLineBuf0[xSrc1]);
+ (xs * (int)alphaLineBuf0[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)alphaLineBuf0[xSrc1]);
alphaLineBuf1[x] = (Guchar)(int)
- (xs * alphaLineBuf1[xSrc0] +
- ((SplashCoord)1 - xs) * alphaLineBuf1[xSrc1]);
+ (xs * (int)alphaLineBuf1[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)alphaLineBuf1[xSrc1]);
}
}
+ // make gcc happy
+ pix[0] = pix[1] = pix[2] = 0;
+#if SPLASH_CMYK
+ pix[3] = 0;
+#endif
+
destPtr = dest->data;
destAlphaPtr = dest->alpha;
for (y = 0; y < scaledHeight; ++y) {
@@ -5612,14 +5754,14 @@ void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData,
xSrc1 = srcWidth - 1;
}
for (i = 0; i < nComps; ++i) {
- lineBuf1[x*nComps+i] =
- (Guchar)(int)(xs * lineBuf1[xSrc0*nComps+i] +
- ((SplashCoord)1 - xs) * lineBuf1[xSrc1*nComps+i]);
+ lineBuf1[x*nComps+i] = (Guchar)(int)
+ (xs * (int)lineBuf1[xSrc0*nComps+i] +
+ ((SplashCoord)1 - xs) * (int)lineBuf1[xSrc1*nComps+i]);
}
if (srcAlpha) {
- alphaLineBuf1[x] =
- (Guchar)(int)(xs * alphaLineBuf1[xSrc0] +
- ((SplashCoord)1 - xs) * alphaLineBuf1[xSrc1]);
+ alphaLineBuf1[x] = (Guchar)(int)
+ (xs * (int)alphaLineBuf1[xSrc0] +
+ ((SplashCoord)1 - xs) * (int)alphaLineBuf1[xSrc1]);
}
}
@@ -5630,8 +5772,9 @@ void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData,
for (x = 0; x < scaledWidth; ++x) {
for (i = 0; i < nComps; ++i) {
- pix[i] = (Guchar)(int)(ys * lineBuf0[x*nComps+i] +
- ((SplashCoord)1 - ys) * lineBuf1[x*nComps+i]);
+ pix[i] = (Guchar)(int)
+ (ys * (int)lineBuf0[x*nComps+i] +
+ ((SplashCoord)1 - ys) * (int)lineBuf1[x*nComps+i]);
}
// store the pixel
@@ -5661,8 +5804,8 @@ void Splash::scaleImageYuXuI(SplashImageSource src, void *srcData,
// process alpha
if (srcAlpha) {
*destAlphaPtr++ = (Guchar)(int)
- (ys * alphaLineBuf0[x] +
- ((SplashCoord)1 - ys) * alphaLineBuf1[x]);
+ (ys * (int)alphaLineBuf0[x] +
+ ((SplashCoord)1 - ys) * (int)alphaLineBuf1[x]);
}
}
}
@@ -5878,82 +6021,287 @@ SplashError Splash::composite(SplashBitmap *src, int xSrc, int ySrc,
int xDest, int yDest, int w, int h,
GBool noClip, GBool nonIsolated) {
SplashPipe pipe;
- int x0, x1, y0, y1, y, t;
+ Guchar *mono1Ptr, *lineBuf, *linePtr;
+ Guchar mono1Mask, b;
+ int x0, x1, x, y0, y1, y, t;
- if (src->mode != bitmap->mode) {
+ if (!(src->mode == bitmap->mode ||
+ (src->mode == splashModeMono8 && bitmap->mode == splashModeMono1) ||
+ (src->mode == splashModeRGB8 && bitmap->mode == splashModeBGR8))) {
return splashErrModeMismatch;
}
pipeInit(&pipe, NULL,
(Guchar)splashRound(state->fillAlpha * 255),
!noClip || src->alpha != NULL, nonIsolated);
- if (noClip) {
- if (src->alpha) {
- for (y = 0; y < h; ++y) {
- // this uses shape instead of alpha, which isn't technically
- // correct, but works out the same
- (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
- src->getAlphaPtr() +
- (ySrc + y) * src->getWidth() + xSrc,
- src->getDataPtr() + (ySrc + y) * src->getRowSize() +
- xSrc * bitmapComps);
+ if (src->mode == splashModeMono1) {
+ // in mono1 mode, pipeRun expects the source to be in mono8
+ // format, so we need to extract the source color values into
+ // scanBuf, expanding them from mono1 to mono8
+ if (noClip) {
+ if (src->alpha) {
+ for (y = 0; y < h; ++y) {
+ mono1Ptr = src->getDataPtr()
+ + (ySrc + y) * src->rowSize + (xSrc >> 3);
+ mono1Mask = 0x80 >> (xSrc & 7);
+ for (x = 0; x < w; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (mono1Mask << 7) | (mono1Mask >> 1);
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->getAlphaPtr() +
+ (ySrc + y) * src->getWidth() + xSrc,
+ scanBuf);
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ mono1Ptr = src->getDataPtr()
+ + (ySrc + y) * src->rowSize + (xSrc >> 3);
+ mono1Mask = 0x80 >> (xSrc & 7);
+ for (x = 0; x < w; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (mono1Mask << 7) | (mono1Mask >> 1);
+ }
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ NULL,
+ scanBuf);
+ }
}
} else {
- for (y = 0; y < h; ++y) {
- (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
- NULL,
- src->getDataPtr() + (ySrc + y) * src->getRowSize() +
- xSrc * bitmapComps);
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ mono1Ptr = src->getDataPtr()
+ + (ySrc + y - yDest) * src->rowSize
+ + ((xSrc + x0 - xDest) >> 3);
+ mono1Mask = 0x80 >> ((xSrc + x0 - xDest) & 7);
+ for (x = x0; x < x1; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (mono1Mask << 7) | (mono1Mask >> 1);
+ }
+ memcpy(scanBuf2 + x0,
+ src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ if (!state->clip->clipSpanBinary(scanBuf2, y, x0, x1 - 1,
+ state->strokeAdjust)) {
+ continue;
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf2 + x0,
+ scanBuf + x0);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ mono1Ptr = src->getDataPtr()
+ + (ySrc + y - yDest) * src->rowSize
+ + ((xSrc + x0 - xDest) >> 3);
+ mono1Mask = 0x80 >> ((xSrc + x0 - xDest) & 7);
+ for (x = x0; x < x1; ++x) {
+ scanBuf[x] = (*mono1Ptr & mono1Mask) ? 0xff : 0x00;
+ mono1Ptr += mono1Mask & 1;
+ mono1Mask = (mono1Mask << 7) | (mono1Mask >> 1);
+ }
+ memset(scanBuf2 + x0, 0xff, x1 - x0);
+ if (!state->clip->clipSpanBinary(scanBuf2, y, x0, x1 - 1,
+ state->strokeAdjust)) {
+ continue;
+ }
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf2 + x0,
+ scanBuf + x0);
+ }
+ }
}
}
- } else {
- x0 = xDest;
- if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
- x0 = t;
- }
- x1 = xDest + w;
- if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
- x1 = t;
- }
- y0 = yDest;
- if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
- y0 = t;
- }
- y1 = yDest + h;
- if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
- y1 = t;
- }
- if (x0 < x1 && y0 < y1) {
+
+ } else if (src->mode == splashModeBGR8) {
+ // in BGR8 mode, pipeRun expects the source to be in RGB8 format,
+ // so we need to swap bytes
+ lineBuf = (Guchar *)gmallocn(w, 3);
+ if (noClip) {
if (src->alpha) {
- for (y = y0; y < y1; ++y) {
- memcpy(scanBuf + x0,
- src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() +
- (xSrc + x0 - xDest),
- x1 - x0);
- if (!state->clip->clipSpanBinary(scanBuf, y, x0, x1 - 1,
- state->strokeAdjust)) {
- continue;
+ for (y = 0; y < h; ++y) {
+ memcpy(lineBuf,
+ src->getDataPtr() + (ySrc + y) * src->rowSize + xSrc * 3,
+ w * 3);
+ for (x = 0, linePtr = lineBuf; x < w; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
}
// this uses shape instead of alpha, which isn't technically
// correct, but works out the same
- (this->*pipe.run)(&pipe, x0, x1 - 1, y,
- scanBuf + x0,
- src->getDataPtr() +
- (ySrc + y - yDest) * src->getRowSize() +
- (xSrc + x0 - xDest) * bitmapComps);
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->getAlphaPtr() +
+ (ySrc + y) * src->getWidth() + xSrc,
+ lineBuf);
}
} else {
- for (y = y0; y < y1; ++y) {
- memset(scanBuf + x0, 0xff, x1 - x0);
- if (!state->clip->clipSpanBinary(scanBuf, y, x0, x1 - 1,
- state->strokeAdjust)) {
- continue;
+ for (y = 0; y < h; ++y) {
+ memcpy(lineBuf,
+ src->getDataPtr() + (ySrc + y) * src->rowSize + xSrc * 3,
+ w * 3);
+ for (x = 0, linePtr = lineBuf; x < w; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
}
(this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
- scanBuf + x0,
- src->getDataPtr() +
- (ySrc + y - yDest) * src->getRowSize() +
- (xSrc - xDest) * bitmapComps);
+ NULL, lineBuf);
+ }
+ }
+ } else {
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ memcpy(scanBuf + x0,
+ src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ memcpy(lineBuf,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * 3,
+ (x1 - x0) * 3);
+ for (x = 0, linePtr = lineBuf; x < x1 - x0; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
+ }
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf + x0, lineBuf);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ memset(scanBuf + x0, 0xff, x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ memcpy(lineBuf,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * 3,
+ (x1 - x0) * 3);
+ for (x = 0, linePtr = lineBuf; x < x1 - x0; ++x, linePtr += 3) {
+ b = linePtr[0];
+ linePtr[0] = linePtr[2];
+ linePtr[2] = b;
+ }
+ (this->*pipe.run)(&pipe, x0, x1 - 1, yDest + y,
+ scanBuf + x0,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ }
+ }
+ }
+ gfree(lineBuf);
+
+ } else { // src->mode not mono1 or BGR8
+ if (noClip) {
+ if (src->alpha) {
+ for (y = 0; y < h; ++y) {
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ src->getAlphaPtr() +
+ (ySrc + y) * src->getWidth() + xSrc,
+ src->getDataPtr() + (ySrc + y) * src->rowSize +
+ xSrc * bitmapComps);
+ }
+ } else {
+ for (y = 0; y < h; ++y) {
+ (this->*pipe.run)(&pipe, xDest, xDest + w - 1, yDest + y,
+ NULL,
+ src->getDataPtr() + (ySrc + y) * src->rowSize +
+ xSrc * bitmapComps);
+ }
+ }
+ } else {
+ x0 = xDest;
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > x0) {
+ x0 = t;
+ }
+ x1 = xDest + w;
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < x1) {
+ x1 = t;
+ }
+ y0 = yDest;
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > y0) {
+ y0 = t;
+ }
+ y1 = yDest + h;
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < y1) {
+ y1 = t;
+ }
+ if (x0 < x1 && y0 < y1) {
+ if (src->alpha) {
+ for (y = y0; y < y1; ++y) {
+ memcpy(scanBuf + x0,
+ src->getAlphaPtr() + (ySrc + y - yDest) * src->getWidth() +
+ (xSrc + x0 - xDest),
+ x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ // this uses shape instead of alpha, which isn't technically
+ // correct, but works out the same
+ (this->*pipe.run)(&pipe, x0, x1 - 1, y,
+ scanBuf + x0,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
+ } else {
+ for (y = y0; y < y1; ++y) {
+ memset(scanBuf + x0, 0xff, x1 - x0);
+ state->clip->clipSpan(scanBuf, y, x0, x1 - 1, state->strokeAdjust);
+ (this->*pipe.run)(&pipe, x0, x1 - 1, yDest + y,
+ scanBuf + x0,
+ src->getDataPtr() +
+ (ySrc + y - yDest) * src->rowSize +
+ (xSrc + x0 - xDest) * bitmapComps);
+ }
}
}
}
@@ -5980,13 +6328,21 @@ void Splash::compositeBackground(SplashColorPtr color) {
mask = 0x80;
for (x = 0; x < bitmap->width; ++x) {
alpha = *q++;
- alpha1 = 255 - alpha;
- c = (*p & mask) ? 0xff : 0x00;
- c = div255(alpha1 * color0 + alpha * c);
- if (c & 0x80) {
- *p |= mask;
- } else {
- *p &= ~mask;
+ if (alpha == 0) {
+ if (color0 & 0x80) {
+ *p |= mask;
+ } else {
+ *p &= ~mask;
+ }
+ } else if (alpha != 255) {
+ alpha1 = 255 - alpha;
+ c = (*p & mask) ? 0xff : 0x00;
+ c = div255(alpha1 * color0 + alpha * c);
+ if (c & 0x80) {
+ *p |= mask;
+ } else {
+ *p &= ~mask;
+ }
}
if (!(mask >>= 1)) {
mask = 0x80;
@@ -6002,8 +6358,12 @@ void Splash::compositeBackground(SplashColorPtr color) {
q = &bitmap->alpha[y * bitmap->width];
for (x = 0; x < bitmap->width; ++x) {
alpha = *q++;
- alpha1 = 255 - alpha;
- p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ if (alpha == 0) {
+ p[0] = color0;
+ } else if (alpha != 255) {
+ alpha1 = 255 - alpha;
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ }
++p;
}
}
@@ -6018,10 +6378,16 @@ void Splash::compositeBackground(SplashColorPtr color) {
q = &bitmap->alpha[y * bitmap->width];
for (x = 0; x < bitmap->width; ++x) {
alpha = *q++;
- alpha1 = 255 - alpha;
- p[0] = div255(alpha1 * color0 + alpha * p[0]);
- p[1] = div255(alpha1 * color1 + alpha * p[1]);
- p[2] = div255(alpha1 * color2 + alpha * p[2]);
+ if (alpha == 0) {
+ p[0] = color0;
+ p[1] = color1;
+ p[2] = color2;
+ } else if (alpha != 255) {
+ alpha1 = 255 - alpha;
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ p[1] = div255(alpha1 * color1 + alpha * p[1]);
+ p[2] = div255(alpha1 * color2 + alpha * p[2]);
+ }
p += 3;
}
}
@@ -6037,11 +6403,18 @@ void Splash::compositeBackground(SplashColorPtr color) {
q = &bitmap->alpha[y * bitmap->width];
for (x = 0; x < bitmap->width; ++x) {
alpha = *q++;
- alpha1 = 255 - alpha;
- p[0] = div255(alpha1 * color0 + alpha * p[0]);
- p[1] = div255(alpha1 * color1 + alpha * p[1]);
- p[2] = div255(alpha1 * color2 + alpha * p[2]);
- p[3] = div255(alpha1 * color3 + alpha * p[3]);
+ if (alpha == 0) {
+ p[0] = color0;
+ p[1] = color1;
+ p[2] = color2;
+ p[3] = color3;
+ } else if (alpha != 255) {
+ alpha1 = 255 - alpha;
+ p[0] = div255(alpha1 * color0 + alpha * p[0]);
+ p[1] = div255(alpha1 * color1 + alpha * p[1]);
+ p[2] = div255(alpha1 * color2 + alpha * p[2]);
+ p[3] = div255(alpha1 * color3 + alpha * p[3]);
+ }
p += 4;
}
}
@@ -6120,11 +6493,95 @@ SplashError Splash::blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
return splashOk;
}
+SplashError Splash::blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h) {
+ SplashColorPtr p, q;
+ Guchar *alpha0Ptr;
+ Guchar alpha0, aSrc;
+ int x, y, mask, srcMask;
+
+ if (bitmap->mode != dest->mode ||
+ !bitmap->alpha ||
+ !dest->alpha ||
+ !groupBackBitmap) {
+ return splashErrModeMismatch;
+ }
+
+ switch (bitmap->mode) {
+ case splashModeMono1:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + (xDest >> 3)];
+ mask = 0x80 >> (xDest & 7);
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + (xSrc >> 3)];
+ srcMask = 0x80 >> (xSrc & 7);
+ for (x = 0; x < w; ++x) {
+ if (*q & srcMask) {
+ *p |= mask;
+ } else {
+ *p &= ~mask;
+ }
+ if (!(mask >>= 1)) {
+ mask = 0x80;
+ ++p;
+ }
+ if (!(srcMask >>= 1)) {
+ srcMask = 0x80;
+ ++q;
+ }
+ }
+ }
+ break;
+ case splashModeMono8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + xSrc];
+ memcpy(p, q, w);
+ }
+ break;
+ case splashModeRGB8:
+ case splashModeBGR8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + 3 * xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + 3 * xSrc];
+ memcpy(p, q, 3 * w);
+ }
+ break;
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ for (y = 0; y < h; ++y) {
+ p = &dest->data[(yDest + y) * dest->rowSize + 4 * xDest];
+ q = &bitmap->data[(ySrc + y) * bitmap->rowSize + 4 * xSrc];
+ memcpy(p, q, 4 * w);
+ }
+ break;
+#endif
+ }
+
+ for (y = 0; y < h; ++y) {
+ p = &dest->alpha[(yDest + y) * dest->width + xDest];
+ q = &bitmap->alpha[(ySrc + y) * bitmap->width + xSrc];
+ alpha0Ptr = &groupBackBitmap->alpha[(groupBackY + ySrc + y)
+ * groupBackBitmap->width +
+ (groupBackX + xSrc)];
+ for (x = 0; x < w; ++x) {
+ alpha0 = *alpha0Ptr++;
+ aSrc = *q++;
+ *p++ = alpha0 + aSrc - div255(alpha0 * aSrc);
+ }
+ }
+
+ return splashOk;
+}
+
SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
- GBool flatten) {
+ int lineCap, int lineJoin,
+ GBool flatten) {
SplashPath *pathIn, *dashPath, *pathOut;
SplashCoord d, dx, dy, wdx, wdy, dxNext, dyNext, wdxNext, wdyNext;
SplashCoord crossprod, dotprod, miter, m;
+ SplashCoord angle, angleNext, dAngle, xc, yc;
+ SplashCoord dxJoin, dyJoin, dJoin, kappa;
+ SplashCoord cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
GBool first, last, closed;
int subpathStart0, subpathStart1, seg, i0, i1, j0, j1, k0, k1;
int left0, left1, left2, right0, right1, right2, join0, join1, join2;
@@ -6184,7 +6641,7 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
j1 = j0;
}
if (pathIn->flags[i1] & splashPathLast) {
- if (first && state->lineCap == splashLineCapRound) {
+ if (first && lineCap == splashLineCapRound) {
// special case: zero-length subpath with round line caps -->
// draw a circle
pathOut->moveTo(pathIn->pts[i0].x + (SplashCoord)0.5 * w,
@@ -6250,16 +6707,17 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
wdy = (SplashCoord)0.5 * w * dy;
// draw the start cap
- pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
if (i0 == subpathStart0) {
- firstPt = pathOut->length - 1;
+ firstPt = pathOut->length;
}
if (first && !closed) {
- switch (state->lineCap) {
+ switch (lineCap) {
case splashLineCapButt:
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
break;
case splashLineCapRound:
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
pathOut->curveTo(pathIn->pts[i0].x - wdy - bezierCircle * wdx,
pathIn->pts[i0].y + wdx - bezierCircle * wdy,
pathIn->pts[i0].x - wdx - bezierCircle * wdy,
@@ -6274,29 +6732,27 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
pathIn->pts[i0].y - wdx);
break;
case splashLineCapProjecting:
- pathOut->lineTo(pathIn->pts[i0].x - wdx - wdy,
+ pathOut->moveTo(pathIn->pts[i0].x - wdx - wdy,
pathIn->pts[i0].y + wdx - wdy);
pathOut->lineTo(pathIn->pts[i0].x - wdx + wdy,
pathIn->pts[i0].y - wdx - wdy);
- pathOut->lineTo(pathIn->pts[i0].x + wdy,
- pathIn->pts[i0].y - wdx);
break;
}
} else {
+ pathOut->moveTo(pathIn->pts[i0].x - wdy, pathIn->pts[i0].y + wdx);
pathOut->lineTo(pathIn->pts[i0].x + wdy, pathIn->pts[i0].y - wdx);
}
- // draw the left side of the segment rectangle
+ // draw the left side of the segment rectangle and the end cap
left2 = pathOut->length - 1;
- pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
-
- // draw the end cap
if (last && !closed) {
- switch (state->lineCap) {
+ switch (lineCap) {
case splashLineCapButt:
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
break;
case splashLineCapRound:
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
pathOut->curveTo(pathIn->pts[j0].x + wdy + bezierCircle * wdx,
pathIn->pts[j0].y - wdx + bezierCircle * wdy,
pathIn->pts[j0].x + wdx + bezierCircle * wdy,
@@ -6315,11 +6771,10 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
pathIn->pts[j0].y - wdx + wdy);
pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx,
pathIn->pts[j0].y + wdx + wdy);
- pathOut->lineTo(pathIn->pts[j0].x - wdy,
- pathIn->pts[j0].y + wdx);
break;
}
} else {
+ pathOut->lineTo(pathIn->pts[j0].x + wdy, pathIn->pts[j0].y - wdx);
pathOut->lineTo(pathIn->pts[j0].x - wdy, pathIn->pts[j0].y + wdx);
}
@@ -6327,7 +6782,7 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
// (NB: if stroke adjustment is enabled, the closepath operation MUST
// add a segment because this segment is used for a hint)
right2 = pathOut->length - 1;
- pathOut->close(state->strokeAdjust);
+ pathOut->close(state->strokeAdjust != splashStrokeAdjustOff);
// draw the join
join2 = pathOut->length;
@@ -6372,43 +6827,121 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
}
// round join
- if (state->lineJoin == splashLineJoinRound) {
- pathOut->moveTo(pathIn->pts[j0].x + (SplashCoord)0.5 * w,
- pathIn->pts[j0].y);
- pathOut->curveTo(pathIn->pts[j0].x + (SplashCoord)0.5 * w,
- pathIn->pts[j0].y + bezierCircle2 * w,
- pathIn->pts[j0].x + bezierCircle2 * w,
- pathIn->pts[j0].y + (SplashCoord)0.5 * w,
- pathIn->pts[j0].x,
- pathIn->pts[j0].y + (SplashCoord)0.5 * w);
- pathOut->curveTo(pathIn->pts[j0].x - bezierCircle2 * w,
- pathIn->pts[j0].y + (SplashCoord)0.5 * w,
- pathIn->pts[j0].x - (SplashCoord)0.5 * w,
- pathIn->pts[j0].y + bezierCircle2 * w,
- pathIn->pts[j0].x - (SplashCoord)0.5 * w,
- pathIn->pts[j0].y);
- pathOut->curveTo(pathIn->pts[j0].x - (SplashCoord)0.5 * w,
- pathIn->pts[j0].y - bezierCircle2 * w,
- pathIn->pts[j0].x - bezierCircle2 * w,
- pathIn->pts[j0].y - (SplashCoord)0.5 * w,
- pathIn->pts[j0].x,
- pathIn->pts[j0].y - (SplashCoord)0.5 * w);
- pathOut->curveTo(pathIn->pts[j0].x + bezierCircle2 * w,
- pathIn->pts[j0].y - (SplashCoord)0.5 * w,
- pathIn->pts[j0].x + (SplashCoord)0.5 * w,
- pathIn->pts[j0].y - bezierCircle2 * w,
- pathIn->pts[j0].x + (SplashCoord)0.5 * w,
- pathIn->pts[j0].y);
+ if (lineJoin == splashLineJoinRound) {
+ // join angle < 180
+ if (crossprod < 0) {
+ angle = atan2((double)dx, (double)-dy);
+ angleNext = atan2((double)dxNext, (double)-dyNext);
+ if (angle < angleNext) {
+ angle += 2 * M_PI;
+ }
+ dAngle = (angle - angleNext) / M_PI;
+ if (dAngle < 0.501) {
+ // span angle is <= 90 degrees -> draw a single arc
+ kappa = dAngle * bezierCircle * w;
+ cx1 = pathIn->pts[j0].x - wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y + wdx + kappa * dy;
+ cx2 = pathIn->pts[j0].x - wdyNext - kappa * dxNext;
+ cy2 = pathIn->pts[j0].y + wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
+ pathIn->pts[j0].y + wdxNext);
+ pathOut->curveTo(cx2, cy2, cx1, cy1,
+ pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ } else {
+ // span angle is > 90 degrees -> split into two arcs
+ dJoin = splashDist(-wdy, wdx, -wdyNext, wdxNext);
+ if (dJoin > 0) {
+ dxJoin = (-wdyNext + wdy) / dJoin;
+ dyJoin = (wdxNext - wdx) / dJoin;
+ xc = pathIn->pts[j0].x
+ + (SplashCoord)0.5 * w
+ * cos((double)((SplashCoord)0.5 * (angle + angleNext)));
+ yc = pathIn->pts[j0].y
+ + (SplashCoord)0.5 * w
+ * sin((double)((SplashCoord)0.5 * (angle + angleNext)));
+ kappa = dAngle * bezierCircle2 * w;
+ cx1 = pathIn->pts[j0].x - wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y + wdx + kappa * dy;
+ cx2 = xc - kappa * dxJoin;
+ cy2 = yc - kappa * dyJoin;
+ cx3 = xc + kappa * dxJoin;
+ cy3 = yc + kappa * dyJoin;
+ cx4 = pathIn->pts[j0].x - wdyNext - kappa * dxNext;
+ cy4 = pathIn->pts[j0].y + wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
+ pathIn->pts[j0].y + wdxNext);
+ pathOut->curveTo(cx4, cy4, cx3, cy3, xc, yc);
+ pathOut->curveTo(cx2, cy2, cx1, cy1,
+ pathIn->pts[j0].x - wdy,
+ pathIn->pts[j0].y + wdx);
+ }
+ }
+
+ // join angle >= 180
+ } else {
+ angle = atan2((double)-dx, (double)dy);
+ angleNext = atan2((double)-dxNext, (double)dyNext);
+ if (angleNext < angle) {
+ angleNext += 2 * M_PI;
+ }
+ dAngle = (angleNext - angle) / M_PI;
+ if (dAngle < 0.501) {
+ // span angle is <= 90 degrees -> draw a single arc
+ kappa = dAngle * bezierCircle * w;
+ cx1 = pathIn->pts[j0].x + wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y - wdx + kappa * dy;
+ cx2 = pathIn->pts[j0].x + wdyNext - kappa * dxNext;
+ cy2 = pathIn->pts[j0].y - wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
+ pathIn->pts[j0].y - wdx);
+ pathOut->curveTo(cx1, cy1, cx2, cy2,
+ pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
+ } else {
+ // span angle is > 90 degrees -> split into two arcs
+ dJoin = splashDist(wdy, -wdx, wdyNext, -wdxNext);
+ if (dJoin > 0) {
+ dxJoin = (wdyNext - wdy) / dJoin;
+ dyJoin = (-wdxNext + wdx) / dJoin;
+ xc = pathIn->pts[j0].x
+ + (SplashCoord)0.5 * w
+ * cos((double)((SplashCoord)0.5 * (angle + angleNext)));
+ yc = pathIn->pts[j0].y
+ + (SplashCoord)0.5 * w
+ * sin((double)((SplashCoord)0.5 * (angle + angleNext)));
+ kappa = dAngle * bezierCircle2 * w;
+ cx1 = pathIn->pts[j0].x + wdy + kappa * dx;
+ cy1 = pathIn->pts[j0].y - wdx + kappa * dy;
+ cx2 = xc - kappa * dxJoin;
+ cy2 = yc - kappa * dyJoin;
+ cx3 = xc + kappa * dxJoin;
+ cy3 = yc + kappa * dyJoin;
+ cx4 = pathIn->pts[j0].x + wdyNext - kappa * dxNext;
+ cy4 = pathIn->pts[j0].y - wdxNext - kappa * dyNext;
+ pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
+ pathOut->lineTo(pathIn->pts[j0].x + wdy,
+ pathIn->pts[j0].y - wdx);
+ pathOut->curveTo(cx1, cy1, cx2, cy2, xc, yc);
+ pathOut->curveTo(cx3, cy3, cx4, cy4,
+ pathIn->pts[j0].x + wdyNext,
+ pathIn->pts[j0].y - wdxNext);
+ }
+ }
+ }
} else {
pathOut->moveTo(pathIn->pts[j0].x, pathIn->pts[j0].y);
- // angle < 180
+ // join angle < 180
if (crossprod < 0) {
pathOut->lineTo(pathIn->pts[j0].x - wdyNext,
pathIn->pts[j0].y + wdxNext);
// miter join inside limit
- if (state->lineJoin == splashLineJoinMiter &&
+ if (lineJoin == splashLineJoinMiter &&
splashSqrt(miter) <= state->miterLimit) {
pathOut->lineTo(pathIn->pts[j0].x - wdy + wdx * m,
pathIn->pts[j0].y + wdx + wdy * m);
@@ -6420,12 +6953,12 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
pathIn->pts[j0].y + wdx);
}
- // angle >= 180
+ // join angle >= 180
} else {
pathOut->lineTo(pathIn->pts[j0].x + wdy,
pathIn->pts[j0].y - wdx);
// miter join inside limit
- if (state->lineJoin == splashLineJoinMiter &&
+ if (lineJoin == splashLineJoinMiter &&
splashSqrt(miter) <= state->miterLimit) {
pathOut->lineTo(pathIn->pts[j0].x + wdy + wdx * m,
pathIn->pts[j0].y - wdx + wdy * m);
@@ -6443,36 +6976,106 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
}
// add stroke adjustment hints
- if (state->strokeAdjust) {
- if (seg == 0 && !closed) {
- if (state->lineCap == splashLineCapButt) {
+ if (state->strokeAdjust != splashStrokeAdjustOff) {
+
+ // subpath with one segment
+ if (seg == 0 && last) {
+ switch (lineCap) {
+ case splashLineCapButt:
pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
- firstPt, firstPt + 1);
- if (last) {
- pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
- left2 + 1, left2 + 2);
- }
- } else if (state->lineCap == splashLineCapProjecting) {
- if (last) {
- pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 2,
- firstPt + 1, firstPt + 2);
- pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 2,
- left2 + 2, left2 + 3);
- } else {
- pathOut->addStrokeAdjustHint(firstPt + 1, left2 + 1,
- firstPt + 1, firstPt + 2);
+ firstPt, pathOut->length - 1);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(firstPt, left2 + 1,
+ firstPt, pathOut->length - 1, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
+ pathOut->addStrokeAdjustHint(left2, right2,
+ firstPt, pathOut->length - 1);
+ } else {
+
+ // start of subpath
+ if (seg == 1) {
+
+ // start cap
+ if (!closed) {
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ firstPt, firstPt + 1);
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ right1 + 1, right1 + 1);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ firstPt, firstPt + 1, gTrue);
+ pathOut->addStrokeAdjustHint(firstPt, left1 + 1,
+ right1 + 1, right1 + 1, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
}
+
+ // first segment
+ pathOut->addStrokeAdjustHint(left1, right1, firstPt, left2);
+ pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1);
}
- }
- if (seg >= 1) {
- if (seg >= 2) {
+
+ // middle of subpath
+ if (seg > 1) {
pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
pathOut->addStrokeAdjustHint(left1, right1, join0, left2);
- } else {
- pathOut->addStrokeAdjustHint(left1, right1, firstPt, left2);
+ pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1);
+ }
+
+ // end of subpath
+ if (last) {
+
+ if (closed) {
+ // first segment
+ pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
+ left2 + 1, right2);
+ pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
+ join2, pathOut->length - 1);
+
+ // last segment
+ pathOut->addStrokeAdjustHint(left2, right2,
+ left1 + 1, right1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ join1, pathOut->length - 1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ leftFirst - 1, leftFirst);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ rightFirst + 1, rightFirst + 1);
+
+ } else {
+
+ // last segment
+ pathOut->addStrokeAdjustHint(left2, right2,
+ left1 + 1, right1);
+ pathOut->addStrokeAdjustHint(left2, right2,
+ join1, pathOut->length - 1);
+
+ // end cap
+ switch (lineCap) {
+ case splashLineCapButt:
+ pathOut->addStrokeAdjustHint(left2 - 1, left2 + 1,
+ left2 + 1, left2 + 2);
+ break;
+ case splashLineCapProjecting:
+ pathOut->addStrokeAdjustHint(left2 - 1, left2 + 1,
+ left2 + 1, left2 + 2, gTrue);
+ break;
+ case splashLineCapRound:
+ break;
+ }
+ }
}
- pathOut->addStrokeAdjustHint(left1, right1, right2 + 1, right2 + 1);
}
+
left0 = left1;
left1 = left2;
right0 = right1;
@@ -6483,34 +7086,6 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
leftFirst = left2;
rightFirst = right2;
}
- if (last) {
- if (seg >= 2) {
- pathOut->addStrokeAdjustHint(left1, right1, left0 + 1, right0);
- pathOut->addStrokeAdjustHint(left1, right1,
- join0, pathOut->length - 1);
- } else {
- pathOut->addStrokeAdjustHint(left1, right1,
- firstPt, pathOut->length - 1);
- }
- if (closed) {
- pathOut->addStrokeAdjustHint(left1, right1, firstPt, leftFirst);
- pathOut->addStrokeAdjustHint(left1, right1,
- rightFirst + 1, rightFirst + 1);
- pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
- left1 + 1, right1);
- pathOut->addStrokeAdjustHint(leftFirst, rightFirst,
- join1, pathOut->length - 1);
- }
- if (!closed && seg > 0) {
- if (state->lineCap == splashLineCapButt) {
- pathOut->addStrokeAdjustHint(left1 - 1, left1 + 1,
- left1 + 1, left1 + 2);
- } else if (state->lineCap == splashLineCapProjecting) {
- pathOut->addStrokeAdjustHint(left1 - 1, left1 + 2,
- left1 + 2, left1 + 3);
- }
- }
- }
}
i0 = j0;
@@ -6525,6 +7100,29 @@ SplashPath *Splash::makeStrokePath(SplashPath *path, SplashCoord w,
return pathOut;
}
+SplashClipResult Splash::limitRectToClipRect(int *xMin, int *yMin,
+ int *xMax, int *yMax) {
+ int t;
+
+ if ((t = state->clip->getXMinI(state->strokeAdjust)) > *xMin) {
+ *xMin = t;
+ }
+ if ((t = state->clip->getXMaxI(state->strokeAdjust) + 1) < *xMax) {
+ *xMax = t;
+ }
+ if ((t = state->clip->getYMinI(state->strokeAdjust)) > *yMin) {
+ *yMin = t;
+ }
+ if ((t = state->clip->getYMaxI(state->strokeAdjust) + 1) < *yMax) {
+ *yMax = t;
+ }
+ if (*xMin >= *xMax || *yMin >= *yMax) {
+ return splashClipAllOutside;
+ }
+ return state->clip->testRect(*xMin, *yMin, *xMax - 1, *yMax - 1,
+ state->strokeAdjust);
+}
+
void Splash::dumpPath(SplashPath *path) {
int i;
@@ -6536,6 +7134,15 @@ void Splash::dumpPath(SplashPath *path) {
(path->flags[i] & splashPathClosed) ? " closed" : "",
(path->flags[i] & splashPathCurve) ? " curve" : "");
}
+ if (path->hintsLength == 0) {
+ printf(" no hints\n");
+ } else {
+ for (i = 0; i < path->hintsLength; ++i) {
+ printf(" hint %3d: ctrl0=%d ctrl1=%d pts=%d..%d\n",
+ i, path->hints[i].ctrl0, path->hints[i].ctrl1,
+ path->hints[i].firstPt, path->hints[i].lastPt);
+ }
+ }
}
void Splash::dumpXPath(SplashXPath *path) {
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/Splash.h b/Build/source/libs/xpdf/xpdf-src/splash/Splash.h
index 7409e0cd6b4..3ca57982e15 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/Splash.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/Splash.h
@@ -95,7 +95,7 @@ public:
SplashCoord *getLineDash();
int getLineDashLength();
SplashCoord getLineDashPhase();
- GBool getStrokeAdjust();
+ SplashStrokeAdjustMode getStrokeAdjust();
SplashClip *getClip();
SplashBitmap *getSoftMask();
GBool getInNonIsolatedGroup();
@@ -118,7 +118,7 @@ public:
// the <lineDash> array will be copied
void setLineDash(SplashCoord *lineDash, int lineDashLength,
SplashCoord lineDashPhase);
- void setStrokeAdjust(GBool strokeAdjust);
+ void setStrokeAdjust(SplashStrokeAdjustMode strokeAdjust);
// NB: uses transformed coordinates.
void clipResetToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1);
@@ -133,6 +133,7 @@ public:
GBool nonIsolated, GBool knockout);
void setTransfer(Guchar *red, Guchar *green, Guchar *blue, Guchar *gray);
void setOverprintMask(Guint overprintMask);
+ void setEnablePathSimplification(GBool en);
//----- state save/restore
@@ -150,9 +151,6 @@ public:
// Fill a path using the current fill pattern.
SplashError fill(SplashPath *path, GBool eo);
- // Fill a path, XORing with the current fill pattern.
- SplashError xorFill(SplashPath *path, GBool eo);
-
// Draw a character, using the current fill pattern.
SplashError fillChar(SplashCoord x, SplashCoord y, int c, SplashFont *font);
@@ -213,6 +211,12 @@ public:
SplashError blitTransparent(SplashBitmap *src, int xSrc, int ySrc,
int xDest, int yDest, int w, int h);
+ // Copy a rectangular region from the bitmap belonging to this
+ // Splash object to <dest>. The alpha values are corrected for a
+ // non-isolated group.
+ SplashError blitCorrectedAlpha(SplashBitmap *dest, int xSrc, int ySrc,
+ int xDest, int yDest, int w, int h);
+
//----- misc
// Construct a path for a stroke, given the path to be stroked and
@@ -220,8 +224,15 @@ public:
// the current state. If <flatten> is true, this function will
// first flatten the path and handle the linedash.
SplashPath *makeStrokePath(SplashPath *path, SplashCoord w,
+ int lineCap, int lineJoin,
GBool flatten = gTrue);
+ // Reduce the size of a rectangle as much as possible by moving any
+ // edges that are completely outside the clip region. Returns the
+ // clipping status of the resulting rectangle.
+ SplashClipResult limitRectToClipRect(int *xMin, int *yMin,
+ int *xMax, int *yMax);
+
// Return the associated bitmap.
SplashBitmap *getBitmap() { return bitmap; }
@@ -296,7 +307,8 @@ private:
void updateModY(int y);
void strokeNarrow(SplashPath *path);
void drawStrokeSpan(SplashPipe *pipe, int x0, int x1, int y, GBool noClip);
- void strokeWide(SplashPath *path, SplashCoord w);
+ void strokeWide(SplashPath *path, SplashCoord w,
+ int lineCap, int lineJoin);
SplashPath *flattenPath(SplashPath *path, SplashCoord *matrix,
SplashCoord flatness);
void flattenCurve(SplashCoord x0, SplashCoord y0,
@@ -407,10 +419,10 @@ private:
int bitmapComps;
SplashState *state;
Guchar *scanBuf;
+ Guchar *scanBuf2;
SplashBitmap // for transparency groups, this is the bitmap
*groupBackBitmap; // containing the alpha0/color0 values
int groupBackX, groupBackY; // offset within groupBackBitmap
- Guchar aaGamma[256];
SplashCoord minLineWidth;
int modXMin, modYMin, modXMax, modYMax;
SplashClipResult opClipRes;
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashBitmap.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashBitmap.cc
index 3606a917beb..32ecc3fdd03 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashBitmap.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashBitmap.cc
@@ -15,6 +15,7 @@
#include <stdio.h>
#include <limits.h>
#include "gmem.h"
+#include "gmempp.h"
#include "SplashErrorCodes.h"
#include "SplashBitmap.h"
@@ -154,7 +155,18 @@ SplashError SplashBitmap::writePNMFile(FILE *f) {
#if SPLASH_CMYK
case splashModeCMYK8:
- // PNM doesn't support CMYK
+ fprintf(f, "P7\n");
+ fprintf(f, "WIDTH %d\n", width);
+ fprintf(f, "HEIGHT %d\n", height);
+ fprintf(f, "DEPTH 4\n");
+ fprintf(f, "MAXVAL 255\n");
+ fprintf(f, "TUPLTYPE CMYK\n");
+ fprintf(f, "ENDHDR\n");
+ row = data;
+ for (y = 0; y < height; ++y) {
+ fwrite(row, 1, 4 * width, f);
+ row += rowSize;
+ }
break;
#endif
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc
index 6865c574f4e..bf7b802cf0d 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.cc
@@ -15,6 +15,7 @@
#include <stdlib.h>
#include <string.h>
#include "gmem.h"
+#include "gmempp.h"
#include "SplashErrorCodes.h"
#include "SplashPath.h"
#include "SplashXPath.h"
@@ -52,6 +53,8 @@ SplashClip::SplashClip(int hardXMinA, int hardYMinA,
eo = NULL;
scanners = NULL;
length = size = 0;
+ isSimple = gTrue;
+ prev = NULL;
if ((w = hardXMax + 1) <= 0) {
w = 1;
}
@@ -59,7 +62,7 @@ SplashClip::SplashClip(int hardXMinA, int hardYMinA,
}
SplashClip::SplashClip(SplashClip *clip) {
- int w, i;
+ int w;
hardXMin = clip->hardXMin;
hardYMin = clip->hardYMin;
@@ -75,17 +78,12 @@ SplashClip::SplashClip(SplashClip *clip) {
yMaxI = clip->yMaxI;
intBoundsValid = clip->intBoundsValid;
intBoundsStrokeAdjust = clip->intBoundsStrokeAdjust;
- length = clip->length;
- size = clip->size;
- paths = (SplashXPath **)gmallocn(size, sizeof(SplashXPath *));
- eo = (Guchar *)gmallocn(size, sizeof(Guchar));
- scanners = (SplashXPathScanner **)
- gmallocn(size, sizeof(SplashXPathScanner *));
- for (i = 0; i < length; ++i) {
- paths[i] = clip->paths[i]->copy();
- eo[i] = clip->eo[i];
- scanners[i] = new SplashXPathScanner(paths[i], eo[i], yMinI, yMaxI);
- }
+ paths = NULL;
+ eo = NULL;
+ scanners = NULL;
+ length = size = 0;
+ isSimple = clip->isSimple;
+ prev = clip;
if ((w = splashCeil(xMax)) <= 0) {
w = 1;
}
@@ -96,8 +94,8 @@ SplashClip::~SplashClip() {
int i;
for (i = 0; i < length; ++i) {
- delete paths[i];
delete scanners[i];
+ delete paths[i];
}
gfree(paths);
gfree(eo);
@@ -136,6 +134,8 @@ void SplashClip::resetToRect(SplashCoord x0, SplashCoord y0,
eo = NULL;
scanners = NULL;
length = size = 0;
+ isSimple = gTrue;
+ prev = NULL;
if (x0 < x1) {
xMin = x0;
@@ -202,11 +202,15 @@ SplashError SplashClip::clipToRect(SplashCoord x0, SplashCoord y0,
}
SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
- SplashCoord flatness, GBool eoA) {
+ SplashCoord flatness, GBool eoA,
+ GBool enablePathSimplification,
+ SplashStrokeAdjustMode strokeAdjust) {
SplashXPath *xPath;
SplashCoord t;
- xPath = new SplashXPath(path, matrix, flatness, gTrue);
+ xPath = new SplashXPath(path, matrix, flatness, gTrue,
+ enablePathSimplification,
+ strokeAdjust);
// check for an empty path
if (xPath->length == 0) {
@@ -218,33 +222,8 @@ SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
}
// check for a rectangle
- if (xPath->length == 4 &&
- xPath->segs[0].y0 == xPath->segs[0].y1 &&
- xPath->segs[1].x0 == xPath->segs[1].x1 &&
- xPath->segs[2].x0 == xPath->segs[2].x1 &&
- xPath->segs[3].y0 == xPath->segs[3].y1) {
- clipToRect(xPath->segs[1].x0, xPath->segs[0].y0,
- xPath->segs[2].x0, xPath->segs[3].y0);
- delete xPath;
- return splashOk;
- }
- if (xPath->length == 4 &&
- xPath->segs[0].x0 == xPath->segs[0].x1 &&
- xPath->segs[1].y0 == xPath->segs[1].y1 &&
- xPath->segs[2].x0 == xPath->segs[2].x1 &&
- xPath->segs[3].y0 == xPath->segs[3].y1) {
- clipToRect(xPath->segs[0].x0, xPath->segs[1].y0,
- xPath->segs[2].x0, xPath->segs[3].y0);
- delete xPath;
- return splashOk;
- }
- if (xPath->length == 4 &&
- xPath->segs[0].x0 == xPath->segs[0].x1 &&
- xPath->segs[1].x0 == xPath->segs[1].x1 &&
- xPath->segs[2].y0 == xPath->segs[2].y1 &&
- xPath->segs[3].y0 == xPath->segs[3].y1) {
- clipToRect(xPath->segs[0].x0, xPath->segs[2].y0,
- xPath->segs[1].x0, xPath->segs[3].y0);
+ if (xPath->isRect) {
+ clipToRect(xPath->rectX0, xPath->rectY0, xPath->rectX1, xPath->rectY1);
delete xPath;
return splashOk;
}
@@ -268,13 +247,14 @@ SplashError SplashClip::clipToPath(SplashPath *path, SplashCoord *matrix,
scanners[length] = new SplashXPathScanner(xPath, eoA, splashFloor(yMin),
splashCeil(yMax) - 1);
++length;
+ isSimple = gFalse;
return splashOk;
}
SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
int rectXMax, int rectYMax,
- GBool strokeAdjust) {
+ SplashStrokeAdjustMode strokeAdjust) {
// In general, this function tests the rectangle:
// x = [rectXMin, rectXMax + 1) (note: coords are ints)
// y = [rectYMin, rectYMax + 1)
@@ -282,7 +262,7 @@ SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
// x = [xMin, xMax) (note: coords are fp)
// y = [yMin, yMax)
- if (strokeAdjust && length == 0) {
+ if (strokeAdjust != splashStrokeAdjustOff && isSimple) {
// special case for stroke adjustment with a simple clipping
// rectangle -- the clipping region is:
// x = [xMinI, xMaxI + 1)
@@ -313,7 +293,7 @@ SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
(SplashCoord)rectYMin >= yMax) {
return splashClipAllOutside;
}
- if (length == 0 &&
+ if (isSimple &&
(SplashCoord)rectXMin >= xMin &&
(SplashCoord)(rectXMax + 1) <= xMax &&
(SplashCoord)rectYMin >= yMin &&
@@ -325,9 +305,10 @@ SplashClipResult SplashClip::testRect(int rectXMin, int rectYMin,
}
void SplashClip::clipSpan(Guchar *line, int y, int x0, int x1,
- GBool strokeAdjust) {
+ SplashStrokeAdjustMode strokeAdjust) {
+ SplashClip *clip;
SplashCoord d;
- int x0a, x1a, x, i;
+ int x0a, x1a, x0b, x1b, x, i;
updateIntBounds(strokeAdjust);
@@ -360,7 +341,7 @@ void SplashClip::clipSpan(Guchar *line, int y, int x0, int x1,
//--- clip to the floating point rectangle
// (if stroke adjustment is disabled)
- if (!strokeAdjust) {
+ if (strokeAdjust == splashStrokeAdjustOff) {
// clip left edge (xMin)
if (x0a == xMinI) {
@@ -391,22 +372,31 @@ void SplashClip::clipSpan(Guchar *line, int y, int x0, int x1,
}
}
- if (length == 0) {
+ if (isSimple) {
return;
}
//--- clip to the paths
- for (i = 0; i < length; ++i) {
- scanners[i]->getSpan(buf, y, x0a, x1a);
- for (x = x0a; x <= x1a; ++x) {
- line[x] = mul255(line[x], buf[x]);
+ for (clip = this; clip; clip = clip->prev) {
+ for (i = 0; i < clip->length; ++i) {
+ clip->scanners[i]->getSpan(buf, y, x0a, x1a, &x0b, &x1b);
+ if (x0a < x0b) {
+ memset(line + x0a, 0, x0b - x0a);
+ }
+ for (x = x0b; x <= x1b; ++x) {
+ line[x] = mul255(line[x], buf[x]);
+ }
+ if (x1b < x1a) {
+ memset(line + x1b + 1, 0, x1a - x1b);
+ }
}
}
}
GBool SplashClip::clipSpanBinary(Guchar *line, int y, int x0, int x1,
- GBool strokeAdjust) {
+ SplashStrokeAdjustMode strokeAdjust) {
+ SplashClip *clip;
int x0a, x1a, x0b, x1b, x, i;
Guchar any;
@@ -438,7 +428,7 @@ GBool SplashClip::clipSpanBinary(Guchar *line, int y, int x0, int x1,
return gFalse;
}
- if (length == 0) {
+ if (isSimple) {
for (x = x0a; x <= x1a; ++x) {
if (line[x]) {
return gTrue;
@@ -448,52 +438,63 @@ GBool SplashClip::clipSpanBinary(Guchar *line, int y, int x0, int x1,
}
any = 0;
- for (i = 0; i < length; ++i) {
- scanners[i]->getSpanBinary(buf, y, x0a, x1a);
- for (x0b = x0a; x0b <= x1a && !buf[x0b]; ++x0b) ;
- if (x0a < x0b) {
- memset(line + x0a, 0, x0b - x0a);
- }
- for (x1b = x1a; x1b >= x0b && !buf[x1b]; --x1b) ;
- if (x1b < x1a) {
- memset(line + x1b + 1, 0, x1a - x1b);
- }
- for (x = x0b; x <= x1b; ++x) {
- line[x] &= buf[x];
- any |= line[x];
+ for (clip = this; clip; clip = clip->prev) {
+ for (i = 0; i < clip->length; ++i) {
+ clip->scanners[i]->getSpanBinary(buf, y, x0a, x1a, &x0b, &x1b);
+ if (x0a < x0b) {
+ memset(line + x0a, 0, x0b - x0a);
+ }
+ for (x = x0b; x <= x1b; ++x) {
+ line[x] &= buf[x];
+ any |= line[x];
+ }
+ if (x1b < x1a) {
+ memset(line + x1b + 1, 0, x1a - x1b);
+ }
}
}
return any != 0;
}
-int SplashClip::getXMinI(GBool strokeAdjust) {
+int SplashClip::getXMinI(SplashStrokeAdjustMode strokeAdjust) {
updateIntBounds(strokeAdjust);
return xMinI;
}
-int SplashClip::getXMaxI(GBool strokeAdjust) {
+int SplashClip::getXMaxI(SplashStrokeAdjustMode strokeAdjust) {
updateIntBounds(strokeAdjust);
return xMaxI;
}
-int SplashClip::getYMinI(GBool strokeAdjust) {
+int SplashClip::getYMinI(SplashStrokeAdjustMode strokeAdjust) {
updateIntBounds(strokeAdjust);
return yMinI;
}
-int SplashClip::getYMaxI(GBool strokeAdjust) {
+int SplashClip::getYMaxI(SplashStrokeAdjustMode strokeAdjust) {
updateIntBounds(strokeAdjust);
return yMaxI;
}
-void SplashClip::updateIntBounds(GBool strokeAdjust) {
+int SplashClip::getNumPaths() {
+ SplashClip *clip;
+ int n;
+
+ n = 0;
+ for (clip = this; clip; clip = clip->prev) {
+ n += clip->length;
+ }
+ return n;
+}
+
+void SplashClip::updateIntBounds(SplashStrokeAdjustMode strokeAdjust) {
if (intBoundsValid && strokeAdjust == intBoundsStrokeAdjust) {
return;
}
- if (strokeAdjust && length == 0) {
- splashStrokeAdjust(xMin, xMax, &xMinI, &xMaxI);
- splashStrokeAdjust(yMin, yMax, &yMinI, &yMaxI);
+ if (strokeAdjust != splashStrokeAdjustOff && isSimple) {
+ splashStrokeAdjust(xMin, xMax, &xMinI, &xMaxI, strokeAdjust);
+ splashStrokeAdjust(yMin, yMax, &yMinI, &yMaxI, strokeAdjust);
} else {
xMinI = splashFloor(xMin);
yMinI = splashFloor(yMin);
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.h
index 42986222976..fb86ed8fd72 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashClip.h
@@ -57,7 +57,9 @@ public:
// Interesect the clip with <path>.
SplashError clipToPath(SplashPath *path, SplashCoord *matrix,
- SplashCoord flatness, GBool eoA);
+ SplashCoord flatness, GBool eoA,
+ GBool enablePathSimplification,
+ SplashStrokeAdjustMode strokeAdjust);
// Tests a rectangle against the clipping region. Returns one of:
// - splashClipAllInside if the entire rectangle is inside the
@@ -70,18 +72,18 @@ public:
// outside the clipping region
SplashClipResult testRect(int rectXMin, int rectYMin,
int rectXMax, int rectYMax,
- GBool strokeAdjust);
+ SplashStrokeAdjustMode strokeAdjust);
// Clip a scan line. Modifies line[] by multiplying with clipping
// shape values for one scan line: ([x0, x1], y).
void clipSpan(Guchar *line, int y, int x0, int x1,
- GBool strokeAdjust);
+ SplashStrokeAdjustMode strokeAdjust);
// Like clipSpan(), but uses the values 0 and 255 only.
// Returns true if there are any non-zero values in the result
// (i.e., returns false if the entire line is clipped out).
GBool clipSpanBinary(Guchar *line, int y, int x0, int x1,
- GBool strokeAdjust);
+ SplashStrokeAdjustMode strokeAdjust);
// Get the rectangle part of the clip region.
SplashCoord getXMin() { return xMin; }
@@ -90,19 +92,19 @@ public:
SplashCoord getYMax() { return yMax; }
// Get the rectangle part of the clip region, in integer coordinates.
- int getXMinI(GBool strokeAdjust);
- int getXMaxI(GBool strokeAdjust);
- int getYMinI(GBool strokeAdjust);
- int getYMaxI(GBool strokeAdjust);
+ int getXMinI(SplashStrokeAdjustMode strokeAdjust);
+ int getXMaxI(SplashStrokeAdjustMode strokeAdjust);
+ int getYMinI(SplashStrokeAdjustMode strokeAdjust);
+ int getYMaxI(SplashStrokeAdjustMode strokeAdjust);
// Get the number of arbitrary paths used by the clip region.
- int getNumPaths() { return length; }
+ int getNumPaths();
private:
SplashClip(SplashClip *clip);
void grow(int nPaths);
- void updateIntBounds(GBool strokeAdjust);
+ void updateIntBounds(SplashStrokeAdjustMode strokeAdjust);
int hardXMin, hardYMin, // coordinates cannot fall outside of
hardXMax, hardYMax; // [hardXMin, hardXMax), [hardYMin, hardYMax)
@@ -120,6 +122,8 @@ private:
Guchar *eo;
SplashXPathScanner **scanners;
int length, size;
+ GBool isSimple;
+ SplashClip *prev;
Guchar *buf;
};
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.cc
index 6fc6b946b65..884092b050c 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.cc
@@ -8,7 +8,7 @@
#include <aconf.h>
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
@@ -19,6 +19,7 @@
#include FT_SIZES_H
#include FT_GLYPH_H
#include "gmem.h"
+#include "gmempp.h"
#include "SplashMath.h"
#include "SplashGlyphBitmap.h"
#include "SplashPath.h"
@@ -66,6 +67,10 @@ SplashFTFont::SplashFTFont(SplashFTFontFile *fontFileA, SplashCoord *matA,
// if the textMat values are too small, FreeType's fixed point
// arithmetic doesn't work so well
textScale = splashDist(0, 0, textMat[2], textMat[3]) / size;
+ // avoid problems with singular (or close-to-singular) matrices
+ if (textScale < 0.00001) {
+ textScale = 0.00001;
+ }
div = face->bbox.xMax > 20000 ? 65536 : 1;
@@ -220,7 +225,7 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
SplashFTFontFile *ff;
FT_Vector offset;
FT_GlyphSlot slot;
- FT_UInt gid;
+ int gid;
FT_Int32 flags;
int rowSize;
Guchar *p, *q;
@@ -235,11 +240,11 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
slot = ff->face->glyph;
if (ff->codeToGID && c < ff->codeToGIDLen) {
- gid = (FT_UInt)ff->codeToGID[c];
+ gid = ff->codeToGID[c];
} else {
- gid = (FT_UInt)c;
+ gid = c;
}
- if (ff->trueType && gid < 0) {
+ if (ff->fontType == splashFontTrueType && gid < 0) {
// skip the TrueType notdef glyph
return gFalse;
}
@@ -258,13 +263,19 @@ GBool SplashFTFont::makeGlyph(int c, int xFrac, int yFrac,
flags = FT_LOAD_NO_BITMAP;
if (ff->engine->flags & splashFTNoHinting) {
flags |= FT_LOAD_NO_HINTING;
- } else if (ff->useLightHinting) {
+ } else if (ff->fontType == splashFontType1) {
flags |= FT_LOAD_TARGET_LIGHT;
} else {
flags |= FT_LOAD_NO_AUTOHINT;
}
- if (FT_Load_Glyph(ff->face, gid, flags)) {
- return gFalse;
+ if (FT_Load_Glyph(ff->face, (FT_UInt)gid, flags)) {
+ // fonts with broken hinting instructions can cause errors here;
+ // try again with no hinting (this is probably only relevant for
+ // TrueType fonts)
+ flags = FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING;
+ if (FT_Load_Glyph(ff->face, (FT_UInt)gid, flags)) {
+ return gFalse;
+ }
}
if (FT_Render_Glyph(slot, aa ? FT_RENDER_MODE_NORMAL
: FT_RENDER_MODE_MONO)) {
@@ -321,7 +332,7 @@ SplashPath *SplashFTFont::getGlyphPath(int c) {
SplashFTFontFile *ff;
SplashFTFontPath path;
FT_GlyphSlot slot;
- FT_UInt gid;
+ int gid;
FT_Glyph glyph;
ff = (SplashFTFontFile *)fontFile;
@@ -331,14 +342,20 @@ SplashPath *SplashFTFont::getGlyphPath(int c) {
if (ff->codeToGID && c < ff->codeToGIDLen) {
gid = ff->codeToGID[c];
} else {
- gid = (FT_UInt)c;
+ gid = c;
}
- if (ff->trueType && gid < 0) {
+ if (ff->fontType == splashFontTrueType && gid < 0) {
// skip the TrueType notdef glyph
return NULL;
}
- if (FT_Load_Glyph(ff->face, gid, FT_LOAD_NO_BITMAP)) {
- return NULL;
+ if (FT_Load_Glyph(ff->face, (FT_UInt)gid, FT_LOAD_NO_BITMAP)) {
+ // fonts with broken hinting instructions can cause errors here;
+ // try again with no hinting (this is probably only relevant for
+ // TrueType fonts)
+ if (FT_Load_Glyph(ff->face, (FT_UInt)gid,
+ FT_LOAD_NO_BITMAP | FT_LOAD_NO_HINTING)) {
+ return NULL;
+ }
}
if (FT_Get_Glyph(slot, &glyph)) {
return NULL;
@@ -429,4 +446,4 @@ static int glyphPathCubicTo(const FT_Vector *ctrl1, const FT_Vector *ctrl2,
return 0;
}
-#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#endif // HAVE_FREETYPE_H
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.h
index 560b74c3bfe..ac08b007747 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFont.h
@@ -11,7 +11,7 @@
#include <aconf.h>
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
@@ -55,6 +55,6 @@ private:
SplashCoord textScale;
};
-#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#endif // HAVE_FREETYPE_H
#endif
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.cc
index 3ba033c9db3..33939541051 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.cc
@@ -8,7 +8,7 @@
#include <aconf.h>
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
@@ -19,6 +19,7 @@
# include <unistd.h>
#endif
#include "gmem.h"
+#include "gmempp.h"
#include "GString.h"
#include "gfile.h"
#include "FoFiTrueType.h"
@@ -87,13 +88,13 @@ SplashFontFile *SplashFTFontEngine::loadType1Font(SplashFontFileID *idA,
GBool deleteFile,
#endif
const char **enc) {
- return SplashFTFontFile::loadType1Font(this, idA,
+ return SplashFTFontFile::loadType1Font(this, idA, splashFontType1,
#if LOAD_FONTS_FROM_MEM
fontBuf,
#else
fileName, deleteFile,
#endif
- enc, gTrue);
+ enc);
}
SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA,
@@ -104,13 +105,13 @@ SplashFontFile *SplashFTFontEngine::loadType1CFont(SplashFontFileID *idA,
GBool deleteFile,
#endif
const char **enc) {
- return SplashFTFontFile::loadType1Font(this, idA,
+ return SplashFTFontFile::loadType1Font(this, idA, splashFontType1C,
#if LOAD_FONTS_FROM_MEM
fontBuf,
#else
fileName, deleteFile,
#endif
- enc, gFalse);
+ enc);
}
SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
@@ -143,8 +144,8 @@ SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
fontBuf2 = new GString();
ff->convertToType1(NULL, enc, gFalse, &gstringWrite, fontBuf2);
delete ff;
- ret = SplashFTFontFile::loadType1Font(this, idA, fontBuf2, enc,
- gFalse);
+ ret = SplashFTFontFile::loadType1Font(this, idA, splashFontType1,
+ fontBuf2, enc);
if (ret) {
delete fontBuf;
} else {
@@ -159,8 +160,9 @@ SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
ff->convertToType1(NULL, enc, gFalse, &fileWrite, tmpFile);
delete ff;
fclose(tmpFile);
- ret = SplashFTFontFile::loadType1Font(this, idA, tmpFileName->getCString(),
- gTrue, enc, gFalse);
+ ret = SplashFTFontFile::loadType1Font(this, idA, splashFontType1,
+ tmpFileName->getCString(),
+ gTrue, enc);
if (ret) {
if (deleteFile) {
unlink(fileName);
@@ -172,32 +174,36 @@ SplashFontFile *SplashFTFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
#endif
} else {
delete ff;
- ret = SplashFTFontFile::loadType1Font(this, idA,
+ ret = SplashFTFontFile::loadType1Font(this, idA, splashFontOpenTypeT1C,
#if LOAD_FONTS_FROM_MEM
fontBuf,
#else
fileName, deleteFile,
#endif
- enc, gFalse);
+ enc);
}
return ret;
}
SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA,
#if LOAD_FONTS_FROM_MEM
- GString *fontBuf
+ GString *fontBuf,
#else
char *fileName,
- GBool deleteFile
+ GBool deleteFile,
#endif
- ) {
+ int *codeToGID,
+ int codeToGIDLen) {
FoFiType1C *ff;
int *cidToGIDMap;
int nCIDs;
SplashFontFile *ret;
// check for a CFF font
- if (useCIDs) {
+ if (codeToGID) {
+ cidToGIDMap = NULL;
+ nCIDs = 0;
+ } else if (useCIDs) {
cidToGIDMap = NULL;
nCIDs = 0;
#if LOAD_FONTS_FROM_MEM
@@ -212,13 +218,14 @@ SplashFontFile *SplashFTFontEngine::loadCIDFont(SplashFontFileID *idA,
cidToGIDMap = NULL;
nCIDs = 0;
}
- ret = SplashFTFontFile::loadCIDFont(this, idA,
+ ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontCID,
#if LOAD_FONTS_FROM_MEM
fontBuf,
#else
fileName, deleteFile,
#endif
- cidToGIDMap, nCIDs);
+ codeToGID ? codeToGID : cidToGIDMap,
+ codeToGID ? codeToGIDLen : nCIDs);
if (!ret) {
gfree(cidToGIDMap);
}
@@ -266,8 +273,8 @@ SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
if (!useCIDs) {
cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
}
- ret = SplashFTFontFile::loadCIDFont(this, idA, fontBuf2,
- cidToGIDMap, nCIDs);
+ ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF,
+ fontBuf2, cidToGIDMap, nCIDs);
if (ret) {
delete fontBuf;
} else {
@@ -284,7 +291,7 @@ SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
if (!useCIDs) {
cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
}
- ret = SplashFTFontFile::loadCIDFont(this, idA,
+ ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF,
tmpFileName->getCString(), gTrue,
cidToGIDMap, nCIDs);
if (ret) {
@@ -300,7 +307,7 @@ SplashFontFile *SplashFTFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
if (!codeToGID && !useCIDs && ff->isOpenTypeCFF()) {
cidToGIDMap = ff->getCIDToGIDMap(&nCIDs);
}
- ret = SplashFTFontFile::loadCIDFont(this, idA,
+ ret = SplashFTFontFile::loadCIDFont(this, idA, splashFontOpenTypeCFF,
#if LOAD_FONTS_FROM_MEM
fontBuf,
#else
@@ -356,7 +363,7 @@ SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
fclose(tmpFile);
#endif
delete ff;
- ret = SplashFTFontFile::loadTrueTypeFont(this, idA,
+ ret = SplashFTFontFile::loadTrueTypeFont(this, idA, splashFontTrueType,
#if LOAD_FONTS_FROM_MEM
fontBuf2,
#else
@@ -382,4 +389,4 @@ SplashFontFile *SplashFTFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
return ret;
}
-#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#endif // HAVE_FREETYPE_H
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.h
index 37e882007fe..24db3c6cdba 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontEngine.h
@@ -11,7 +11,7 @@
#include <aconf.h>
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
@@ -60,11 +60,11 @@ public:
const char **enc);
SplashFontFile *loadCIDFont(SplashFontFileID *idA,
#if LOAD_FONTS_FROM_MEM
- GString *fontBuf
+ GString *fontBuf,
#else
- char *fileName, GBool deleteFile
+ char *fileName, GBool deleteFile,
#endif
- );
+ int *codeToGID, int codeToGIDLen);
SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA,
#if LOAD_FONTS_FROM_MEM
GString *fontBuf,
@@ -94,6 +94,6 @@ private:
friend class SplashFTFont;
};
-#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#endif // HAVE_FREETYPE_H
#endif
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.cc
index 5b01fcf490c..b5fd02af4a0 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.cc
@@ -8,13 +8,14 @@
#include <aconf.h>
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma implementation
#endif
#include "gmem.h"
+#include "gmempp.h"
#include "GString.h"
#include "SplashFTFontEngine.h"
#include "SplashFTFont.h"
@@ -26,14 +27,14 @@
SplashFontFile *SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA,
#else
char *fileNameA,
GBool deleteFileA,
#endif
- const char **encA,
- GBool useLightHintingA) {
+ const char **encA) {
FT_Face faceA;
int *codeToGIDA;
const char *name;
@@ -55,18 +56,18 @@ SplashFontFile *SplashFTFontFile::loadType1Font(SplashFTFontEngine *engineA,
}
}
- return new SplashFTFontFile(engineA, idA,
+ return new SplashFTFontFile(engineA, idA, fontTypeA,
#if LOAD_FONTS_FROM_MEM
fontBufA,
#else
fileNameA, deleteFileA,
#endif
- faceA, codeToGIDA, 256,
- gFalse, useLightHintingA);
+ faceA, codeToGIDA, 256);
}
SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA,
#else
@@ -86,18 +87,18 @@ SplashFontFile *SplashFTFontFile::loadCIDFont(SplashFTFontEngine *engineA,
return NULL;
}
- return new SplashFTFontFile(engineA, idA,
+ return new SplashFTFontFile(engineA, idA, fontTypeA,
#if LOAD_FONTS_FROM_MEM
fontBufA,
#else
fileNameA, deleteFileA,
#endif
- faceA, codeToGIDA, codeToGIDLenA,
- gFalse, gFalse);
+ faceA, codeToGIDA, codeToGIDLenA);
}
SplashFontFile *SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA,
#else
@@ -118,38 +119,35 @@ SplashFontFile *SplashFTFontFile::loadTrueTypeFont(SplashFTFontEngine *engineA,
return NULL;
}
- return new SplashFTFontFile(engineA, idA,
+ return new SplashFTFontFile(engineA, idA, fontTypeA,
#if LOAD_FONTS_FROM_MEM
fontBufA,
#else
fileNameA, deleteFileA,
#endif
- faceA, codeToGIDA, codeToGIDLenA,
- gTrue, gFalse);
+ faceA, codeToGIDA, codeToGIDLenA);
}
SplashFTFontFile::SplashFTFontFile(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA,
#else
char *fileNameA, GBool deleteFileA,
#endif
FT_Face faceA,
- int *codeToGIDA, int codeToGIDLenA,
- GBool trueTypeA, GBool useLightHintingA):
+ int *codeToGIDA, int codeToGIDLenA):
#if LOAD_FONTS_FROM_MEM
- SplashFontFile(idA, fontBufA)
+ SplashFontFile(idA, fontTypeA, fontBufA)
#else
- SplashFontFile(idA, fileNameA, deleteFileA)
+ SplashFontFile(idA, fontTypeA, fileNameA, deleteFileA)
#endif
{
engine = engineA;
face = faceA;
codeToGID = codeToGIDA;
codeToGIDLen = codeToGIDLenA;
- trueType = trueTypeA;
- useLightHinting = useLightHintingA;
}
SplashFTFontFile::~SplashFTFontFile() {
@@ -170,4 +168,4 @@ SplashFont *SplashFTFontFile::makeFont(SplashCoord *mat,
return font;
}
-#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#endif // HAVE_FREETYPE_H
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.h
index 21fa517a594..3a6b9b7aa43 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFTFontFile.h
@@ -11,7 +11,7 @@
#include <aconf.h>
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
#ifdef USE_GCC_PRAGMAS
#pragma interface
@@ -33,15 +33,16 @@ public:
static SplashFontFile *loadType1Font(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA,
#else
char *fileNameA, GBool deleteFileA,
#endif
- const char **encA,
- GBool useLightHintingA);
+ const char **encA);
static SplashFontFile *loadCIDFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA,
#else
@@ -50,6 +51,7 @@ public:
int *codeToGIDA, int codeToGIDLenA);
static SplashFontFile *loadTrueTypeFont(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA,
#else
@@ -71,25 +73,23 @@ private:
SplashFTFontFile(SplashFTFontEngine *engineA,
SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA,
#else
char *fileNameA, GBool deleteFileA,
#endif
FT_Face faceA,
- int *codeToGIDA, int codeToGIDLenA,
- GBool trueTypeA, GBool useLightHintingA);
+ int *codeToGIDA, int codeToGIDLenA);
SplashFTFontEngine *engine;
FT_Face face;
int *codeToGID;
int codeToGIDLen;
- GBool trueType;
- GBool useLightHinting;
friend class SplashFTFont;
};
-#endif // HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#endif // HAVE_FREETYPE_H
#endif
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFont.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashFont.cc
index 37a320050be..add34311756 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFont.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFont.cc
@@ -14,6 +14,7 @@
#include <string.h>
#include "gmem.h"
+#include "gmempp.h"
#include "SplashMath.h"
#include "SplashGlyphBitmap.h"
#include "SplashFontFile.h"
@@ -66,6 +67,12 @@ void SplashFont::initCache() {
// deal with rounding errors
glyphW = xMax - xMin + 3;
glyphH = yMax - yMin + 3;
+ if (glyphW > 1000 || glyphH > 1000) {
+ // if the glyphs are too large, don't cache them -- setting the
+ // cache bitmap size to something tiny will cause getGlyph() to
+ // fall back to the uncached case
+ glyphW = glyphH = 1;
+ }
if (aa) {
glyphSize = glyphW * glyphH;
} else {
@@ -76,7 +83,7 @@ void SplashFont::initCache() {
cacheAssoc = splashFontCacheAssoc;
for (cacheSets = splashFontCacheMaxSets;
cacheSets > 1 &&
- cacheSets * cacheAssoc * glyphSize > splashFontCacheSize;
+ glyphSize > splashFontCacheSize / (cacheSets * cacheAssoc);
cacheSets >>= 1) ;
cache = (Guchar *)gmallocn(cacheSets * cacheAssoc, glyphSize);
cacheTags = (SplashFontCacheTag *)gmallocn(cacheSets * cacheAssoc,
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFont.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashFont.h
index 3d151122a14..2bb96545867 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFont.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFont.h
@@ -17,6 +17,7 @@
#include "gtypes.h"
#include "SplashTypes.h"
+#include "SplashMath.h"
struct SplashGlyphBitmap;
struct SplashFontCacheTag;
@@ -54,10 +55,14 @@ public:
GBool matches(SplashFontFile *fontFileA, SplashCoord *matA,
SplashCoord *textMatA) {
return fontFileA == fontFile &&
- matA[0] == mat[0] && matA[1] == mat[1] &&
- matA[2] == mat[2] && matA[3] == mat[3] &&
- textMatA[0] == textMat[0] && textMatA[1] == textMat[1] &&
- textMatA[2] == textMat[2] && textMatA[3] == textMat[3];
+ splashAbs(matA[0] - mat[0]) < 0.0001 &&
+ splashAbs(matA[1] - mat[1]) < 0.0001 &&
+ splashAbs(matA[2] - mat[2]) < 0.0001 &&
+ splashAbs(matA[3] - mat[3]) < 0.0001 &&
+ splashAbs(textMatA[0] - textMat[0]) < 0.0001 &&
+ splashAbs(textMatA[1] - textMat[1]) < 0.0001 &&
+ splashAbs(textMatA[2] - textMat[2]) < 0.0001 &&
+ splashAbs(textMatA[3] - textMat[3]) < 0.0001;
}
// Get a glyph - this does a cache lookup first, and if not found,
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.cc
index d4673a7a7c4..e435fe80c9a 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.cc
@@ -18,6 +18,7 @@
# include <unistd.h>
#endif
#include "gmem.h"
+#include "gmempp.h"
#include "GString.h"
#include "SplashMath.h"
#include "SplashFTFontEngine.h"
@@ -37,7 +38,7 @@ extern "C" int unlink(char *filename);
//------------------------------------------------------------------------
SplashFontEngine::SplashFontEngine(
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
GBool enableFreeType,
Guint freeTypeFlags,
#endif
@@ -48,7 +49,7 @@ SplashFontEngine::SplashFontEngine(
fontCache[i] = NULL;
}
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
if (enableFreeType) {
ftEngine = SplashFTFontEngine::init(aa, freeTypeFlags);
} else {
@@ -66,7 +67,7 @@ SplashFontEngine::~SplashFontEngine() {
}
}
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
if (ftEngine) {
delete ftEngine;
}
@@ -99,7 +100,7 @@ SplashFontFile *SplashFontEngine::loadType1Font(SplashFontFileID *idA,
SplashFontFile *fontFile;
fontFile = NULL;
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadType1Font(idA,
#if LOAD_FONTS_FROM_MEM
@@ -135,7 +136,7 @@ SplashFontFile *SplashFontEngine::loadType1CFont(SplashFontFileID *idA,
SplashFontFile *fontFile;
fontFile = NULL;
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadType1CFont(idA,
#if LOAD_FONTS_FROM_MEM
@@ -171,7 +172,7 @@ SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
SplashFontFile *fontFile;
fontFile = NULL;
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadOpenTypeT1CFont(idA,
#if LOAD_FONTS_FROM_MEM
@@ -198,24 +199,25 @@ SplashFontFile *SplashFontEngine::loadOpenTypeT1CFont(SplashFontFileID *idA,
SplashFontFile *SplashFontEngine::loadCIDFont(SplashFontFileID *idA,
#if LOAD_FONTS_FROM_MEM
- GString *fontBuf
+ GString *fontBuf,
#else
char *fileName,
- GBool deleteFile
+ GBool deleteFile,
#endif
- ) {
+ int *codeToGID,
+ int codeToGIDLen) {
SplashFontFile *fontFile;
fontFile = NULL;
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadCIDFont(idA,
#if LOAD_FONTS_FROM_MEM
- fontBuf
+ fontBuf,
#else
- fileName, deleteFile
+ fileName, deleteFile,
#endif
- );
+ codeToGID, codeToGIDLen);
}
#endif
@@ -244,7 +246,7 @@ SplashFontFile *SplashFontEngine::loadOpenTypeCFFFont(SplashFontFileID *idA,
SplashFontFile *fontFile;
fontFile = NULL;
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadOpenTypeCFFFont(idA,
#if LOAD_FONTS_FROM_MEM
@@ -283,7 +285,7 @@ SplashFontFile *SplashFontEngine::loadTrueTypeFont(SplashFontFileID *idA,
SplashFontFile *fontFile;
fontFile = NULL;
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
if (!fontFile && ftEngine) {
fontFile = ftEngine->loadTrueTypeFont(idA,
#if LOAD_FONTS_FROM_MEM
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.h
index 43eb6d3eb48..ac2558ee52d 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontEngine.h
@@ -29,7 +29,7 @@ class SplashFont;
#define splashFontCacheSize 16
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
#define splashFTNoHinting (1 << 0)
#endif
@@ -42,7 +42,7 @@ public:
// Create a font engine.
SplashFontEngine(
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
GBool enableFreeType,
Guint freeTypeFlags,
#endif
@@ -78,11 +78,11 @@ public:
const char **enc);
SplashFontFile *loadCIDFont(SplashFontFileID *idA,
#if LOAD_FONTS_FROM_MEM
- GString *fontBuf
+ GString *fontBuf,
#else
- char *fileName, GBool deleteFile
+ char *fileName, GBool deleteFile,
#endif
- );
+ int *codeToGID, int codeToGIDLen);
SplashFontFile *loadOpenTypeCFFFont(SplashFontFileID *idA,
#if LOAD_FONTS_FROM_MEM
GString *fontBuf,
@@ -115,7 +115,7 @@ private:
SplashFont *fontCache[splashFontCacheSize];
-#if HAVE_FREETYPE_FREETYPE_H || HAVE_FREETYPE_H
+#if HAVE_FREETYPE_H
SplashFTFontEngine *ftEngine;
#endif
};
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.cc
index d0e36a20c49..2d260e38239 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.cc
@@ -16,6 +16,7 @@
#ifndef _WIN32
# include <unistd.h>
#endif
+#include "gmempp.h"
#include "GString.h"
#include "SplashFontFile.h"
#include "SplashFontFileID.h"
@@ -31,6 +32,7 @@ extern "C" int unlink(char *filename);
//------------------------------------------------------------------------
SplashFontFile::SplashFontFile(SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA
#else
@@ -38,6 +40,7 @@ SplashFontFile::SplashFontFile(SplashFontFileID *idA,
#endif
) {
id = idA;
+ fontType = fontTypeA;
#if LOAD_FONTS_FROM_MEM
fontBuf = fontBufA;
#else
@@ -60,11 +63,22 @@ SplashFontFile::~SplashFontFile() {
}
void SplashFontFile::incRefCnt() {
+#if MULTITHREADED
+ gAtomicIncrement(&refCnt);
+#else
++refCnt;
+#endif
}
void SplashFontFile::decRefCnt() {
- if (!--refCnt) {
+ GBool done;
+
+#if MULTITHREADED
+ done = gAtomicDecrement(&refCnt) == 0;
+#else
+ done = --refCnt == 0;
+#endif
+ if (done) {
delete this;
}
}
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.h
index 5f53eced170..133e6ab87dc 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFile.h
@@ -18,12 +18,30 @@
#include "gtypes.h"
#include "SplashTypes.h"
+#if MULTITHREADED
+#include "GMutex.h"
+#endif
+
class GString;
class SplashFontEngine;
class SplashFont;
class SplashFontFileID;
//------------------------------------------------------------------------
+// SplashFontType
+//------------------------------------------------------------------------
+
+enum SplashFontType {
+ splashFontType1, // GfxFontType.fontType1
+ splashFontType1C, // GfxFontType.fontType1C
+ splashFontOpenTypeT1C, // GfxFontType.fontType1COT
+ splashFontCID, // GfxFontType.fontCIDType0/fontCIDType0C
+ splashFontOpenTypeCFF, // GfxFontType.fontCIDType0COT
+ splashFontTrueType // GfxFontType.fontTrueType/fontTrueTypeOT/
+ // fontCIDType2/fontCIDType2OT
+};
+
+//------------------------------------------------------------------------
// SplashFontFile
//------------------------------------------------------------------------
@@ -49,6 +67,7 @@ public:
protected:
SplashFontFile(SplashFontFileID *idA,
+ SplashFontType fontTypeA,
#if LOAD_FONTS_FROM_MEM
GString *fontBufA
#else
@@ -57,13 +76,18 @@ protected:
);
SplashFontFileID *id;
+ SplashFontType fontType;
#if LOAD_FONTS_FROM_MEM
GString *fontBuf;
#else
GString *fileName;
GBool deleteFile;
#endif
+#if MULTITHREADED
+ GAtomicCounter refCnt;
+#else
int refCnt;
+#endif
friend class SplashFontEngine;
};
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFileID.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFileID.cc
index 327484788f6..27f52031d50 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFileID.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashFontFileID.cc
@@ -12,6 +12,7 @@
#pragma implementation
#endif
+#include "gmempp.h"
#include "SplashFontFileID.h"
//------------------------------------------------------------------------
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashMath.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashMath.h
index 4b7ab1fdfbd..b57c8fdacc5 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashMath.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashMath.h
@@ -12,9 +12,13 @@
#include <aconf.h>
#if USE_FIXEDPONT
-#include "FixedPoint.h"
+# include "FixedPoint.h"
#else
-#include <math.h>
+# include <math.h>
+# if (defined(__GNUC__) && defined(__SSE2__)) || \
+ (defined(_WIN32) && (_M_IX86_FP == 2 || defined(_M_X64)))
+# include <emmintrin.h>
+# endif
#endif
#include "SplashTypes.h"
@@ -26,14 +30,40 @@ static inline SplashCoord splashAbs(SplashCoord x) {
#endif
}
+// floor() and (int)() are implemented separately, which results
+// in changing the FPCW multiple times - so we optimize it with
+// some inline assembly or SSE intrinsics.
static inline int splashFloor(SplashCoord x) {
#if USE_FIXEDPOINT
+
+ //--- fixed point
+
return FixedPoint::floor(x);
-#else
-#if __GNUC__ && __i386__
- // floor() and (int)() are implemented separately, which results
- // in changing the FPCW multiple times - so we optimize it with
- // some inline assembly
+
+#elif (defined(__GNUC__) && defined(__SSE2__)) || \
+ (defined(_WIN32) && (_M_IX86_FP == 2 || defined(_M_X64)))
+
+ //--- SSE2 intrinsics
+ // NB: 64-bit x86 guarantees availability of SSE2.
+
+ __m128d m1, m2;
+ __m128i m3;
+ int s, i;
+
+ m1 = _mm_set_sd(x); // m1 = x
+ i = _mm_cvttsd_si32(m1); // i = trunc(x)
+ m2 = _mm_cvtsi32_sd(m1, i); // m2 = (double)trunc(x)
+ m1 = _mm_sub_sd(m1, m2); // m1 = x - trunc(x)
+ m3 = _mm_castpd_si128(m1); // m3 = m1 (as 64-bit int)
+ m3 = _mm_srli_epi64(m3, 63); // m3 = m3 >> 63
+ s = _mm_cvtsi128_si32(m3); // s = m3 = sign bit of x - trunc(x)
+ return i - s; // trunc(x) - sign bit
+
+#elif defined(__GNUC__) && defined(__i386__) && !defined(__APPLE__)
+
+ //--- x87 inline assembly (gcc/clang)
+ // (this code fails on OSX for reasons I don't understand)
+
Gushort oldCW, newCW, t;
int result;
@@ -48,10 +78,11 @@ static inline int splashFloor(SplashCoord x) {
: "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
: "t" (x));
return result;
+
#elif defined(_WIN32) && defined(_M_IX86)
- // floor() and (int)() are implemented separately, which results
- // in changing the FPCW multiple times - so we optimize it with
- // some inline assembly
+
+ //--- x87 inline assembly (VC)
+
Gushort oldCW, newCW;
int result;
@@ -65,20 +96,50 @@ static inline int splashFloor(SplashCoord x) {
__asm fistp DWORD PTR result
__asm fldcw WORD PTR oldCW
return result;
+
#else
+
+ //--- all others
+
return (int)floor(x);
-#endif
+
#endif
}
+// ceil() and (int)() are implemented separately, which results
+// in changing the FPCW multiple times - so we optimize it with
+// some inline assembly or SSE intrinsics.
static inline int splashCeil(SplashCoord x) {
#if USE_FIXEDPOINT
+
+ //--- fixed point
+
return FixedPoint::ceil(x);
-#else
-#if __GNUC__ && __i386__
- // ceil() and (int)() are implemented separately, which results
- // in changing the FPCW multiple times - so we optimize it with
- // some inline assembly
+
+#elif (defined(__GNUC__) && defined(__SSE2__)) || \
+ (defined(_WIN32) && (_M_IX86_FP == 2 || defined(_M_X64)))
+
+ //--- SSE2 intrinsics
+ // NB: 64-bit x86 guarantees availability of SSE2.
+
+ __m128d m1, m2;
+ __m128i m3;
+ int s, i;
+
+ m1 = _mm_set_sd(x); // m1 = x
+ i = _mm_cvttsd_si32(m1); // i = trunc(x)
+ m2 = _mm_cvtsi32_sd(m1, i); // m2 = (double)trunc(x)
+ m2 = _mm_sub_sd(m2, m1); // m2 = trunc(x) - x
+ m3 = _mm_castpd_si128(m2); // m3 = m2 (as 64-bit int)
+ m3 = _mm_srli_epi64(m3, 63); // m3 = m3 >> 63
+ s = _mm_cvtsi128_si32(m3); // s = m3 = sign bit of x - trunc(x)
+ return i + s; // trunc(x) + sign bit
+
+#elif defined(__GNUC__) && defined(__i386__) && !defined(__APPLE__)
+
+ //--- x87 inline assembly (gcc/clang)
+ // (this code fails on OSX for reasons I don't understand)
+
Gushort oldCW, newCW, t;
int result;
@@ -93,7 +154,11 @@ static inline int splashCeil(SplashCoord x) {
: "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
: "t" (x));
return result;
+
#elif defined(_WIN32) && defined(_M_IX86)
+
+ //--- x87 inline assembly (VC)
+
// ceil() and (int)() are implemented separately, which results
// in changing the FPCW multiple times - so we optimize it with
// some inline assembly
@@ -110,56 +175,29 @@ static inline int splashCeil(SplashCoord x) {
__asm fistp DWORD PTR result
__asm fldcw WORD PTR oldCW
return result;
+
#else
+
+ //--- all others
+
return (int)ceil(x);
-#endif
+
#endif
}
static inline int splashRound(SplashCoord x) {
#if USE_FIXEDPOINT
+
+ //--- fixed point
+
return FixedPoint::round(x);
+
#else
-#if __GNUC__ && __i386__
- // this could use round-to-nearest mode and avoid the "+0.5",
- // but that produces slightly different results (because i+0.5
- // sometimes rounds up and sometimes down using the even rule)
- Gushort oldCW, newCW, t;
- int result;
- x += 0.5;
- __asm__ volatile("fnstcw %0\n"
- "movw %0, %3\n"
- "andw $0xf3ff, %3\n"
- "orw $0x0400, %3\n"
- "movw %3, %1\n" // round down
- "fldcw %1\n"
- "fistl %2\n"
- "fldcw %0\n"
- : "=m" (oldCW), "=m" (newCW), "=m" (result), "=r" (t)
- : "t" (x));
- return result;
-#elif defined(_WIN32) && defined(_M_IX86)
- // this could use round-to-nearest mode and avoid the "+0.5",
- // but that produces slightly different results (because i+0.5
- // sometimes rounds up and sometimes down using the even rule)
- Gushort oldCW, newCW;
- int result;
+ //--- all others
+
+ return splashFloor(x + 0.5);
- x += 0.5;
- __asm fld QWORD PTR x
- __asm fnstcw WORD PTR oldCW
- __asm mov ax, WORD PTR oldCW
- __asm and ax, 0xf3ff
- __asm or ax, 0x0400
- __asm mov WORD PTR newCW, ax // round down
- __asm fldcw WORD PTR newCW
- __asm fistp DWORD PTR result
- __asm fldcw WORD PTR oldCW
- return result;
-#else
- return (int)floor(x + 0.5);
-#endif
#endif
}
@@ -262,23 +300,53 @@ static inline GBool splashCheckDet(SplashCoord m11, SplashCoord m12,
// but
// xMin = 10.1 xMax = 11.3 (width = 1.2)
// --> xMinI = 10 xMaxI = 12 (width = 2)
+//
+// 4. Use a hybrid approach, choosing between two of the above
+// options, based on width. E.g., use #2 if width <= 4, and use #1
+// if width > 4.
+//
+// If w >= 0 and strokeAdjMode is splashStrokeAdjustCAD then a special
+// mode for projecting line caps is enabled, with w being the
+// transformed line width.
+
static inline void splashStrokeAdjust(SplashCoord xMin, SplashCoord xMax,
- int *xMinI, int *xMaxI) {
+ int *xMinI, int *xMaxI,
+ SplashStrokeAdjustMode strokeAdjMode,
+ SplashCoord w = -1) {
int x0, x1;
- // NB: enable exactly one of these.
+ // this will never be called with strokeAdjMode == splashStrokeAdjustOff
+ if (strokeAdjMode == splashStrokeAdjustCAD) {
+ x0 = splashRound(xMin);
+ if (w >= 0) {
+ x1 = splashRound(xMax - w) + splashRound(w);
+ } else {
+ x1 = x0 + splashRound(xMax - xMin);
+ }
+ } else {
+ // NB: enable exactly one of these.
#if 1 // 1. Round both edge coordinates.
- x0 = splashRound(xMin);
- x1 = splashRound(xMax);
+ x0 = splashRound(xMin);
+ x1 = splashRound(xMax);
#endif
#if 0 // 2. Round the min coordinate; add the ceiling of the width.
- x0 = splashRound(xMin);
- x1 = x0 + splashCeil(xMax - xMin);
+ x0 = splashRound(xMin);
+ x1 = x0 + splashCeil(xMax - xMin);
#endif
#if 0 // 3. Use floor on the min coord and ceiling on the max coord.
- x0 = splashFloor(xMin);
- x1 = splashCeil(xMax);
+ x0 = splashFloor(xMin);
+ x1 = splashCeil(xMax);
#endif
+#if 0 // 4. Hybrid.
+ SplashCoord w = xMax - xMin;
+ x0 = splashRound(xMin);
+ if (w > 4) {
+ x1 = splashRound(xMax);
+ } else {
+ x1 = x0 + splashRound(w);
+ }
+#endif
+ }
if (x1 == x0) {
++x1;
}
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashPath.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashPath.cc
index 4ee8be02809..8bf2575a083 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashPath.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashPath.cc
@@ -14,6 +14,7 @@
#include <string.h>
#include "gmem.h"
+#include "gmempp.h"
#include "SplashErrorCodes.h"
#include "SplashPath.h"
@@ -156,7 +157,8 @@ SplashError SplashPath::close(GBool force) {
}
void SplashPath::addStrokeAdjustHint(int ctrl0, int ctrl1,
- int firstPt, int lastPt) {
+ int firstPt, int lastPt,
+ GBool projectingCap) {
if (hintsLength == hintsSize) {
hintsSize = hintsLength ? 2 * hintsLength : 8;
hints = (SplashPathHint *)greallocn(hints, hintsSize,
@@ -166,6 +168,7 @@ void SplashPath::addStrokeAdjustHint(int ctrl0, int ctrl1,
hints[hintsLength].ctrl1 = ctrl1;
hints[hintsLength].firstPt = firstPt;
hints[hintsLength].lastPt = lastPt;
+ hints[hintsLength].projectingCap = projectingCap;
++hintsLength;
}
@@ -186,3 +189,25 @@ GBool SplashPath::getCurPt(SplashCoord *x, SplashCoord *y) {
*y = pts[length - 1].y;
return gTrue;
}
+
+GBool SplashPath::containsZeroLengthSubpaths() {
+ GBool zeroLength;
+ int i;
+
+ zeroLength = gTrue; // make gcc happy
+ for (i = 0; i < length; ++i) {
+ if (flags[i] & splashPathFirst) {
+ zeroLength = gTrue;
+ } else {
+ if (pts[i].x != pts[i-1].x || pts[i].y != pts[i-1].y) {
+ zeroLength = gFalse;
+ }
+ if (flags[i] & splashPathLast) {
+ if (zeroLength) {
+ return gTrue;
+ }
+ }
+ }
+ }
+ return gFalse;
+}
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashPath.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashPath.h
index a8715302042..b5732b8b408 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashPath.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashPath.h
@@ -49,6 +49,7 @@ struct SplashPathPoint {
struct SplashPathHint {
int ctrl0, ctrl1;
int firstPt, lastPt;
+ GBool projectingCap;
};
//------------------------------------------------------------------------
@@ -89,7 +90,10 @@ public:
// Add a stroke adjustment hint. The controlling segments are
// <ctrl0> and <ctrl1> (where segments are identified by their first
// point), and the points to be adjusted are <firstPt> .. <lastPt>.
- void addStrokeAdjustHint(int ctrl0, int ctrl1, int firstPt, int lastPt);
+ // <projectingCap> is true if the points are part of a projecting
+ // line cap.
+ void addStrokeAdjustHint(int ctrl0, int ctrl1, int firstPt, int lastPt,
+ GBool projectingCap = gFalse);
// Add (<dx>, <dy>) to every point on this path.
void offset(SplashCoord dx, SplashCoord dy);
@@ -102,6 +106,10 @@ public:
// Get the current point.
GBool getCurPt(SplashCoord *x, SplashCoord *y);
+ // Returns true if the path contains one or more zero length
+ // subpaths.
+ GBool containsZeroLengthSubpaths();
+
private:
SplashPath(SplashPath *path);
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashPattern.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashPattern.cc
index 6ca4fb274e8..55ae865111c 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashPattern.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashPattern.cc
@@ -12,6 +12,7 @@
#pragma implementation
#endif
+#include "gmempp.h"
#include "SplashMath.h"
#include "SplashScreen.h"
#include "SplashPattern.h"
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.cc
index 68a762f7f2a..41c852531f1 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.cc
@@ -18,6 +18,7 @@
#include <algorithm>
#endif
#include "gmem.h"
+#include "gmempp.h"
#include "SplashMath.h"
#include "SplashScreen.h"
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.h
index 4e9767be5f6..560e2759d82 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashScreen.h
@@ -21,6 +21,8 @@
// SplashScreen
//------------------------------------------------------------------------
+typedef Guchar *SplashScreenCursor;
+
class SplashScreen {
public:
@@ -39,6 +41,20 @@ public:
return value < mat[(yy << log2Size) + xx] ? 0 : 1;
}
+ // To do a series of tests with the same y value, call
+ // getTestCursor(y), and then call testWithCursor(cursor, x, value)
+ // for each x.
+ SplashScreenCursor getTestCursor(int y) {
+ int yy;
+ yy = y & sizeM1;
+ return &mat[yy << log2Size];
+ }
+
+ int testWithCursor(SplashScreenCursor cursor, int x, Guchar value) {
+ int xx = x & sizeM1;
+ return value >= cursor[xx];
+ }
+
// Returns true if value is above the white threshold or below the
// black threshold, i.e., if the corresponding halftone will be
// solid white or black.
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc
index 09c1949eb3d..17ac8d17a19 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashState.cc
@@ -14,6 +14,7 @@
#include <string.h>
#include "gmem.h"
+#include "gmempp.h"
#include "SplashPattern.h"
#include "SplashScreen.h"
#include "SplashClip.h"
@@ -55,7 +56,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
lineDash = NULL;
lineDashLength = 0;
lineDashPhase = 0;
- strokeAdjust = gFalse;
+ strokeAdjust = splashStrokeAdjustOff;
clip = new SplashClip(0, 0, width, height);
clipIsShared = gFalse;
softMask = NULL;
@@ -67,12 +68,15 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
rgbTransferG[i] = (Guchar)i;
rgbTransferB[i] = (Guchar)i;
grayTransfer[i] = (Guchar)i;
+#if SPLASH_CMYK
cmykTransferC[i] = (Guchar)i;
cmykTransferM[i] = (Guchar)i;
cmykTransferY[i] = (Guchar)i;
cmykTransferK[i] = (Guchar)i;
+#endif
}
overprintMask = 0xffffffff;
+ enablePathSimplification = gFalse;
next = NULL;
}
@@ -99,7 +103,7 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
lineDash = NULL;
lineDashLength = 0;
lineDashPhase = 0;
- strokeAdjust = gFalse;
+ strokeAdjust = splashStrokeAdjustOff;
clip = new SplashClip(0, 0, width, height);
clipIsShared = gFalse;
softMask = NULL;
@@ -111,12 +115,15 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
rgbTransferG[i] = (Guchar)i;
rgbTransferB[i] = (Guchar)i;
grayTransfer[i] = (Guchar)i;
+#if SPLASH_CMYK
cmykTransferC[i] = (Guchar)i;
cmykTransferM[i] = (Guchar)i;
cmykTransferY[i] = (Guchar)i;
cmykTransferK[i] = (Guchar)i;
+#endif
}
overprintMask = 0xffffffff;
+ enablePathSimplification = gFalse;
next = NULL;
}
@@ -153,11 +160,14 @@ SplashState::SplashState(SplashState *state) {
memcpy(rgbTransferG, state->rgbTransferG, 256);
memcpy(rgbTransferB, state->rgbTransferB, 256);
memcpy(grayTransfer, state->grayTransfer, 256);
+#if SPLASH_CMYK
memcpy(cmykTransferC, state->cmykTransferC, 256);
memcpy(cmykTransferM, state->cmykTransferM, 256);
memcpy(cmykTransferY, state->cmykTransferY, 256);
memcpy(cmykTransferK, state->cmykTransferK, 256);
+#endif
overprintMask = state->overprintMask;
+ enablePathSimplification = state->enablePathSimplification;
next = NULL;
}
@@ -202,6 +212,32 @@ void SplashState::setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
lineDashPhase = lineDashPhaseA;
}
+GBool SplashState::lineDashContainsZeroLengthDashes() {
+ int i;
+
+ if (lineDashLength == 0) {
+ return gFalse;
+ }
+
+ // if the line dash array has an odd number of elements, we need to
+ // check all of the elements; if the length is even, we only need to
+ // check even-number elements
+ if (lineDashLength & 1) {
+ for (i = 0; i < lineDashLength; ++i) {
+ if (lineDash[i] == 0) {
+ return gTrue;
+ }
+ }
+ } else {
+ for (i = 0; i < lineDashLength; i += 2) {
+ if (lineDash[i] == 0) {
+ return gTrue;
+ }
+ }
+ }
+ return gFalse;
+}
+
void SplashState::clipResetToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1) {
if (clipIsShared) {
@@ -225,7 +261,8 @@ SplashError SplashState::clipToPath(SplashPath *path, GBool eo) {
clip = clip->copy();
clipIsShared = gFalse;
}
- return clip->clipToPath(path, matrix, flatness, eo);
+ return clip->clipToPath(path, matrix, flatness, eo,
+ enablePathSimplification, strokeAdjust);
}
void SplashState::setSoftMask(SplashBitmap *softMaskA) {
@@ -238,16 +275,20 @@ void SplashState::setSoftMask(SplashBitmap *softMaskA) {
void SplashState::setTransfer(Guchar *red, Guchar *green, Guchar *blue,
Guchar *gray) {
+#if SPLASH_CMYK
int i;
+#endif
memcpy(rgbTransferR, red, 256);
memcpy(rgbTransferG, green, 256);
memcpy(rgbTransferB, blue, 256);
memcpy(grayTransfer, gray, 256);
+#if SPLASH_CMYK
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];
}
+#endif
}
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h
index fe773a5403f..2a957cecd19 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashState.h
@@ -70,6 +70,10 @@ public:
void setLineDash(SplashCoord *lineDashA, int lineDashLengthA,
SplashCoord lineDashPhaseA);
+ // Returns true if the current line dash pattern contains one or
+ // more zero-length "on" sections (dashes).
+ GBool lineDashContainsZeroLengthDashes();
+
void clipResetToRect(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1);
SplashError clipToRect(SplashCoord x0, SplashCoord y0,
@@ -101,7 +105,7 @@ private:
SplashCoord *lineDash;
int lineDashLength;
SplashCoord lineDashPhase;
- GBool strokeAdjust;
+ SplashStrokeAdjustMode strokeAdjust;
SplashClip *clip;
GBool clipIsShared;
SplashBitmap *softMask;
@@ -112,11 +116,14 @@ private:
rgbTransferG[256],
rgbTransferB[256];
Guchar grayTransfer[256];
+#if SPLASH_CMYK
Guchar cmykTransferC[256],
cmykTransferM[256],
cmykTransferY[256],
cmykTransferK[256];
+#endif
Guint overprintMask;
+ GBool enablePathSimplification;
SplashState *next; // used by Splash class
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashTypes.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashTypes.h
index 240cb6f7b8c..0e1829dcf1d 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashTypes.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashTypes.h
@@ -107,6 +107,16 @@ typedef void (*SplashBlendFunc)(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm);
//------------------------------------------------------------------------
+// stroke adjustment mode
+//------------------------------------------------------------------------
+
+enum SplashStrokeAdjustMode {
+ splashStrokeAdjustOff,
+ splashStrokeAdjustNormal,
+ splashStrokeAdjustCAD
+};
+
+//------------------------------------------------------------------------
// screen parameters
//------------------------------------------------------------------------
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.cc
index a1599885e2b..f0164a85bd4 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.cc
@@ -18,12 +18,18 @@
#include <algorithm>
#endif
#include "gmem.h"
+#include "gmempp.h"
#include "SplashMath.h"
#include "SplashPath.h"
#include "SplashXPath.h"
//------------------------------------------------------------------------
+#define minCosSquaredJoinAngle 0.75
+#define maxPointToLineDistanceSquared 0.04
+
+//------------------------------------------------------------------------
+
struct SplashXPathPoint {
SplashCoord x, y;
};
@@ -54,29 +60,58 @@ inline void SplashXPath::transform(SplashCoord *matrix,
// SplashXPath
//------------------------------------------------------------------------
+// SplashXPath segment coords are clipped to +/-maxCoord to avoid
+// problems. The xMin/yMin/xMax/yMax fields are 32-bit integers, so
+// coords need to be < 2^31 / aa{Horiz,Vert}.
+#define maxCoord 100000000.0
+
+void SplashXPath::clampCoords(SplashCoord *x, SplashCoord *y) {
+#if !USE_FIXEDPOINT
+ if (*x > maxCoord) {
+ *x = maxCoord;
+ } else if (*x < -maxCoord) {
+ *x = -maxCoord;
+ }
+ if (*y > maxCoord) {
+ *y = maxCoord;
+ } else if (*y < -maxCoord) {
+ *y = -maxCoord;
+ }
+#endif
+}
+
SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
- SplashCoord flatness, GBool closeSubpaths) {
+ SplashCoord flatness, GBool closeSubpaths,
+ GBool simplify,
+ SplashStrokeAdjustMode strokeAdjMode) {
SplashXPathPoint *pts;
- SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xsp, ysp;
- SplashCoord xMinFP, xMaxFP, yMinFP, yMaxFP;
- int curSubpath, i;
+ SplashCoord x0, y0, x1, y1, x2, y2, x3, y3, xsp, ysp, t;
+ int curSubpath, firstSegInSubpath, i;
+ GBool adjusted;
- // transform the points
+ //--- transform the points
pts = (SplashXPathPoint *)gmallocn(path->length, sizeof(SplashXPathPoint));
for (i = 0; i < path->length; ++i) {
transform(matrix, path->pts[i].x, path->pts[i].y, &pts[i].x, &pts[i].y);
+ clampCoords(&pts[i].x, &pts[i].y);
}
- // do stroke adjustment
+ //--- do stroke adjustment
if (path->hints) {
- strokeAdjust(pts, path->hints, path->hintsLength);
+ adjusted = strokeAdjust(pts, path->hints, path->hintsLength,
+ strokeAdjMode);
+ } else {
+ adjusted = gFalse;
}
+ //--- construct the segments
+
segs = NULL;
length = size = 0;
x0 = y0 = xsp = ysp = 0; // make gcc happy
curSubpath = 0;
+ firstSegInSubpath = 0;
i = 0;
while (i < path->length) {
@@ -123,66 +158,85 @@ SplashXPath::SplashXPath(SplashPath *path, SplashCoord *matrix,
++i;
}
- // close a subpath
- if (closeSubpaths &&
- (path->flags[i-1] & splashPathLast) &&
- (pts[i-1].x != pts[curSubpath].x ||
- pts[i-1].y != pts[curSubpath].y)) {
- addSegment(x0, y0, xsp, ysp);
+ // end a subpath
+ if (path->flags[i-1] & splashPathLast) {
+ if (closeSubpaths &&
+ (pts[i-1].x != pts[curSubpath].x ||
+ pts[i-1].y != pts[curSubpath].y)) {
+ addSegment(x0, y0, xsp, ysp);
+ }
+ if (simplify && !adjusted) {
+ mergeSegments(firstSegInSubpath);
+ }
+ firstSegInSubpath = length;
}
}
}
gfree(pts);
+ finishSegments();
+
+ //--- check for a rectangle
+ isRect = gFalse;
+ rectX0 = rectY0 = rectX1 = rectY1 = 0;
+ if (length == 4) {
#if HAVE_STD_SORT
- std::sort(segs, segs + length, SplashXPathSeg::cmpY);
+ std::sort(segs, segs + length, SplashXPathSeg::cmpY);
#else
- qsort(segs, length, sizeof(SplashXPathSeg), &SplashXPathSeg::cmpY);
+ qsort(segs, length, sizeof(SplashXPathSeg), &SplashXPathSeg::cmpY);
#endif
-
- if (length == 0) {
- xMin = yMin = xMax = yMax = 0;
- } else {
- if (segs[0].x0 < segs[0].x1) {
- xMinFP = segs[0].x0;
- xMaxFP = segs[0].x1;
- } else {
- xMinFP = segs[0].x1;
- xMaxFP = segs[0].x0;
+ if (segs[0].y0 == segs[0].y1 &&
+ segs[1].x0 == segs[1].x1 &&
+ segs[2].x0 == segs[2].x1 &&
+ segs[3].y0 == segs[3].y1) {
+ isRect = gTrue;
+ rectX0 = segs[1].x0;
+ rectX1 = segs[2].x0;
+ rectY0 = segs[0].y0;
+ rectY1 = segs[3].y0;
+ } else if (segs[0].x0 == segs[0].x1 &&
+ segs[1].y0 == segs[1].y1 &&
+ segs[2].x0 == segs[2].x1 &&
+ segs[3].y0 == segs[3].y1) {
+ isRect = gTrue;
+ rectX0 = segs[0].x0;
+ rectX1 = segs[2].x0;
+ rectY0 = segs[1].y0;
+ rectY1 = segs[3].y0;
+ } else if (segs[0].x0 == segs[0].x1 &&
+ segs[1].x0 == segs[1].x1 &&
+ segs[2].y0 == segs[2].y1 &&
+ segs[3].y0 == segs[3].y1) {
+ isRect = gTrue;
+ rectX0 = segs[0].x0;
+ rectX1 = segs[1].x0;
+ rectY0 = segs[2].y0;
+ rectY1 = segs[3].y0;
}
- yMinFP = segs[0].y0;
- yMaxFP = segs[0].y1;
- for (i = 1; i < length; ++i) {
- if (segs[i].x0 < xMinFP) {
- xMinFP = segs[i].x0;
- } else if (segs[i].x0 > xMaxFP) {
- xMaxFP = segs[i].x0;
- }
- if (segs[i].x1 < xMinFP) {
- xMinFP = segs[i].x1;
- } else if (segs[i].x1 > xMaxFP) {
- xMaxFP = segs[i].x1;
+ if (isRect) {
+ if (rectX0 > rectX1) {
+ t = rectX0; rectX0 = rectX1; rectX1 = t;
}
- if (segs[i].y1 > yMaxFP) {
- yMaxFP = segs[i].y1;
+ if (rectY0 > rectY1) {
+ t = rectY0; rectY0 = rectY1; rectY1 = t;
}
}
- xMin = splashFloor(xMinFP);
- yMin = splashFloor(yMinFP);
- xMax = splashFloor(xMaxFP);
- yMax = splashFloor(yMaxFP);
}
}
-void SplashXPath::strokeAdjust(SplashXPathPoint *pts,
- SplashPathHint *hints, int nHints) {
+GBool SplashXPath::strokeAdjust(SplashXPathPoint *pts,
+ SplashPathHint *hints, int nHints,
+ SplashStrokeAdjustMode strokeAdjMode) {
SplashXPathAdjust *adjusts, *adjust;
SplashPathHint *hint;
SplashCoord x0, y0, x1, y1, x2, y2, x3, y3;
- SplashCoord adj0, adj1, d;
+ SplashCoord adj0, adj1, w, d;
int xi0, xi1;
int i, j;
+ GBool adjusted;
+
+ adjusted = gFalse;
// set up the stroke adjustment hints
adjusts = (SplashXPathAdjust *)gmallocn(nHints, sizeof(SplashXPathAdjust));
@@ -192,14 +246,21 @@ void SplashXPath::strokeAdjust(SplashXPathPoint *pts,
x1 = pts[hint->ctrl0 + 1].x; y1 = pts[hint->ctrl0 + 1].y;
x2 = pts[hint->ctrl1 ].x; y2 = pts[hint->ctrl1 ].y;
x3 = pts[hint->ctrl1 + 1].x; y3 = pts[hint->ctrl1 + 1].y;
+ w = -1;
if (x0 == x1 && x2 == x3) {
adjusts[i].vert = gTrue;
adj0 = x0;
adj1 = x2;
+ if (hint->projectingCap) {
+ w = splashAbs(y1 - y0);
+ }
} else if (y0 == y1 && y2 == y3) {
adjusts[i].vert = gFalse;
adj0 = y0;
adj1 = y2;
+ if (hint->projectingCap) {
+ w = splashAbs(x1 - x0);
+ }
} else {
goto done;
}
@@ -220,7 +281,7 @@ void SplashXPath::strokeAdjust(SplashXPathPoint *pts,
adjusts[i].xmb = (SplashCoord)0.5 * (adj0 + adj1) + d;
adjusts[i].x1a = adj1 - d;
adjusts[i].x1b = adj1 + d;
- splashStrokeAdjust(adj0, adj1, &xi0, &xi1);
+ splashStrokeAdjust(adj0, adj1, &xi0, &xi1, strokeAdjMode, w);
adjusts[i].x0 = (SplashCoord)xi0;
// the "minus epsilon" thing here is needed when vector
// antialiasing is turned off -- otherwise stroke adjusted lines
@@ -255,9 +316,11 @@ void SplashXPath::strokeAdjust(SplashXPathPoint *pts,
}
}
}
+ adjusted = gTrue;
done:
gfree(adjusts);
+ return adjusted;
}
SplashXPath::SplashXPath(SplashXPath *xPath) {
@@ -380,38 +443,202 @@ void SplashXPath::addCurve(SplashCoord x0, SplashCoord y0,
void SplashXPath::addSegment(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1) {
grow(1);
- if (y0 <= y1) {
- segs[length].x0 = x0;
- segs[length].y0 = y0;
- segs[length].x1 = x1;
- segs[length].y1 = y1;
- segs[length].count = 1;
- } else {
- segs[length].x0 = x1;
- segs[length].y0 = y1;
- segs[length].x1 = x0;
- segs[length].y1 = y0;
- segs[length].count = -1;
+ segs[length].x0 = x0;
+ segs[length].y0 = y0;
+ segs[length].x1 = x1;
+ segs[length].y1 = y1;
+ ++length;
+}
+
+// Returns true if the angle between (x0,y0)-(x1,y1) and
+// (x1,y1)-(x2,y2) is close to 180 degrees.
+static GBool joinAngleIsFlat(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2) {
+ SplashCoord dx1, dy1, dx2, dy2, d, len1, len2;
+
+ dx1 = x1 - x0;
+ dy1 = y1 - y0;
+ dx2 = x2 - x1;
+ dy2 = y2 - y1;
+ d = dx1 * dx2 + dy1 * dy2;
+ len1 = dx1 * dx1 + dy1 * dy1;
+ len2 = dx2 * dx2 + dy2 * dy2;
+ return d > 0 && d * d > len1 * len2 * minCosSquaredJoinAngle;
+}
+
+// Returns true if (x1,y1) is sufficiently close to the segment
+// (x0,y0)-(x2,y2), looking at the perpendicular point-to-line
+// distance.
+static GBool pointCloseToSegment(SplashCoord x0, SplashCoord y0,
+ SplashCoord x1, SplashCoord y1,
+ SplashCoord x2, SplashCoord y2) {
+ SplashCoord t1, t2, dx, dy;
+
+ // compute the perpendicular distance from the point to the segment,
+ // i.e., the projection of (x0,y0)-(x1,y1) onto a unit normal to the
+ // segment (this actually computes the square of the distance)
+ dx = x2 - x0;
+ dy = y2 - y0;
+ t1 = dx*dx + dy*dy;
+ if (t1 < 0.0001) {
+ // degenerate case: (x0,y0) and (x2,y2) are (nearly) identical --
+ // just compute the distance to (x1,y1)
+ dx = x0 - x1;
+ dy = y0 - y1;
+ t2 = dx*dx + dy*dy;
+ return t2 < maxPointToLineDistanceSquared;
}
-#if USE_FIXEDPOINT
- if (y0 == y1 || x0 == x1 ||
- !FixedPoint::divCheck(x1 - x0, y1 - y0, &segs[length].dxdy) ||
- !FixedPoint::divCheck(y1 - y0, x1 - x0, &segs[length].dydx)) {
- segs[length].dxdy = 0;
- segs[length].dydx = 0;
+ t2 = x1 * dy - dx * y1 - x0 * y2 + x2 * y0;
+ // actual distance = t2 / sqrt(t1)
+ return t2 * t2 < t1 * maxPointToLineDistanceSquared;
+}
+
+// Attempt to simplify the path by merging sequences of consecutive
+// segments in [first] .. [length]-1.
+void SplashXPath::mergeSegments(int first) {
+ GBool horiz, vert;
+ int in, out, prev, i, j;
+
+ in = out = first;
+ while (in < length) {
+
+ // skip zero-length segments
+ if (segs[in].x0 == segs[in].x1 && segs[in].y0 == segs[in].y1) {
+ ++in;
+ continue;
+ }
+
+ horiz = segs[in].y0 == segs[in].y1;
+ vert = segs[in].x0 == segs[in].x1;
+
+ // check for a sequence of mergeable segments: in .. i
+ prev = in;
+ for (i = in + 1; i < length; ++i) {
+
+ // skip zero-length segments
+ if (segs[i].x0 == segs[i].x1 && segs[i].y0 == segs[i].y1) {
+ continue;
+ }
+
+ // check for a horizontal or vertical segment
+ if ((horiz && segs[in].y0 != segs[in].y1) ||
+ (vert && segs[in].x0 != segs[in].x1)) {
+ break;
+ }
+
+ // check the angle between segs i-1 and i
+ // (actually, we compare seg i to the previous non-zero-length
+ // segment, which may not be i-1)
+ if (!joinAngleIsFlat(segs[prev].x0, segs[prev].y0,
+ segs[i].x0, segs[i].y0,
+ segs[i].x1, segs[i].y1)) {
+ break;
+ }
+
+ // check the distances from the ends of segs in .. i-1 to the
+ // proposed new segment
+ for (j = in; j < i; ++j) {
+ if (!pointCloseToSegment(segs[in].x0, segs[in].y0,
+ segs[j].x1, segs[j].y1,
+ segs[i].x1, segs[i].y1)) {
+ break;
+ }
+ }
+ if (j < i) {
+ break;
+ }
+
+ prev = i;
+ }
+
+ // we can merge segs: in .. i-1
+ // (this may be the single segment: in)
+ segs[out].x0 = segs[in].x0;
+ segs[out].y0 = segs[in].y0;
+ segs[out].x1 = segs[i-1].x1;
+ segs[out].y1 = segs[i-1].y1;
+ in = i;
+ ++out;
}
+
+ length = out;
+}
+
+void SplashXPath::finishSegments() {
+ SplashXPathSeg *seg;
+ SplashCoord xMinFP, xMaxFP, yMinFP, yMaxFP, t;
+ int i;
+
+ xMinFP = yMinFP = xMaxFP = yMaxFP = 0;
+
+ for (i = 0; i < length; ++i) {
+ seg = &segs[i];
+
+ //--- compute the slopes
+ if (seg->y0 <= seg->y1) {
+ seg->count = 1;
+ } else {
+ t = seg->x0; seg->x0 = seg->x1; seg->x1 = t;
+ t = seg->y0; seg->y0 = seg->y1; seg->y1 = t;
+ seg->count = -1;
+ }
+#if USE_FIXEDPOINT
+ if (seg->y0 == seg->y1 || seg->x0 == seg->x1 ||
+ !FixedPoint::divCheck(seg->x1 - seg->x0, seg->y1 - seg->y0,
+ &seg->dxdy) ||
+ !FixedPoint::divCheck(seg->y1 - seg->y0, seg->x1 - seg->x0,
+ &seg->dydx)) {
+ seg->dxdy = 0;
+ seg->dydx = 0;
+ }
#else
- if (y0 == y1 || x0 == x1) {
- segs[length].dxdy = 0;
- segs[length].dydx = 0;
- } else {
- segs[length].dxdy = (x1 - x0) / (y1 - y0);
- if (segs[length].dxdy == 0) {
- segs[length].dydx = 0;
+ if (seg->y0 == seg->y1 || seg->x0 == seg->x1) {
+ seg->dxdy = 0;
+ seg->dydx = 0;
} else {
- segs[length].dydx = 1 / segs[length].dxdy;
+ seg->dxdy = (seg->x1 - seg->x0) / (seg->y1 - seg->y0);
+ if (seg->dxdy == 0) {
+ seg->dydx = 0;
+ } else {
+ seg->dydx = 1 / seg->dxdy;
+ }
}
- }
#endif
- ++length;
+
+ //--- update bbox
+ if (i == 0) {
+ if (seg->x0 <= seg->x1) {
+ xMinFP = seg->x0;
+ xMaxFP = seg->x1;
+ } else {
+ xMinFP = seg->x1;
+ xMaxFP = seg->x0;
+ }
+ yMinFP = seg->y0;
+ yMaxFP = seg->y1;
+ } else {
+ if (seg->x0 < xMinFP) {
+ xMinFP = seg->x0;
+ } else if (seg->x0 > xMaxFP) {
+ xMaxFP = seg->x0;
+ }
+ if (seg->x1 < xMinFP) {
+ xMinFP = seg->x1;
+ } else if (seg->x1 > xMaxFP) {
+ xMaxFP = seg->x1;
+ }
+ if (seg->y0 < yMinFP) {
+ yMinFP = seg->y0;
+ }
+ if (seg->y1 > yMaxFP) {
+ yMaxFP = seg->y1;
+ }
+ }
+ }
+
+ xMin = splashFloor(xMinFP);
+ yMin = splashFloor(yMinFP);
+ xMax = splashFloor(xMaxFP);
+ yMax = splashFloor(yMaxFP);
}
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.h
index 5bcec61cd25..82d7889c447 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPath.h
@@ -37,36 +37,48 @@ struct SplashXPathSeg {
int count; // EO/NZWN counter increment
//----- used by SplashXPathScanner
- SplashCoord xCur0, xCur1; // current x values
+ int iy;
+ SplashCoord sx0, sx1, mx;
+ SplashXPathSeg *prev, *next;
#if HAVE_STD_SORT
+
+ static bool cmpMX(const SplashXPathSeg &s0,
+ const SplashXPathSeg &s1) {
+ if (s0.iy != s1.iy) {
+ return s0.iy < s1.iy;
+ }
+ return s0.mx < s1.mx;
+ }
+
static bool cmpY(const SplashXPathSeg &seg0,
const SplashXPathSeg &seg1) {
return seg0.y0 < seg1.y0;
}
+
#else
- static int cmpY(const void *seg0, const void *seg1) {
+
+ static int cmpMX(const void *p0, const void *p1) {
+ SplashXPathSeg *s0 = (SplashXPathSeg *)p0;
+ SplashXPathSeg *s1 = (SplashXPathSeg *)p1;
SplashCoord cmp;
- cmp = ((SplashXPathSeg *)seg0)->y0
- - ((SplashXPathSeg *)seg1)->y0;
- return (cmp > 0) ? 1 : (cmp < 0) ? -1 : 0;
+ if (s0->iy != s1->iy) {
+ return s0->iy - s1->iy;
+ }
+ cmp = s0->mx - s1->mx;
+ return (cmp < 0) ? -1 : (cmp > 0) ? 1 : 0;
}
-#endif
- static int cmpX(SplashXPathSeg *seg0, SplashXPathSeg *seg1) {
+ static int cmpY(const void *seg0, const void *seg1) {
SplashCoord cmp;
- if ((cmp = seg0->xCur0 - seg1->xCur0) == 0) {
- cmp = seg0->dxdy - seg1->dxdy;
- }
+ cmp = ((SplashXPathSeg *)seg0)->y0
+ - ((SplashXPathSeg *)seg1)->y0;
return (cmp > 0) ? 1 : (cmp < 0) ? -1 : 0;
}
- static int cmpXi(const void *p0, const void *p1) {
- return cmpX(*(SplashXPathSeg **)p0, *(SplashXPathSeg **)p1);
- }
-
+#endif
};
//------------------------------------------------------------------------
@@ -81,7 +93,8 @@ public:
// space, via <matrix>. If <closeSubpaths> is true, closes all open
// subpaths.
SplashXPath(SplashPath *path, SplashCoord *matrix,
- SplashCoord flatness, GBool closeSubpaths);
+ SplashCoord flatness, GBool closeSubpaths,
+ GBool simplify, SplashStrokeAdjustMode strokeAdjMode);
// Copy an expanded path.
SplashXPath *copy() { return new SplashXPath(this); }
@@ -95,11 +108,13 @@ public:
private:
+ static void clampCoords(SplashCoord *x, SplashCoord *y);
SplashXPath(SplashXPath *xPath);
void transform(SplashCoord *matrix, SplashCoord xi, SplashCoord yi,
SplashCoord *xo, SplashCoord *yo);
- void strokeAdjust(SplashXPathPoint *pts,
- SplashPathHint *hints, int nHints);
+ GBool strokeAdjust(SplashXPathPoint *pts,
+ SplashPathHint *hints, int nHints,
+ SplashStrokeAdjustMode strokeAdjMode);
void grow(int nSegs);
void addCurve(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1,
@@ -107,14 +122,19 @@ private:
SplashCoord x3, SplashCoord y3,
SplashCoord flatness,
GBool first, GBool last, GBool end0, GBool end1);
+ void mergeSegments(int first);
void addSegment(SplashCoord x0, SplashCoord y0,
SplashCoord x1, SplashCoord y1);
+ void finishSegments();
SplashXPathSeg *segs;
int length, size; // length and size of segs array
int xMin, xMax;
int yMin, yMax;
+ GBool isRect;
+ SplashCoord rectX0, rectY0, rectX1, rectY1;
+
friend class SplashXPathScanner;
friend class SplashClip;
friend class Splash;
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc
index aee60cce61e..3f167b8b311 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.cc
@@ -18,6 +18,7 @@
#include <algorithm>
#endif
#include "gmem.h"
+#include "gmempp.h"
#include "GList.h"
#include "SplashMath.h"
#include "SplashXPath.h"
@@ -25,543 +26,595 @@
//------------------------------------------------------------------------
-#define minVertStep 0.05
+#if ANTIALIAS_256
+
+#define aaVert 15
+#define aaHoriz 17
+
+#else
+
+#define aaVert 4
+#define aaHoriz 4
+
+static Guchar map16to255[17] = {
+ 0,
+ 16,
+ 32,
+ 48,
+ 64,
+ 80,
+ 96,
+ 112,
+ 128,
+ 143,
+ 159,
+ 175,
+ 191,
+ 207,
+ 223,
+ 239,
+ 255
+};
+
+#endif
//------------------------------------------------------------------------
-SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eoA,
+SplashXPathScanner::SplashXPathScanner(SplashXPath *xPathA, GBool eo,
int yMinA, int yMaxA) {
xPath = xPathA;
- eo = eoA;
+ eoMask = eo ? 1 : 0xffffffff;
yMin = yMinA;
yMax = yMaxA;
+ if (xPath->isRect) {
+ rectX0I = splashFloor(xPath->rectX0);
+ rectY0I = splashFloor(xPath->rectY0);
+ rectX1I = splashFloor(xPath->rectX1);
+ rectY1I = splashFloor(xPath->rectY1);
+ }
- activeSegs = new GList();
- nextSeg = 0;
- yNext = xPath->yMin;
+ pre = &preSeg;
+ post = &postSeg;
+ pre->mx = xPath->xMin - 1;
+ post->mx = xPath->xMax + 1;
+
+ resetDone = gFalse;
+ resetAA = gFalse;
}
SplashXPathScanner::~SplashXPathScanner() {
- delete activeSegs;
}
-void SplashXPathScanner::getSpan(Guchar *line, int y, int x0, int x1) {
- SplashXPathSeg *seg, *seg0;
- SplashCoord y0, y1, y1p;
- GBool intersect, last;
- int eoMask, state0, state1, count, i;
+void SplashXPathScanner::insertSegmentBefore(SplashXPathSeg *s,
+ SplashXPathSeg *sNext) {
+ SplashXPathSeg *sPrev;
- //--- clear the scan line buffer
- memset(line + x0, 0, x1 - x0 + 1);
+ sPrev = sNext->prev;
+ sPrev->next = s;
+ s->prev = sPrev;
+ s->next = sNext;
+ sNext->prev = s;
+}
+
+void SplashXPathScanner::removeSegment(SplashXPathSeg *s) {
+ SplashXPathSeg *sPrev, *sNext;
+
+ sPrev = s->prev;
+ sNext = s->next;
+ sPrev->next = sNext;
+ sNext->prev = sPrev;
+ s->prev = s->next = NULL;
+}
- //--- reset the path
- if (yNext != y) {
- delete activeSegs;
- activeSegs = new GList();
- nextSeg = 0;
- while (nextSeg < xPath->length) {
- seg = &xPath->segs[nextSeg];
- if (seg->y0 >= y) {
- break;
+void SplashXPathScanner::moveSegmentAfter(SplashXPathSeg *s,
+ SplashXPathSeg *sPrev) {
+ SplashXPathSeg *sNext;
+
+ s->prev->next = s->next;
+ s->next->prev = s->prev;
+
+ sNext = sPrev->next;
+ sPrev->next = s;
+ s->prev = sPrev;
+ s->next = sNext;
+ sNext->prev = s;
+}
+
+void SplashXPathScanner::reset(GBool aa, GBool aaChanged) {
+ SplashXPathSeg *seg;
+ SplashCoord y;
+ int i;
+
+ //--- initialize segment parameters
+ for (i = 0; i < xPath->length; ++i) {
+ seg = &xPath->segs[i];
+ if (aa) {
+ if (aaChanged) {
+ seg->iy = splashFloor(seg->y0 * aaVert);
}
- if (seg->y0 != seg->y1 && seg->y1 > y) {
- if (seg->y0 == y) {
- seg->xCur0 = seg->x0;
- } else {
- seg->xCur0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy;
- }
- activeSegs->append(seg);
+ y = (SplashCoord)(seg->iy + 1) / (SplashCoord)aaVert;
+ } else {
+ if (aaChanged) {
+ seg->iy = splashFloor(seg->y0);
}
- ++nextSeg;
+ y = (SplashCoord)(seg->iy + 1);
+ }
+ seg->sx0 = seg->x0;
+ if (seg->y1 <= y) {
+ seg->sx1 = seg->x1;
+ } else {
+ seg->sx1 = seg->x0 + (y - seg->y0) * seg->dxdy;
}
- activeSegs->sort(&SplashXPathSeg::cmpXi);
+ seg->mx = (seg->sx0 <= seg->sx1) ? seg->sx0 : seg->sx1;
+ seg->prev = seg->next = NULL;
}
- //--- process the scan line
- y0 = y;
- while (y0 < y + 1) {
+ //--- sort the inactive segments by iy, mx
+ if (aaChanged) {
+#if HAVE_STD_SORT
+ std::sort(xPath->segs, xPath->segs + xPath->length, &SplashXPathSeg::cmpMX);
+#else
+ qsort(xPath->segs, xPath->length, sizeof(SplashXPathSeg),
+ &SplashXPathSeg::cmpMX);
+#endif
+ }
- //--- delete finished segs
- i = 0;
- while (i < activeSegs->getLength()) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- if (seg->y1 <= y0) {
- activeSegs->del(i);
- } else {
- ++i;
- }
- }
+ //--- initialize the active list
+ pre->prev = NULL;
+ pre->next = post;
+ post->prev = pre;
+ post->next = NULL;
- //--- check for bottom of path
- if (!activeSegs->getLength() && nextSeg >= xPath->length) {
- break;
+ //--- initialize the scan state
+ nextSeg = 0;
+ if (xPath->length) {
+ yBottomI = xPath->segs[0].iy;
+ if (aa) {
+ yBottomI -= yBottomI % aaVert;
}
+ } else {
+ yBottomI = 0;
+ }
+ yTopI = yBottomI - 1;
+ if (aa) {
+ yTop = (SplashCoord)yTopI / (SplashCoord)aaVert;
+ yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert;
+ } else {
+ yTop = (SplashCoord)yTopI;
+ yBottom = (SplashCoord)yBottomI;
+ }
+
+ resetDone = gTrue;
+ resetAA = aa;
+}
- //--- sort activeSegs
- sortActiveSegs();
+void SplashXPathScanner::skip(int newYBottomI, GBool aa) {
+ SplashXPathSeg *s0, *s1,*s2;
+ int iy;
+
+ yTopI = newYBottomI - 1;
+ yBottomI = newYBottomI;
+ if (aa) {
+ yTop = (SplashCoord)yTopI / (SplashCoord)aaVert;
+ yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert;
+ } else {
+ yTop = (SplashCoord)yTopI;
+ yBottom = (SplashCoord)yBottomI;
+ }
- //--- add waiting segs
- while (nextSeg < xPath->length) {
- seg = &xPath->segs[nextSeg];
- if (seg->y0 > y0) {
- break;
+ //--- remove finished segments; update sx0, sx1, mx for active segments
+ s0 = pre->next;
+ while (s0 != post) {
+ s1 = s0->next;
+
+ // check for a finished segment
+ if (s0->y1 < yTop) {
+ removeSegment(s0);
+
+ // compute sx0, sx1, mx
+ } else {
+ if (s0->y0 >= yTop) {
+ s0->sx0 = s0->x0;
+ } else {
+ s0->sx0 = s0->x0 + (yTop - s0->y0) * s0->dxdy;
}
- if (seg->y0 != seg->y1) {
- seg->xCur0 = seg->x0;
- insertActiveSeg(seg);
+ if (s0->y1 <= yBottom) {
+ s0->sx1 = s0->x1;
+ } else {
+ s0->sx1 = s0->x0 + (yBottom - s0->y0) * s0->dxdy;
}
- ++nextSeg;
+ s0->mx = (s0->sx0 <= s0->sx1) ? s0->sx0 : s0->sx1;
}
- //--- get the next "interesting" y value
- y1 = y + 1;
- if (nextSeg < xPath->length && xPath->segs[nextSeg].y0 < y1) {
- y1 = xPath->segs[nextSeg].y0;
- }
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- if (seg->y1 < y1) {
- y1 = seg->y1;
+ s0 = s1;
+ }
+
+ //--- check for intersections
+ s0 = pre->next;
+ if (s0 != post) {
+ s1 = s0->next;
+ while (s1 != post) {
+ if (s1->mx < s0->mx) {
+ for (s2 = s0->prev; s1->mx < s2->mx; s2 = s2->prev) ;
+ moveSegmentAfter(s1, s2);
+ } else {
+ s0 = s1;
}
+ s1 = s0->next;
}
+ }
- //--- compute xCur1 values, check for intersections
- seg0 = NULL;
- intersect = gFalse;
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- if (seg->y1 == y1) {
- seg->xCur1 = seg->x1;
- } else {
- seg->xCur1 = seg->x0 + (y1 - seg->y0) * seg->dxdy;
+ //--- insert new segments with a merge sort
+ // - this has to be done one (sub)scanline at a time, because the
+ // inactive list is bin-sorted by (sub)scanline
+ while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= yTopI) {
+ // the first inactive segment determines the next scanline to process
+ iy = xPath->segs[nextSeg].iy;
+ s0 = pre->next;
+ do {
+ s1 = &xPath->segs[nextSeg];
+ ++nextSeg;
+ if (s1->y1 < yTop) {
+ continue;
}
- if (seg0 && seg0->xCur1 > seg->xCur1) {
- intersect = gTrue;
+ if (s1->y0 >= yTop) {
+ s1->sx0 = s1->x0;
+ } else {
+ s1->sx0 = s1->x0 + (yTop - s1->y0) * s1->dxdy;
}
- seg0 = seg;
- }
-
- //--- draw rectangles
- if (intersect) {
- for (; y0 < y1; y0 += minVertStep) {
- if ((y1p = y0 + minVertStep) >= y1) {
- y1p = y1;
- last = gTrue;
- } else {
- last = gFalse;
- }
- state0 = state1 = count = 0;
- seg0 = NULL;
- eoMask = eo ? 1 : 0xffffffff;
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- if (last && seg->y1 == y1) {
- seg->xCur1 = seg->x1;
- } else {
- seg->xCur1 = seg->x0 + (y1p - seg->y0) * seg->dxdy;
- }
- count += seg->count;
- state1 = count & eoMask;
- if (!state0 && state1) {
- seg0 = seg;
- } else if (state0 && !state1) {
- drawRectangle(line, x0, x1, y0, y1p, seg0->xCur0, seg->xCur0);
- }
- state0 = state1;
- }
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- seg->xCur0 = seg->xCur1;
- }
- sortActiveSegs();
+ if (s1->y1 <= yBottom) {
+ s1->sx1 = s1->x1;
+ } else {
+ s1->sx1 = s1->x0 + (yBottom - s1->y0) * s1->dxdy;
}
+ s1->mx = (s1->sx0 <= s1->sx1) ? s1->sx0 : s1->sx1;
+ insertSegmentBefore(s1, s0);
+ } while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= iy);
+ }
+}
- //--- draw trapezoids
- } else {
- state0 = state1 = count = 0;
- seg0 = NULL;
- eoMask = eo ? 1 : 0xffffffff;
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- count += seg->count;
- state1 = count & eoMask;
- if (!state0 && state1) {
- seg0 = seg;
- } else if (state0 && !state1) {
- drawTrapezoid(line, x0, x1, y0, y1,
- seg0->xCur0, seg0->xCur1, seg0->dydx,
- seg->xCur0, seg->xCur1, seg->dydx);
- }
- state0 = state1;
- }
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- seg->xCur0 = seg->xCur1;
- }
- }
+void SplashXPathScanner::advance(GBool aa) {
+ SplashXPathSeg *s, *sNext, *s1;
- //--- next slice
- y0 = y1;
+ yTopI = yBottomI;
+ yTop = yBottom;
+ yBottomI = yTopI + 1;
+ if (aa) {
+ yBottom = (SplashCoord)yBottomI / (SplashCoord)aaVert;
+ } else {
+ yBottom = (SplashCoord)yBottomI;
}
- yNext = y + 1;
-}
+ s = pre->next;
+ while (s != post) {
+ sNext = s->next;
-void SplashXPathScanner::getSpanBinary(Guchar *line, int y, int x0, int x1) {
- SplashXPathSeg *seg;
- int xx0, xx1, xx;
- int eoMask, state0, state1, count, i;
+ // check for a finished segment
+ if (s->y1 < yTop) {
+ removeSegment(s);
- //--- clear the scan line buffer
- memset(line + x0, 0, x1 - x0 + 1);
+ } else {
- //--- reset the path
- if (yNext != y) {
- delete activeSegs;
- activeSegs = new GList();
- nextSeg = 0;
- while (nextSeg < xPath->length) {
- seg = &xPath->segs[nextSeg];
- if (seg->y0 >= y) {
- break;
+ // compute sx0, sx1, mx
+ s->sx0 = s->sx1;
+ if (s->y1 <= yBottom) {
+ s->sx1 = s->x1;
+ } else {
+ s->sx1 = s->x0 + (yBottom - s->y0) * s->dxdy;
}
- if (seg->y1 > y) {
- if (seg->y0 == y) {
- seg->xCur0 = seg->x0;
- } else {
- seg->xCur0 = seg->x0 + ((SplashCoord)y - seg->y0) * seg->dxdy;
- }
- activeSegs->append(seg);
+ s->mx = (s->sx0 <= s->sx1) ? s->sx0 : s->sx1;
+
+ // check for intersection
+ if (s->mx < s->prev->mx) {
+ for (s1 = s->prev->prev; s->mx < s1->mx; s1 = s1->prev) ;
+ moveSegmentAfter(s, s1);
}
- ++nextSeg;
}
- activeSegs->sort(&SplashXPathSeg::cmpXi);
- }
- //--- delete finished segs
- i = 0;
- while (i < activeSegs->getLength()) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- if (seg->y1 <= y) {
- activeSegs->del(i);
- } else {
- ++i;
- }
+ s = sNext;
}
- //--- sort activeSegs
- sortActiveSegs();
-
- //--- add waiting segs
- while (nextSeg < xPath->length) {
- seg = &xPath->segs[nextSeg];
- if (seg->y0 >= y + 1) {
- break;
- }
- seg->xCur0 = seg->x0;
- insertActiveSeg(seg);
+ // insert new segments
+ s = pre->next;
+ while (nextSeg < xPath->length && xPath->segs[nextSeg].iy <= yTopI) {
+ s1 = &xPath->segs[nextSeg];
++nextSeg;
- }
-
- //--- compute xCur1 values
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- if (seg->y1 <= y + 1) {
- seg->xCur1 = seg->x1;
- } else {
- seg->xCur1 = seg->x0 + ((SplashCoord)(y + 1) - seg->y0) * seg->dxdy;
+ while (s1->mx > s->mx) {
+ s = s->next;
}
+ insertSegmentBefore(s1, s);
}
+}
- //--- draw spans
- state0 = state1 = count = 0;
- eoMask = eo ? 1 : 0xffffffff;
- xx0 = xx1 = 0; // make gcc happy
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- if (seg->y0 <= y && seg->y0 < seg->y1) {
- count += seg->count;
- state1 = count & eoMask;
- }
- if (state0) {
- xx = splashCeil(seg->xCur0) - 1;
- if (xx > xx1) {
- xx1 = xx;
- }
- xx = splashFloor(seg->xCur1);
- if (xx < xx0) {
- xx0 = xx;
- }
- xx = splashCeil(seg->xCur1) - 1;
- if (xx > xx1) {
- xx1 = xx;
- }
- } else {
- if (seg->xCur0 < seg->xCur1) {
- xx0 = splashFloor(seg->xCur0);
- xx1 = splashCeil(seg->xCur1) - 1;
- } else {
- xx0 = splashFloor(seg->xCur1);
- xx1 = splashCeil(seg->xCur0) - 1;
- }
+void SplashXPathScanner::generatePixels(int x0, int x1, Guchar *line,
+ int *xMin, int *xMax) {
+ SplashXPathSeg *s;
+ int fillCount, x, xEnd, ix0, ix1, t;
+
+ fillCount = 0;
+ x = x0 * aaHoriz;
+ xEnd = (x1 + 1) * aaHoriz;
+ for (s = pre->next; s != post && x < xEnd; s = s->next) {
+ ix0 = splashFloor(s->sx0 * aaHoriz);
+ ix1 = splashFloor(s->sx1 * aaHoriz);
+ if (ix0 > ix1) {
+ t = ix0; ix0 = ix1; ix1 = t;
}
- if (!state1) {
- if (xx0 < x0) {
- xx0 = x0;
- }
- if (xx1 > x1) {
- xx1 = x1;
- }
- for (xx = xx0; xx <= xx1; ++xx) {
- line[xx] = 0xff;
+ if (!(fillCount & eoMask)) {
+ if (ix0 > x) {
+ x = ix0;
}
}
- state0 = state1;
+ if (ix1 >= xEnd) {
+ ix1 = xEnd - 1;
+ }
+ if (x / aaHoriz < *xMin) {
+ *xMin = x / aaHoriz;
+ }
+ if (ix1 / aaHoriz > *xMax) {
+ *xMax = ix1 / aaHoriz;
+ }
+ for (; x <= ix1; ++x) {
+ ++line[x / aaHoriz];
+ }
+ if (s->y0 <= yTop && s->y1 > yTop) {
+ fillCount += s->count;
+ }
}
+}
- //--- update xCur0 values
- for (i = 0; i < activeSegs->getLength(); ++i) {
- seg = (SplashXPathSeg *)activeSegs->get(i);
- seg->xCur0 = seg->xCur1;
+void SplashXPathScanner::generatePixelsBinary(int x0, int x1, Guchar *line,
+ int *xMin, int *xMax) {
+ SplashXPathSeg *s;
+ int fillCount, x, xEnd, ix0, ix1, t;
+
+ fillCount = 0;
+ x = x0;
+ xEnd = x1 + 1;
+ for (s = pre->next; s != post && x < xEnd; s = s->next) {
+ ix0 = splashFloor(s->sx0);
+ ix1 = splashFloor(s->sx1);
+ if (ix0 > ix1) {
+ t = ix0; ix0 = ix1; ix1 = t;
+ }
+ if (!(fillCount & eoMask)) {
+ if (ix0 > x) {
+ x = ix0;
+ }
+ }
+ if (ix1 >= xEnd) {
+ ix1 = xEnd - 1;
+ }
+ if (x < *xMin) {
+ *xMin = x;
+ }
+ if (ix1 > *xMax) {
+ *xMax = ix1;
+ }
+ for (; x <= ix1; ++x) {
+ line[x] = 255;
+ }
+ if (s->y0 <= yTop && s->y1 > yTop) {
+ fillCount += s->count;
+ }
}
-
- yNext = y + 1;
}
-inline void SplashXPathScanner::addArea(Guchar *line, int x, SplashCoord a) {
- int a2, t;
+void SplashXPathScanner::drawRectangleSpan(Guchar *line, int y,
+ int x0, int x1,
+ int *xMin, int *xMax) {
+ SplashCoord edge;
+ Guchar pix;
+ int xe, x;
- a2 = splashRound(a * 255);
- if (a2 <= 0) {
+ if (rectX0I > x1 || rectX1I < x0) {
return;
}
- t = line[x] + a2;
- if (t > 255) {
- t = 255;
- }
- line[x] = t;
-}
-// Draw a trapezoid with edges:
-// top: (xa0, y0) - (xb0, y0)
-// left: (xa0, y0) - (xa1, y1)
-// right: (xb0, y0) - (xb1, y1)
-// bottom: (xa1, y1) - (xb1, y1)
-void SplashXPathScanner::drawTrapezoid(Guchar *line, int xMin, int xMax,
- SplashCoord y0, SplashCoord y1,
- SplashCoord xa0, SplashCoord xa1,
- SplashCoord dydxa,
- SplashCoord xb0, SplashCoord xb1,
- SplashCoord dydxb) {
- SplashCoord a, dy;
- int x0, x1, x2, x3, x;
-
- // check for a rectangle
- if (dydxa == 0 && dydxb == 0 && xa0 >= xMin && xb0 <= xMax) {
- x0 = splashFloor(xa0);
- x3 = splashFloor(xb0);
- dy = y1 - y0;
- if (x0 == x3) {
- addArea(line, x0, (xb0 - xa0) * dy);
+ *xMin = x0 <= rectX0I ? rectX0I : x0;
+ *xMax = rectX1I <= x1 ? rectX1I : x1;
+
+ //--- upper edge
+ if (y == rectY0I) {
+
+ // handle a rectangle less than one pixel high
+ if (rectY0I == rectY1I) {
+ edge = xPath->rectY1 - xPath->rectY0;
+ } else {
+ edge = (SplashCoord)1 - (xPath->rectY0 - rectY0I);
+ }
+
+ // upper left corner
+ if (x0 <= rectX0I) {
+ pix = (Guchar)splashCeil(edge
+ * ((SplashCoord)1 - (xPath->rectX0 - rectX0I))
+ * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ line[rectX0I] = pix;
+ x = rectX0I + 1;
} else {
- addArea(line, x0, ((SplashCoord)1 - (xa0 - x0)) * dy);
- for (x = x0 + 1; x <= x3 - 1; ++x) {
- addArea(line, x, y1 - y0);
+ x = x0;
+ }
+
+ // upper right corner
+ if (rectX1I <= x1) {
+ pix = (Guchar)splashCeil(edge * (xPath->rectX1 - rectX1I) * 255);
+ if (pix < 16) {
+ pix = 16;
}
- addArea(line, x3, (xb0 - x3) * (y1 - y0));
+ line[rectX1I] = pix;
+ xe = rectX1I - 1;
+ } else {
+ xe = x1;
}
- return;
- }
- if (dydxa > 0) {
- x0 = splashFloor(xa0);
- x1 = splashFloor(xa1);
- } else {
- x0 = splashFloor(xa1);
- x1 = splashFloor(xa0);
- }
- if (x0 < xMin) {
- x0 = xMin;
- }
- if (dydxb > 0) {
- x2 = splashFloor(xb0);
- x3 = splashFloor(xb1);
- } else {
- x2 = splashFloor(xb1);
- x3 = splashFloor(xb0);
- }
- if (x3 > xMax) {
- x3 = xMax;
- }
- for (x = x0; x <= x3; ++x) {
- a = y1 - y0;
- if (x <= x1) {
- a -= areaLeft(x, xa0, y0, xa1, y1, dydxa);
+ // upper edge
+ pix = (Guchar)splashCeil(edge * 255);
+ if (pix < 16) {
+ pix = 16;
}
- if (x >= x2) {
- a -= areaRight(x, xb0, y0, xb1, y1, dydxb);
+ for (; x <= xe; ++x) {
+ line[x] = pix;
}
- addArea(line, x, a);
- }
-}
-// Compute area within a pixel slice ((xp,y0)-(xp+1,y1)) to the left
-// of a trapezoid edge ((x0,y0)-(x1,y1)).
-SplashCoord SplashXPathScanner::areaLeft(int xp,
- SplashCoord x0, SplashCoord y0,
- SplashCoord x1, SplashCoord y1,
- SplashCoord dydx) {
- SplashCoord a, ya, yb;
-
- if (dydx >= 0) {
- if (x0 >= xp) {
- if (x1 <= xp + 1) {
- a = ((x0 + x1) * 0.5 - xp) * (y1 - y0);
- } else {
- yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx;
- a = (y1 - y0) - ((SplashCoord)(xp + 1) - x0) * (yb - y0) * 0.5;
+ //--- lower edge
+ } else if (y == rectY1I) {
+ edge = xPath->rectY1 - rectY1I;
+
+ // lower left corner
+ if (x0 <= rectX0I) {
+ pix = (Guchar)splashCeil(edge
+ * ((SplashCoord)1 - (xPath->rectX0 - rectX0I))
+ * 255);
+ if (pix < 16) {
+ pix = 16;
}
+ line[rectX0I] = pix;
+ x = rectX0I + 1;
} else {
- if (x1 <= xp + 1) {
- ya = y0 + ((SplashCoord)xp - x0) * dydx;
- a = (x1 - xp) * (y1 - ya) * 0.5;
- } else {
- // ya = y1 - (x1 - xp - 0.5) * dydx;
- // a = y1 - ya;
- a = (x1 - xp - 0.5) * dydx;
- }
+ x = x0;
}
- } else {
- if (x0 <= xp + 1) {
- if (x1 >= xp) {
- a = ((x0 + x1) * 0.5 - xp) * (y1 - y0);
- } else {
- ya = y0 + ((SplashCoord)xp - x0) * dydx;
- a = (x0 - xp) * (ya - y0) * 0.5;
+
+ // lower right corner
+ if (rectX1I <= x1) {
+ pix = (Guchar)splashCeil(edge * (xPath->rectX1 - rectX1I) * 255);
+ if (pix < 16) {
+ pix = 16;
}
+ line[rectX1I] = pix;
+ xe = rectX1I - 1;
} else {
- if (x1 >= xp) {
- yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx;
- a = (y1 - y0) - ((SplashCoord)(xp + 1) - x1) * (y1 - yb) * 0.5;
- } else {
- // ya = y0 + (xp - x0 + 0.5) * dydx;
- // a = ya - y0;
- a = ((SplashCoord)xp - x0 + 0.5) * dydx;
- }
+ xe = x1;
}
- }
- return a;
-}
-// Compute area within a pixel slice ((xp,y0)-(xp+1,y1)) to the left
-// of a trapezoid edge ((x0,y0)-(x1,y1)).
-SplashCoord SplashXPathScanner::areaRight(int xp,
- SplashCoord x0, SplashCoord y0,
- SplashCoord x1, SplashCoord y1,
- SplashCoord dydx) {
- SplashCoord a, ya, yb;
-
- if (dydx >= 0) {
- if (x0 >= xp) {
- if (x1 <= xp + 1) {
- a = ((SplashCoord)(xp + 1) - (x0 + x1) * 0.5) * (y1 - y0);
- } else {
- yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx;
- a = ((SplashCoord)(xp + 1) - x0) * (yb - y0) * 0.5;
+ // lower edge
+ pix = (Guchar)splashCeil(edge * 255);
+ if (pix < 16) {
+ pix = 16;
+ }
+ for (; x <= xe; ++x) {
+ line[x] = pix;
+ }
+
+ //--- between the upper and lower edges
+ } else if (y > rectY0I && y < rectY1I) {
+
+ // left edge
+ if (x0 <= rectX0I) {
+ pix = (Guchar)splashCeil(((SplashCoord)1 - (xPath->rectX0 - rectX0I))
+ * 255);
+ if (pix < 16) {
+ pix = 16;
}
+ line[rectX0I] = pix;
+ x = rectX0I + 1;
} else {
- if (x1 <= xp + 1) {
- ya = y0 + ((SplashCoord)xp - x0) * dydx;
- a = (y1 - y0) - (x1 - xp) * (y1 - ya) * 0.5;
- } else {
- // ya = y0 + (xp - x0 + 0.5) * dydx;
- // a = ya - y0;
- a = ((SplashCoord)xp + 0.5 - x0) * dydx;
- }
+ x = x0;
}
- } else {
- if (x0 <= xp + 1) {
- if (x1 >= xp) {
- a = ((SplashCoord)(xp + 1) - (x0 + x1) * 0.5) * (y1 - y0);
- } else {
- ya = y0 + ((SplashCoord)xp - x0) * dydx;
- a = (y1 - y0) - (x0 - xp) * (ya - y0) * 0.5;
+
+ // right edge
+ if (rectX1I <= x1) {
+ pix = (Guchar)splashCeil((xPath->rectX1 - rectX1I) * 255);
+ if (pix < 16) {
+ pix = 16;
}
+ line[rectX1I] = pix;
+ xe = rectX1I - 1;
} else {
- if (x1 >= xp) {
- yb = y0 + ((SplashCoord)(xp + 1) - x0) * dydx;
- a = ((SplashCoord)(xp + 1) - x1) * (y1 - yb) * 0.5;
- } else {
- // ya = y1 - (x1 - xp - 0.5) * dydx;
- // a = y1 - ya;
- a = (x1 - xp - 0.5) * dydx;
- }
+ xe = x1;
+ }
+
+ // middle
+ for (; x <= xe; ++x) {
+ line[x] = 255;
}
}
- return a;
}
-void SplashXPathScanner::drawRectangle(Guchar *line, int xMin, int xMax,
- SplashCoord y0, SplashCoord y1,
- SplashCoord x0, SplashCoord x1) {
- SplashCoord dy, a;
- int xx0, xx1, x;
+void SplashXPathScanner::drawRectangleSpanBinary(Guchar *line, int y,
+ int x0, int x1,
+ int *xMin, int *xMax) {
+ int xe, x;
- xx0 = splashFloor(x0);
- if (xx0 < xMin) {
- xx0 = xMin;
- }
- xx1 = splashFloor(x1);
- if (xx1 > xMax) {
- xx1 = xMax;
- }
- dy = y1 - y0;
- for (x = xx0; x <= xx1; ++x) {
- a = dy;
- if ((SplashCoord)x < x0) {
- a -= (x0 - x) * dy;
+ if (y >= rectY0I && y <= rectY1I) {
+ if (x0 <= rectX0I) {
+ x = rectX0I;
+ } else {
+ x = x0;
}
- if ((SplashCoord)(x + 1) > x1) {
- a -= ((SplashCoord)(x + 1) - x1) * dy;
+ *xMin = x;
+ if (rectX1I <= x1) {
+ xe = rectX1I;
+ } else {
+ xe = x1;
+ }
+ *xMax = xe;
+ for (; x <= xe; ++x) {
+ line[x] = 255;
}
- addArea(line, x, a);
}
}
-void SplashXPathScanner::sortActiveSegs() {
- SplashXPathSeg *seg0, *seg1;
- int i, j, k;
+void SplashXPathScanner::getSpan(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax) {
+ int iy, x, k;
- if (activeSegs->getLength() < 2) {
+ iy = y * aaVert;
+ if (!resetDone || !resetAA) {
+ reset(gTrue, gTrue);
+ } else if (yBottomI > iy) {
+ reset(gTrue, gFalse);
+ }
+ memset(line + x0, 0, x1 - x0 + 1);
+
+ *xMin = x1 + 1;
+ *xMax = x0 - 1;
+
+ if (xPath->isRect) {
+ drawRectangleSpan(line, y, x0, x1, xMin, xMax);
return;
}
- seg0 = (SplashXPathSeg *)activeSegs->get(0);
- for (i = 1; i < activeSegs->getLength(); ++i) {
- seg1 = (SplashXPathSeg *)activeSegs->get(i);
- if (SplashXPathSeg::cmpX(seg0, seg1) > 0) {
- for (j = i - 1; j > 0; --j) {
- if (SplashXPathSeg::cmpX((SplashXPathSeg *)activeSegs->get(j - 1),
- seg1) <= 0) {
- break;
- }
- }
- for (k = i; k > j; --k) {
- activeSegs->put(k, activeSegs->get(k-1));
- }
- activeSegs->put(j, seg1);
- } else {
- seg0 = seg1;
- }
+
+ if (yBottomI < iy) {
+ skip(iy, gTrue);
+ }
+ for (k = 0; k < aaVert; ++k, ++iy) {
+ advance(gTrue);
+ generatePixels(x0, x1, line, xMin, xMax);
+ }
+
+#if !ANTIALIAS_256
+ for (x = *xMin; x <= *xMax; ++x) {
+ line[x] = map16to255[line[x]];
}
+#endif
}
-void SplashXPathScanner::insertActiveSeg(SplashXPathSeg *seg) {
- int i;
+void SplashXPathScanner::getSpanBinary(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax) {
+ int iy;
- for (i = 0; i < activeSegs->getLength(); ++i) {
- if (SplashXPathSeg::cmpX(seg, (SplashXPathSeg *)activeSegs->get(i)) < 0) {
- break;
- }
+ iy = y;
+ if (!resetDone || resetAA) {
+ reset(gFalse, gTrue);
+ } else if (yBottomI > iy) {
+ reset(gFalse, gFalse);
+ }
+ memset(line + x0, 0, x1 - x0 + 1);
+
+ *xMin = x1 + 1;
+ *xMax = x0 - 1;
+
+ if (xPath->isRect) {
+ drawRectangleSpanBinary(line, y, x0, x1, xMin, xMax);
+ return;
+ }
+
+ if (yBottomI < iy) {
+ skip(iy, gFalse);
}
- activeSegs->insert(i, seg);
+ advance(gFalse);
+ generatePixelsBinary(x0, x1, line, xMin, xMax);
}
diff --git a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.h b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.h
index 519ff4dfcac..39cc0eb022a 100644
--- a/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.h
+++ b/Build/source/libs/xpdf/xpdf-src/splash/SplashXPathScanner.h
@@ -16,9 +16,15 @@
#endif
#include "SplashTypes.h"
+#include "SplashXPath.h"
class GList;
-class SplashXPath;
+
+//------------------------------------------------------------------------
+
+// Set this to 0 for antialiasing with 16 levels of gray.
+// Set it to 1 for (much slower) antialiasing with 256 levels of gray.
+#define ANTIALIAS_256 0
//------------------------------------------------------------------------
// SplashXPathScanner
@@ -28,48 +34,51 @@ class SplashXPathScanner {
public:
// Create a new SplashXPathScanner object. <xPathA> must be sorted.
- SplashXPathScanner(SplashXPath *xPathA, GBool eoA,
+ SplashXPathScanner(SplashXPath *xPathA, GBool eo,
int yMinA, int yMaxA);
~SplashXPathScanner();
// Compute shape values for a scan line. Fills in line[] with shape
// values for one scan line: ([x0, x1], y). The values are in [0,
- // 255].
- void getSpan(Guchar *line, int y, int x0, int x1);
+ // 255]. Also returns the min/max x positions with non-zero shape
+ // values.
+ void getSpan(Guchar *line, int y, int x0, int x1, int *xMin, int *xMax);
// Like getSpan(), but uses the values 0 and 255 only. Writes 255
// for all pixels which include non-zero area inside the path.
- void getSpanBinary(Guchar *line, int y, int x0, int x1);
+ void getSpanBinary(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax);
private:
- inline void addArea(Guchar *line, int x, SplashCoord a);
- void drawTrapezoid(Guchar *line, int xMin, int xMax,
- SplashCoord y0, SplashCoord y1,
- SplashCoord xa0, SplashCoord xa1, SplashCoord dydxa,
- SplashCoord xb0, SplashCoord xb1, SplashCoord dydxb);
- SplashCoord areaLeft(int xp,
- SplashCoord x0, SplashCoord y0,
- SplashCoord x1, SplashCoord y1,
- SplashCoord dydx);
- SplashCoord areaRight(int xp,
- SplashCoord x0, SplashCoord y0,
- SplashCoord x1, SplashCoord y1,
- SplashCoord dydx);
- void drawRectangle(Guchar *line, int xMin, int xMax,
- SplashCoord y0, SplashCoord y1,
- SplashCoord x0, SplashCoord x1);
- void sortActiveSegs();
- void insertActiveSeg(SplashXPathSeg *seg);
+ void insertSegmentBefore(SplashXPathSeg *s, SplashXPathSeg *sNext);
+ void removeSegment(SplashXPathSeg *s);
+ void moveSegmentAfter(SplashXPathSeg *s, SplashXPathSeg *sPrev);
+ void reset(GBool aa, GBool aaChanged);
+ void skip(int newYBottomI, GBool aa);
+ void advance(GBool aa);
+ void generatePixels(int x0, int x1, Guchar *line, int *xMin, int *xMax);
+ void generatePixelsBinary(int x0, int x1, Guchar *line,
+ int *xMin, int *xMax);
+ void drawRectangleSpan(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax);
+ void drawRectangleSpanBinary(Guchar *line, int y, int x0, int x1,
+ int *xMin, int *xMax);
SplashXPath *xPath;
- GBool eo;
+ int eoMask;
int yMin, yMax;
+ int rectX0I, rectY0I, rectX1I, rectY1I;
+
+ SplashXPathSeg preSeg, postSeg;
+ SplashXPathSeg *pre, *post;
- GList *activeSegs; // [SplashXPathSeg]
+ GBool resetDone;
+ GBool resetAA;
int nextSeg;
- int yNext;
+ int yTopI, yBottomI;
+ SplashCoord yTop, yBottom;
};
#endif