poppler/CairoOutputDev.cc | 28 +++++++++ poppler/CairoOutputDev.h | 2 poppler/Gfx.cc | 141 +++++++++++++++++++++++++++------------------- poppler/OutputDev.h | 2 poppler/PSOutputDev.cc | 3 poppler/PSOutputDev.h | 2 6 files changed, 117 insertions(+), 61 deletions(-)
New commits: commit 53c3d636ad645a350b576160e1498726238a7bd1 Author: Carlos Garcia Campos <[email protected]> Date: Fri Jul 31 18:23:57 2009 +0200 [cairo] Implement radialShadedFill in cairo backend using cairo gradients Fixes bugs #10942, #14160 diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index 89335f8..e86ee12 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -683,6 +683,34 @@ GBool CairoOutputDev::axialShadedSupportExtend(GfxState *state, GfxAxialShading return (shading->getExtend0() == shading->getExtend1()); } +GBool CairoOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax) { + double x0, y0, r0, x1, y1, r1; + double dx, dy, dr; + + shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); + dx = x1 - x0; + dy = y1 - y0; + dr = r1 - r0; + cairo_pattern_destroy(fill_pattern); + fill_pattern = cairo_pattern_create_radial (x0 + sMin * dx, + y0 + sMin * dy, + r0 + sMin * dr, + x0 + sMax * dx, + y0 + sMax * dy, + r0 + sMax * dr); + if (shading->getExtend0() && shading->getExtend1()) + cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_PAD); + else + cairo_pattern_set_extend (fill_pattern, CAIRO_EXTEND_NONE); + + return gFalse; +} + +GBool CairoOutputDev::radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading) +{ + return (shading->getExtend0() == shading->getExtend1()); +} + 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 f2bcb55..071c171 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -153,6 +153,8 @@ public: virtual void eoFill(GfxState *state); virtual GBool axialShadedFill(GfxState *state, GfxAxialShading *shading, double tMin, double tMax); virtual GBool axialShadedSupportExtend(GfxState *state, GfxAxialShading *shading); + virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double sMin, double sMax); + virtual GBool radialShadedSupportExtend(GfxState *state, GfxRadialShading *shading); //----- path clipping virtual void clip(GfxState *state); diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc index 4b8ff35..e71a0dd 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -2652,11 +2652,7 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { int ia, ib, k, n; double *ctm; double theta, alpha, angle, t; - - if (out->useShadedFills() && - out->radialShadedFill(state, shading)) { - return; - } + GBool needExtend = gTrue; // get the shading info shading->getCoords(&x0, &y0, &r0, &x1, &y1, &r1); @@ -2753,6 +2749,11 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { } } + if (out->useShadedFills() && + out->radialShadedFill(state, shading, sMin, sMax)) { + return; + } + // compute the number of steps into which circles must be divided to // achieve a curve flatness of 0.1 pixel in device space for the // largest circle (note that "device space" is 72 dpi when generating @@ -2799,6 +2800,8 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { shading->getColor(ta, &colorA); } + needExtend = !out->radialShadedSupportExtend(state, shading); + // fill the circles while (ia < radialMaxSplits) { @@ -2849,63 +2852,67 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { colorA.c[k] = (colorA.c[k] + colorB.c[k]) / 2; } state->setFillColor(&colorA); - out->updateFillColor(state); - - if (enclosed) { - - // construct path for first circle (counterclockwise) - state->moveTo(xa + ra, ya); - for (k = 1; k < n; ++k) { - angle = ((double)k / (double)n) * 2 * M_PI; - state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); - } - state->closePath(); - - // construct and append path for second circle (clockwise) - state->moveTo(xb + rb, yb); - for (k = 1; k < n; ++k) { - angle = -((double)k / (double)n) * 2 * M_PI; - state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); - } - state->closePath(); - - } else { + if (out->useFillColorStop()) + out->updateFillColorStop(state, (sa - sMin)/(sMax - sMin)); + else + out->updateFillColor(state); - // construct the first subpath (clockwise) - state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI), - ya + ra * sin(alpha + theta + 0.5 * M_PI)); - for (k = 0; k < n; ++k) { - angle = alpha + theta + 0.5 * M_PI - - ((double)k / (double)n) * (2 * theta + M_PI); - state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); - } - for (k = 0; k < n; ++k) { - angle = alpha - theta - 0.5 * M_PI - + ((double)k / (double)n) * (2 * theta - M_PI); - state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); - } - state->closePath(); + if (needExtend) { + if (enclosed) { + // construct path for first circle (counterclockwise) + state->moveTo(xa + ra, ya); + for (k = 1; k < n; ++k) { + angle = ((double)k / (double)n) * 2 * M_PI; + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); - // construct the second subpath (counterclockwise) - state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI), - ya + ra * sin(alpha + theta + 0.5 * M_PI)); - for (k = 0; k < n; ++k) { - angle = alpha + theta + 0.5 * M_PI - + ((double)k / (double)n) * (-2 * theta + M_PI); - state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); - } - for (k = 0; k < n; ++k) { - angle = alpha - theta - 0.5 * M_PI - + ((double)k / (double)n) * (2 * theta + M_PI); - state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + // construct and append path for second circle (clockwise) + state->moveTo(xb + rb, yb); + for (k = 1; k < n; ++k) { + angle = -((double)k / (double)n) * 2 * M_PI; + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + state->closePath(); + } else { + // construct the first subpath (clockwise) + state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI), + ya + ra * sin(alpha + theta + 0.5 * M_PI)); + for (k = 0; k < n; ++k) { + angle = alpha + theta + 0.5 * M_PI + - ((double)k / (double)n) * (2 * theta + M_PI); + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + for (k = 0; k < n; ++k) { + angle = alpha - theta - 0.5 * M_PI + + ((double)k / (double)n) * (2 * theta - M_PI); + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); + + // construct the second subpath (counterclockwise) + state->moveTo(xa + ra * cos(alpha + theta + 0.5 * M_PI), + ya + ra * sin(alpha + theta + 0.5 * M_PI)); + for (k = 0; k < n; ++k) { + angle = alpha + theta + 0.5 * M_PI + + ((double)k / (double)n) * (-2 * theta + M_PI); + state->lineTo(xb + rb * cos(angle), yb + rb * sin(angle)); + } + for (k = 0; k < n; ++k) { + angle = alpha - theta - 0.5 * M_PI + + ((double)k / (double)n) * (2 * theta + M_PI); + state->lineTo(xa + ra * cos(angle), ya + ra * sin(angle)); + } + state->closePath(); } - state->closePath(); } - // fill the path - if (!contentIsHidden()) - out->fill(state); - state->clearPath(); + if (!out->useFillColorStop()) { + // fill the path + if (!contentIsHidden()) + out->fill(state); + state->clearPath(); + } // step to the next value of t ia = ib; @@ -2917,6 +2924,26 @@ void Gfx::doRadialShFill(GfxRadialShading *shading) { colorA = colorB; } + if (out->useFillColorStop()) { + // make sure we add stop color when sb = sMax + state->setFillColor(&colorA); + out->updateFillColorStop(state, (sb - sMin)/(sMax - sMin)); + + // fill the path + state->moveTo(xMin, yMin); + state->lineTo(xMin, yMax); + state->lineTo(xMax, yMax); + state->lineTo(xMax, yMin); + state->closePath(); + + if (!contentIsHidden()) + out->fill(state); + state->clearPath(); + } + + if (!needExtend) + return; + if (enclosed) { // extend the smaller circle if ((shading->getExtend0() && r0 <= r1) || diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h index d1cb2b0..d7fb10f 100644 --- a/poppler/OutputDev.h +++ b/poppler/OutputDev.h @@ -201,7 +201,7 @@ public: { return gFalse; } virtual GBool axialShadedSupportExtend(GfxState * /*state*/, GfxAxialShading * /*shading*/) { return gFalse; } - virtual GBool radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/) + virtual GBool radialShadedFill(GfxState * /*state*/, GfxRadialShading * /*shading*/, double /*sMin*/, double /*sMax*/) { return gFalse; } virtual GBool radialShadedSupportExtend(GfxState * /*state*/, GfxRadialShading * /*shading*/) { return gFalse; } diff --git a/poppler/PSOutputDev.cc b/poppler/PSOutputDev.cc index 779c5c5..9c72294 100644 --- a/poppler/PSOutputDev.cc +++ b/poppler/PSOutputDev.cc @@ -3944,8 +3944,7 @@ GBool PSOutputDev::axialShadedFill(GfxState *state, GfxAxialShading *shading, do return gTrue; } -GBool PSOutputDev::radialShadedFill(GfxState *state, - GfxRadialShading *shading) { +GBool PSOutputDev::radialShadedFill(GfxState *state, GfxRadialShading *shading, double /*sMin*/, double /*sMax*/) { double xMin, yMin, xMax, yMax; double x0, y0, r0, x1, y1, r1, t0, t1; double xa, ya, ra; diff --git a/poppler/PSOutputDev.h b/poppler/PSOutputDev.h index be4763d..5fc3edd 100644 --- a/poppler/PSOutputDev.h +++ b/poppler/PSOutputDev.h @@ -216,7 +216,7 @@ public: 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); + virtual GBool radialShadedFill(GfxState *state, GfxRadialShading *shading, double /*sMin*/, double /*sMax*/); //----- path clipping virtual void clip(GfxState *state); _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
