[cairo-commit] 5 commits - src/cairo-clip-polygon.c src/cairo-image-compositor.c src/cairo-spans-compositor.c src/cairo-surface-subsurface.c src/skia test/reference

Chris Wilson ickle at kemper.freedesktop.org
Tue Mar 13 04:23:18 PDT 2012


 src/cairo-clip-polygon.c                      |    5 -
 src/cairo-image-compositor.c                  |  106 +++++++++++++++++++++++---
 src/cairo-spans-compositor.c                  |    4 
 src/cairo-surface-subsurface.c                |    5 +
 src/skia/cairo-skia-context.cpp               |    8 +
 test/reference/operator-source.argb32.ref.png |binary
 test/reference/operator-source.rgb24.ref.png  |binary
 7 files changed, 112 insertions(+), 16 deletions(-)

New commits:
commit 91113a9e4583fac275cc0fa01fc957abd9b7dc0e
Author: Chuanbo Weng <strgnm at gmail.com>
Date:   Tue Mar 13 11:19:23 2012 +0000

    subsurface: Avoid potential crash when subsurface's size is less than 0
    
    When cairo_surface_create_for_rectangle() is given non-integer parameters,
    the subsurface's size may be negative(e.g x = 0.2, width = 0.7, the
    final width will be -1). This illegal surface may cause crash somewhere
    upon later use, and although the fractional subsurface is ill-defined,
    we should never crash!

diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index 8590bf0..071dd75 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -461,6 +461,9 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
 {
     cairo_surface_subsurface_t *surface;
 
+    if (unlikely (width < 0 || height < 0))
+	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE));
+
     if (unlikely (target->status))
 	return _cairo_surface_create_in_error (target->status);
     if (unlikely (target->finished))
