summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Freitag <Thomas.Freitag@alfa.de>2016-03-10 12:05:28 +0100
committerAlbert Astals Cid <aacid@kde.org>2016-03-10 12:05:28 +0100
commite58d310c1802b77a6356ec0d3d0180a2a1605b41 (patch)
treed1e75ed2a04d007acfc1f288da532c6583d5ae6e
parent09e2ae234179c42ccf06b040a0f6c89d65d69713 (diff)
Implement function shading in splash
Bug #94441
-rw-r--r--poppler/SplashOutputDev.cc117
-rw-r--r--poppler/SplashOutputDev.h31
2 files changed, 147 insertions, 1 deletions
diff --git a/poppler/SplashOutputDev.cc b/poppler/SplashOutputDev.cc
index a1f5980c..7bccd382 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<double>(xMin, x[i]);
+ yMin = std::min<double>(yMin, y[i]);
+ xMax = std::max<double>(xMax, x[i]);
+ yMax = std::max<double>(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 16a6e81d..ff72afeb 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);