poppler/CairoOutputDev.cc | 139 ++++++++++++++++++++++++++++++++++++++++++++++ poppler/CairoOutputDev.h | 12 +++ poppler/Gfx.cc | 10 ++- poppler/OutputDev.h | 2 4 files changed, 161 insertions(+), 2 deletions(-)
New commits: commit e57c75fbd95ef8399b0785500f6893465bc808c3 Author: Adrian Johnson <[email protected]> Date: Mon Jan 24 19:48:09 2011 +1030 cairo: Implement Type 4,5,6,7 shadings using cairo mesh gradients Fixes bugs #19076 and #32791. diff --git a/poppler/CairoOutputDev.cc b/poppler/CairoOutputDev.cc index 03e6c06..6bfe5a8 100644 --- a/poppler/CairoOutputDev.cc +++ b/poppler/CairoOutputDev.cc @@ -816,6 +816,145 @@ GBool CairoOutputDev::radialShadedSupportExtend(GfxState *state, GfxRadialShadin return (shading->getExtend0() == shading->getExtend1()); } +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2) +GBool CairoOutputDev::gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading) +{ + double x0, y0, x1, y1, x2, y2; + GfxColor color[3]; + int i, j; + GfxRGB rgb; + + cairo_pattern_destroy(fill_pattern); + fill_pattern = cairo_pattern_create_mesh (); + + for (i = 0; i < shading->getNTriangles(); i++) { + shading->getTriangle(i, + &x0, &y0, &color[0], + &x1, &y1, &color[1], + &x2, &y2, &color[2]); + + cairo_pattern_mesh_begin_patch (fill_pattern); + + cairo_pattern_mesh_move_to (fill_pattern, x0, y0); + cairo_pattern_mesh_line_to (fill_pattern, x1, y1); + cairo_pattern_mesh_line_to (fill_pattern, x2, y2); + + for (j = 0; j < 3; j++) { + shading->getColorSpace()->getRGB(&color[j], &rgb); + cairo_pattern_mesh_set_corner_color_rgb (fill_pattern, j, + colToDbl(rgb.r), + colToDbl(rgb.g), + colToDbl(rgb.b)); + } + + cairo_pattern_mesh_end_patch (fill_pattern); + } + + double xMin, yMin, xMax, yMax; + // get the clip region bbox + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + state->moveTo(xMin, yMin); + state->lineTo(xMin, yMax); + state->lineTo(xMax, yMax); + state->lineTo(xMax, yMin); + state->closePath(); + fill(state); + state->clearPath(); + + return gTrue; +} + +GBool CairoOutputDev::patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading) +{ + int i, j, k; + + cairo_pattern_destroy(fill_pattern); + fill_pattern = cairo_pattern_create_mesh (); + + for (i = 0; i < shading->getNPatches(); i++) { + GfxPatch *patch = shading->getPatch(i); + GfxColor color; + GfxRGB rgb; + + cairo_pattern_mesh_begin_patch (fill_pattern); + + cairo_pattern_mesh_move_to (fill_pattern, patch->x[0][0], patch->y[0][0]); + cairo_pattern_mesh_curve_to (fill_pattern, + patch->x[0][1], patch->y[0][1], + patch->x[0][2], patch->y[0][2], + patch->x[0][3], patch->y[0][3]); + + cairo_pattern_mesh_curve_to (fill_pattern, + patch->x[1][3], patch->y[1][3], + patch->x[2][3], patch->y[2][3], + patch->x[3][3], patch->y[3][3]); + + cairo_pattern_mesh_curve_to (fill_pattern, + patch->x[3][2], patch->y[3][2], + patch->x[3][1], patch->y[3][1], + patch->x[3][0], patch->y[3][0]); + + cairo_pattern_mesh_curve_to (fill_pattern, + patch->x[2][0], patch->y[2][0], + patch->x[1][0], patch->y[1][0], + patch->x[0][0], patch->y[0][0]); + + cairo_pattern_mesh_set_control_point (fill_pattern, 0, patch->x[1][1], patch->y[1][1]); + cairo_pattern_mesh_set_control_point (fill_pattern, 1, patch->x[1][2], patch->y[1][2]); + cairo_pattern_mesh_set_control_point (fill_pattern, 2, patch->x[2][2], patch->y[2][2]); + cairo_pattern_mesh_set_control_point (fill_pattern, 3, patch->x[2][1], patch->y[2][1]); + + for (j = 0; j < 4; j++) { + int u, v; + + switch (j) { + case 0: + u = 0; v = 0; + break; + case 1: + u = 0; v = 1; + break; + case 2: + u = 1; v = 1; + break; + case 3: + u = 1; v = 0; + break; + } + + if (shading->isParameterized()) { + shading->getParameterizedColor (patch->color[u][v].c[0], &color); + } else { + for (k = 0; k < shading->getColorSpace()->getNComps(); k++) { + // simply cast to the desired type; that's all what is needed. + color.c[k] = GfxColorComp (patch->color[u][v].c[k]); + } + } + + shading->getColorSpace()->getRGB(&color, &rgb); + cairo_pattern_mesh_set_corner_color_rgb (fill_pattern, j, + colToDbl(rgb.r), + colToDbl(rgb.g), + colToDbl(rgb.b)); + } + cairo_pattern_mesh_end_patch (fill_pattern); + } + + double xMin, yMin, xMax, yMax; + // get the clip region bbox + state->getUserClipBBox(&xMin, &yMin, &xMax, &yMax); + state->moveTo(xMin, yMin); + state->lineTo(xMin, yMax); + state->lineTo(xMax, yMax); + state->lineTo(xMax, yMin); + state->closePath(); + fill(state); + state->clearPath(); + + return gTrue; +} +#endif /* CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2) */ + 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 72ca6a0..8e25575 100644 --- a/poppler/CairoOutputDev.h +++ b/poppler/CairoOutputDev.h @@ -107,7 +107,11 @@ public: // 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. +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2) + virtual GBool useShadedFills(int type) { return type <= 7; } +#else virtual GBool useShadedFills(int type) { return type < 4; } +#endif // Does this device use FillColorStop()? virtual GBool useFillColorStop() { return gTrue; } @@ -166,6 +170,10 @@ public: 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); +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2) + virtual GBool gouraudTriangleShadedFill(GfxState *state, GfxGouraudTriangleShading *shading); + virtual GBool patchMeshShadedFill(GfxState *state, GfxPatchMeshShading *shading); +#endif //----- path clipping virtual void clip(GfxState *state); @@ -362,7 +370,11 @@ public: // 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. +#if CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 11, 2) + virtual GBool useShadedFills(int type) { return type <= 7; } +#else virtual GBool useShadedFills(int type) { return type < 4; } +#endif // Does this device use FillColorStop()? virtual GBool useFillColorStop() { return gFalse; } diff --git a/poppler/Gfx.cc b/poppler/Gfx.cc index 09c5381..9cff25f 100644 --- a/poppler/Gfx.cc +++ b/poppler/Gfx.cc @@ -3119,10 +3119,11 @@ void Gfx::doGouraudTriangleShFill(GfxGouraudTriangleShading *shading) { double x0, y0, x1, y1, x2, y2; int i; - if( out->useShadedFills( shading->getType() ) ) { - if( out->gouraudTriangleShadedFill( state, shading ) ) + if (out->useShadedFills( shading->getType()) && !contentIsHidden()) { + if (out->gouraudTriangleShadedFill( state, shading)) return; } + // preallocate a path (speed improvements) state->moveTo(0., 0.); state->lineTo(1., 0.); @@ -3270,6 +3271,11 @@ void Gfx::gouraudFillTriangle(double x0, double y0, double color0, void Gfx::doPatchMeshShFill(GfxPatchMeshShading *shading) { int start, i; + if (out->useShadedFills( shading->getType()) && !contentIsHidden()) { + if (out->patchMeshShadedFill( state, shading)) + return; + } + if (shading->getNPatches() > 128) { start = 3; } else if (shading->getNPatches() > 64) { diff --git a/poppler/OutputDev.h b/poppler/OutputDev.h index 057d84a..af016b6 100644 --- a/poppler/OutputDev.h +++ b/poppler/OutputDev.h @@ -51,6 +51,8 @@ class GfxAxialShading; class GfxGouraudTriangleShading; class GfxPatchMeshShading; class GfxRadialShading; +class GfxGouraudTriangleShading; +class GfxPatchMeshShading; class Stream; class Links; class Link; _______________________________________________ poppler mailing list [email protected] http://lists.freedesktop.org/mailman/listinfo/poppler