@@ -484,6 +487,8 @@ cairo_surface_create_for_rectangle (cairo_surface_t *target,
     surface->extents.y = ceil (y);
     surface->extents.width = floor (x + width) - surface->extents.x;
     surface->extents.height = floor (y + height) - surface->extents.y;
+    if ((surface->extents.width | surface->extents.height) < 0)
+	surface->extents.width = surface->extents.height = 0;
 
     if (target->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
 	/* Maintain subsurfaces as 1-depth */
commit d67f02e23e008b21425e319b5c95022348363749
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 13 11:16:39 2012 +0000

    spans-compositor: Only destroy the clip if we made the copy
    
    The extents->clip may be replaced elsewhere and so we cannot assume that
    simply because it changed from the stashed value, that it was us that
    made that copy. So becareful to only free our copy.
    
    Fixes a double-free of a clip after a complex fallback operation.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-spans-compositor.c b/src/cairo-spans-compositor.c
index e9fedcd..70fc1c2 100644
--- a/src/cairo-spans-compositor.c
+++ b/src/cairo-spans-compositor.c
@@ -984,7 +984,7 @@ _cairo_spans_compositor_stroke (const cairo_compositor_t	*_compositor,
 	    status = clip_and_composite_polygon (compositor, extents, &polygon,
 						 fill_rule, antialias);
 
-	    if (extents->clip != saved_clip) {
+	    if (extents->is_bounded) {
 		_cairo_clip_destroy (extents->clip);
 		extents->clip = saved_clip;
 	    }
@@ -1056,7 +1056,7 @@ _cairo_spans_compositor_fill (const cairo_compositor_t		*_compositor,
 	    status = clip_and_composite_polygon (compositor, extents, &polygon,
 						 fill_rule, antialias);
 
-	    if (extents->clip != saved_clip) {
+	    if (extents->is_bounded) {
 		_cairo_clip_destroy (extents->clip);
 		extents->clip = saved_clip;
 	    }
commit 94a9e06a930ba985de461826ea3e64fd7c222bc6
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 18:41:45 2012 +0000

    clip: Intialise polygon fill-rule prior to use
    
    The earliest use of the clip path's polygon fill rule is now for
    intersecting the original polygon with the plurality of clip boxes.
    However, the initialisation of the fill rule remained after the
    intersection.
    
    ==8968== Conditional jump or move depends on uninitialised value(s)
    ==8968==    at 0x4C99449: _cairo_polygon_intersect (cairo-polygon-intersect.c:1382)
    ==8968==    by 0x4C9B788: _cairo_polygon_intersect_with_boxes.part.12 (cairo-polygon-intersect.c:1520)
    ==8968==    by 0x4C6AE6E: _cairo_clip_get_polygon (cairo-clip-polygon.c:104)
    ==8968==    by 0x4CAA667: clip_and_composite_boxes.part.13 (cairo-spans-compositor.c:773)
    ==8968==    by 0x4CAAD1D: clip_and_composite_boxes (cairo-spans-compositor.c:758)
    ==8968==    by 0x4CAB25C: _cairo_spans_compositor_fill (cairo-spans-compositor.c:1023)
    ==8968==    by 0x4C6CB69: _cairo_compositor_fill (cairo-compositor.c:184)
    ==8968==    by 0x4C7CE3E: _cairo_image_surface_fill (cairo-image-surface.c:945)
    ==8968==    by 0x4CAE2B6: _cairo_surface_fill (cairo-surface.c:2047)
    ==8968==    by 0x4C74AB7: _cairo_gstate_fill (cairo-gstate.c:1268)
    ==8968==    by 0x4C6E6D3: _cairo_default_context_fill (cairo-default-context.c:1009)
    ==8968==    by 0x4C67944: cairo_fill (cairo.c:2105)
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-clip-polygon.c b/src/cairo-clip-polygon.c
index db0298f..d5208d3 100644
--- a/src/cairo-clip-polygon.c
+++ b/src/cairo-clip-polygon.c
@@ -94,6 +94,9 @@ _cairo_clip_get_polygon (const cairo_clip_t *clip,
 	_cairo_polygon_init_with_clip (polygon, NULL);
 
     clip_path = clip->path;
+    *fill_rule = clip_path->fill_rule;
+    *antialias = clip_path->antialias;
+
     status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
 						clip_path->tolerance,
 						polygon);
@@ -110,8 +113,6 @@ _cairo_clip_get_polygon (const cairo_clip_t *clip,
     polygon->limits = NULL;
     polygon->num_limits = 0;
 
-    *fill_rule = clip_path->fill_rule;
-    *antialias = clip_path->antialias;
     while ((clip_path = clip_path->prev) != NULL) {
 	cairo_polygon_t next;
 
commit ea0703524f1a508b4c60c7a3ea5b5da3c40bca2f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Mar 12 18:20:16 2012 +0000

    image: Support SRC compositing with in the inline span-compositor
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-image-compositor.c b/src/cairo-image-compositor.c
index 8db8250..990226a 100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -2260,6 +2260,89 @@ _inplace_spans (void *abstract_renderer,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_inplace_src_spans (void *abstract_renderer,
+		    int y, int h,
+		    const cairo_half_open_span_t *spans,
+		    unsigned num_spans)
+{
+    cairo_image_span_renderer_t *r = abstract_renderer;
+    uint8_t *mask;
+    int x0, y0;
+
+    if (num_spans == 0)
+	return CAIRO_STATUS_SUCCESS;
+
+    x0 = r->composite->unbounded.x;
+    y0 = r->u.composite.mask_y;
+    r->u.composite.mask_y = y + h;
+    if (y != y0) {
+	pixman_image_composite32 (PIXMAN_OP_CLEAR, r->src, NULL, r->u.composite.dst,
+				  0, 0,
+				  0, 0,
+				  x0, y0,
+				  r->composite->unbounded.width, y - y0);
+    }
+
+    mask = (uint8_t *)pixman_image_get_data (r->mask);
+    if (spans[0].x != x0) {
+	memset(mask, 0, spans[0].x - x0);
+	mask += spans[0].x - x0;
+    }
+    do {
+	int len = spans[1].x - spans[0].x;
+	*mask++ = spans[0].coverage;
+	if (len > 1) {
+	    memset (mask, spans[0].coverage, --len);
+	    mask += len;
+	}
+	spans++;
+    } while (--num_spans > 1);
+    if (spans[0].x-x0 != r->composite->unbounded.width)
+	memset(mask, 0, r->composite->unbounded.width+x0 - spans[0].x);
+
+#if PIXMAN_HAS_OP_LERP
+    pixman_image_composite32 (PIXMAN_OP_LERP_SRC, r->src, r->mask, r->u.composite.dst,
+			      x0 + r->u.composite.src_x,
+			      y + r->u.composite.src_y,
+			      0, 0,
+			      x0, y,
+			      r->composite->unbounded.width, h);
+#else
+    pixman_image_composite32 (PIXMAN_OP_OUT_REVERSE, r->mask, NULL, r->u.composite.dst,
+			      0, 0,
+			      0, 0,
+			      x0, y,
+			      r->composite->unbounded.width, h);
+    pixman_image_composite32 (PIXMAN_OP_ADD, r->src, r->mask, r->u.composite.dst,
+			      x0 + r->u.composite.src_x,
+			      y + r->u.composite.src_y,
+			      0, 0,
+			      x0, y,
+			      r->composite->unbounded.width, h);
+#endif
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_inplace_src_finish (void *abstract_renderer)
+{
+    cairo_image_span_renderer_t *r = abstract_renderer;
+    int y0 = r->u.composite.mask_y;
+    int y1 = r->composite->unbounded.y + r->composite->unbounded.height;
+
+    if (y0 != y1) {
+	pixman_image_composite32 (PIXMAN_OP_CLEAR, r->src, NULL, r->u.composite.dst,
+				  0, 0,
+				  0, 0,
+				  r->composite->unbounded.x, y0,
+				  r->composite->unbounded.width, y1 - y0);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_int_status_t
 inplace_renderer_init (cairo_image_span_renderer_t	*r,
 		       const cairo_composite_rectangles_t *composite,
@@ -2350,6 +2433,7 @@ inplace_renderer_init (cairo_image_span_renderer_t	*r,
     }
     if (r->base.render_rows == NULL) {
 	unsigned int width;
+	const cairo_pattern_t *src = &composite->source_pattern.base;
 
 	if (r->op != 0xff)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
@@ -2357,25 +2441,29 @@ inplace_renderer_init (cairo_image_span_renderer_t	*r,
 	if (composite->is_bounded == 0)
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
+	width = (composite->bounded.width + 3) & ~3;
+	r->base.render_rows = _inplace_spans;
 	if (dst->base.is_clear &&
 	    (composite->op == CAIRO_OPERATOR_SOURCE ||
 	     composite->op == CAIRO_OPERATOR_OVER ||
 	     composite->op == CAIRO_OPERATOR_ADD)) {
 	    r->op = PIXMAN_OP_SRC;
+	} else if (composite->op == CAIRO_OPERATOR_SOURCE) {
+	    r->base.render_rows = _inplace_src_spans;
+	    r->base.finish = _inplace_src_finish;
+	    r->u.composite.mask_y = r->composite->unbounded.y;
+	    width = (composite->unbounded.width + 3) & ~3;
+	} else if (composite->op == CAIRO_OPERATOR_CLEAR) {
+	    r->op = PIXMAN_OP_OUT_REVERSE;
+	    src = NULL;
 	} else {
-	    if (composite->op == CAIRO_OPERATOR_SOURCE ||
-		composite->op == CAIRO_OPERATOR_CLEAR)
-		return CAIRO_INT_STATUS_UNSUPPORTED;
-
 	    r->op = _pixman_operator (composite->op);
 	}
 
-	width = (composite->bounded.width + 3) & ~3;
 	if (width > sizeof (r->buf))
 	    return CAIRO_INT_STATUS_UNSUPPORTED;
 
-	r->src = _pixman_image_for_pattern (dst,
-					    &composite->source_pattern.base, FALSE,
+	r->src = _pixman_image_for_pattern (dst, src, FALSE,
 					    &composite->bounded,
 					    &composite->source_sample_area,
 					    &r->u.composite.src_x, &r->u.composite.src_y);
@@ -2384,8 +2472,7 @@ inplace_renderer_init (cairo_image_span_renderer_t	*r,
 
 	/* Create an effectively unbounded mask by repeating the single line */
 	r->mask = pixman_image_create_bits (PIXMAN_a8,
-					    composite->bounded.width,
-					    composite->bounded.height,
+					    width, composite->unbounded.height,
 					    (uint32_t *)r->buf, 0);
 	if (unlikely (r->mask == NULL)) {
 	    pixman_image_unref (r->src);
@@ -2393,7 +2480,6 @@ inplace_renderer_init (cairo_image_span_renderer_t	*r,
 	}
 
 	r->u.composite.dst = dst->pixman_image;
-	r->base.render_rows = _inplace_spans;
     }
 
     r->bpp = PIXMAN_FORMAT_BPP(dst->pixman_format);
diff --git a/test/reference/operator-source.argb32.ref.png b/test/reference/operator-source.argb32.ref.png
index ca3d18c..87e7374 100644
Binary files a/test/reference/operator-source.argb32.ref.png and b/test/reference/operator-source.argb32.ref.png differ
diff --git a/test/reference/operator-source.rgb24.ref.png b/test/reference/operator-source.rgb24.ref.png
index 8109d9c..473e1f2 100644
Binary files a/test/reference/operator-source.rgb24.ref.png and b/test/reference/operator-source.rgb24.ref.png differ
commit e0be011207a2efdd81f9fdededa6f6ec2031cbf1
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Mar 10 11:02:13 2012 +0000

    skia: Setup opacity for cairo_paint_with_alpha()
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/skia/cairo-skia-context.cpp b/src/skia/cairo-skia-context.cpp
index e5d4828..327e536 100644
--- a/src/skia/cairo-skia-context.cpp
+++ b/src/skia/cairo-skia-context.cpp
@@ -1258,12 +1258,16 @@ _cairo_skia_context_paint_with_alpha (void *abstract_cr,
 				      double alpha)
 {
     cairo_skia_context_t *cr = (cairo_skia_context_t *) abstract_cr;
+    cairo_status_t status;
 
     if (CAIRO_ALPHA_IS_OPAQUE (alpha))
 	return _cairo_skia_context_paint (cr);
 
-    /*XXX */
-    return _cairo_skia_context_paint (cr);
+    cr->paint->setAlpha(SkScalarRound(255*alpha));
+    status = _cairo_skia_context_paint (cr);
+    cr->paint->setAlpha(255);
+
+    return status;
 }
 
 static cairo_status_t


More information about the cairo-commit mailing list