[poppler] goo/ImgWriter.h goo/JpegWriter.cc goo/JpegWriter.h poppler/Gfx.cc poppler/GfxState.cc poppler/GfxState.h poppler/OutputDev.h poppler/SplashOutputDev.cc poppler/SplashOutputDev.h splash/SplashBitmap.cc splash/SplashBitmap.h splash/Splash.cc splash/Splash.h splash/SplashPattern.cc splash/SplashPattern.h splash/SplashState.cc splash/SplashState.h splash/SplashTypes.h utils/pdftoppm.cc
Albert Astals Cid
aacid at kemper.freedesktop.org
Thu Jul 28 15:33:25 PDT 2011
goo/ImgWriter.h | 2
goo/JpegWriter.cc | 54 ++++++-
goo/JpegWriter.h | 7 -
poppler/Gfx.cc | 98 +++++++++++++-
poppler/GfxState.cc | 1
poppler/GfxState.h | 4
poppler/OutputDev.h | 1
poppler/SplashOutputDev.cc | 307 +++++++++++++++++++++++++++++++++++++++------
poppler/SplashOutputDev.h | 51 ++++++-
splash/Splash.cc | 86 +++++++++---
splash/Splash.h | 9 -
splash/SplashBitmap.cc | 64 +++++++++
splash/SplashBitmap.h | 1
splash/SplashPattern.cc | 16 ++
splash/SplashPattern.h | 7 +
splash/SplashState.cc | 11 +
splash/SplashState.h | 22 +++
splash/SplashTypes.h | 5
utils/pdftoppm.cc | 36 ++++-
19 files changed, 686 insertions(+), 96 deletions(-)
New commits:
commit 861a7bfb9431609e1e148240447f23c8e83b9d0f
Author: Thomas Freitag <Thomas.Freitag at alfa.de>
Date: Fri Jul 29 00:30:58 2011 +0200
Implement overprint in Splash
See the "Implementing overprint in Splash" thread in the mailing list for more info
diff --git a/goo/ImgWriter.h b/goo/ImgWriter.h
index 50fe9d7..185c230 100644
--- a/goo/ImgWriter.h
+++ b/goo/ImgWriter.h
@@ -8,6 +8,7 @@
// Copyright (C) 2009, 2011 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2010 Adrian Johnson <ajohnson at redneon.com>
// Copyright (C) 2010 Brian Cameron <brian.cameron at oracle.com>
+// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
//
//========================================================================
@@ -26,6 +27,7 @@ class ImgWriter
virtual bool writeRow(unsigned char **row) = 0;
virtual bool close() = 0;
+ virtual bool supportCMYK() { return false; }
};
#endif
diff --git a/goo/JpegWriter.cc b/goo/JpegWriter.cc
index c9b7052..7ed5d52 100644
--- a/goo/JpegWriter.cc
+++ b/goo/JpegWriter.cc
@@ -7,6 +7,7 @@
// Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
// Copyright (C) 2010 Adrian Johnson <ajohnson at redneon.com>
// Copyright (C) 2010 Harry Roberts <harry.roberts at midnight-labs.org>
+// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
//
//========================================================================
@@ -27,13 +28,13 @@ void outputMessage(j_common_ptr cinfo)
error(-1, "%s", buffer);
}
-JpegWriter::JpegWriter(int q, bool p)
-: progressive(p), quality(q)
+JpegWriter::JpegWriter(int q, bool p, J_COLOR_SPACE cm)
+: progressive(p), quality(q), colorMode(cm)
{
}
-JpegWriter::JpegWriter()
-: progressive(false), quality(-1)
+JpegWriter::JpegWriter(J_COLOR_SPACE cm)
+: progressive(false), quality(-1), colorMode(cm)
{
}
@@ -61,9 +62,26 @@ bool JpegWriter::init(FILE *f, int width, int height, int hDPI, int vDPI)
cinfo.density_unit = 1; // dots per inch
cinfo.X_density = hDPI;
cinfo.Y_density = vDPI;
- cinfo.input_components = 3; /* # of color components per pixel */
- cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
+ cinfo.in_color_space = colorMode; /* colorspace of input image */
+ /* # of color components per pixel */
+ switch (colorMode) {
+ case JCS_GRAYSCALE:
+ cinfo.input_components = 1;
+ break;
+ case JCS_RGB:
+ cinfo.input_components = 3;
+ break;
+ case JCS_CMYK:
+ cinfo.input_components = 4;
+ break;
+ default:
+ return false;
+ }
jpeg_set_defaults(&cinfo);
+ if (cinfo.in_color_space == JCS_CMYK) {
+ jpeg_set_colorspace(&cinfo, JCS_YCCK);
+ cinfo.write_JFIF_header = TRUE;
+ }
// Set quality
if( quality >= 0 && quality <= 100 ) {
@@ -83,16 +101,36 @@ bool JpegWriter::init(FILE *f, int width, int height, int hDPI, int vDPI)
bool JpegWriter::writePointers(unsigned char **rowPointers, int rowCount)
{
+ if (colorMode == JCS_CMYK) {
+ for (int y = 0; y < rowCount; y++) {
+ unsigned char *row = rowPointers[y];
+ for (unsigned int x = 0; x < cinfo.image_width; x++) {
+ for (int n = 0; n < 4; n++) {
+ *row = 0xff - *row;
+ row++;
+ }
+ }
+ }
+ }
// Write all rows to the file
jpeg_write_scanlines(&cinfo, rowPointers, rowCount);
return true;
}
-bool JpegWriter::writeRow(unsigned char **row)
+bool JpegWriter::writeRow(unsigned char **rowPointer)
{
+ if (colorMode == JCS_CMYK) {
+ unsigned char *row = rowPointer[0];
+ for (unsigned int x = 0; x < cinfo.image_width; x++) {
+ for (int n = 0; n < 4; n++) {
+ *row = 0xff - *row;
+ row++;
+ }
+ }
+ }
// Write the row to the file
- jpeg_write_scanlines(&cinfo, row, 1);
+ jpeg_write_scanlines(&cinfo, rowPointer, 1);
return true;
}
diff --git a/goo/JpegWriter.h b/goo/JpegWriter.h
index cd2a035..7af6870 100644
--- a/goo/JpegWriter.h
+++ b/goo/JpegWriter.h
@@ -10,6 +10,7 @@
// Copyright (C) 2010 Harry Roberts <harry.roberts at midnight-labs.org>
// Copyright (C) 2010 Brian Cameron <brian.cameron at oracle.com>
// Copyright (C) 2011 Albert Astals Cid <aacid at kde.org>
+// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
//
//========================================================================
@@ -30,8 +31,8 @@ extern "C" {
class JpegWriter : public ImgWriter
{
public:
- JpegWriter(int quality, bool progressive);
- JpegWriter();
+ JpegWriter(int quality, bool progressive, J_COLOR_SPACE colorMode = JCS_RGB);
+ JpegWriter(J_COLOR_SPACE colorMode = JCS_RGB);
~JpegWriter();
bool init(FILE *f, int width, int height, int hDPI, int vDPI);
@@ -40,10 +41,12 @@ class JpegWriter : public ImgWriter
bool writeRow(unsigned char **row);
bool close();
+ bool supportCMYK() { return colorMode == JCS_CMYK; }
private:
bool progressive;
int quality;
+ J_COLOR_SPACE colorMode;
struct jpeg_compress_struct cinfo;
struct jpeg_error_mgr jerr;
};
diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc
index dc5f8e3..ca93477 100644
--- a/poppler/Gfx.cc
+++ b/poppler/Gfx.cc
@@ -1021,6 +1021,11 @@ void Gfx::opSetExtGState(Object args[], int numArgs) {
}
}
obj2.free();
+ if (obj1.dictLookup("OPM", &obj2)->isInt()) {
+ state->setOverprintMode(obj2.getInt());
+ out->updateOverprintMode(state);
+ }
+ obj2.free();
// stroke adjust
if (obj1.dictLookup("SA", &obj2)->isBool()) {
@@ -1314,6 +1319,8 @@ void Gfx::opSetRenderingIntent(Object args[], int numArgs) {
void Gfx::opSetFillGray(Object args[], int numArgs) {
GfxColor color;
+ GfxColorSpace *colorSpace;
+ Object obj;
if (textHaveCSPattern && drawText) {
GBool needFill = out->deviceHasTextClip(state);
@@ -1324,7 +1331,14 @@ void Gfx::opSetFillGray(Object args[], int numArgs) {
out->restoreState(state);
}
state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceGrayColorSpace());
+ res->lookupColorSpace("DefaultGray", &obj);
+ if (obj.isNull()) {
+ colorSpace = new GfxDeviceGrayColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj, this);
+ }
+ obj.free();
+ state->setFillColorSpace(colorSpace);
out->updateFillColorSpace(state);
color.c[0] = dblToCol(args[0].getNum());
state->setFillColor(&color);
@@ -1340,9 +1354,18 @@ void Gfx::opSetFillGray(Object args[], int numArgs) {
void Gfx::opSetStrokeGray(Object args[], int numArgs) {
GfxColor color;
+ GfxColorSpace *colorSpace;
+ Object obj;
state->setStrokePattern(NULL);
- state->setStrokeColorSpace(new GfxDeviceGrayColorSpace());
+ res->lookupColorSpace("DefaultGray", &obj);
+ if (obj.isNull()) {
+ colorSpace = new GfxDeviceGrayColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj, this);
+ }
+ obj.free();
+ state->setStrokeColorSpace(colorSpace);
out->updateStrokeColorSpace(state);
color.c[0] = dblToCol(args[0].getNum());
state->setStrokeColor(&color);
@@ -1351,6 +1374,8 @@ void Gfx::opSetStrokeGray(Object args[], int numArgs) {
void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
GfxColor color;
+ GfxColorSpace *colorSpace;
+ Object obj;
int i;
if (textHaveCSPattern && drawText) {
@@ -1361,8 +1386,15 @@ void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
}
out->restoreState(state);
}
+ res->lookupColorSpace("DefaultCMYK", &obj);
+ if (obj.isNull()) {
+ colorSpace = new GfxDeviceCMYKColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj, this);
+ }
+ obj.free();
state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceCMYKColorSpace());
+ state->setFillColorSpace(colorSpace);
out->updateFillColorSpace(state);
for (i = 0; i < 4; ++i) {
color.c[i] = dblToCol(args[i].getNum());
@@ -1380,10 +1412,19 @@ void Gfx::opSetFillCMYKColor(Object args[], int numArgs) {
void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
GfxColor color;
+ GfxColorSpace *colorSpace;
+ Object obj;
int i;
state->setStrokePattern(NULL);
- state->setStrokeColorSpace(new GfxDeviceCMYKColorSpace());
+ res->lookupColorSpace("DefaultCMYK", &obj);
+ if (obj.isNull()) {
+ colorSpace = new GfxDeviceCMYKColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj, this);
+ }
+ obj.free();
+ state->setStrokeColorSpace(colorSpace);
out->updateStrokeColorSpace(state);
for (i = 0; i < 4; ++i) {
color.c[i] = dblToCol(args[i].getNum());
@@ -1393,6 +1434,8 @@ void Gfx::opSetStrokeCMYKColor(Object args[], int numArgs) {
}
void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
+ Object obj;
+ GfxColorSpace *colorSpace;
GfxColor color;
int i;
@@ -1405,7 +1448,14 @@ void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
out->restoreState(state);
}
state->setFillPattern(NULL);
- state->setFillColorSpace(new GfxDeviceRGBColorSpace());
+ res->lookupColorSpace("DefaultRGB", &obj);
+ if (obj.isNull()) {
+ colorSpace = new GfxDeviceRGBColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj, this);
+ }
+ obj.free();
+ state->setFillColorSpace(colorSpace);
out->updateFillColorSpace(state);
for (i = 0; i < 3; ++i) {
color.c[i] = dblToCol(args[i].getNum());
@@ -1422,11 +1472,20 @@ void Gfx::opSetFillRGBColor(Object args[], int numArgs) {
}
void Gfx::opSetStrokeRGBColor(Object args[], int numArgs) {
+ Object obj;
+ GfxColorSpace *colorSpace;
GfxColor color;
int i;
state->setStrokePattern(NULL);
- state->setStrokeColorSpace(new GfxDeviceRGBColorSpace());
+ res->lookupColorSpace("DefaultRGB", &obj);
+ if (obj.isNull()) {
+ colorSpace = new GfxDeviceRGBColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&obj, this);
+ }
+ obj.free();
+ state->setStrokeColorSpace(colorSpace);
out->updateStrokeColorSpace(state);
for (i = 0; i < 3; ++i) {
color.c[i] = dblToCol(args[i].getNum());
@@ -4132,11 +4191,32 @@ void Gfx::doImage(Object *ref, Stream *str, GBool inlineImg) {
if (!obj1.isNull()) {
colorSpace = GfxColorSpace::parse(&obj1, this);
} else if (csMode == streamCSDeviceGray) {
- colorSpace = new GfxDeviceGrayColorSpace();
+ Object objCS;
+ res->lookupColorSpace("DefaultGray", &objCS);
+ if (objCS.isNull()) {
+ colorSpace = new GfxDeviceGrayColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&objCS, this);
+ }
+ objCS.free();
} else if (csMode == streamCSDeviceRGB) {
- colorSpace = new GfxDeviceRGBColorSpace();
+ Object objCS;
+ res->lookupColorSpace("DefaultRGB", &objCS);
+ if (objCS.isNull()) {
+ colorSpace = new GfxDeviceRGBColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&objCS, this);
+ }
+ objCS.free();
} else if (csMode == streamCSDeviceCMYK) {
- colorSpace = new GfxDeviceCMYKColorSpace();
+ Object objCS;
+ res->lookupColorSpace("DefaultCMYK", &objCS);
+ if (objCS.isNull()) {
+ colorSpace = new GfxDeviceCMYKColorSpace();
+ } else {
+ colorSpace = GfxColorSpace::parse(&objCS, this);
+ }
+ objCS.free();
} else {
colorSpace = NULL;
}
diff --git a/poppler/GfxState.cc b/poppler/GfxState.cc
index 893540f..bce57cc 100644
--- a/poppler/GfxState.cc
+++ b/poppler/GfxState.cc
@@ -5431,6 +5431,7 @@ GfxState::GfxState(double hDPIA, double vDPIA, PDFRectangle *pageBox,
strokeOpacity = 1;
fillOverprint = gFalse;
strokeOverprint = gFalse;
+ overprintMode = 0;
transfer[0] = transfer[1] = transfer[2] = transfer[3] = NULL;
lineWidth = 1;
diff --git a/poppler/GfxState.h b/poppler/GfxState.h
index b7f94cd..c2bb1be 100644
--- a/poppler/GfxState.h
+++ b/poppler/GfxState.h
@@ -20,6 +20,7 @@
// Copyright (C) 2009-2011 Albert Astals Cid <aacid at kde.org>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
// Copyright (C) 2011 Andrea Canciani <ranma42 at gmail.com>
+// Copyright (C) 2011 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
@@ -1334,6 +1335,7 @@ public:
double getStrokeOpacity() { return strokeOpacity; }
GBool getFillOverprint() { return fillOverprint; }
GBool getStrokeOverprint() { return strokeOverprint; }
+ int getOverprintMode() { return overprintMode; }
Function **getTransfer() { return transfer; }
double getLineWidth() { return lineWidth; }
void getLineDash(double **dash, int *length, double *start)
@@ -1404,6 +1406,7 @@ public:
void setStrokeOpacity(double opac) { strokeOpacity = opac; }
void setFillOverprint(GBool op) { fillOverprint = op; }
void setStrokeOverprint(GBool op) { strokeOverprint = op; }
+ void setOverprintMode(int op) { overprintMode = op; }
void setTransfer(Function **funcs);
void setLineWidth(double width) { lineWidth = width; }
void setLineDash(double *dash, int length, double start);
@@ -1484,6 +1487,7 @@ private:
double strokeOpacity; // stroke opacity
GBool fillOverprint; // fill overprint
GBool strokeOverprint; // stroke overprint
+ int overprintMode; // overprint mode
Function *transfer[4]; // transfer function (entries may be: all
// NULL = identity; last three NULL =
// single function; all four non-NULL =
diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h
index c922c7a..2e3f9ae 100644
--- a/poppler/OutputDev.h
+++ b/poppler/OutputDev.h
@@ -177,6 +177,7 @@ public:
virtual void updateStrokeOpacity(GfxState * /*state*/) {}
virtual void updateFillOverprint(GfxState * /*state*/) {}
virtual void updateStrokeOverprint(GfxState * /*state*/) {}
+ virtual void updateOverprintMode(GfxState * /*state*/) {}
virtual void updateTransfer(GfxState * /*state*/) {}
virtual void updateFillColorStop(GfxState * /*state*/, double /*offset*/) {}
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index 92c7f00..e0683db 100644
--- a/poppler/SplashOutputDev.cc
+++ b/poppler/SplashOutputDev.cc
@@ -95,6 +95,11 @@ static inline void convertGfxColor(SplashColorPtr dest,
GfxCMYK cmyk;
#endif
+ // make gcc happy
+ color[0] = color[1] = color[2] = 0;
+#if SPLASH_CMYK
+ color[3] = 0;
+#endif
switch (colorMode) {
case splashModeMono1:
case splashModeMono8:
@@ -123,18 +128,200 @@ static inline void convertGfxColor(SplashColorPtr dest,
splashColorCopy(dest, color);
}
+static inline SplashPattern *createOverprintPattern(GfxColorSpace *colorSpace, SplashColorPtr color, GBool image, Guchar tolerance = 0x01) {
+ switch (colorSpace->getMode()) {
+ case csDeviceCMYK:
+ if (image) {
+ return new SplashSolidColor(color);
+ }
+ case csSeparation:
+ case csDeviceN:
+ if (image && colorSpace->getMode() == csDeviceN) {
+ GfxDeviceNColorSpace *deviceNSpace = (GfxDeviceNColorSpace *) colorSpace;
+ GBool hasSpot = gFalse;
+ GBool hasProcess = gFalse;
+ for (int i = 0; i < deviceNSpace->getNComps(); i++) {
+ GooString *name = deviceNSpace->getColorantName(i)->upperCase();
+ if (name->cmp("CYAN") != 0 &&
+ name->cmp("MAGENTA") != 0 &&
+ name->cmp("YELLOW") != 0 &&
+ name->cmp("BLACK") != 0 &&
+ name->cmp("NONE") != 0) {
+ hasSpot = gTrue;
+ } else {
+ hasProcess = gTrue;
+ }
+ }
+ if (hasSpot && hasProcess)
+ return new SplashSolidColor(color);
+ }
+ return new SplashOverprintColor(colorSpace, color, tolerance);
+ case csIndexed:
+ return createOverprintPattern(((GfxIndexedColorSpace *) colorSpace)->getBase(), color, image);
+ case csICCBased:
+ if (image) {
+ return createOverprintPattern(((GfxICCBasedColorSpace *) colorSpace)->getAlt(), color, gFalse, 0x05);
+ }
+ case csDeviceGray:
+ if (image) {
+ return new SplashOverprintColor(colorSpace, color, tolerance);
+ }
+ default: // knockout
+ return new SplashSolidColor(color);
+ }
+}
+
+
+//------------------------------------------------------------------------
+// SplashOverprintColor
+//------------------------------------------------------------------------
+
+SplashOverprintColor::SplashOverprintColor(GfxColorSpace *colorSpaceA, SplashColorPtr colorA, Guchar toleranceA) {
+ splashColorCopy(color, colorA);
+ colorSpace = colorSpaceA;
+ tolerance = toleranceA;
+}
+
+SplashOverprintColor::~SplashOverprintColor() {
+}
+
+GBool SplashOverprintColor::getColor(int x, int y, SplashColorPtr c) {
+ splashColorCopy(c, color);
+ return gTrue;
+}
+
+void SplashOverprintColor::overprint(GBool op, Guchar aSrc, SplashColorPtr cSrc,
+ Guchar aDest, SplashColorPtr cDest,
+ SplashColorPtr colorResult) {
+ switch(colorSpace->getMode()) {
+ case csDeviceGray: // only in case of grayscale images
+ colorResult[0] = cDest[0];
+ colorResult[1] = cDest[1];
+ colorResult[2] = cDest[2];
+ colorResult[3] = (Guchar)(((aDest - aSrc) * cDest[3] +
+ aSrc * cSrc[3]) / aDest);
+ break;
+ case csDeviceCMYK:
+ colorResult[0] = (cSrc[0] < tolerance && op) ?
+ cDest[0] :
+ (Guchar)(((aDest - aSrc) * cDest[0] + aSrc * cSrc[0]) / aDest);
+ colorResult[1] = (cSrc[1] < tolerance && op) ?
+ cDest[1] :
+ (Guchar)(((aDest - aSrc) * cDest[1] + aSrc * cSrc[1]) / aDest);
+ colorResult[2] = (cSrc[2] < tolerance && op) ?
+ cDest[2] :
+ (Guchar)(((aDest - aSrc) * cDest[2] + aSrc * cSrc[2]) / aDest);
+ colorResult[3] = (cSrc[3] < tolerance && op) ?
+ cDest[3] :
+ (Guchar)(((aDest - aSrc) * cDest[3] + aSrc * cSrc[3]) / aDest);
+ break;
+
+ case csSeparation:
+ {
+ GfxSeparationColorSpace *sepSpace = (GfxSeparationColorSpace *) colorSpace;
+ GooString *name = sepSpace->getName()->upperCase();
+ if (name->cmp("CYAN") == 0) {
+ colorResult[0] = (Guchar)(((aDest - aSrc) * cDest[0] +
+ aSrc * cSrc[0]) / aDest);
+ colorResult[1] = cDest[1];
+ colorResult[2] = cDest[2];
+ colorResult[3] = cDest[3];
+ } else if (name->cmp("MAGENTA") == 0) {
+ colorResult[0] = cDest[0];
+ colorResult[1] = (Guchar)(((aDest - aSrc) * cDest[1] +
+ aSrc * cSrc[1]) / aDest);
+ colorResult[2] = cDest[2];
+ colorResult[3] = cDest[3];
+ } else if (name->cmp("YELLOW") == 0) {
+ colorResult[0] = cDest[0];
+ colorResult[1] = cDest[1];
+ colorResult[2] = (Guchar)(((aDest - aSrc) * cDest[2] +
+ aSrc * cSrc[2]) / aDest);
+ colorResult[3] = cDest[3];
+ } else if (name->cmp("BLACK") == 0) {
+ colorResult[0] = cDest[0];
+ colorResult[1] = cDest[1];
+ colorResult[2] = cDest[2];
+ colorResult[3] = (Guchar)(((aDest - aSrc) * cDest[3] +
+ aSrc * cSrc[3]) / aDest);
+ } else {
+ colorResult[0] = ((int) cDest[0] + cSrc[0]) > 0xff ? 0xff : cDest[0] + cSrc[0];
+ colorResult[1] = ((int) cDest[1] + cSrc[1]) > 0xff ? 0xff : cDest[1] + cSrc[1];
+ colorResult[2] = ((int) cDest[2] + cSrc[2]) > 0xff ? 0xff : cDest[2] + cSrc[2];
+ colorResult[3] = ((int) cDest[3] + cSrc[3]) > 0xff ? 0xff : cDest[3] + cSrc[3];
+ }
+ }
+ break;
+ case csDeviceN:
+ {
+ GfxDeviceNColorSpace *deviceNSpace = (GfxDeviceNColorSpace *) colorSpace;
+ colorResult[0] = cDest[0];
+ colorResult[1] = cDest[1];
+ colorResult[2] = cDest[2];
+ colorResult[3] = cDest[3];
+ for (int i = 0; i < deviceNSpace->getNComps(); i++) {
+ GooString *name = deviceNSpace->getColorantName(i)->upperCase();
+ if (name->cmp("CYAN") == 0) {
+ colorResult[0] = (Guchar)(((aDest - aSrc) * cDest[0] +
+ aSrc * cSrc[0]) / aDest);
+ } else if (name->cmp("MAGENTA") == 0) {
+ colorResult[1] = (Guchar)(((aDest - aSrc) * cDest[1] +
+ aSrc * cSrc[1]) / aDest);
+ } else if (name->cmp("YELLOW") == 0) {
+ colorResult[2] = (Guchar)(((aDest - aSrc) * cDest[2] +
+ aSrc * cSrc[2]) / aDest);
+ } else if (name->cmp("BLACK") == 0) {
+ colorResult[3] = (Guchar)(((aDest - aSrc) * cDest[3] +
+ aSrc * cSrc[3]) / aDest);
+ } else if (name->cmp("NONE") != 0) {
+ colorResult[0] = (cSrc[0] < tolerance && op) ?
+ cDest[0] :
+ (Guchar)(((aDest - aSrc) * cDest[0] + aSrc * cSrc[0]) / aDest);
+ colorResult[1] = (cSrc[1] < tolerance && op) ?
+ cDest[1] :
+ (Guchar)(((aDest - aSrc) * cDest[1] + aSrc * cSrc[1]) / aDest);
+ colorResult[2] = (cSrc[2] < tolerance && op) ?
+ cDest[2] :
+ (Guchar)(((aDest - aSrc) * cDest[2] + aSrc * cSrc[2]) / aDest);
+ colorResult[3] = (cSrc[3] < tolerance && op) ?
+ cDest[3] :
+ (Guchar)(((aDest - aSrc) * cDest[3] + aSrc * cSrc[3]) / aDest);
+ break;
+ }
+ }
+ }
+ break;
+ default:
+ // default for overprint is knockout:
+ colorResult[0] = (Guchar)(((aDest - aSrc) * cDest[0] +
+ aSrc * cSrc[0]) / aDest);
+ colorResult[1] = (Guchar)(((aDest - aSrc) * cDest[1] +
+ aSrc * cSrc[1]) / aDest);
+ colorResult[2] = (Guchar)(((aDest - aSrc) * cDest[2] +
+ aSrc * cSrc[2]) / aDest);
+ colorResult[3] = (Guchar)(((aDest - aSrc) * cDest[3] +
+ aSrc * cSrc[3]) / aDest);
+ }
+}
//------------------------------------------------------------------------
// SplashGouraudPattern
//------------------------------------------------------------------------
SplashGouraudPattern::SplashGouraudPattern(GBool bDirectColorTranslationA,
- GfxState *stateA, GfxGouraudTriangleShading *shadingA) {
+ GfxState *stateA, GfxGouraudTriangleShading *shadingA, SplashColorMode modeA) {
+ SplashColor defaultColor;
+ GfxColor srcColor;
state = stateA;
shading = shadingA;
+ mode = modeA;
bDirectColorTranslation = bDirectColorTranslationA;
+ shadingA->getColorSpace()->getDefaultColor(&srcColor);
+ convertGfxColor(defaultColor, mode, shadingA->getColorSpace(), &srcColor);
+ opPattern = new SplashOverprintColor(shadingA->getColorSpace(), defaultColor, 0x01);
}
SplashGouraudPattern::~SplashGouraudPattern() {
+ delete opPattern;
}
void SplashGouraudPattern::getParameterizedColor(double colorinterp, SplashColorMode mode, SplashColorPtr dest) {
@@ -156,6 +343,11 @@ void SplashGouraudPattern::getParameterizedColor(double colorinterp, SplashColor
}
}
+void SplashGouraudPattern::overprint(GBool op, Guchar aSrc, SplashColorPtr cSrc,
+ Guchar aDest, SplashColorPtr cDest,
+ SplashColorPtr colorResult) {
+ opPattern->overprint(op, aSrc, cSrc, aDest, cDest, colorResult);
+}
//------------------------------------------------------------------------
// SplashUnivariatePattern
//------------------------------------------------------------------------
@@ -214,6 +406,9 @@ GBool SplashUnivariatePattern::testPosition(int x, int y) {
SplashRadialPattern::SplashRadialPattern(SplashColorMode colorModeA, GfxState *stateA, GfxRadialShading *shadingA):
SplashUnivariatePattern(colorModeA, stateA, shadingA)
{
+ SplashColor defaultColor;
+ GfxColor srcColor;
+
shadingA->getCoords(&x0, &y0, &r0, &dx, &dy, &dr);
dx -= x0;
dy -= y0;
@@ -221,9 +416,13 @@ SplashRadialPattern::SplashRadialPattern(SplashColorMode colorModeA, GfxState *s
a = dx*dx + dy*dy - dr*dr;
if (fabs(a) > RADIAL_EPSILON)
inva = 1.0 / a;
+ shadingA->getColorSpace()->getDefaultColor(&srcColor);
+ convertGfxColor(defaultColor, colorModeA, shadingA->getColorSpace(), &srcColor);
+ opPattern = new SplashOverprintColor(shadingA->getColorSpace(), defaultColor, 0x01);
}
SplashRadialPattern::~SplashRadialPattern() {
+ delete opPattern;
}
GBool SplashRadialPattern::getParameter(double xs, double ys, SplashCoord *t) {
@@ -309,6 +508,12 @@ GBool SplashRadialPattern::getParameter(double xs, double ys, SplashCoord *t) {
return gFalse;
}
+void SplashRadialPattern::overprint(GBool op, Guchar aSrc, SplashColorPtr cSrc,
+ Guchar aDest, SplashColorPtr cDest,
+ SplashColorPtr colorResult) {
+ opPattern->overprint(op, aSrc, cSrc, aDest, cDest, colorResult);
+}
+
#undef RADIAL_EPSILON
//------------------------------------------------------------------------
@@ -318,13 +523,20 @@ GBool SplashRadialPattern::getParameter(double xs, double ys, SplashCoord *t) {
SplashAxialPattern::SplashAxialPattern(SplashColorMode colorModeA, GfxState *stateA, GfxAxialShading *shadingA):
SplashUnivariatePattern(colorModeA, stateA, shadingA)
{
+ SplashColor defaultColor;
+ GfxColor srcColor;
+
shadingA->getCoords(&x0, &y0, &x1, &y1);
dx = x1 - x0;
dy = y1 - y0;
mul = 1 / (dx * dx + dy * dy);
+ shadingA->getColorSpace()->getDefaultColor(&srcColor);
+ convertGfxColor(defaultColor, colorModeA, shadingA->getColorSpace(), &srcColor);
+ opPattern = new SplashOverprintColor(shadingA->getColorSpace(), defaultColor, 0x01);
}
SplashAxialPattern::~SplashAxialPattern() {
+ delete opPattern;
}
GBool SplashAxialPattern::getParameter(double xc, double yc, double *t) {
@@ -347,6 +559,12 @@ GBool SplashAxialPattern::getParameter(double xc, double yc, double *t) {
return gTrue;
}
+void SplashAxialPattern::overprint(GBool op, Guchar aSrc, SplashColorPtr cSrc,
+ Guchar aDest, SplashColorPtr cDest,
+ SplashColorPtr colorResult) {
+ opPattern->overprint(op, aSrc, cSrc, aDest, cDest, colorResult);
+}
+
//------------------------------------------------------------------------
// Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result.
@@ -1405,7 +1623,7 @@ void SplashOutputDev::updateFillColor(GfxState *state) {
state->getFillRGB(&rgb);
#if SPLASH_CMYK
state->getFillCMYK(&cmyk);
- splash->setFillPattern(getColor(gray, &rgb, &cmyk));
+ splash->setFillPattern(getColor(state->getFillColorSpace(), gray, &rgb, &cmyk));
#else
splash->setFillPattern(getColor(gray, &rgb));
#endif
@@ -1422,14 +1640,14 @@ void SplashOutputDev::updateStrokeColor(GfxState *state) {
state->getStrokeRGB(&rgb);
#if SPLASH_CMYK
state->getStrokeCMYK(&cmyk);
- splash->setStrokePattern(getColor(gray, &rgb, &cmyk));
+ splash->setStrokePattern(getColor(state->getStrokeColorSpace(), gray, &rgb, &cmyk));
#else
splash->setStrokePattern(getColor(gray, &rgb));
#endif
}
#if SPLASH_CMYK
-SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb,
+SplashPattern *SplashOutputDev::getColor(GfxColorSpace *colorSpace, GfxGray gray, GfxRGB *rgb,
GfxCMYK *cmyk) {
#else
SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb) {
@@ -1471,7 +1689,7 @@ SplashPattern *SplashOutputDev::getColor(GfxGray gray, GfxRGB *rgb) {
color[1] = colToByte(cmyk->m);
color[2] = colToByte(cmyk->y);
color[3] = colToByte(cmyk->k);
- pattern = new SplashSolidColor(color);
+ pattern = createOverprintPattern(colorSpace, color, gFalse);
break;
#endif
}
@@ -1491,6 +1709,18 @@ void SplashOutputDev::updateStrokeOpacity(GfxState *state) {
splash->setStrokeAlpha((SplashCoord)state->getStrokeOpacity());
}
+void SplashOutputDev::updateFillOverprint(GfxState *state) {
+ splash->setFillOverprint(state->getFillOverprint());
+}
+
+void SplashOutputDev::updateStrokeOverprint(GfxState *state) {
+ splash->setStrokeOverprint(state->getStrokeOverprint());
+}
+
+void SplashOutputDev::updateOverprintMode(GfxState *state) {
+ splash->setOverprintMode(state->getOverprintMode());
+}
+
void SplashOutputDev::updateFont(GfxState * /*state*/) {
needFontUpdate = gTrue;
}
@@ -2663,12 +2893,15 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
SplashCoord mat[6];
SplashOutImageData imgData;
SplashColorMode srcMode;
+ SplashColor defaultColor;
+ GfxColor srcColor;
SplashImageSource src;
GfxGray gray;
GfxRGB rgb;
#if SPLASH_CMYK
GfxCMYK cmyk;
#endif
+ GBool grayIndexed = gFalse;
Guchar pix;
int n, i;
@@ -2733,15 +2966,25 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
break;
#if SPLASH_CMYK
case splashModeCMYK8:
+ grayIndexed = colorMap->getColorSpace()->getMode() != csDeviceGray;
imgData.lookup = (SplashColorPtr)gmallocn(n, 4);
for (i = 0; i < n; ++i) {
pix = (Guchar)i;
colorMap->getCMYK(&pix, &cmyk);
+ if (cmyk.c != 0 || cmyk.m != 0 || cmyk.y != 0) {
+ grayIndexed = gFalse;
+ }
imgData.lookup[4*i] = colToByte(cmyk.c);
imgData.lookup[4*i+1] = colToByte(cmyk.m);
imgData.lookup[4*i+2] = colToByte(cmyk.y);
imgData.lookup[4*i+3] = colToByte(cmyk.k);
}
+#ifndef USE_CMS
+ if (colorMap->getColorSpace()->getMode() == csIndexed) {
+ if (((GfxIndexedColorSpace *) colorMap->getColorSpace())->getBase()->getMode() == csICCBased)
+ grayIndexed = gFalse;
+ }
+#endif
break;
#endif
break;
@@ -2754,8 +2997,12 @@ void SplashOutputDev::drawImage(GfxState *state, Object *ref, Stream *str,
srcMode = colorMode;
}
src = maskColors ? &alphaImageSrc : &imageSrc;
+ colorMap->getColorSpace()->getDefaultColor(&srcColor);
+ convertGfxColor(defaultColor, srcMode, colorMap->getColorSpace(), &srcColor);
+ SplashPattern *pattern = createOverprintPattern(colorMap->getColorSpace(), defaultColor, !grayIndexed);
splash->drawImage(src, &imgData, srcMode, maskColors ? gTrue : gFalse,
- width, height, mat);
+ width, height, mat, pattern);
+ delete pattern;
if (inlineImg) {
while (imgData.y < height) {
imgData.imgStr->getLine();
@@ -2913,6 +3160,8 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
delete maskColorMap;
} else {
+ SplashColor defaultColor;
+ GfxColor srcColor;
//----- scale the mask image to the same size as the source image
@@ -3025,9 +3274,12 @@ void SplashOutputDev::drawMaskedImage(GfxState *state, Object *ref,
} else {
srcMode = colorMode;
}
+ colorMap->getColorSpace()->getDefaultColor(&srcColor);
+ convertGfxColor(defaultColor, srcMode, colorMap->getColorSpace(), &srcColor);
+ SplashPattern *pattern = createOverprintPattern(colorMap->getColorSpace(), defaultColor, gTrue);
splash->drawImage(&maskedImageSrc, &imgData, srcMode, gTrue,
- width, height, mat);
-
+ width, height, mat, pattern);
+ delete pattern;
delete maskBitmap;
gfree(imgData.lookup);
delete imgData.imgStr;
@@ -3051,6 +3303,8 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
SplashBitmap *maskBitmap;
Splash *maskSplash;
SplashColor maskColor;
+ SplashColor defaultColor;
+ GfxColor srcColor;
GfxGray gray;
GfxRGB rgb;
#if SPLASH_CMYK
@@ -3173,8 +3427,12 @@ void SplashOutputDev::drawSoftMaskedImage(GfxState *state, Object *ref,
} else {
srcMode = colorMode;
}
- splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat);
+ colorMap->getColorSpace()->getDefaultColor(&srcColor);
+ convertGfxColor(defaultColor, srcMode, colorMap->getColorSpace(), &srcColor);
+ SplashPattern *pattern = createOverprintPattern(colorMap->getColorSpace(), defaultColor, gTrue);
+ splash->drawImage(&imageSrc, &imgData, srcMode, gFalse, width, height, mat, pattern);
+ delete pattern;
splash->setSoftMask(NULL);
gfree(imgData.lookup);
delete imgData.imgStr;
@@ -3499,31 +3757,6 @@ void SplashOutputDev::clearModRegion() {
splash->clearModRegion();
}
-void SplashOutputDev::setFillColor(int r, int g, int b) {
- GfxRGB rgb;
- GfxGray gray;
-#if SPLASH_CMYK
- GfxCMYK cmyk;
-#endif
-
- rgb.r = byteToCol(r);
- rgb.g = byteToCol(g);
- rgb.b = byteToCol(b);
- gray = (GfxColorComp)(0.299 * rgb.r + 0.587 * rgb.g + 0.114 * rgb.b + 0.5);
- if (gray > gfxColorComp1) {
- gray = gfxColorComp1;
- }
-#if SPLASH_CMYK
- cmyk.c = gfxColorComp1 - rgb.r;
- cmyk.m = gfxColorComp1 - rgb.g;
- cmyk.y = gfxColorComp1 - rgb.b;
- cmyk.k = 0;
- splash->setFillPattern(getColor(gray, &rgb, &cmyk));
-#else
- splash->setFillPattern(getColor(gray, &rgb));
-#endif
-}
-
#if 1 //~tmp: turn off anti-aliasing temporarily
GBool SplashOutputDev::getVectorAntialias() {
return splash->getVectorAntialias();
@@ -3545,7 +3778,7 @@ GBool SplashOutputDev::tilingPatternFill(GfxState *state, Catalog *catalog, Obje
double *ptm, int paintType, Dict *resDict,
double *mat, double *bbox,
int x0, int y0, int x1, int y1,
- double xStep, double yStep)
+ double xStep, double yStep)
{
PDFRectangle box;
Gfx *gfx;
@@ -3653,7 +3886,7 @@ GBool SplashOutputDev::tilingPatternFill(GfxState *state, Catalog *catalog, Obje
m1.m[4] = -kx;
m1.m[5] = -ky;
- bitmap = new SplashBitmap(surface_width, surface_height, colorMode != splashModeMono1,
+ bitmap = new SplashBitmap(surface_width, surface_height, colorMode != splashModeMono1,
(paintType == 1) ? colorMode : splashModeMono8, gTrue);
memset(bitmap->getAlphaPtr(), 0, bitmap->getWidth() * bitmap->getHeight());
if (paintType == 2) {
@@ -3723,7 +3956,7 @@ GBool SplashOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTria
default:
break;
}
- SplashGouraudColor *splashShading = new SplashGouraudPattern(bDirectColorTranslation, state, shading);
+ SplashGouraudColor *splashShading = new SplashGouraudPattern(bDirectColorTranslation, state, shading, colorMode);
// restore vector antialias because we support it here
if (shading->isParameterized()) {
GBool vaa = getVectorAntialias();
diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h
index 26f3ddf..e44e61c 100644
--- a/poppler/SplashOutputDev.h
+++ b/poppler/SplashOutputDev.h
@@ -51,6 +51,33 @@ struct T3GlyphStack;
struct SplashTransparencyGroup;
//------------------------------------------------------------------------
+// SplashOverprintColor
+//------------------------------------------------------------------------
+
+class SplashOverprintColor: public SplashPattern {
+public:
+ SplashOverprintColor(GfxColorSpace *colorSpace, SplashColorPtr colorA, Guchar tolerance);
+
+ virtual SplashPattern *copy() { return new SplashOverprintColor(colorSpace, color, tolerance); }
+
+ virtual ~SplashOverprintColor();
+
+ virtual GBool getColor(int x, int y, SplashColorPtr c);
+
+ virtual GBool testPosition(int x, int y) { return gFalse; }
+
+ virtual GBool isStatic() { return gTrue; }
+
+ virtual void overprint(GBool op, Guchar alphaSrc, SplashColorPtr colorSrc,
+ Guchar alphaDest, SplashColorPtr colorDest, SplashColorPtr colorResult);
+
+private:
+ GfxColorSpace *colorSpace;
+ SplashColor color;
+ Guchar tolerance;
+};
+
+//------------------------------------------------------------------------
// Splash dynamic pattern
//------------------------------------------------------------------------
@@ -90,18 +117,22 @@ public:
virtual GBool getParameter(double xs, double ys, double *t);
+ virtual void overprint(GBool op, Guchar alphaSrc, SplashColorPtr colorSrc,
+ Guchar alphaDest, SplashColorPtr colorDest, SplashColorPtr colorResult);
+
private:
double x0, y0, x1, y1;
double dx, dy, mul;
+ SplashOverprintColor *opPattern;
};
// see GfxState.h, GfxGouraudTriangleShading
class SplashGouraudPattern: public SplashGouraudColor {
public:
- SplashGouraudPattern(GBool bDirectColorTranslation, GfxState *state, GfxGouraudTriangleShading *shading);
+ SplashGouraudPattern(GBool bDirectColorTranslation, GfxState *state, GfxGouraudTriangleShading *shading, SplashColorMode mode);
- virtual SplashPattern *copy() { return new SplashGouraudPattern(bDirectColorTranslation, state, shading); }
+ virtual SplashPattern *copy() { return new SplashGouraudPattern(bDirectColorTranslation, state, shading, mode); }
virtual ~SplashGouraudPattern();
@@ -120,10 +151,14 @@ public:
virtual void getParameterizedColor(double t, SplashColorMode mode, SplashColorPtr c);
+ virtual void overprint(GBool op, Guchar alphaSrc, SplashColorPtr colorSrc,
+ Guchar alphaDest, SplashColorPtr colorDest, SplashColorPtr colorResult);
private:
GfxGouraudTriangleShading *shading;
GfxState *state;
GBool bDirectColorTranslation;
+ SplashOverprintColor *opPattern;
+ SplashColorMode mode;
};
// see GfxState.h, GfxRadialShading
@@ -138,9 +173,13 @@ public:
virtual GBool getParameter(double xs, double ys, double *t);
+ virtual void overprint(GBool op, Guchar alphaSrc, SplashColorPtr colorSrc,
+ Guchar alphaDest, SplashColorPtr colorDest, SplashColorPtr colorResult);
+
private:
double x0, y0, r0, dx, dy, dr;
double a, inva;
+ SplashOverprintColor *opPattern;
};
//------------------------------------------------------------------------
@@ -220,6 +259,9 @@ public:
virtual void updateBlendMode(GfxState *state);
virtual void updateFillOpacity(GfxState *state);
virtual void updateStrokeOpacity(GfxState *state);
+ virtual void updateFillOverprint(GfxState *state);
+ virtual void updateStrokeOverprint(GfxState *state);
+ virtual void updateOverprintMode(GfxState *state);
//----- update text state
virtual void updateFont(GfxState *state);
@@ -327,9 +369,6 @@ public:
// Clear the modified region.
void clearModRegion();
- // Set the Splash fill color.
- void setFillColor(int r, int g, int b);
-
SplashFont *getCurrentFont() { return font; }
#if 1 //~tmp: turn off anti-aliasing temporarily
@@ -344,7 +383,7 @@ private:
void setupScreenParams(double hDPI, double vDPI);
#if SPLASH_CMYK
- SplashPattern *getColor(GfxGray gray, GfxRGB *rgb, GfxCMYK *cmyk);
+ SplashPattern *getColor(GfxColorSpace *colorSpace, GfxGray gray, GfxRGB *rgb, GfxCMYK *cmyk);
#else
SplashPattern *getColor(GfxGray gray, GfxRGB *rgb);
#endif
diff --git a/splash/Splash.cc b/splash/Splash.cc
index fe7c001..e5c8096 100644
--- a/splash/Splash.cc
+++ b/splash/Splash.cc
@@ -103,6 +103,10 @@ struct SplashPipe {
// non-isolated group correction
int nonIsolatedGroup;
+
+ // stroke / fill operation and pattern for calculate overprint
+ GBool stroke;
+ SplashPattern *overprintPattern;
};
SplashPipeResultColorCtrl Splash::pipeResultColorNoAlphaBlend[] = {
@@ -188,7 +192,7 @@ inline void Splash::updateModY(int y) {
inline void Splash::pipeInit(SplashPipe *pipe, int x, int y,
SplashPattern *pattern, SplashColorPtr cSrc,
SplashCoord aInput, GBool usesShape,
- GBool nonIsolatedGroup) {
+ GBool nonIsolatedGroup, SplashPattern *opPattern, GBool strokeA) {
pipeSetXY(pipe, x, y);
pipe->pattern = NULL;
@@ -239,6 +243,8 @@ inline void Splash::pipeInit(SplashPipe *pipe, int x, int y,
} else {
pipe->nonIsolatedGroup = 0;
}
+ pipe->stroke = strokeA;
+ pipe->overprintPattern = opPattern;
}
inline void Splash::pipeRun(SplashPipe *pipe) {
@@ -297,10 +303,25 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
break;
#if SPLASH_CMYK
case splashModeCMYK8:
- *pipe->destColorPtr++ = pipe->cSrc[0];
- *pipe->destColorPtr++ = pipe->cSrc[1];
- *pipe->destColorPtr++ = pipe->cSrc[2];
- *pipe->destColorPtr++ = pipe->cSrc[3];
+ if (pipe->overprintPattern != NULL &&
+ ((pipe->stroke && state->strokeOverprint) ||
+ (!pipe->stroke && state->fillOverprint))) {
+ SplashColor cResult;
+ cDest[0] = pipe->destColorPtr[0];
+ cDest[1] = pipe->destColorPtr[1];
+ cDest[2] = pipe->destColorPtr[2];
+ cDest[3] = pipe->destColorPtr[3];
+ pipe->overprintPattern->overprint(state->overprintMode == 1, pipe->aSrc, pipe->cSrc, 255, cDest, cResult);
+ *pipe->destColorPtr++ = cResult[0];
+ *pipe->destColorPtr++ = cResult[1];
+ *pipe->destColorPtr++ = cResult[2];
+ *pipe->destColorPtr++ = cResult[3];
+ } else {
+ *pipe->destColorPtr++ = pipe->cSrc[0];
+ *pipe->destColorPtr++ = pipe->cSrc[1];
+ *pipe->destColorPtr++ = pipe->cSrc[2];
+ *pipe->destColorPtr++ = pipe->cSrc[3];
+ }
break;
#endif
}
@@ -435,14 +456,25 @@ inline void Splash::pipeRun(SplashPipe *pipe) {
cResult2 = 0;
cResult3 = 0;
} else {
- cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
+ if (pipe->overprintPattern != NULL &&
+ ((pipe->stroke && state->strokeOverprint) ||
+ (!pipe->stroke && state->fillOverprint))) {
+ SplashColor cResult;
+ pipe->overprintPattern->overprint(state->overprintMode == 1, aSrc, pipe->cSrc, alpha2, cDest, cResult);
+ cResult0 = cResult[0];
+ cResult1 = cResult[1];
+ cResult2 = cResult[2];
+ cResult3 = cResult[3];
+ } else {
+ cResult0 = (Guchar)(((alpha2 - aSrc) * cDest[0] +
aSrc * pipe->cSrc[0]) / alpha2);
- cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
+ cResult1 = (Guchar)(((alpha2 - aSrc) * cDest[1] +
aSrc * pipe->cSrc[1]) / alpha2);
- cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
+ cResult2 = (Guchar)(((alpha2 - aSrc) * cDest[2] +
aSrc * pipe->cSrc[2]) / alpha2);
- cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] +
+ cResult3 = (Guchar)(((alpha2 - aSrc) * cDest[3] +
aSrc * pipe->cSrc[3]) / alpha2);
+ }
}
break;
#endif
@@ -990,6 +1022,18 @@ void Splash::setFillAlpha(SplashCoord alpha) {
state->fillAlpha = alpha;
}
+void Splash::setFillOverprint(GBool fop) {
+ state->fillOverprint = fop;
+}
+
+void Splash::setStrokeOverprint(GBool gop) {
+ state->strokeOverprint = gop;
+}
+
+void Splash::setOverprintMode(int opm) {
+ state->overprintMode = opm;
+}
+
void Splash::setLineWidth(SplashCoord lineWidth) {
state->lineWidth = lineWidth;
}
@@ -1242,7 +1286,7 @@ void Splash::strokeNarrow(SplashPath *path) {
xPath = new SplashXPath(path, state->matrix, state->flatness, gFalse);
pipeInit(&pipe, 0, 0, state->strokePattern, NULL, state->strokeAlpha,
- gFalse, gFalse);
+ gFalse, gFalse, state->strokePattern, gTrue);
for (i = 0, seg = xPath->segs; i < xPath->length; ++i, ++seg) {
@@ -1615,7 +1659,7 @@ SplashError Splash::fillWithPattern(SplashPath *path, GBool eo,
yMaxI = state->clip->getYMaxI();
}
- pipeInit(&pipe, 0, yMinI, pattern, NULL, alpha, vectorAntialias, gFalse);
+ pipeInit(&pipe, 0, yMinI, pattern, NULL, alpha, vectorAntialias, gFalse, pattern);
// draw the spans
if (vectorAntialias) {
@@ -1685,7 +1729,7 @@ SplashError Splash::xorFill(SplashPath *path, GBool eo) {
origBlendFunc = state->blendFunc;
state->blendFunc = &blendXor;
- pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 1, gFalse, gFalse);
+ pipeInit(&pipe, 0, yMinI, state->fillPattern, NULL, 1, gFalse, gFalse, state->fillPattern);
// draw the spans
for (y = yMinI; y <= yMaxI; ++y) {
@@ -1799,7 +1843,7 @@ void Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph, GBool noClip)
if (noClip) {
if (glyph->aa) {
pipeInit(&pipe, xStart, yStart,
- state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
+ state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse, state->fillPattern);
for (yy = 0, y1 = yStart; yy < yyLimit; ++yy, ++y1) {
pipeSetXY(&pipe, xStart, y1);
for (xx = 0, x1 = xStart; xx < xxLimit; ++xx, ++x1) {
@@ -1819,7 +1863,7 @@ void Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph, GBool noClip)
const int widthEight = splashCeil(glyph->w / 8.0);
pipeInit(&pipe, xStart, yStart,
- state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
+ state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse, state->fillPattern);
for (yy = 0, y1 = yStart; yy < yyLimit; ++yy, ++y1) {
pipeSetXY(&pipe, xStart, y1);
for (xx = 0, x1 = xStart; xx < xxLimit; xx += 8) {
@@ -1841,7 +1885,7 @@ void Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph, GBool noClip)
} else {
if (glyph->aa) {
pipeInit(&pipe, xStart, yStart,
- state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse);
+ state->fillPattern, NULL, state->fillAlpha, gTrue, gFalse, state->fillPattern);
for (yy = 0, y1 = yStart; yy < yyLimit; ++yy, ++y1) {
pipeSetXY(&pipe, xStart, y1);
for (xx = 0, x1 = xStart; xx < xxLimit; ++xx, ++x1) {
@@ -1865,7 +1909,7 @@ void Splash::fillGlyph2(int x0, int y0, SplashGlyphBitmap *glyph, GBool noClip)
const int widthEight = splashCeil(glyph->w / 8.0);
pipeInit(&pipe, xStart, yStart,
- state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse);
+ state->fillPattern, NULL, state->fillAlpha, gFalse, gFalse, state->fillPattern);
for (yy = 0, y1 = yStart; yy < yyLimit; ++yy, ++y1) {
pipeSetXY(&pipe, xStart, y1);
for (xx = 0, x1 = xStart; xx < xxLimit; xx += 8) {
@@ -2043,7 +2087,7 @@ SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
// initialize the pixel pipe
pipeInit(&pipe, 0, 0, state->fillPattern, NULL, state->fillAlpha,
- gTrue, gFalse);
+ gTrue, gFalse, state->fillPattern);
if (vectorAntialias) {
drawAAPixelInit();
}
@@ -2178,7 +2222,7 @@ SplashError Splash::fillImageMask(SplashImageMaskSource src, void *srcData,
SplashError Splash::drawImage(SplashImageSource src, void *srcData,
SplashColorMode srcMode, GBool srcAlpha,
- int w, int h, SplashCoord *mat) {
+ int w, int h, SplashCoord *mat, SplashPattern *opImagePattern) {
SplashPipe pipe;
GBool ok, rot;
SplashCoord xScale, yScale, xShear, yShear, yShear1;
@@ -2357,7 +2401,7 @@ SplashError Splash::drawImage(SplashImageSource src, void *srcData,
// initialize the pixel pipe
pipeInit(&pipe, 0, 0, NULL, pix, state->fillAlpha,
srcAlpha || (vectorAntialias && clipRes != splashClipAllInside),
- gFalse);
+ gFalse, opImagePattern);
if (vectorAntialias) {
drawAAPixelInit();
}
@@ -3277,7 +3321,7 @@ GBool Splash::gouraudTriangleShadedFill(SplashGouraudColor *shading)
SplashPipe pipe;
SplashColor cSrcVal;
- pipeInit(&pipe, 0, 0, NULL, cSrcVal, state->strokeAlpha, gFalse, gFalse);
+ pipeInit(&pipe, 0, 0, NULL, cSrcVal, state->strokeAlpha, gFalse, gFalse, NULL, gTrue);
if (vectorAntialias) {
if (aaBuf == NULL)
@@ -3977,7 +4021,7 @@ SplashError Splash::shadedFill(SplashPath *path, GBool hasBBox,
yMaxI = state->clip->getYMaxI();
}
- pipeInit(&pipe, 0, yMinI, pattern, NULL, state->fillAlpha, vectorAntialias && !hasBBox, gFalse);
+ pipeInit(&pipe, 0, yMinI, pattern, NULL, state->fillAlpha, vectorAntialias && !hasBBox, gFalse, pattern);
// draw the spans
if (vectorAntialias) {
diff --git a/splash/Splash.h b/splash/Splash.h
index 43e0229..85f92ed 100644
--- a/splash/Splash.h
+++ b/splash/Splash.h
@@ -13,7 +13,7 @@
//
// Copyright (C) 2005 Marco Pesenti Gritti <mpg at redhat.com>
// Copyright (C) 2007, 2011 Albert Astals Cid <aacid at kde.org>
-// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010, 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
//
// To see a description of the changes please see the Changelog file that
@@ -121,6 +121,9 @@ public:
void setBlendFunc(SplashBlendFunc func);
void setStrokeAlpha(SplashCoord alpha);
void setFillAlpha(SplashCoord alpha);
+ void setFillOverprint(GBool fop);
+ void setStrokeOverprint(GBool sop);
+ void setOverprintMode(int opm);
void setLineWidth(SplashCoord lineWidth);
void setLineCap(int lineCap);
void setLineJoin(int lineJoin);
@@ -203,7 +206,7 @@ public:
// The matrix behaves as for fillImageMask.
SplashError drawImage(SplashImageSource src, void *srcData,
SplashColorMode srcMode, GBool srcAlpha,
- int w, int h, SplashCoord *mat);
+ int w, int h, SplashCoord *mat, SplashPattern *overprintPattern = NULL);
// Composite a rectangular region from <src> onto this Splash
// object.
@@ -262,7 +265,7 @@ private:
void pipeInit(SplashPipe *pipe, int x, int y,
SplashPattern *pattern, SplashColorPtr cSrc,
SplashCoord aInput, GBool usesShape,
- GBool nonIsolatedGroup);
+ GBool nonIsolatedGroup, SplashPattern *overprintPattern = NULL, GBool stroke = gFalse);
void pipeRun(SplashPipe *pipe);
void pipeSetXY(SplashPipe *pipe, int x, int y);
void pipeIncX(SplashPipe *pipe);
diff --git a/splash/SplashBitmap.cc b/splash/SplashBitmap.cc
index 7c26e54..562fbda 100644
--- a/splash/SplashBitmap.cc
+++ b/splash/SplashBitmap.cc
@@ -19,6 +19,7 @@
// Copyright (C) 2010 Harry Roberts <harry.roberts at midnight-labs.org>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger at googlemail.com>
// Copyright (C) 2010 William Bader <williambader at hotmail.com>
+// Copyright (C) 2011 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
@@ -302,6 +303,11 @@ SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, in
#endif
#ifdef ENABLE_LIBJPEG
+ #ifdef SPLASH_CMYK
+ case splashFormatJpegCMYK:
+ writer = new JpegWriter(JCS_CMYK);
+ break;
+ #endif
case splashFormatJpeg:
writer = new JpegWriter();
break;
@@ -329,8 +335,35 @@ SplashError SplashBitmap::writeImgFile(SplashImageFileFormat format, FILE *f, in
return e;
}
+#include "poppler/GfxState_helpers.h"
+
+void SplashBitmap::getRGBLine(int yl, SplashColorPtr line) {
+ SplashColor col;
+ double c, m, y, k, c1, m1, y1, k1, r, g, b;
+
+ for (int x = 0; x < width; x++) {
+ getPixel(x, yl, col);
+ c = byteToDbl(col[0]);
+ m = byteToDbl(col[1]);
+ y = byteToDbl(col[2]);
+ k = byteToDbl(col[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);
+ *line++ = dblToByte(clip01(r));
+ *line++ = dblToByte(clip01(g));
+ *line++ = dblToByte(clip01(b));
+ }
+}
+
SplashError SplashBitmap::writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int vDPI) {
- if (mode != splashModeRGB8 && mode != splashModeMono8 && mode != splashModeMono1 && mode != splashModeXBGR8) {
+ if (mode != splashModeRGB8 && mode != splashModeMono8 && mode != splashModeMono1 && mode != splashModeXBGR8
+#if SPLASH_CMYK
+ && mode != splashModeCMYK8
+#endif
+ ) {
error(-1, "unsupported SplashBitmap mode");
return splashErrGeneric;
}
@@ -340,6 +373,35 @@ SplashError SplashBitmap::writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int
}
switch (mode) {
+#if SPLASH_CMYK
+ case splashModeCMYK8:
+ if (writer->supportCMYK()) {
+ SplashColorPtr row;
+ unsigned char **row_pointers = new unsigned char*[height];
+ row = data;
+
+ for (int y = 0; y < height; ++y) {
+ row_pointers[y] = row;
+ row += rowSize;
+ }
+ if (!writer->writePointers(row_pointers, height)) {
+ delete[] row_pointers;
+ return splashErrGeneric;
+ }
+ delete[] row_pointers;
+ } else {
+ unsigned char *row = new unsigned char[3 * width];
+ for (int y = 0; y < height; y++) {
+ getRGBLine(y, row);
+ if (!writer->writeRow(&row)) {
+ delete[] row;
+ return splashErrGeneric;
+ }
+ }
+ delete[] row;
+ }
+ break;
+#endif
case splashModeRGB8:
{
SplashColorPtr row;
diff --git a/splash/SplashBitmap.h b/splash/SplashBitmap.h
index b276a61..3336507 100644
--- a/splash/SplashBitmap.h
+++ b/splash/SplashBitmap.h
@@ -71,6 +71,7 @@ public:
SplashError writeImgFile(ImgWriter *writer, FILE *f, int hDPI, int vDPI);
void getPixel(int x, int y, SplashColorPtr pixel);
+ void getRGBLine(int y, SplashColorPtr line);
Guchar getAlpha(int x, int y);
private:
diff --git a/splash/SplashPattern.cc b/splash/SplashPattern.cc
index b42714d..6747973 100644
--- a/splash/SplashPattern.cc
+++ b/splash/SplashPattern.cc
@@ -11,7 +11,7 @@
// All changes made under the Poppler project to this file are licensed
// under GPL version 2 or later
//
-// Copyright (C) 2010 Thomas Freitag <Thomas.Freitag at alfa.de>
+// Copyright (C) 2010, 2011 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
@@ -53,3 +53,17 @@ GBool SplashSolidColor::getColor(int x, int y, SplashColorPtr c) {
splashColorCopy(c, color);
return gTrue;
}
+
+void SplashSolidColor::overprint(GBool op, Guchar aSrc, SplashColorPtr cSrc,
+ Guchar aDest, SplashColorPtr cDest,
+ SplashColorPtr colorResult) {
+ // default for overprint is knockout:
+ colorResult[0] = (Guchar)(((aDest - aSrc) * cDest[0] +
+ aSrc * cSrc[0]) / aDest);
+ colorResult[1] = (Guchar)(((aDest - aSrc) * cDest[1] +
+ aSrc * cSrc[1]) / aDest);
+ colorResult[2] = (Guchar)(((aDest - aSrc) * cDest[2] +
+ aSrc * cSrc[2]) / aDest);
+ colorResult[3] = (Guchar)(((aDest - aSrc) * cDest[3] +
+ aSrc * cSrc[3]) / aDest);
+}
diff --git a/splash/SplashPattern.h b/splash/SplashPattern.h
index 42c1660..de1f887 100644
--- a/splash/SplashPattern.h
+++ b/splash/SplashPattern.h
@@ -52,6 +52,10 @@ public:
// value for all pixels.
virtual GBool isStatic() = 0;
+ // calculate destination color if overprint is enables
+ virtual void overprint(GBool op, Guchar alphaSrc, SplashColorPtr colorSrc,
+ Guchar alphaDest, SplashColorPtr colorDest, SplashColorPtr colorResult) = 0;
+
private:
};
@@ -74,6 +78,9 @@ public:
virtual GBool isStatic() { return gTrue; }
+ virtual void overprint(GBool op, Guchar alphaSrc, SplashColorPtr colorSrc,
+ Guchar alphaDest, SplashColorPtr colorDest, SplashColorPtr colorResult);
+
private:
SplashColor color;
diff --git a/splash/SplashState.cc b/splash/SplashState.cc
index b1fa2f5..15b6a72 100644
--- a/splash/SplashState.cc
+++ b/splash/SplashState.cc
@@ -11,7 +11,7 @@
// 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>
+// Copyright (C) 2009, 2011 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
@@ -71,6 +71,9 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
softMask = NULL;
deleteSoftMask = gFalse;
inNonIsolatedGroup = gFalse;
+ fillOverprint = gFalse;
+ strokeOverprint = gFalse;
+ overprintMode = 0;
next = NULL;
}
@@ -101,6 +104,9 @@ SplashState::SplashState(int width, int height, GBool vectorAntialias,
softMask = NULL;
deleteSoftMask = gFalse;
inNonIsolatedGroup = gFalse;
+ fillOverprint = gFalse;
+ strokeOverprint = gFalse;
+ overprintMode = 0;
next = NULL;
}
@@ -131,6 +137,9 @@ SplashState::SplashState(SplashState *state) {
softMask = state->softMask;
deleteSoftMask = gFalse;
inNonIsolatedGroup = state->inNonIsolatedGroup;
+ fillOverprint = state->fillOverprint;
+ strokeOverprint = state->strokeOverprint;
+ overprintMode = state->overprintMode;
next = NULL;
}
diff --git a/splash/SplashState.h b/splash/SplashState.h
index d0e05df..63dadc6 100644
--- a/splash/SplashState.h
+++ b/splash/SplashState.h
@@ -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) 2011 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
+//
+//========================================================================
+
#ifndef SPLASHSTATE_H
#define SPLASHSTATE_H
@@ -68,6 +82,11 @@ public:
// Set the soft mask bitmap.
void setSoftMask(SplashBitmap *softMaskA);
+ // Set the overprint parametes.
+ void setFillOverprint(GBool fillOverprintA) { fillOverprint = fillOverprintA; }
+ void setStrokeOverprint(GBool strokeOverprintA) { strokeOverprint = strokeOverprintA; }
+ void setOverprintMode(int overprintModeA) { overprintMode = overprintModeA; }
+
private:
SplashState(SplashState *state);
@@ -92,6 +111,9 @@ private:
SplashBitmap *softMask;
GBool deleteSoftMask;
GBool inNonIsolatedGroup;
+ GBool fillOverprint;
+ GBool strokeOverprint;
+ int overprintMode;
SplashState *next; // used by Splash class
diff --git a/splash/SplashTypes.h b/splash/SplashTypes.h
index 273c32d..65525b1 100644
--- a/splash/SplashTypes.h
+++ b/splash/SplashTypes.h
@@ -13,7 +13,7 @@
//
// Copyright (C) 2006, 2010 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>
+// Copyright (C) 2009, 2011 Thomas Freitag <Thomas.Freitag at alfa.de>
// Copyright (C) 2009 Stefan Thomas <thomas at eload24.com>
// Copyright (C) 2010 William Bader <williambader at hotmail.com>
//
@@ -162,7 +162,8 @@ typedef int SplashError;
enum SplashImageFileFormat {
splashFormatJpeg,
splashFormatPng,
- splashFormatTiff
+ splashFormatTiff,
+ splashFormatJpegCMYK
};
#endif
diff --git a/utils/pdftoppm.cc b/utils/pdftoppm.cc
index 8a7c702..0923377 100644
--- a/utils/pdftoppm.cc
+++ b/utils/pdftoppm.cc
@@ -23,6 +23,7 @@
// Copyright (C) 2010 Hib Eris <hib at hiberis.nl>
// Copyright (C) 2010 Jonathan Liu <net147 at gmail.com>
// Copyright (C) 2010 William Bader <williambader at hotmail.com>
+// Copyright (C) 2011 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
@@ -71,7 +72,9 @@ static GBool mono = gFalse;
static GBool gray = gFalse;
static GBool png = gFalse;
static GBool jpeg = gFalse;
+static GBool jpegcmyk = gFalse;
static GBool tiff = gFalse;
+static GBool overprint = gFalse;
static char enableFreeTypeStr[16] = "";
static char antialiasStr[16] = "";
static char vectorAntialiasStr[16] = "";
@@ -129,8 +132,16 @@ static const ArgDesc argDesc[] = {
"generate a PNG file"},
#endif
#if ENABLE_LIBJPEG
- {"-jpeg", argFlag, &jpeg, 0,
+ {"-jpeg", argFlag, &jpeg, 0,
"generate a JPEG file"},
+#if SPLASH_CMYK
+ {"-jpegcmyk",argFlag, &jpegcmyk, 0,
+ "generate a CMYK JPEG file"},
+#endif
+#endif
+#if SPLASH_CMYK
+ {"-overprint",argFlag, &overprint, 0,
+ "enable overprint"},
#endif
#if ENABLE_LIBTIFF
{"-tiff", argFlag, &tiff, 0,
@@ -191,6 +202,8 @@ static void savePageSlice(PDFDoc *doc,
bitmap->writeImgFile(splashFormatPng, ppmFile, x_resolution, y_resolution);
} else if (jpeg) {
bitmap->writeImgFile(splashFormatJpeg, ppmFile, x_resolution, y_resolution);
+ } else if (jpegcmyk) {
+ bitmap->writeImgFile(splashFormatJpegCMYK, ppmFile, x_resolution, y_resolution);
} else if (tiff) {
bitmap->writeImgFile(splashFormatTiff, ppmFile, x_resolution, y_resolution, TiffCompressionStr);
} else {
@@ -337,11 +350,24 @@ int main(int argc, char *argv[]) {
}
// write PPM files
- paperColor[0] = 255;
- paperColor[1] = 255;
- paperColor[2] = 255;
+#if SPLASH_CMYK
+ if (jpegcmyk || overprint) {
+ paperColor[0] = 0;
+ paperColor[1] = 0;
+ paperColor[2] = 0;
+ paperColor[3] = 0;
+ } else
+#endif
+ {
+ paperColor[0] = 255;
+ paperColor[1] = 255;
+ paperColor[2] = 255;
+ }
splashOut = new SplashOutputDev(mono ? splashModeMono1 :
gray ? splashModeMono8 :
+#if SPLASH_CMYK
+ (jpegcmyk || overprint) ? splashModeCMYK8 :
+#endif
splashModeRGB8, 4,
gFalse, paperColor);
splashOut->startDoc(doc->getXRef());
@@ -377,7 +403,7 @@ int main(int argc, char *argv[]) {
pg_h = tmp;
}
if (ppmRoot != NULL) {
- const char *ext = png ? "png" : jpeg ? "jpg" : tiff ? "tif" : mono ? "pbm" : gray ? "pgm" : "ppm";
+ const char *ext = png ? "png" : (jpeg || jpegcmyk) ? "jpg" : tiff ? "tif" : mono ? "pbm" : gray ? "pgm" : "ppm";
if (singleFile) {
snprintf(ppmFile, PPM_FILE_SZ, "%.*s.%s",
PPM_FILE_SZ - 32, ppmRoot, ext);
More information about the poppler
mailing list