diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index 0ae5bc5..11e052e 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -80,6 +80,85 @@ extern "C" int unlink(char *filename); #endif //------------------------------------------------------------------------ +// SplashSolidColor +//------------------------------------------------------------------------ + +SplashAxialPattern::SplashAxialPattern(SplashColorMode colorModeA, GfxState *stateA, GfxAxialShading *shadingA) { + Matrix ctm; + + shading = shadingA; + state = stateA; + colorMode = colorModeA; + state->getCTM (&ctm); + ctm.invertTo (&ictm); + + shading->getCoords(&x0, &y0, &x1, &y1); + dx = x1 - x0; + dy = y1 - y0; + mul = 1 / (dx * dx + dy * dy); + + // get the function domain + t0 = shading->getDomain0(); + t1 = shading->getDomain1(); +} + +SplashAxialPattern::~SplashAxialPattern() { +} + +GBool SplashAxialPattern::getColor(int x, int y, SplashColorPtr c) { + SplashColor color; + GfxColor gfxColor; + GfxGray gray; + GfxRGB rgb; +#if SPLASH_CMYK + GfxCMYK cmyk; +#endif + double tt; + + double xc, yc, xaxis; + ictm.transform(x, y, &xc, &yc); + xaxis = ((xc - x0) * dx + (yc - y0) * dy) * mul; + if (xaxis < 0 && shading->getExtend0()) { + tt = t0; + } else if (xaxis > 1 && !shading->getExtend1()) { + tt = t1; + } else if (xaxis >= 0 && xaxis <= 1) { + tt = t0 + (t1 -t0) * xaxis; + } else + return gFalse; + shading->getColor(tt, &gfxColor); + state->setFillColor(&gfxColor); + switch (colorMode) { + case splashModeMono1: + case splashModeMono8: + state->getFillGray(&gray); + color[0] = colToByte(gray); + break; + case splashModeXBGR8: + color[3] = 255; + case splashModeRGB8: + case splashModeBGR8: + state->getFillRGB(&rgb); + color[0] = colToByte(rgb.r); + color[1] = colToByte(rgb.g); + color[2] = colToByte(rgb.b); + break; +#if SPLASH_CMYK + case splashModeCMYK8: + state->getFillCMYK(&cmyk); + color[0] = colToByte(cmyk.c); + color[1] = colToByte(cmyk.m); + color[2] = colToByte(cmyk.y); + color[3] = colToByte(cmyk.k); + break; +#endif + } + + splashColorCopy(c, color); + return gTrue; +} + +//------------------------------------------------------------------------ // Divide a 16-bit value (in [0, 255*255]) by 255, returning an 8-bit result. static inline Guchar div255(int x) { @@ -3186,3 +3265,41 @@ void SplashOutputDev::setFreeTypeHinting(GBool enable) { enableFreeTypeHinting = enable; } + +/* implement shading routines */ +GBool SplashOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) { + double xMin, yMin, xMax, yMax; + SplashPath *path; + + // restore vector antialias because we support it here + setVectorAntialias(gTrue); + // get the clip region bbox + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + + // fill the region + state->moveTo(xMin, yMin); + state->lineTo(xMax, yMin); + state->lineTo(xMax, yMax); + state->lineTo(xMin, yMax); + state->closePath(); + path = convertPath(state, state->getPath()); + + SplashPattern *pattern = new SplashAxialPattern(colorMode, state, shading); + splash->shadedFill(path, gFalse, pattern); + state->clearPath(); + delete path; + + return gTrue; +} + +GBool SplashOutputDev::functionShadedFill(GfxState *state, + GfxFunctionShading *shading) { + // not implemented, therefore: + return gFalse; +} + +GBool SplashOutputDev::radialShadedFill(GfxState *state, + GfxRadialShading *shading, double /*sMin*/, double /*sMax*/) { + // not implemented, therefore: + return gFalse; +} diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h index adbd196..4cf74bf 100644 --- a/poppler/SplashOutputDev.h +++ b/poppler/SplashOutputDev.h @@ -31,6 +31,7 @@ #include "goo/gtypes.h" #include "splash/SplashTypes.h" +#include "splash/SplashPattern.h" #include "poppler-config.h" #include "OutputDev.h" #include "GfxState.h" @@ -39,7 +40,6 @@ class Gfx8BitFont; class SplashBitmap; class Splash; class SplashPath; -class SplashPattern; class SplashFontEngine; class SplashFont; class T3FontCache; @@ -48,6 +48,35 @@ struct T3GlyphStack; struct SplashTransparencyGroup; //------------------------------------------------------------------------ +// Splash dynamic pattern +//------------------------------------------------------------------------ + +class SplashAxialPattern: public SplashPattern { +public: + + SplashAxialPattern(SplashColorMode colorMode, GfxState *state, GfxAxialShading *shading); + + virtual SplashPattern *copy() { return new SplashAxialPattern(colorMode, state, shading); } + + virtual ~SplashAxialPattern(); + + virtual GBool getColor(int x, int y, SplashColorPtr c); + + virtual GBool isStatic() { return gFalse; } + +private: + + Matrix ictm; + double x0, y0, x1, y1; + double dx, dy, mul; + double t0, t1; + GfxAxialShading *shading; + GfxState *state; + SplashColorMode colorMode; + double *bbox; +}; + +//------------------------------------------------------------------------ // number of Type 3 fonts to cache #define splashOutT3FontCacheSize 8 @@ -70,6 +99,11 @@ public: //----- get info about output device + // Does this device use functionShadedFill(), axialShadedFill(), and + // radialShadedFill()? If this returns false, these shaded fills + // will be reduced to a series of other drawing operations. + virtual GBool useShadedFills() { return gTrue; } + // Does this device use upside-down coordinates? // (Upside-down means (0,0) is the top left corner of the page.) virtual GBool upsideDown() { return gTrue; } @@ -121,6 +155,10 @@ public: virtual void stroke(GfxState *state); virtual void fill(GfxState *state); virtual void eoFill(GfxState *state); + virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax); + virtual GBool functionShadedFill(GfxState *state, + GfxFunctionShading *shading); + virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double /*sMin*/, double /*sMax*/); //----- path clipping virtual void clip(GfxState *state); diff --git a/splash/Splash.cc b/splash/Splash.cc index 5e27d42..f005792 100644 --- a/splash/Splash.cc +++ b/splash/Splash.cc @@ -245,7 +245,32 @@ inline void Splash::pipeRun(SplashPipe *pipe) { // dynamic pattern if (pipe->pattern) { - pipe->pattern->getColor(pipe->x, pipe->y, pipe->cSrcVal); + if (!pipe->pattern->getColor(pipe->x, pipe->y, pipe->cSrcVal)) { + switch (bitmap->mode) { + case splashModeMono1: + if (!(pipe->destColorMask >>= 1)) + ++pipe->destColorPtr; + break; + case splashModeMono8: + ++pipe->destColorPtr; + break; + case splashModeBGR8: + case splashModeRGB8: + pipe->destColorPtr += 3; + break; + case splashModeXBGR8: +#if SPLASH_CMYK + case splashModeCMYK8: +#endif + pipe->destColorPtr += 4; + break; + } + if (pipe->destAlphaPtr) { + ++pipe->destAlphaPtr; + } + ++pipe->x; + return; + } } if (pipe->noTransparency && !state->blendFunc) { @@ -3592,3 +3617,52 @@ void Splash::dumpXPath(SplashXPath *path) { (path->segs[i].flags & splashXPathFlip) ? "P" : " "); } } + +SplashError Splash::shadedFill(SplashPath *path, GBool eo, + SplashPattern *pattern) { + SplashPipe pipe; + SplashXPath *xPath; + SplashXPathScanner *scanner; + int xMinI, yMinI, xMaxI, yMaxI, x0, x1, y; + SplashClipResult clipRes; + + if (path->length == 0) { + return splashErrEmptyPath; + } + xPath = new SplashXPath(path, state->matrix, state->flatness, gTrue); + xPath->aaScale(); + xPath->sort(); + scanner = new SplashXPathScanner(xPath, eo); + + // get the min and max x and y values + scanner->getBBoxAA(&xMinI, &yMinI, &xMaxI, &yMaxI); + + // check clipping + if ((clipRes = state->clip->testRect(xMinI, yMinI, xMaxI, yMaxI)) + != splashClipAllOutside) { + + // limit the y range + if (yMinI < state->clip->getYMinI()) { + yMinI = state->clip->getYMinI(); + } + if (yMaxI > state->clip->getYMaxI()) { + yMaxI = state->clip->getYMaxI(); + } + + pipeInit(&pipe, 0, yMinI, pattern, NULL, state->fillAlpha, vectorAntialias, gFalse); + + // draw the spans + for (y = yMinI; y <= yMaxI; ++y) { + scanner->renderAALine(aaBuf, &x0, &x1, y); + if (clipRes != splashClipAllInside) { + state->clip->clipAALine(aaBuf, &x0, &x1, y); + } + drawAALine(&pipe, x0, x1, y); + } + } + opClipRes = clipRes; + + delete scanner; + delete xPath; + return splashOk; +} diff --git a/splash/Splash.h b/splash/Splash.h index c9d57cc..23b3bf4 100644 --- a/splash/Splash.h +++ b/splash/Splash.h @@ -248,6 +248,8 @@ public: GBool getVectorAntialias() { return vectorAntialias; } void setVectorAntialias(GBool vaa) { vectorAntialias = vaa; } #endif + SplashError shadedFill(SplashPath *path, GBool eo, + SplashPattern *pattern); private: diff --git a/splash/SplashPattern.cc b/splash/SplashPattern.cc index ce49078..19fb31f 100644 --- a/splash/SplashPattern.cc +++ b/splash/SplashPattern.cc @@ -35,6 +35,7 @@ SplashSolidColor::SplashSolidColor(SplashColorPtr colorA) { SplashSolidColor::~SplashSolidColor() { } -void SplashSolidColor::getColor(int x, int y, SplashColorPtr c) { +GBool SplashSolidColor::getColor(int x, int y, SplashColorPtr c) { splashColorCopy(c, color); + return gTrue; } diff --git a/splash/SplashPattern.h b/splash/SplashPattern.h index 4e3d9ab..3c0d178 100644 --- a/splash/SplashPattern.h +++ b/splash/SplashPattern.h @@ -29,7 +29,7 @@ public: virtual ~SplashPattern(); // Return the color value for a specific pixel. - virtual void getColor(int x, int y, SplashColorPtr c) = 0; + virtual GBool getColor(int x, int y, SplashColorPtr c) = 0; // Returns true if this pattern object will return the same color // value for all pixels. @@ -51,7 +51,7 @@ public: virtual ~SplashSolidColor(); - virtual void getColor(int x, int y, SplashColorPtr c); + virtual GBool getColor(int x, int y, SplashColorPtr c); virtual GBool isStatic() { return gTrue; }