diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc index a1f5980..7bccd38 100644 --- a/poppler/SplashOutputDev.cc +++ b/poppler/SplashOutputDev.cc @@ -240,6 +240,56 @@ void SplashGouraudPattern::getParameterizedColor(double colorinterp, SplashColor } //------------------------------------------------------------------------ +// SplashFunctionPattern +//------------------------------------------------------------------------ + +SplashFunctionPattern::SplashFunctionPattern(SplashColorMode colorModeA, GfxState *stateA, GfxFunctionShading *shadingA) +{ + Matrix ctm; + SplashColor defaultColor; + GfxColor srcColor; + double *matrix = shadingA->getMatrix(); + + shading = shadingA; + state = stateA; + colorMode = colorModeA; + + state->getCTM(&ctm); + + double a1 = ctm.m[0]; + double b1 = ctm.m[1]; + double c1 = ctm.m[2]; + double d1 = ctm.m[3]; + + ctm.m[0] = matrix[0] * a1 + matrix[1] * c1; + ctm.m[1] = matrix[0] * b1 + matrix[1] * d1; + ctm.m[2] = matrix[2] * a1 + matrix[3] * c1; + ctm.m[3] = matrix[2] * b1 + matrix[3] * d1; + ctm.m[4] = matrix[4] * a1 + matrix[5] * c1 + ctm.m[4]; + ctm.m[5] = matrix[4] * b1 + matrix[5] * d1 + ctm.m[5]; + ctm.invertTo(&ictm); + + gfxMode = shadingA->getColorSpace()->getMode(); + shadingA->getColorSpace()->getDefaultColor(&srcColor); + shadingA->getDomain(&xMin, &yMin, &xMax, &yMax); + convertGfxColor(defaultColor, colorModeA, shadingA->getColorSpace(), &srcColor); +} + +SplashFunctionPattern::~SplashFunctionPattern() { +} + +GBool SplashFunctionPattern::getColor(int x, int y, SplashColorPtr c) { + GfxColor gfxColor; + double xc, yc; + + ictm.transform(x, y, &xc, &yc); + if (xc < xMin || xc > xMax || yc < yMin || yc > yMax) return gFalse; + shading->getColor(xc, yc, &gfxColor); + convertGfxColor(c, colorMode, shading->getColorSpace(), &gfxColor); + return gTrue; +} + +//------------------------------------------------------------------------ // SplashUnivariatePattern //------------------------------------------------------------------------ @@ -4781,6 +4831,73 @@ GBool SplashOutputDev::univariateShadedFill(GfxState *state, SplashUnivariatePat return retVal; } +GBool SplashOutputDev::functionShadedFill(GfxState *state, GfxFunctionShading *shading) { + SplashFunctionPattern *pattern = new SplashFunctionPattern(colorMode, state, shading); + double xMin, yMin, xMax, yMax; + SplashPath *path; + GBool vaa = getVectorAntialias(); + // restore vector antialias because we support it here + setVectorAntialias(gTrue); + + GBool retVal = gFalse; + // get the clip region bbox + if (pattern->getShading()->getHasBBox()) { + pattern->getShading()->getBBox(&xMin, &yMin, &xMax, &yMax); + } else { + state->getClipBBox(&xMin, &yMin, &xMax, &yMax); + + xMin = floor (xMin); + yMin = floor (yMin); + xMax = ceil (xMax); + yMax = ceil (yMax); + + { + Matrix ctm, ictm; + double x[4], y[4]; + int i; + + state->getCTM(&ctm); + ctm.invertTo(&ictm); + + ictm.transform(xMin, yMin, &x[0], &y[0]); + ictm.transform(xMax, yMin, &x[1], &y[1]); + ictm.transform(xMin, yMax, &x[2], &y[2]); + ictm.transform(xMax, yMax, &x[3], &y[3]); + + xMin = xMax = x[0]; + yMin = yMax = y[0]; + for (i = 1; i < 4; i++) { + xMin = std::min(xMin, x[i]); + yMin = std::min(yMin, y[i]); + xMax = std::max(xMax, x[i]); + yMax = std::max(yMax, y[i]); + } + } + } + + // 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(), gTrue); + +#if SPLASH_CMYK + pattern->getShading()->getColorSpace()->createMapping(bitmap->getSeparationList(), SPOT_NCOMPS); +#endif + setOverprintMask(pattern->getShading()->getColorSpace(), state->getFillOverprint(), + state->getOverprintMode(), NULL); + retVal = (splash->shadedFill(path, pattern->getShading()->getHasBBox(), pattern) == splashOk); + state->clearPath(); + setVectorAntialias(vaa); + delete path; + + delete pattern; + + return retVal; +} + GBool SplashOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) { SplashAxialPattern *pattern = new SplashAxialPattern(colorMode, state, shading); GBool retVal = univariateShadedFill(state, pattern, tMin, tMax); diff --git a/poppler/SplashOutputDev.h b/poppler/SplashOutputDev.h index 16a6e81..ff72afe 100644 --- a/poppler/SplashOutputDev.h +++ b/poppler/SplashOutputDev.h @@ -59,6 +59,34 @@ struct SplashTransparencyGroup; // Splash dynamic pattern //------------------------------------------------------------------------ +class SplashFunctionPattern: public SplashPattern { +public: + + SplashFunctionPattern(SplashColorMode colorMode, GfxState *state, GfxFunctionShading *shading); + + virtual SplashPattern *copy() { return new SplashFunctionPattern(colorMode, state, (GfxFunctionShading *) shading); } + + virtual ~SplashFunctionPattern(); + + virtual GBool testPosition(int x, int y) { return gTrue; } + + virtual GBool isStatic() { return gFalse; } + + virtual GBool getColor(int x, int y, SplashColorPtr c); + + virtual GfxFunctionShading *getShading() { return shading; } + + virtual GBool isCMYK() { return gfxMode == csDeviceCMYK; } + +protected: + Matrix ictm; + double xMin, yMin, xMax, yMax; + GfxFunctionShading *shading; + GfxState *state; + SplashColorMode colorMode; + GfxColorSpaceMode gfxMode; +}; + class SplashUnivariatePattern: public SplashPattern { public: @@ -188,7 +216,7 @@ public: // radialShadedFill()? If this returns false, these shaded fills // will be reduced to a series of other drawing operations. virtual GBool useShadedFills(int type) - { return (type >= 2 && type <= 5) ? gTrue : gFalse; } + { return (type >= 1 && type <= 5) ? gTrue : gFalse; } // Does this device use upside-down coordinates? // (Upside-down means (0,0) is the top left corner of the page.) @@ -250,6 +278,7 @@ public: double *mat, double *bbox, int x0, int y0, int x1, int y1, double xStep, double yStep); + virtual GBool functionShadedFill(GfxState *state, GfxFunctionShading *shading); virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax); virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double tMin, double tMax); virtual GBool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading);