[poppler] poppler/CairoOutputDev.cc poppler/CairoOutputDev.h poppler/Gfx.cc poppler/OutputDev.h poppler/PSOutputDev.cc poppler/PSOutputDev.h
Carlos Garcia Campos
carlosgc at kemper.freedesktop.org
Fri Jul 31 09:26:05 PDT 2009
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 <carlosgc at gnome.org>
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);
More information about the poppler
mailing list