From a3c6fc970d00e08b9bb3f23de83f26d280c8a97c Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Tue, 9 Jun 2009 16:15:45 +0200 Subject: [PATCH] Implement axialShadedFill in cairo backend using cairo gradients Fixes bug #10942. --- poppler/CairoOutputDev.cc | 29 +++++++++++++++++++++++++++++ poppler/CairoOutputDev.h | 7 +++++++ poppler/Gfx.cc | 29 ++++++++++++++++++++--------- poppler/OutputDev.h | 3 ++- 4 files changed, 58 insertions(+), 10 deletions(-) diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index 199e5ea..ff98d34 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -458,6 +458,18 @@ void CairoOutputDev::updateStrokeOpacity(GfxState *state) { LOG(printf ("stroke opacity: %f\n", stroke_opacity)); } +void CairoOutputDev::updateFillColorStop(GfxState *state, double offset) { + state->getFillRGB(&fill_color); + + cairo_pattern_add_color_stop_rgba(fill_pattern, offset, + fill_color.r / 65535.0, + fill_color.g / 65535.0, + fill_color.b / 65535.0, + fill_opacity); + LOG(printf ("fill color stop: %f (%d, %d, %d)\n", + offset, fill_color.r, fill_color.g, fill_color.b)); +} + void CairoOutputDev::updateFont(GfxState *state) { cairo_font_face_t *font_face; cairo_matrix_t matrix, invert_matrix; @@ -586,6 +598,23 @@ void CairoOutputDev::eoFill(GfxState *state) { } +GBool CairoOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax) { + double x0, y0, x1, y1; + double dx, dy; + + shading->getCoords(&x0, &y0, &x1, &y1); + dx = x1 - x0; + dy = y1 - y0; + + cairo_pattern_destroy(fill_pattern); + fill_pattern = cairo_pattern_create_linear (x0 + tMin * dx, y0 + tMin * dy, + x0 + tMax * dx, y0 + tMax * dy); + + // TODO: use the actual stops in the shading in the case + // of linear interpolation (Type 2 Exponential functions with N=1) + return gFalse; +} + void CairoOutputDev::clip(GfxState *state) { doPath (cairo, state, state->getPath()); cairo_set_fill_rule (cairo, CAIRO_FILL_RULE_WINDING); diff --git a/poppler/CairoOutputDev.h b/poppler/CairoOutputDev.h index 7a9283f..1c9bc0e 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -98,6 +98,11 @@ public: // Does this device use drawChar() or drawString()? virtual GBool useDrawChar() { return gTrue; } + // 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 beginType3Char/endType3Char? Otherwise, // text in Type 3 fonts will be drawn with drawChar/drawString. virtual GBool interpretType3Chars() { return gFalse; } @@ -132,6 +137,7 @@ public: virtual void updateStrokeColor(GfxState *state); virtual void updateFillOpacity(GfxState *state); virtual void updateStrokeOpacity(GfxState *state); + virtual void updateFillColorStop(GfxState *state, double offset); //----- update text state virtual void updateFont(GfxState *state); @@ -141,6 +147,7 @@ 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); //----- path clipping virtual void clip(GfxState *state); diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc index afd1d15..b275858 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -2354,11 +2354,6 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { int nComps; int i, j, k; - if (out->useShadedFills() && - out->axialShadedFill(state, shading)) { - return; - } - // get the clip region bbox state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); @@ -2388,6 +2383,11 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { } } + if (out->useShadedFills() && + out->axialShadedFill(state, shading, tMin, tMax)) { + return; + } + // get the function domain t0 = shading->getDomain0(); t1 = shading->getDomain1(); @@ -2577,7 +2577,10 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { // set the color state->setFillColor(&color0); - out->updateFillColor(state); + if (out->useShadedFills()) + out->updateFillColorStop(state, (ta[j] - tMin)/(tMax - tMin)); + else + out->updateFillColor(state); // fill the region state->moveTo(ux0, uy0); @@ -2585,9 +2588,11 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { state->lineTo(vx1, vy1); state->lineTo(ux1, uy1); state->closePath(); - if (!contentIsHidden()) - out->fill(state); - state->clearPath(); + if (!out->useShadedFills()) { + if (!contentIsHidden()) + out->fill(state); + state->clearPath(); + } // set up for next region ux0 = ux1; @@ -2597,6 +2602,12 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { color0 = color1; i = next[i]; } + + if (out->useShadedFills()) { + if (!contentIsHidden()) + out->fill(state); + state->clearPath(); + } } void Gfx::doRadialShFill(GfxRadialShading *shading) { diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h index 4866631..b5f50eb 100644 --- a/poppler/OutputDev.h +++ b/poppler/OutputDev.h @@ -168,6 +168,7 @@ public: virtual void updateFillOverprint(GfxState * /*state*/) {} virtual void updateStrokeOverprint(GfxState * /*state*/) {} virtual void updateTransfer(GfxState * /*state*/) {} + virtual void updateFillColorStop(GfxState * /*state*/, double /*offset*/) {} //----- update text state virtual void updateFont(GfxState * /*state*/) {} @@ -192,7 +193,7 @@ public: virtual GBool functionShadedFill(GfxState * /*state*/, GfxFunctionShading * /*shading*/) { return gFalse; } - virtual GBool axialShadedFill(GfxState * /*state*/, GfxAxialShading * /*shading*/) + virtual GBool axialShadedFill(GfxState * /*state*/, GfxAxialShading * /*shading*/, double /*tMin*/, double /*tMax*/) { return gFalse; } virtual GBool radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/) { return gFalse; } -- 1.6.0.4