diff options
author | Federico Mena Quintero <federico@gnome.org> | 2016-12-12 14:31:08 -0600 |
---|---|---|
committer | Federico Mena Quintero <federico@gnome.org> | 2016-12-12 14:31:08 -0600 |
commit | 5b83d786215c88269e60cf55b62de390d71a241a (patch) | |
tree | fddeb7547e83527601877ea3288cddf4c351e008 /rsvg-filter.c | |
parent | c24059c74a38d51f2b9b03e4f501534649375d4e (diff) | |
download | librsvg-5b83d786215c88269e60cf55b62de390d71a241a.tar.gz |
Don't do our own compositing for feComposite; let Cairo handle it
We only do the Arithmetic mode for feComposite. All the others (over,
in, out, atop, xor) are done in Cairo now.
Diffstat (limited to 'rsvg-filter.c')
-rw-r--r-- | rsvg-filter.c | 154 |
1 files changed, 69 insertions, 85 deletions
diff --git a/rsvg-filter.c b/rsvg-filter.c index fbbd9074..973687b0 100644 --- a/rsvg-filter.c +++ b/rsvg-filter.c @@ -2969,20 +2969,36 @@ struct _RsvgFilterPrimitiveComposite { int k1, k2, k3, k4; }; +static cairo_operator_t +composite_mode_to_cairo_operator (RsvgFilterPrimitiveCompositeMode mode) +{ + switch (mode) { + case COMPOSITE_MODE_OVER: + return CAIRO_OPERATOR_OVER; + + case COMPOSITE_MODE_IN: + return CAIRO_OPERATOR_IN; + + case COMPOSITE_MODE_OUT: + return CAIRO_OPERATOR_OUT; + + case COMPOSITE_MODE_ATOP: + return CAIRO_OPERATOR_ATOP; + + case COMPOSITE_MODE_XOR: + return CAIRO_OPERATOR_XOR; + + default: + g_assert_not_reached (); + return CAIRO_OPERATOR_CLEAR; + } +} + static void rsvg_filter_primitive_composite_render (RsvgFilterPrimitive * self, RsvgFilterContext * ctx) { - guchar i; - gint x, y; - gint rowstride, height, width; RsvgIRect boundarys; - - guchar *in_pixels; - guchar *in2_pixels; - guchar *output_pixels; - RsvgFilterPrimitiveComposite *upself; - cairo_surface_t *output, *in, *in2; upself = (RsvgFilterPrimitiveComposite *) self; @@ -2992,35 +3008,39 @@ rsvg_filter_primitive_composite_render (RsvgFilterPrimitive * self, RsvgFilterCo if (in == NULL) return; - cairo_surface_flush (in); - in2 = rsvg_filter_get_in (upself->in2, ctx); if (in2 == NULL) { cairo_surface_destroy (in); return; } - cairo_surface_flush (in2); - - in_pixels = cairo_image_surface_get_data (in); - in2_pixels = cairo_image_surface_get_data (in2); - - height = cairo_image_surface_get_height (in); - width = cairo_image_surface_get_width (in); - - rowstride = cairo_image_surface_get_stride (in); + if (upself->mode == COMPOSITE_MODE_ARITHMETIC) { + guchar i; + gint x, y; + gint rowstride, height, width; + guchar *in_pixels; + guchar *in2_pixels; + guchar *output_pixels; + + height = cairo_image_surface_get_height (in); + width = cairo_image_surface_get_width (in); + rowstride = cairo_image_surface_get_stride (in); + + output = _rsvg_image_surface_new (width, height); + if (output == NULL) { + cairo_surface_destroy (in); + cairo_surface_destroy (in2); + return; + } - output = _rsvg_image_surface_new (width, height); - if (output == NULL) { - cairo_surface_destroy (in); - cairo_surface_destroy (in2); - return; - } + cairo_surface_flush (in); + cairo_surface_flush (in2); - output_pixels = cairo_image_surface_get_data (output); + in_pixels = cairo_image_surface_get_data (in); + in2_pixels = cairo_image_surface_get_data (in2); + output_pixels = cairo_image_surface_get_data (output); - if (upself->mode == COMPOSITE_MODE_ARITHMETIC) - for (y = boundarys.y0; y < boundarys.y1; y++) + for (y = boundarys.y0; y < boundarys.y1; y++) { for (x = boundarys.x0; x < boundarys.x1; x++) { int qr, qa, qb; @@ -3033,7 +3053,7 @@ rsvg_filter_primitive_composite_render (RsvgFilterPrimitive * self, RsvgFilterCo if (qr < 0) qr = 0; output_pixels[4 * x + y * rowstride + 3] = qr; - if (qr) + if (qr) { for (i = 0; i < 3; i++) { int ca, cb, cr; ca = in_pixels[4 * x + y * rowstride + i]; @@ -3046,66 +3066,30 @@ rsvg_filter_primitive_composite_render (RsvgFilterPrimitive * self, RsvgFilterCo if (cr < 0) cr = 0; output_pixels[4 * x + y * rowstride + i] = cr; - } - } - - else - for (y = boundarys.y0; y < boundarys.y1; y++) - for (x = boundarys.x0; x < boundarys.x1; x++) { - int qr, cr, qa, qb, ca, cb, Fa, Fb, Fab, Fo; - - qa = in_pixels[4 * x + y * rowstride + 3]; - qb = in2_pixels[4 * x + y * rowstride + 3]; - cr = 0; - Fa = Fb = Fab = Fo = 0; - switch (upself->mode) { - case COMPOSITE_MODE_OVER: - Fa = 255; - Fb = 255 - qa; - break; - case COMPOSITE_MODE_IN: - Fa = qb; - Fb = 0; - break; - case COMPOSITE_MODE_OUT: - Fa = 255 - qb; - Fb = 0; - break; - case COMPOSITE_MODE_ATOP: - Fa = qb; - Fb = 255 - qa; - break; - case COMPOSITE_MODE_XOR: - Fa = 255 - qb; - Fb = 255 - qa; - break; - default: - break; } + } + } - qr = (Fa * qa + Fb * qb) / 255; - if (qr > 255) - qr = 255; - if (qr < 0) - qr = 0; - - for (i = 0; i < 3; i++) { - ca = in_pixels[4 * x + y * rowstride + i]; - cb = in2_pixels[4 * x + y * rowstride + i]; - - cr = (ca * Fa + cb * Fb + ca * cb * Fab + Fo) / 255; - if (cr > qr) - cr = qr; - if (cr < 0) - cr = 0; - output_pixels[4 * x + y * rowstride + i] = cr; + cairo_surface_mark_dirty (output); + } else { + cairo_t *cr; - } - output_pixels[4 * x + y * rowstride + 3] = qr; - } + cairo_surface_reference (in2); + output = in2; - cairo_surface_mark_dirty (output); + cr = cairo_create (output); + cairo_set_source_surface (cr, in, 0, 0); + cairo_rectangle (cr, + boundarys.x0, + boundarys.y0, + boundarys.x1 - boundarys.x0, + boundarys.y1 - boundarys.y0); + cairo_clip (cr); + cairo_set_operator (cr, composite_mode_to_cairo_operator (upself->mode)); + cairo_paint (cr); + cairo_destroy (cr); + } rsvg_filter_store_result (self->result, output, ctx); |