[poppler] 4 commits - CMakeLists.txt poppler/Gfx.cc poppler/Gfx.h poppler/GfxState.cc poppler/GfxState_helpers.h poppler/Makefile.am poppler/OutputDev.h poppler/PSOutputDev.cc poppler/PSOutputDev.h poppler/SplashOutputDev.cc poppler/SplashOutputDev.h splash/SplashState.cc splash/SplashTypes.h
Albert Astals Cid
aacid at kemper.freedesktop.org
Tue Jun 2 14:02:48 PDT 2009
CMakeLists.txt | 1
poppler/Gfx.cc | 135 ++++++++++++---
poppler/Gfx.h | 7
poppler/GfxState.cc | 63 -------
poppler/GfxState_helpers.h | 80 ++++++++
poppler/Makefile.am | 1
poppler/OutputDev.h | 14 +
poppler/PSOutputDev.cc | 285 ++++++++++++++++++-------------
poppler/PSOutputDev.h | 18 ++
poppler/SplashOutputDev.cc | 404 +++++++++++++++++++++++++++++++++++++--------
poppler/SplashOutputDev.h | 19 ++
splash/SplashState.cc | 17 +
splash/SplashTypes.h | 10 +
13 files changed, 798 insertions(+), 256 deletions(-)
New commits:
commit 104f9286ceb5fcb5f4795bca7633029142d5f6a4
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date: Tue Jun 2 22:59:42 2009 +0200
Support colorizing text in pattern colorspace
This implements commits the final patches for bug 19670 and 19994
Also fixes bugs 15819 and 2807
Also implements blending for SPLASH_CMYK in Splash
It's a quite big change but i've done regression testing over my whole
pdf suite and did not fit anything that went worse, just improvements
Missing the Cairo support
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 03085a5..9e81b39 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -287,6 +287,7 @@ if(ENABLE_XPDF_HEADERS)
poppler/Gfx.h
poppler/GfxFont.h
poppler/GfxState.h
+ poppler/GfxState_helpers.h
poppler/GlobalParams.h
poppler/JArithmeticDecoder.h
poppler/JBIG2Stream.h
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index 72b1068..e907850 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -28,6 +28,7 @@
// Copyright (C) 2008 Michael Vrable <mvrable at cs.ucsd.edu>
// Copyright (C) 2008 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2009 M Joonas Pihlaja <jpihlaja at cc.helsinki.fi>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -498,6 +499,9 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, int pageNum, Dict *resDict, Catalog *cata
subPage = gFalse;
printCommands = globalParams->getPrintCommands();
profileCommands = globalParams->getProfileCommands();
+ textHaveCSPattern = gFalse;
+ drawText = gFalse;
+ maskHaveCSPattern = gFalse;
mcStack = NULL;
// start the resource stack
@@ -542,6 +546,9 @@ Gfx::Gfx(XRef *xrefA, OutputDev *outA, Dict *resDict, Catalog *catalogA,
catalog = catalogA;
subPage = gTrue;
printCommands = globalParams->getPrintCommands();
+ textHaveCSPattern = gFalse;
+ drawText = gFalse;
+ maskHaveCSPattern = gFalse;
mcStack = NULL;
// start the resource stack
@@ -1230,12 +1237,32 @@ void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
void Gfx::opSetFillGray(Object args[], int numArgs) {
GfxColor color;
- state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceGrayColorSpace());
- out->updateFillColorSpace(state);
- color.c[0] = dblToCol(args[0].getNum());
- state->setFillColor(&color);
- out->updateFillColor(state);
+ if (textHaveCSPattern) {
+ GBool needFill = out->deviceHasTextClip(state);
+ out->endTextObject(state);
+ if (needFill) {
+ doPatternFill(gTrue);
+ }
+ out->restoreState(state);
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ out->updateFillColorSpace(state);
+ color.c[0] = dblToCol(args[0].getNum());
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+ out->beginTextObject(state);
+ out->updateRender(state);
+ out->updateTextMat(state);
+ out->updateTextPos(state);
+ textHaveCSPattern = gFalse;
+ } else {
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ out->updateFillColorSpace(state);
+ color.c[0] = dblToCol(args[0].getNum());
+ state->setFillColor(&color);
+ out->updateFillColor(state);
+ }
}
void Gfx::opSetStrokeGray(Object args[], int numArgs) {
@@ -1253,14 +1280,21 @@ void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
GfxColor color;
int i;
- state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
- out->updateFillColorSpace(state);
- for (i = 0; i < 4; ++i) {
- color.c[i] = dblToCol(args[i].getNum());
+ if (textHaveCSPattern) {
+ colorSpaceText = new GfxDeviceCMYKColorSpace();
+ for (i = 0; i < 4; ++i) {
+ colorText.c[i] = dblToCol(args[i].getNum());
+ }
+ } else {
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
+ out->updateFillColorSpace(state);
+ for (i = 0; i < 4; ++i) {
+ color.c[i] = dblToCol(args[i].getNum());
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
}
- state->setFillColor(&color);
- out->updateFillColor(state);
}
void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
@@ -1281,14 +1315,21 @@ void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
GfxColor color;
int i;
- state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceRGBColorSpace());
- out->updateFillColorSpace(state);
- for (i = 0; i < 3; ++i) {
- color.c[i] = dblToCol(args[i].getNum());
+ if (textHaveCSPattern) {
+ colorSpaceText = new GfxDeviceRGBColorSpace();
+ for (i = 0; i < 3; ++i) {
+ colorText.c[i] = dblToCol(args[i].getNum());
+ }
+ } else {
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+ out->updateFillColorSpace(state);
+ for (i = 0; i < 3; ++i) {
+ color.c[i] = dblToCol(args[i].getNum());
+ }
+ state->setFillColor(&color);
+ out->updateFillColor(state);
}
- state->setFillColor(&color);
- out->updateFillColor(state);
}
void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) {
@@ -1324,6 +1365,24 @@ void Gfx::opSetFillColorSpace(Object args[], int numArgs) {
colorSpace->getDefaultColor(&color);
state->setFillColor(&color);
out->updateFillColor(state);
+ if (drawText) {
+ if (colorSpace->getMode() == csPattern) {
+ colorSpaceText = NULL;
+ textHaveCSPattern = gTrue;
+ out->beginTextObject(state);
+ } else if (textHaveCSPattern) {
+ GBool needFill = out->deviceHasTextClip(state);
+ out->endTextObject(state);
+ if (needFill) {
+ doPatternFill(gTrue);
+ }
+ out->beginTextObject(state);
+ out->updateRender(state);
+ out->updateTextMat(state);
+ out->updateTextPos(state);
+ textHaveCSPattern = gFalse;
+ }
+ }
} else {
error(getPos(), "Bad color space (fill)");
}
@@ -1847,7 +1906,7 @@ void Gfx::doTilingPatternFill(GfxTilingPattern *tPat,
if (stroke) {
state->clipToStrokePath();
out->clipToStrokePath(state);
- } else {
+ } else if (!textHaveCSPattern && !maskHaveCSPattern) {
state->clip();
if (eoFill) {
out->eoClip(state);
@@ -1975,7 +2034,7 @@ void Gfx::doShadingPatternFill(GfxShadingPattern *sPat,
if (stroke) {
state->clipToStrokePath();
out->clipToStrokePath(state);
- } else {
+ } else if (!textHaveCSPattern && !maskHaveCSPattern) {
state->clip();
if (eoFill) {
out->eoClip(state);
@@ -3121,15 +3180,38 @@ void Gfx::opEOClip(Object args[], int numArgs) {
//------------------------------------------------------------------------
void Gfx::opBeginText(Object args[], int numArgs) {
+ out->beginTextObject(state);
+ drawText = gTrue;
state->setTextMat(1, 0, 0, 1, 0, 0);
state->textMoveTo(0, 0);
out->updateTextMat(state);
out->updateTextPos(state);
fontChanged = gTrue;
+ if (out->supportTextCSPattern(state)) {
+ colorSpaceText = NULL;
+ textHaveCSPattern = gTrue;
+ }
}
void Gfx::opEndText(Object args[], int numArgs) {
+ GBool needFill = out->deviceHasTextClip(state);
out->endTextObject(state);
+ drawText = gFalse;
+ if (out->supportTextCSPattern(state) && textHaveCSPattern) {
+ if (needFill) {
+ doPatternFill(gTrue);
+ }
+ out->restoreState(state);
+ if (colorSpaceText != NULL) {
+ state->setFillPattern(NULL);
+ state->setFillColorSpace(colorSpaceText);
+ out->updateFillColorSpace(state);
+ state->setFillColor(&colorText);
+ out->updateFillColor(state);
+ colorSpaceText = NULL;
+ }
+ }
+ textHaveCSPattern = gFalse;
}
//------------------------------------------------------------------------
@@ -3170,6 +3252,9 @@ void Gfx::opSetTextLeading(Object args[], int numArgs) {
void Gfx::opSetTextRender(Object args[], int numArgs) {
state->setRender(args[0].getInt());
+ if (args[0].getInt() == 7) {
+ textHaveCSPattern = gFalse;
+ }
out->updateRender(state);
}
@@ -3695,6 +3780,12 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
// draw it
if (!contentIsHidden())
out->drawImageMask(state, ref, str, width, height, invert, inlineImg);
+ if (out->fillMaskCSPattern(state)) {
+ maskHaveCSPattern = gTrue;
+ doPatternFill(gTrue);
+ out->endMaskClip(state);
+ maskHaveCSPattern = gFalse;
+ }
} else {
diff --git a/poppler/Gfx.h b/poppler/Gfx.h
index a75a92a..e03d025 100644
--- a/poppler/Gfx.h
+++ b/poppler/Gfx.h
@@ -18,6 +18,7 @@
// Copyright (C) 2008 Brad Hards <bradh at kde.org>
// Copyright (C) 2008 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2009 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -33,6 +34,7 @@
#include "goo/gtypes.h"
#include "goo/GooList.h"
+#include "GfxState.h"
#include "Object.h"
class GooString;
@@ -175,6 +177,11 @@ private:
GBool subPage; // is this a sub-page object?
GBool printCommands; // print the drawing commands (for debugging)
GBool profileCommands; // profile the drawing commands (for debugging)
+ GBool textHaveCSPattern; // in text drawing and text has pattern colorspace
+ GBool drawText; // in text drawing
+ GBool maskHaveCSPattern; // in mask drawing and mask has pattern colorspace
+ GfxColorSpace *colorSpaceText;// colorspace after text has filled with pattern
+ GfxColor colorText; // fill color after after text has filled with pattern
GfxResources *res; // resource stack
int updateLevel;
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 14c0a3f..d75e015 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -40,19 +40,12 @@
#include "Array.h"
#include "Page.h"
#include "GfxState.h"
+#include "GfxState_helpers.h"
#include "GfxFont.h"
#include "GlobalParams.h"
//------------------------------------------------------------------------
-static inline GfxColorComp clip01(GfxColorComp x) {
- return (x < 0) ? 0 : (x > gfxColorComp1) ? gfxColorComp1 : x;
-}
-
-static inline double clip01(double x) {
- return (x < 0) ? 0 : (x > 1) ? 1 : x;
-}
-
GBool Matrix::invertTo(Matrix *other)
{
double det;
@@ -1077,7 +1070,7 @@ void GfxDeviceCMYKColorSpace::getGray(GfxColor *color, GfxGray *gray) {
}
void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
- double c, m, y, k, c1, m1, y1, k1, r, g, b, x;
+ double c, m, y, k, c1, m1, y1, k1, r, g, b;
c = colToDbl(color->c[0]);
m = colToDbl(color->c[1]);
@@ -1087,52 +1080,7 @@ void GfxDeviceCMYKColorSpace::getRGB(GfxColor *color, GfxRGB *rgb) {
m1 = 1 - m;
y1 = 1 - y;
k1 = 1 - k;
- // this is a matrix multiplication, unrolled for performance
- // C M Y K
- x = c1 * m1 * y1 * k1; // 0 0 0 0
- r = g = b = x;
- x = c1 * m1 * y1 * k; // 0 0 0 1
- r += 0.1373 * x;
- g += 0.1216 * x;
- b += 0.1255 * x;
- x = c1 * m1 * y * k1; // 0 0 1 0
- r += x;
- g += 0.9490 * x;
- x = c1 * m1 * y * k; // 0 0 1 1
- r += 0.1098 * x;
- g += 0.1020 * x;
- x = c1 * m * y1 * k1; // 0 1 0 0
- r += 0.9255 * x;
- b += 0.5490 * x;
- x = c1 * m * y1 * k; // 0 1 0 1
- r += 0.1412 * x;
- x = c1 * m * y * k1; // 0 1 1 0
- r += 0.9294 * x;
- g += 0.1098 * x;
- b += 0.1412 * x;
- x = c1 * m * y * k; // 0 1 1 1
- r += 0.1333 * x;
- x = c * m1 * y1 * k1; // 1 0 0 0
- g += 0.6784 * x;
- b += 0.9373 * x;
- x = c * m1 * y1 * k; // 1 0 0 1
- g += 0.0588 * x;
- b += 0.1412 * x;
- x = c * m1 * y * k1; // 1 0 1 0
- g += 0.6510 * x;
- b += 0.3137 * x;
- x = c * m1 * y * k; // 1 0 1 1
- g += 0.0745 * x;
- x = c * m * y1 * k1; // 1 1 0 0
- r += 0.1804 * x;
- g += 0.1922 * x;
- b += 0.5725 * x;
- x = c * m * y1 * k; // 1 1 0 1
- b += 0.0078 * x;
- x = c * m * y * k1; // 1 1 1 0
- r += 0.2118 * x;
- g += 0.2119 * x;
- b += 0.2235 * x;
+ cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b);
rgb->r = clip01(dblToCol(r));
rgb->g = clip01(dblToCol(g));
rgb->b = clip01(dblToCol(b));
diff --git a/poppler/GfxState_helpers.h b/poppler/GfxState_helpers.h
new file mode 100644
index 0000000..77ac710
--- /dev/null
+++ b/poppler/GfxState_helpers.h
@@ -0,0 +1,80 @@
+//========================================================================
+//
+// GfxState.cc
+//
+// Copyright 1996-2003 Glyph & Cog, LLC
+//
+//========================================================================
+
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2009 Albert Astals Cid <aacid at kde.org>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
+static inline GfxColorComp clip01(GfxColorComp x) {
+ return (x < 0) ? 0 : (x > gfxColorComp1) ? gfxColorComp1 : x;
+}
+
+static inline double clip01(double x) {
+ return (x < 0) ? 0 : (x > 1) ? 1 : x;
+}
+
+static inline void cmykToRGBMatrixMultiplication(const double &c, const double &m, const double &y, const double &k, const double &c1, const double &m1, const double &y1, const double &k1, double &r, double &g, double &b)
+{
+ double x;
+ // this is a matrix multiplication, unrolled for performance
+ // C M Y K
+ x = c1 * m1 * y1 * k1; // 0 0 0 0
+ r = g = b = x;
+ x = c1 * m1 * y1 * k; // 0 0 0 1
+ r += 0.1373 * x;
+ g += 0.1216 * x;
+ b += 0.1255 * x;
+ x = c1 * m1 * y * k1; // 0 0 1 0
+ r += x;
+ g += 0.9490 * x;
+ x = c1 * m1 * y * k; // 0 0 1 1
+ r += 0.1098 * x;
+ g += 0.1020 * x;
+ x = c1 * m * y1 * k1; // 0 1 0 0
+ r += 0.9255 * x;
+ b += 0.5490 * x;
+ x = c1 * m * y1 * k; // 0 1 0 1
+ r += 0.1412 * x;
+ x = c1 * m * y * k1; // 0 1 1 0
+ r += 0.9294 * x;
+ g += 0.1098 * x;
+ b += 0.1412 * x;
+ x = c1 * m * y * k; // 0 1 1 1
+ r += 0.1333 * x;
+ x = c * m1 * y1 * k1; // 1 0 0 0
+ g += 0.6784 * x;
+ b += 0.9373 * x;
+ x = c * m1 * y1 * k; // 1 0 0 1
+ g += 0.0588 * x;
+ b += 0.1412 * x;
+ x = c * m1 * y * k1; // 1 0 1 0
+ g += 0.6510 * x;
+ b += 0.3137 * x;
+ x = c * m1 * y * k; // 1 0 1 1
+ g += 0.0745 * x;
+ x = c * m * y1 * k1; // 1 1 0 0
+ r += 0.1804 * x;
+ g += 0.1922 * x;
+ b += 0.5725 * x;
+ x = c * m * y1 * k; // 1 1 0 1
+ b += 0.0078 * x;
+ x = c * m * y * k1; // 1 1 1 0
+ r += 0.2118 * x;
+ g += 0.2119 * x;
+ b += 0.2235 * x;
+}
diff --git a/poppler/Makefile.am b/poppler/Makefile.am
index 1c63284..4f0f410 100644
--- a/poppler/Makefile.am
+++ b/poppler/Makefile.am
@@ -169,6 +169,7 @@ poppler_include_HEADERS = \
Gfx.h \
GfxFont.h \
GfxState.h \
+ GfxState_helpers.h \
GlobalParams.h \
JArithmeticDecoder.h \
JBIG2Stream.h \
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index 66b5c38..4866631 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -17,6 +17,7 @@
// Copyright (C) 2006 Thorkild Stray <thorkild at ifi.uio.no>
// Copyright (C) 2007 Jeff Muizelaar <jeff at infidigm.net>
// Copyright (C) 2007 Adrian Johnson <ajohnson at redneon.com>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -94,6 +95,17 @@ public:
// Does this device need non-text content?
virtual GBool needNonText() { return gTrue; }
+ // If current colorspace ist pattern,
+ // does this device support text in pattern colorspace?
+ // Default is false
+ virtual GBool supportTextCSPattern(GfxState * /*state*/) { return gFalse; }
+
+ // If current colorspace ist pattern,
+ // need this device special handling for masks in pattern colorspace?
+ // Default is false
+ virtual GBool fillMaskCSPattern(GfxState * /*state*/) { return gFalse; }
+ virtual void endMaskClip(GfxState * /*state*/) {}
+
//----- initialization and control
// Set default transform matrix.
@@ -204,6 +216,8 @@ public:
double /*dx*/, double /*dy*/,
CharCode /*code*/, Unicode * /*u*/, int /*uLen*/);
virtual void endType3Char(GfxState * /*state*/) {}
+ virtual void beginTextObject(GfxState * /*state*/) {}
+ virtual GBool deviceHasTextClip(GfxState * /*state*/) { return gFalse; }
virtual void endTextObject(GfxState * /*state*/) {}
//----- image drawing
diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc
index f02bd98..d24e77e 100644
--- a/poppler/PSOutputDev.cc
+++ b/poppler/PSOutputDev.cc
@@ -20,6 +20,7 @@
// Copyright (C) 2007, 2008 Brad Hards <bradh at kde.org>
// Copyright (C) 2008 Koji Otani <sho at bbr.jp>
// Copyright (C) 2008 Hib Eris <hib at hiberis.nl>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -493,6 +494,8 @@ static char *prolog[] = {
" pdfTextMat dtransform rmoveto } def",
"/Tclip { pdfTextClipPath cvx exec clip newpath",
" /pdfTextClipPath [] def } def",
+ "/Tclip* { pdfTextClipPath cvx exec eoclip newpath",
+ " /pdfTextClipPath [] def } def",
"~1ns",
"% Level 1 image operators",
"~1n",
@@ -990,6 +993,7 @@ PSOutputDev::PSOutputDev(const char *fileName, XRef *xrefA, Catalog *catalog,
embFontList = NULL;
customColors = NULL;
haveTextClip = gFalse;
+ haveCSPattern = gFalse;
t3String = NULL;
forceRasterize = forceRasterizeA;
@@ -1053,6 +1057,7 @@ PSOutputDev::PSOutputDev(PSOutputFunc outputFuncA, void *outputStreamA,
embFontList = NULL;
customColors = NULL;
haveTextClip = gFalse;
+ haveCSPattern = gFalse;
t3String = NULL;
forceRasterize = forceRasterizeA;
@@ -2755,6 +2760,9 @@ void PSOutputDev::setupImage(Ref id, Stream *str) {
++col;
}
}
+ if (c == (useASCIIHex ? '>' : '~') || c == EOF) {
+ break;
+ }
// each line is: "dup nnnnn <~...data...~> put<eol>"
// so max data length = 255 - 20 = 235
// chunks are 1 or 4 bytes each, so we have to stop at 232
@@ -3632,6 +3640,10 @@ void PSOutputDev::updateRender(GfxState *state) {
int rm;
rm = state->getRender();
+ if (rm == 7 && haveCSPattern) {
+ haveCSPattern = gFalse;
+ restoreState(state);
+ }
writePSFmt("{0:d} Tr\n", rm);
rm &= 3;
if (rm != 0 && rm != 3) {
@@ -4283,34 +4295,71 @@ void PSOutputDev::drawString(GfxState *state, GooString *s) {
}
}
+void PSOutputDev::beginTextObject(GfxState *state) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ saveState(state);
+ haveCSPattern = gTrue;
+ savedRender = state->getRender();
+ state->setRender(7);
+ writePSFmt("{0:d} Tr\n", 7);
+ }
+}
+
void PSOutputDev::endTextObject(GfxState *state) {
- if (haveTextClip) {
+ if (haveCSPattern) {
+ if (haveTextClip) {
+ writePS("Tclip*\n");
+ haveTextClip = gFalse;
+ state->setRender(savedRender);
+ if (state->getFillColorSpace()->getMode() != csPattern) {
+ double cxMin, cyMin, cxMax, cyMax;
+ state->getClipBBox(&cxMin, &cyMin, &cxMax, &cyMax);
+ writePSFmt("{0:.4g} {1:.4g} {2:.4g} {3:.4g} re\n",
+ cxMin, cyMin,
+ cxMax, cyMax);
+ writePS("f*\n");
+ restoreState(state);
+ updateFillColor(state);
+ }
+ } else {
+ state->setRender(savedRender);
+ }
+ haveCSPattern = gFalse;
+ } else if (haveTextClip) {
writePS("Tclip\n");
haveTextClip = gFalse;
}
}
+void PSOutputDev::endMaskClip(GfxState * state) {
+ writePS("pdfImClipEnd\n");
+}
+
void PSOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg) {
int len;
len = height * ((width + 7) / 8);
- switch (level) {
- case psLevel1:
- case psLevel1Sep:
- doImageL1(ref, NULL, invert, inlineImg, str, width, height, len);
- break;
- case psLevel2:
- case psLevel2Sep:
- doImageL2(ref, NULL, invert, inlineImg, str, width, height, len,
- NULL, NULL, 0, 0, gFalse);
- break;
- case psLevel3:
- case psLevel3Sep:
- doImageL3(ref, NULL, invert, inlineImg, str, width, height, len,
- NULL, NULL, 0, 0, gFalse);
- break;
+ if (state->getFillColorSpace()->getMode() == csPattern && (level != psLevel1 && level != psLevel1Sep)) {
+ maskToClippingPath(str, width, height, invert);
+ } else {
+ switch (level) {
+ case psLevel1:
+ case psLevel1Sep:
+ doImageL1(ref, NULL, invert, inlineImg, str, width, height, len);
+ break;
+ case psLevel2:
+ case psLevel2Sep:
+ doImageL2(ref, NULL, invert, inlineImg, str, width, height, len,
+ NULL, NULL, 0, 0, gFalse);
+ break;
+ case psLevel3:
+ case psLevel3Sep:
+ doImageL3(ref, NULL, invert, inlineImg, str, width, height, len,
+ NULL, NULL, 0, 0, gFalse);
+ break;
+ }
}
}
@@ -4547,6 +4596,110 @@ void PSOutputDev::doImageL1Sep(GfxImageColorMap *colorMap,
gfree(lineBuf);
}
+void PSOutputDev::maskToClippingPath(Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert) {
+ ImageStream *imgStr;
+ Guchar *line;
+ PSOutImgClipRect *rects0, *rects1, *rectsTmp, *rectsOut;
+ int rects0Len, rects1Len, rectsSize, rectsOutLen, rectsOutSize;
+ GBool emitRect, addRect, extendRect;
+ int i, x0, x1, y, maskXor;
+
+ imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
+ imgStr->reset();
+ rects0Len = rects1Len = rectsOutLen = 0;
+ rectsSize = rectsOutSize = 64;
+ rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
+ rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
+ rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize, sizeof(PSOutImgClipRect));
+ maskXor = maskInvert ? 1 : 0;
+ for (y = 0; y < maskHeight; ++y) {
+ if (!(line = imgStr->getLine())) {
+ break;
+ }
+ i = 0;
+ rects1Len = 0;
+ for (x0 = 0; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ;
+ for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ;
+ while (x0 < maskWidth || i < rects0Len) {
+ emitRect = addRect = extendRect = gFalse;
+ if (x0 >= maskWidth) {
+ emitRect = gTrue;
+ } else if (i >= rects0Len) {
+ addRect = gTrue;
+ } else if (rects0[i].x0 < x0) {
+ emitRect = gTrue;
+ } else if (x0 < rects0[i].x0) {
+ addRect = gTrue;
+ } else if (rects0[i].x1 == x1) {
+ extendRect = gTrue;
+ } else {
+ emitRect = addRect = gTrue;
+ }
+ if (emitRect) {
+ if (rectsOutLen == rectsOutSize) {
+ rectsOutSize *= 2;
+ rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, sizeof(PSOutImgClipRect));
+ }
+ rectsOut[rectsOutLen].x0 = rects0[i].x0;
+ rectsOut[rectsOutLen].x1 = rects0[i].x1;
+ rectsOut[rectsOutLen].y0 = maskHeight - y - 1;
+ rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1;
+ ++rectsOutLen;
+ ++i;
+ }
+ if (addRect || extendRect) {
+ if (rects1Len == rectsSize) {
+ rectsSize *= 2;
+ rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize, sizeof(PSOutImgClipRect));
+ rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize, sizeof(PSOutImgClipRect));
+ }
+ rects1[rects1Len].x0 = x0;
+ rects1[rects1Len].x1 = x1;
+ if (addRect) {
+ rects1[rects1Len].y0 = y;
+ }
+ if (extendRect) {
+ rects1[rects1Len].y0 = rects0[i].y0;
+ ++i;
+ }
+ ++rects1Len;
+ for (x0 = x1; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ;
+ for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ;
+ }
+ }
+ rectsTmp = rects0;
+ rects0 = rects1;
+ rects1 = rectsTmp;
+ i = rects0Len;
+ rects0Len = rects1Len;
+ rects1Len = i;
+ }
+ for (i = 0; i < rects0Len; ++i) {
+ if (rectsOutLen == rectsOutSize) {
+ rectsOutSize *= 2;
+ rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize, sizeof(PSOutImgClipRect));
+ }
+ rectsOut[rectsOutLen].x0 = rects0[i].x0;
+ rectsOut[rectsOutLen].x1 = rects0[i].x1;
+ rectsOut[rectsOutLen].y0 = maskHeight - y - 1;
+ rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1;
+ ++rectsOutLen;
+ }
+ writePSFmt("{0:d} array 0\n", rectsOutLen * 4);
+ for (i = 0; i < rectsOutLen; ++i) {
+ writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n",
+ rectsOut[i].x0, rectsOut[i].y0,
+ rectsOut[i].x1 - rectsOut[i].x0,
+ rectsOut[i].y1 - rectsOut[i].y0);
+ }
+ writePSFmt("pop {0:d} {1:d} pdfImClip\n", maskWidth, maskHeight);
+ gfree(rectsOut);
+ gfree(rects0);
+ gfree(rects1);
+ delete imgStr;
+ maskStr->close();
+}
+
void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
GBool invert, GBool inlineImg,
Stream *str, int width, int height, int len,
@@ -4713,105 +4866,7 @@ void PSOutputDev::doImageL2(Object *ref, GfxImageColorMap *colorMap,
// explicit masking
} else if (maskStr) {
- imgStr = new ImageStream(maskStr, maskWidth, 1, 1);
- imgStr->reset();
- rects0Len = rects1Len = rectsOutLen = 0;
- rectsSize = rectsOutSize = 64;
- rects0 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
- rects1 = (PSOutImgClipRect *)gmallocn(rectsSize, sizeof(PSOutImgClipRect));
- rectsOut = (PSOutImgClipRect *)gmallocn(rectsOutSize,
- sizeof(PSOutImgClipRect));
- maskXor = maskInvert ? 1 : 0;
- for (y = 0; y < maskHeight; ++y) {
- if (!(line = imgStr->getLine())) {
- break;
- }
- i = 0;
- rects1Len = 0;
- for (x0 = 0; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ;
- for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ;
- while (x0 < maskWidth || i < rects0Len) {
- emitRect = addRect = extendRect = gFalse;
- if (x0 >= maskWidth) {
- emitRect = gTrue;
- } else if (i >= rects0Len) {
- addRect = gTrue;
- } else if (rects0[i].x0 < x0) {
- emitRect = gTrue;
- } else if (x0 < rects0[i].x0) {
- addRect = gTrue;
- } else if (rects0[i].x1 == x1) {
- extendRect = gTrue;
- } else {
- emitRect = addRect = gTrue;
- }
- if (emitRect) {
- if (rectsOutLen == rectsOutSize) {
- rectsOutSize *= 2;
- rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize,
- sizeof(PSOutImgClipRect));
- }
- rectsOut[rectsOutLen].x0 = rects0[i].x0;
- rectsOut[rectsOutLen].x1 = rects0[i].x1;
- rectsOut[rectsOutLen].y0 = maskHeight - y - 1;
- rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1;
- ++rectsOutLen;
- ++i;
- }
- if (addRect || extendRect) {
- if (rects1Len == rectsSize) {
- rectsSize *= 2;
- rects0 = (PSOutImgClipRect *)greallocn(rects0, rectsSize,
- sizeof(PSOutImgClipRect));
- rects1 = (PSOutImgClipRect *)greallocn(rects1, rectsSize,
- sizeof(PSOutImgClipRect));
- }
- rects1[rects1Len].x0 = x0;
- rects1[rects1Len].x1 = x1;
- if (addRect) {
- rects1[rects1Len].y0 = y;
- }
- if (extendRect) {
- rects1[rects1Len].y0 = rects0[i].y0;
- ++i;
- }
- ++rects1Len;
- for (x0 = x1; x0 < maskWidth && (line[x0] ^ maskXor); ++x0) ;
- for (x1 = x0; x1 < maskWidth && !(line[x1] ^ maskXor); ++x1) ;
- }
- }
- rectsTmp = rects0;
- rects0 = rects1;
- rects1 = rectsTmp;
- i = rects0Len;
- rects0Len = rects1Len;
- rects1Len = i;
- }
- for (i = 0; i < rects0Len; ++i) {
- if (rectsOutLen == rectsOutSize) {
- rectsOutSize *= 2;
- rectsOut = (PSOutImgClipRect *)greallocn(rectsOut, rectsOutSize,
- sizeof(PSOutImgClipRect));
- }
- rectsOut[rectsOutLen].x0 = rects0[i].x0;
- rectsOut[rectsOutLen].x1 = rects0[i].x1;
- rectsOut[rectsOutLen].y0 = maskHeight - y - 1;
- rectsOut[rectsOutLen].y1 = maskHeight - rects0[i].y0 - 1;
- ++rectsOutLen;
- }
- writePSFmt("{0:d} array 0\n", rectsOutLen * 4);
- for (i = 0; i < rectsOutLen; ++i) {
- writePSFmt("[{0:d} {1:d} {2:d} {3:d}] pr\n",
- rectsOut[i].x0, rectsOut[i].y0,
- rectsOut[i].x1 - rectsOut[i].x0,
- rectsOut[i].y1 - rectsOut[i].y0);
- }
- writePSFmt("pop {0:d} {1:d} pdfImClip\n", maskWidth, maskHeight);
- gfree(rectsOut);
- gfree(rects0);
- gfree(rects1);
- delete imgStr;
- maskStr->close();
+ maskToClippingPath(maskStr, maskWidth, maskHeight, maskInvert);
}
// color space
diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h
index e490110..0aea502 100644
--- a/poppler/PSOutputDev.h
+++ b/poppler/PSOutputDev.h
@@ -17,6 +17,7 @@
// Copyright (C) 2005 Kristian Høgsberg <krh at redhat.com>
// Copyright (C) 2006-2008 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2007 Brad Hards <bradh at kde.org>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -33,6 +34,7 @@
#include <poppler-config.h>
#include <stddef.h>
#include "Object.h"
+#include "GfxState.h"
#include "GlobalParams.h"
#include "OutputDev.h"
@@ -125,6 +127,10 @@ public:
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gFalse; }
+ // This device now supports text in pattern colorspace!
+ virtual GBool supportTextCSPattern(GfxState *state)
+ { return state->getFillColorSpace()->getMode() == csPattern; }
+
//----- header/trailer (used only if manualCtrl is true)
// Write the document-level header.
@@ -216,6 +222,8 @@ public:
//----- text drawing
virtual void drawString(GfxState *state, GooString *s);
+ virtual void beginTextObject(GfxState *state);
+ virtual GBool deviceHasTextClip(GfxState *state) { return haveTextClip && haveCSPattern; }
virtual void endTextObject(GfxState *state);
//----- image drawing
@@ -230,6 +238,12 @@ public:
GfxImageColorMap *colorMap,
Stream *maskStr, int maskWidth, int maskHeight,
GBool maskInvert);
+ // If current colorspace ist pattern,
+ // need this device special handling for masks in pattern colorspace?
+ // Default is false
+ virtual GBool fillMaskCSPattern(GfxState * state)
+ { return state->getFillColorSpace()->getMode() == csPattern && (level != psLevel1 && level != psLevel1Sep); }
+ virtual void endMaskClip(GfxState * /*state*/);
#if OPI_SUPPORT
//----- OPI functions
@@ -295,6 +309,7 @@ private:
void addProcessColor(double c, double m, double y, double k);
void addCustomColor(GfxSeparationColorSpace *sepCS);
void doPath(GfxPath *path);
+ void maskToClippingPath(Stream *maskStr, int maskWidth, int maskHeight, GBool maskInvert);
void doImageL1(Object *ref, GfxImageColorMap *colorMap,
GBool invert, GBool inlineImg,
Stream *str, int width, int height, int len);
@@ -400,6 +415,9 @@ private:
GBool haveTextClip; // set if text has been drawn with a
// clipping render mode
+ GBool haveCSPattern; // set if text has been drawn with a
+ // clipping render mode because of pattern colorspace
+ int savedRender; // use if pattern colorspace
GBool inType3Char; // inside a Type 3 CharProc
GooString *t3String; // Type 3 content string
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index ca44682..9341c86 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -20,6 +20,7 @@
// Copyright (C) 2006 Scott Turner <scotty1024 at mac.com>
// Copyright (C) 2007 Koji Otani <sho at bbr.jp>
// Copyright (C) 2009 Petr Gajdos <pgajdos at novell.com>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -70,6 +71,54 @@ static inline Guchar div255(int x) {
return (Guchar)((x + (x >> 8) + 0x80) >> 8);
}
+#if SPLASH_CMYK
+
+#include "GfxState_helpers.h"
+
+//-------------------------------------------------------------------------
+// helper for Blend functions (convert CMYK to RGB, do blend, convert back)
+//-------------------------------------------------------------------------
+
+// based in GfxState.cc
+
+static void cmykToRGB(SplashColorPtr cmyk, SplashColor rgb) {
+ double c, m, y, k, c1, m1, y1, k1, r, g, b;
+
+ c = colToDbl(byteToCol(cmyk[0]));
+ m = colToDbl(byteToCol(cmyk[1]));
+ y = colToDbl(byteToCol(cmyk[2]));
+ k = colToDbl(byteToCol(cmyk[3]));
+ c1 = 1 - c;
+ m1 = 1 - m;
+ y1 = 1 - y;
+ k1 = 1 - k;
+ cmykToRGBMatrixMultiplication(c, m, y, k, c1, m1, y1, k1, r, g, b);
+ rgb[0] = colToByte(clip01(dblToCol(r)));
+ rgb[1] = colToByte(clip01(dblToCol(g)));
+ rgb[2] = colToByte(clip01(dblToCol(b)));
+}
+
+static void rgbToCMYK(SplashColor rgb, SplashColorPtr cmyk) {
+ GfxColorComp c, m, y, k;
+
+ c = clip01(gfxColorComp1 - byteToCol(rgb[0]));
+ m = clip01(gfxColorComp1 - byteToCol(rgb[1]));
+ y = clip01(gfxColorComp1 - byteToCol(rgb[2]));
+ k = c;
+ if (m < k) {
+ k = m;
+ }
+ if (y < k) {
+ k = y;
+ }
+ cmyk[0] = colToByte(c - k);
+ cmyk[1] = colToByte(m - k);
+ cmyk[2] = colToByte(y - k);
+ cmyk[3] = colToByte(k);
+}
+
+#endif
+
//------------------------------------------------------------------------
// Blend functions
//------------------------------------------------------------------------
@@ -78,8 +127,23 @@ static void splashOutBlendMultiply(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = (dest[i] * src[i]) / 255;
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ rgbBlend[i] = (rgbDest[i] * rgbSrc[i]) / 255;
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ blend[i] = (dest[i] * src[i]) / 255;
+ }
}
}
@@ -87,8 +151,23 @@ static void splashOutBlendScreen(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] + src[i] - (dest[i] * src[i]) / 255;
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ rgbBlend[i] = rgbDest[i] + rgbSrc[i] - (rgbDest[i] * rgbSrc[i]) / 255;
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ blend[i] = dest[i] + src[i] - (dest[i] * src[i]) / 255;
+ }
}
}
@@ -96,10 +175,27 @@ static void splashOutBlendOverlay(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] < 0x80
- ? (src[i] * 2 * dest[i]) / 255
- : 255 - 2 * ((255 - src[i]) * (255 - dest[i])) / 255;
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ rgbBlend[i] = rgbDest[i] < 0x80
+ ? (rgbSrc[i] * 2 * rgbDest[i]) / 255
+ : 255 - 2 * ((255 - rgbSrc[i]) * (255 - rgbDest[i])) / 255;
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ blend[i] = dest[i] < 0x80
+ ? (src[i] * 2 * dest[i]) / 255
+ : 255 - 2 * ((255 - src[i]) * (255 - dest[i])) / 255;
+ }
}
}
@@ -107,8 +203,23 @@ static void splashOutBlendDarken(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] < src[i] ? dest[i] : src[i];
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ rgbBlend[i] = rgbDest[i] < rgbSrc[i] ? rgbDest[i] : rgbSrc[i];
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ blend[i] = dest[i] < src[i] ? dest[i] : src[i];
+ }
}
}
@@ -116,8 +227,23 @@ static void splashOutBlendLighten(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] > src[i] ? dest[i] : src[i];
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ rgbBlend[i] = rgbDest[i] > rgbSrc[i] ? rgbDest[i] : rgbSrc[i];
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ blend[i] = dest[i] > src[i] ? dest[i] : src[i];
+ }
}
}
@@ -126,12 +252,32 @@ static void splashOutBlendColorDodge(SplashColorPtr src, SplashColorPtr dest,
SplashColorMode cm) {
int i, x;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- if (src[i] == 255) {
- blend[i] = 255;
- } else {
- x = (dest[i] * 255) / (255 - src[i]);
- blend[i] = x <= 255 ? x : 255;
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ if (rgbSrc[i] == 255) {
+ rgbBlend[i] = 255;
+ } else {
+ x = (rgbDest[i] * 255) / (255 - rgbSrc[i]);
+ rgbBlend[i] = x <= 255 ? x : 255;
+ }
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ if (src[i] == 255) {
+ blend[i] = 255;
+ } else {
+ x = (dest[i] * 255) / (255 - src[i]);
+ blend[i] = x <= 255 ? x : 255;
+ }
}
}
}
@@ -140,12 +286,32 @@ static void splashOutBlendColorBurn(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i, x;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- if (src[i] == 0) {
- blend[i] = 0;
- } else {
- x = ((255 - dest[i]) * 255) / src[i];
- blend[i] = x <= 255 ? 255 - x : 0;
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ if (rgbSrc[i] == 0) {
+ rgbBlend[i] = 0;
+ } else {
+ x = ((255 - rgbDest[i]) * 255) / rgbSrc[i];
+ rgbBlend[i] = x <= 255 ? 255 - x : 0;
+ }
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ if (src[i] == 0) {
+ blend[i] = 0;
+ } else {
+ x = ((255 - dest[i]) * 255) / src[i];
+ blend[i] = x <= 255 ? 255 - x : 0;
+ }
}
}
}
@@ -154,10 +320,27 @@ static void splashOutBlendHardLight(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = src[i] < 0x80
- ? (dest[i] * 2 * src[i]) / 255
- : 255 - 2 * ((255 - dest[i]) * (255 - src[i])) / 255;
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ rgbBlend[i] = rgbSrc[i] < 0x80
+ ? (rgbDest[i] * 2 * rgbSrc[i]) / 255
+ : 255 - 2 * ((255 - rgbDest[i]) * (255 - rgbSrc[i])) / 255;
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ blend[i] = src[i] < 0x80
+ ? (dest[i] * 2 * src[i]) / 255
+ : 255 - 2 * ((255 - dest[i]) * (255 - src[i])) / 255;
+ }
}
}
@@ -165,18 +348,40 @@ static void splashOutBlendSoftLight(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i, x;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- if (src[i] < 0x80) {
- blend[i] = dest[i] - (255 - 2 * src[i]) * dest[i] * (255 - dest[i]) /
- (255 * 255);
- } else {
- if (dest[i] < 0x40) {
- x = (((((16 * dest[i] - 12 * 255) * dest[i]) / 255)
- + 4 * 255) * dest[i]) / 255;
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ if (rgbSrc[i] < 0x80) {
+ rgbBlend[i] = rgbDest[i] - (255 - 2 * rgbSrc[i]) * rgbDest[i] * (255 - rgbDest[i]) / (255 * 255);
} else {
- x = (int)sqrt(255.0 * dest[i]);
+ if (rgbDest[i] < 0x40) {
+ x = (((((16 * rgbDest[i] - 12 * 255) * rgbDest[i]) / 255) + 4 * 255) * rgbDest[i]) / 255;
+ } else {
+ x = (int)sqrt(255.0 * rgbDest[i]);
+ }
+ rgbBlend[i] = rgbDest[i] + (2 * rgbSrc[i] - 255) * (x - rgbDest[i]) / 255;
+ }
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ if (src[i] < 0x80) {
+ blend[i] = dest[i] - (255 - 2 * src[i]) * dest[i] * (255 - dest[i]) / (255 * 255);
+ } else {
+ if (dest[i] < 0x40) {
+ x = (((((16 * dest[i] - 12 * 255) * dest[i]) / 255) + 4 * 255) * dest[i]) / 255;
+ } else {
+ x = (int)sqrt(255.0 * dest[i]);
+ }
+ blend[i] = dest[i] + (2 * src[i] - 255) * (x - dest[i]) / 255;
}
- blend[i] = dest[i] + (2 * src[i] - 255) * (x - dest[i]) / 255;
}
}
}
@@ -187,7 +392,12 @@ static void splashOutBlendDifference(SplashColorPtr src, SplashColorPtr dest,
int i;
for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] < src[i] ? src[i] - dest[i] : dest[i] - src[i];
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ blend[i] = dest[i] < src[i] ? 255 - (src[i] - dest[i]) : 255 - (dest[i] - src[i]);
+ } else {
+#endif
+ blend[i] = dest[i] < src[i] ? src[i] - dest[i] : dest[i] - src[i];
}
}
@@ -195,8 +405,23 @@ static void splashOutBlendExclusion(SplashColorPtr src, SplashColorPtr dest,
SplashColorPtr blend, SplashColorMode cm) {
int i;
- for (i = 0; i < splashColorModeNComps[cm]; ++i) {
- blend[i] = dest[i] + src[i] - (2 * dest[i] * src[i]) / 255;
+#ifdef SPLASH_CMYK
+ if (cm == splashModeCMYK8) {
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ for (i = 0; i < 3; ++i) {
+ rgbBlend[i] = rgbDest[i] + rgbSrc[i] - (2 * rgbDest[i] * rgbSrc[i]) / 255;
+ }
+ rgbToCMYK(rgbBlend, blend);
+ } else
+#endif
+ {
+ for (i = 0; i < splashColorModeNComps[cm]; ++i) {
+ blend[i] = dest[i] + src[i] - (2 * dest[i] * src[i]) / 255;
+ }
}
}
@@ -355,19 +580,15 @@ static void splashOutBlendColor(SplashColorPtr src, SplashColorPtr dest,
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- //~ (0xff - ...) should be clipped
- cvtRGBToHSV(0xff - (src[0] + src[3]),
- 0xff - (src[1] + src[3]),
- 0xff - (src[2] + src[3]), &hs, &ss, &vs);
- cvtRGBToHSV(0xff - (dest[0] + dest[3]),
- 0xff - (dest[1] + dest[3]),
- 0xff - (dest[2] + dest[3]), &hd, &sd, &vd);
- cvtHSVToRGB(hs, ss, vd, &r, &g, &b);
- //~ should do black generation
- blend[0] = 0xff - r;
- blend[1] = 0xff - g;
- blend[2] = 0xff - b;
- blend[3] = 0;
+ SplashColor rgbSrc;
+ SplashColor rgbDest;
+ SplashColor rgbBlend;
+ cmykToRGB(src, rgbSrc);
+ cmykToRGB(dest, rgbDest);
+ cvtRGBToHSV(rgbSrc[0], rgbSrc[1], rgbSrc[2], &hs, &ss, &vs);
+ cvtRGBToHSV(rgbDest[0], rgbDest[1], rgbDest[2], &hd, &sd, &vd);
+ cvtHSVToRGB(hs, ss, vd, &rgbBlend[0], &rgbBlend[1], &rgbBlend[2]);
+ rgbToCMYK(rgbBlend, blend);
break;
#endif
}
@@ -607,7 +828,12 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
colorMode != splashModeMono1;
setupScreenParams(72.0, 72.0);
reverseVideo = reverseVideoA;
- splashColorCopy(paperColor, paperColorA);
+ if (paperColorA != NULL) {
+ splashColorCopy(paperColor, paperColorA);
+ } else {
+ splashClearColor(paperColor);
+ }
+ keepAlphaChannel = paperColorA == NULL;
xref = NULL;
@@ -624,7 +850,7 @@ SplashOutputDev::SplashOutputDev(SplashColorMode colorModeA,
font = NULL;
needFontUpdate = gFalse;
textClipPath = NULL;
-
+ haveCSPattern = gFalse;
transpGroupStack = NULL;
}
@@ -791,7 +1017,7 @@ void SplashOutputDev::startPage(int pageNum, GfxState *state) {
}
void SplashOutputDev::endPage() {
- if (colorMode != splashModeMono1) {
+ if (colorMode != splashModeMono1 && !keepAlphaChannel) {
splash->compositeBackground(paperColor);
}
}
@@ -982,6 +1208,15 @@ void SplashOutputDev::updateFont(GfxState * /*state*/) {
needFontUpdate = gTrue;
}
+void SplashOutputDev::updateRender(GfxState *state) {
+ int rm;
+ rm = state->getRender();
+ if (rm == 7 && haveCSPattern) {
+ haveCSPattern = gFalse;
+ restoreState(state);
+ }
+}
+
void SplashOutputDev::doUpdateFont(GfxState *state) {
GfxFont *gfxFont;
GfxFontType fontType;
@@ -1674,7 +1909,29 @@ void SplashOutputDev::drawType3Glyph(T3FontCache *t3Font,
splash->fillGlyph(0, 0, &glyph);
}
+void SplashOutputDev::beginTextObject(GfxState *state) {
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ haveCSPattern = gTrue;
+ saveState(state);
+ savedRender = state->getRender();
+ state->setRender(7);
+ }
+}
+
void SplashOutputDev::endTextObject(GfxState *state) {
+ if (haveCSPattern) {
+ state->setRender(savedRender);
+ haveCSPattern = gFalse;
+ if (state->getFillColorSpace()->getMode() != csPattern) {
+ if (textClipPath) {
+ splash->fill(textClipPath, gTrue);
+ delete textClipPath;
+ textClipPath = NULL;
+ }
+ restoreState(state);
+ updateFillColor(state);
+ }
+ }
if (textClipPath) {
splash->clipToPath(textClipPath, gFalse);
delete textClipPath;
@@ -1706,6 +1963,10 @@ GBool SplashOutputDev::imageMaskSrc(void *data, SplashColorPtr line) {
return gTrue;
}
+void SplashOutputDev::endMaskClip(GfxState * state) {
+ splash->setSoftMask(NULL);
+}
+
void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
int width, int height, GBool invert,
GBool inlineImg) {
@@ -1732,12 +1993,27 @@ void SplashOutputDev::drawImageMask(GfxState *state, Object *ref, Stream *str,
imgMaskData.height = height;
imgMaskData.y = 0;
- splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat,
- t3GlyphStack != NULL);
- if (inlineImg) {
- while (imgMaskData.y < height) {
- imgMaskData.imgStr->getLine();
- ++imgMaskData.y;
+ if (state->getFillColorSpace()->getMode() == csPattern) {
+ SplashBitmap *maskBitmap;
+ Splash *maskSplash;
+ SplashColor maskColor;
+
+ maskBitmap = new SplashBitmap(bitmap->getWidth(), bitmap->getHeight(), 1, splashModeMono8, gFalse);
+ maskSplash = new Splash(maskBitmap, vectorAntialias);
+ maskColor[0] = 0;
+ maskSplash->clear(maskColor);
+ maskColor[0] = 0xff;
+ maskSplash->setFillPattern(new SplashSolidColor(maskColor));
+ maskSplash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat, t3GlyphStack != NULL);
+ delete maskSplash;
+ splash->setSoftMask(maskBitmap);
+ } else {
+ splash->fillImageMask(&imageMaskSrc, &imgMaskData, width, height, mat, t3GlyphStack != NULL);
+ if (inlineImg) {
+ while (imgMaskData.y < height) {
+ imgMaskData.imgStr->getLine();
+ ++imgMaskData.y;
+ }
}
}
@@ -2724,7 +3000,7 @@ void SplashOutputDev::setSoftMask(GfxState * /*state*/, double * /*bbox*/,
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- lum = (1 - color[4] / 255.0)
+ lum = (1 - color[3] / 255.0)
- (0.3 / 255.0) * color[0]
- (0.59 / 255.0) * color[1]
- (0.11 / 255.0) * color[2];
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index 02c7f9a..b9a7aad 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -14,6 +14,7 @@
// under GPL version 2 or later
//
// Copyright (C) 2005 Takashi Iwai <tiwai at suse.de>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -79,6 +80,10 @@ public:
// text in Type 3 fonts will be drawn with drawChar/drawString.
virtual GBool interpretType3Chars() { return gTrue; }
+ // This device now supports text in pattern colorspace!
+ virtual GBool supportTextCSPattern(GfxState *state)
+ { return state->getFillColorSpace()->getMode() == csPattern; }
+
//----- initialization and control
// Start a page.
@@ -110,6 +115,7 @@ public:
//----- update text state
virtual void updateFont(GfxState *state);
+ virtual void updateRender(GfxState *state);
//----- path painting
virtual void stroke(GfxState *state);
@@ -130,6 +136,8 @@ public:
double dx, double dy,
CharCode code, Unicode *u, int uLen);
virtual void endType3Char(GfxState *state);
+ virtual void beginTextObject(GfxState *state);
+ virtual GBool deviceHasTextClip(GfxState *state) { return textClipPath && haveCSPattern; }
virtual void endTextObject(GfxState *state);
//----- image drawing
@@ -150,6 +158,12 @@ public:
Stream *maskStr,
int maskWidth, int maskHeight,
GfxImageColorMap *maskColorMap);
+ // If current colorspace ist pattern,
+ // need this device special handling for masks in pattern colorspace?
+ // Default is false
+ virtual GBool fillMaskCSPattern(GfxState * state)
+ { return state->getFillColorSpace()->getMode() == csPattern; }
+ virtual void endMaskClip(GfxState * /*state*/);
//----- Type 3 font operators
virtual void type3D0(GfxState *state, double wx, double wy);
@@ -225,6 +239,11 @@ private:
static GBool maskedImageSrc(void *data, SplashColorPtr line,
Guchar *alphaLine);
+ GBool haveCSPattern; // set if text has been drawn with a
+ // clipping render mode because of pattern colorspace
+ int savedRender; // use if pattern colorspace
+ GBool keepAlphaChannel; // don't fill with paper color, keep alpha channel
+
SplashColorMode colorMode;
int bitmapRowPad;
GBool bitmapTopDown;
commit d3e4563146cbff4cb507522783e60462461c7524
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date: Sun May 31 23:23:07 2009 +0200
Set memory to 0 after allocation, fixes problems on Sun machines, should not hurt for others
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 361060c..14c0a3f 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -18,6 +18,7 @@
// Copyright (C) 2006 Carlos Garcia Campos <carlosgc at gnome.org>
// Copyright (C) 2006-2009 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2009 Koji Otani <sho at bbr.jp>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -3356,9 +3357,11 @@ GfxGouraudTriangleShading *GfxGouraudTriangleShading::parse(int typeA,
break;
}
if (nVerticesA == vertSize) {
+ int oldVertSize = vertSize;
vertSize = (vertSize == 0) ? 16 : 2 * vertSize;
verticesA = (GfxGouraudVertex *)
greallocn(verticesA, vertSize, sizeof(GfxGouraudVertex));
+ memset(verticesA + oldVertSize, 0, (vertSize - oldVertSize) * sizeof(GfxGouraudVertex));
}
verticesA[nVerticesA].x = xMin + xMul * (double)x;
verticesA[nVerticesA].y = yMin + yMul * (double)y;
@@ -3678,9 +3681,11 @@ GfxPatchMeshShading *GfxPatchMeshShading::parse(int typeA, Dict *dict,
break;
}
if (nPatchesA == patchesSize) {
+ int oldPatchesSize = patchesSize;
patchesSize = (patchesSize == 0) ? 16 : 2 * patchesSize;
patchesA = (GfxPatch *)greallocn(patchesA,
patchesSize, sizeof(GfxPatch));
+ memset(patchesA + oldPatchesSize, 0, (patchesSize - oldPatchesSize) * sizeof(GfxPatch));
}
p = &patchesA[nPatchesA];
if (typeA == 6) {
commit 78a58931b4347ecb505bad5a51104382ef5f91c7
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date: Sun May 31 22:52:23 2009 +0200
Add splashClearColor that assigns white to the given colorptr
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h
index ba12a82..a868652 100644
--- a/splash/SplashTypes.h
+++ b/splash/SplashTypes.h
@@ -13,6 +13,7 @@
//
// Copyright (C) 2006 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2008 Tomas Are Haavet <tomasare at gmail.com>
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
//
// To see a description of the changes please see the Changelog file that
// came with your tarball or type make ChangeLog if you are building from git
@@ -90,6 +91,15 @@ static inline Guchar splashCMYK8Y(SplashColorPtr cmyk8) { return cmyk8[2]; }
static inline Guchar splashCMYK8K(SplashColorPtr cmyk8) { return cmyk8[3]; }
#endif
+static inline void splashClearColor(SplashColorPtr dest) {
+ dest[0] = 0;
+ dest[1] = 0;
+ dest[2] = 0;
+#if SPLASH_CMYK
+ dest[3] = 0;
+#endif
+}
+
static inline void splashColorCopy(SplashColorPtr dest, SplashColorPtr src) {
dest[0] = src[0];
dest[1] = src[1];
commit 47c26747b32c242ec8ac60e7b93150a67eb22e31
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date: Sun May 31 22:51:22 2009 +0200
Fix splashColorModeNComps to correctly include all values for each SplashColorMode
diff --git a/splash/SplashState.cc b/splash/SplashState.cc
index 70a79ac..b1fa2f5 100644
--- a/splash/SplashState.cc
+++ b/splash/SplashState.cc
@@ -4,6 +4,20 @@
//
//========================================================================
+//========================================================================
+//
+// Modified under the Poppler project - http://poppler.freedesktop.org
+//
+// All changes made under the Poppler project to this file are licensed
+// under GPL version 2 or later
+//
+// Copyright (C) 2009 Thomas Freitag <Thomas.Freitag at alfa.de>
+//
+// To see a description of the changes please see the Changelog file that
+// came with your tarball or type make ChangeLog if you are building from git
+//
+//========================================================================
+
#include <config.h>
#ifdef USE_GCC_PRAGMAS
@@ -25,6 +39,9 @@
// number of components in each color mode
int splashColorModeNComps[] = {
1, 1, 3, 3, 4
+#if SPLASH_CMYK
+ ,4
+#endif
};
SplashState::SplashState(int width, int height, GBool vectorAntialias,
More information about the poppler
mailing list