Commit 861a7bfb authored by Thomas Freitag's avatar Thomas Freitag Committed by Albert Astals Cid

Implement overprint in Splash

See the "Implementing overprint in Splash" thread in the mailing list for more info
parent e2fa8a2c
......@@ -8,6 +8,7 @@
// Copyright (C) 2009, 2011 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2010 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2010 Brian Cameron <brian.cameron@oracle.com>
// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@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
......@@ -7,6 +7,7 @@
// Copyright (C) 2009 Stefan Thomas <thomas@eload24.com>
// Copyright (C) 2010 Adrian Johnson <ajohnson@redneon.com>
// Copyright (C) 2010 Harry Roberts <harry.roberts@midnight-labs.org>
// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@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;
}
......
......@@ -10,6 +10,7 @@
// Copyright (C) 2010 Harry Roberts <harry.roberts@midnight-labs.org>
// Copyright (C) 2010 Brian Cameron <brian.cameron@oracle.com>
// Copyright (C) 2011 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@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;
};
......
......@@ -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;
}
......
......@@ -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;
......
......@@ -20,6 +20,7 @@
// Copyright (C) 2009-2011 Albert Astals Cid <aacid@kde.org>
// Copyright (C) 2010 Christian Feuersänger <cfeuersaenger@googlemail.com>
// Copyright (C) 2011 Andrea Canciani <ranma42@gmail.com>
// Copyright (C) 2011 Thomas Freitag <Thomas.Freitag@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 =
......
......@@ -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*/) {}
......
This diff is collapsed.
......@@ -50,6 +50,33 @@ struct T3FontCacheTag;
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
......
......@@ -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);