Commit 569627ac authored by Carlos Garcia Campos's avatar Carlos Garcia Campos

Implement axialShadedFill in cairo backend using cairo gradients

See bug #10942.
parent 6ae0a6c0
......@@ -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);
......
......@@ -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);
......
......@@ -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) {
......
......@@ -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; }
......
......@@ -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;
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment