Commit e57c75fb authored by Adrian Johnson's avatar Adrian Johnson Committed by Carlos Garcia Campos

cairo: Implement Type 4,5,6,7 shadings using cairo mesh gradients

Fixes bugs #19076 and #32791.
parent 5081356f
......@@ -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);
......
......@@ -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; }
......
......@@ -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) {
......
......@@ -51,6 +51,8 @@ class GfxAxialShading;
class GfxGouraudTriangleShading;
class GfxPatchMeshShading;
class GfxRadialShading;
class GfxGouraudTriangleShading;
class GfxPatchMeshShading;
class Stream;
class Links;
class Link;
......
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