From 15fd3ed0f7b03e78efb91b072f5cf948563a6820 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Wed, 8 Jul 2009 13:02:16 +0200 Subject: [PATCH] Implement axialShadedFill in cairo backend using cairo gradients See bug #10942. --- poppler/CairoOutputDev.cc | 29 +++++++++++++++++++++++++++++ poppler/CairoOutputDev.h | 10 ++++++++++ poppler/Gfx.cc | 29 ++++++++++++++++++++--------- poppler/OutputDev.h | 6 +++++- poppler/PSOutputDev.cc | 2 +- poppler/PSOutputDev.h | 2 +- 6 files changed, 66 insertions(+), 12 deletions(-) diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index 2fa9815..7611711 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 5af832d..cd66cb7 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -98,6 +98,14 @@ 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 FillColorStop()? + virtual GBool useFillColorStop() { 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 +140,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 +150,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 c11f551..c3f257f 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -2361,11 +2361,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); @@ -2395,6 +2390,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(); @@ -2584,7 +2584,10 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { // set the color state->setFillColor(&color0); - out->updateFillColor(state); + if (out->useFillColorStop()) + out->updateFillColorStop(state, (ta[j] - tMin)/(tMax - tMin)); + else + out->updateFillColor(state); // fill the region state->moveTo(ux0, uy0); @@ -2592,9 +2595,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->useFillColorStop()) { + if (!contentIsHidden()) + out->fill(state); + state->clearPath(); + } // set up for next region ux0 = ux1; @@ -2604,6 +2609,12 @@ void Gfx::doAxialShFill(GfxAxialShading *shading) { color0 = color1; i = next[i]; } + + if (out->useFillColorStop()) { + if (!contentIsHidden()) + out->fill(state); + state->clearPath(); + } } void Gfx::doRadialShFill(GfxRadialShading *shading) { diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h index 35adadd..76d3611 100644 --- a/poppler/OutputDev.h +++ b/poppler/OutputDev.h @@ -85,6 +85,9 @@ public: // will be reduced to a series of other drawing operations. virtual GBool useShadedFills() { return gFalse; } + // Does this device use FillColorStop()? + virtual GBool useFillColorStop() { return gFalse; } + // Does this device use drawForm()? If this returns false, // form-type XObjects will be interpreted (i.e., unrolled). virtual GBool useDrawForm() { return gFalse; } @@ -169,6 +172,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*/) {} @@ -193,7 +197,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; } diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc index 6bec12d..ea8aeea 100644 --- a/poppler/PSOutputDev.cc +++ b/poppler/PSOutputDev.cc @@ -3850,7 +3850,7 @@ GBool PSOutputDev::functionShadedFill(GfxState *state, return gTrue; } -GBool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading) { +GBool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, double /*tMin*/, double /*tMax*/) { double xMin, yMin, xMax, yMax; double x0, y0, x1, y1, dx, dy, mul; double tMin, tMax, t, t0, t1; diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h index 6310375..be4763d 100644 --- a/poppler/PSOutputDev.h +++ b/poppler/PSOutputDev.h @@ -215,7 +215,7 @@ public: double xStep, double yStep); virtual GBool functionShadedFill(GfxState *state, GfxFunctionShading *shading); - virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading); + virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double /*tMin*/, double /*tMax*/); virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading); //----- path clipping -- 1.6.0.4