[cairo-commit] 6 commits - src/cairo-clip-polygon.c src/cairo-image-compositor.c src/cairo-surface-wrapper.c src/cairo-traps-compositor.c src/cairo-xlib-render-compositor.c

Chris Wilson ickle at kemper.freedesktop.org
Tue Mar 6 13:18:04 PST 2012


 src/cairo-clip-polygon.c           |   26 +++++--
 src/cairo-image-compositor.c       |  120 ++++++++++++++++++++++++++++------
 src/cairo-surface-wrapper.c        |    8 +-
 src/cairo-traps-compositor.c       |  129 ++++++++++++++++++++++++++++++-------
 src/cairo-xlib-render-compositor.c |   10 +-
 5 files changed, 234 insertions(+), 59 deletions(-)

New commits:
commit 345460445973548374c171e30e6add02de1e1922
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 6 21:05:40 2012 +0000

    xlib: Apply the glyph offset
    
    The (dst_x, dst_y) parameters passed to the XRenderCompositeText are
    misleading and do not perform any adjustment, so we have to do it
    ourselves.
    
    Fixes clip-operator
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-xlib-render-compositor.c b/src/cairo-xlib-render-compositor.c
index 86641b9..401313b 100644
--- a/src/cairo-xlib-render-compositor.c
+++ b/src/cairo-xlib-render-compositor.c
@@ -1217,8 +1217,8 @@ _emit_glyphs_chunk (cairo_xlib_display_t *display,
 	  }
 	  elts[nelt].chars = char8 + size * j;
 	  elts[nelt].glyphset = info->glyphset;
-	  elts[nelt].xOff = glyphs[i].i.x;
-	  elts[nelt].yOff = glyphs[i].i.y;
+	  elts[nelt].xOff = glyphs[i].i.x - dst_x;
+	  elts[nelt].yOff = glyphs[i].i.y - dst_y;
       }
 
       switch (width) {
@@ -1245,9 +1245,9 @@ _emit_glyphs_chunk (cairo_xlib_display_t *display,
 			 src->picture,
 			 dst->picture,
 			 use_mask ? info->xrender_format : NULL,
-			 src_x + elts[0].xOff,
-			 src_y + elts[0].yOff,
-			 elts[0].xOff - dst_x, elts[0].yOff - dst_y,
+			 src_x + elts[0].xOff + dst_x,
+			 src_y + elts[0].yOff + dst_y,
+			 elts[0].xOff, elts[0].yOff,
 			 (XGlyphElt8 *) elts, nelt);
 
     if (elts != stack_elts)
commit ad758280b6e7d9f7bcc3b02796b3a1d9df908471
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 6 21:03:02 2012 +0000

    traps: The CompositeTrapezoids requires the unbounded fixup for clipping
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c
index 371393c..284a0be 100644
--- a/src/cairo-traps-compositor.c
+++ b/src/cairo-traps-compositor.c
@@ -153,6 +153,21 @@ static void blt_in(void *closure,
 				  &info->boxes);
 }
 
+static void
+add_rect_with_offset (cairo_boxes_t *boxes, int x1, int y1, int x2, int y2, int dx, int dy)
+{
+    cairo_box_t box;
+    cairo_int_status_t status;
+
+    box.p1.x = _cairo_fixed_from_int (x1 - dx);
+    box.p1.y = _cairo_fixed_from_int (y1 - dy);
+    box.p2.x = _cairo_fixed_from_int (x2 - dx);
+    box.p2.y = _cairo_fixed_from_int (y2 - dy);
+
+    status = _cairo_boxes_add (boxes, CAIRO_ANTIALIAS_DEFAULT, &box);
+    assert (status == CAIRO_INT_STATUS_SUCCESS);
+}
+
 static cairo_int_status_t
 combine_clip_as_traps (const cairo_traps_compositor_t *compositor,
 		       cairo_surface_t *mask,
@@ -164,6 +179,8 @@ combine_clip_as_traps (const cairo_traps_compositor_t *compositor,
     cairo_antialias_t antialias;
     cairo_traps_t traps;
     cairo_surface_t *src;
+    cairo_box_t box;
+    cairo_rectangle_int_t fixup;
     int src_x, src_y;
     cairo_int_status_t status;
 
@@ -196,8 +213,59 @@ combine_clip_as_traps (const cairo_traps_compositor_t *compositor,
 					  extents,
 					  antialias, &traps);
 
-    cairo_surface_destroy (src);
+    _cairo_traps_extents (&traps, &box);
+    _cairo_box_round_to_rectangle (&box, &fixup);
     _cairo_traps_fini (&traps);
+    cairo_surface_destroy (src);
+
+    if (status == CAIRO_INT_STATUS_SUCCESS &&
+	(fixup.width < extents->width || fixup.height < extents->height)) {
+	cairo_boxes_t clear;
+
+	_cairo_boxes_init (&clear);
+
+	/* top */
+	if (fixup.y != extents->y) {
+	    add_rect_with_offset (&clear,
+				  extents->x, extents->y,
+				  extents->x + extents->width,
+				  fixup.y,
+				  extents->x, extents->y);
+	}
+	/* left */
+	if (fixup.x != extents->x) {
+	    add_rect_with_offset (&clear,
+				  extents->x, fixup.y,
+				  fixup.x,
+				  fixup.y + fixup.height,
+				  extents->x, extents->y);
+	}
+	/* right */
+	if (fixup.x + fixup.width != extents->x + extents->width) {
+	    add_rect_with_offset (&clear,
+				  fixup.x + fixup.width,
+				  fixup.y,
+				  extents->x + extents->width,
+				  fixup.y + fixup.height,
+				  extents->x, extents->y);
+	}
+	/* bottom */
+	if (fixup.y + fixup.height != extents->y + extents->height) {
+	    add_rect_with_offset (&clear,
+				  extents->x,
+				  fixup.y + fixup.height,
+				  extents->x + extents->width,
+				  extents->y + extents->height,
+				  extents->x, extents->y);
+	}
+
+	status = compositor->fill_boxes (mask,
+					 CAIRO_OPERATOR_CLEAR,
+					 CAIRO_COLOR_TRANSPARENT,
+					 &clear);
+
+	_cairo_boxes_fini (&clear);
+    }
 
     return status;
 }
commit 753007ea0097ecd3ea9611dba69e995f755d5f5c
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 6 15:01:05 2012 +0000

    traps: Avoid double application of unaligned clip boxes
    
    Both combine-with-clip functions now take care of any intersection with
    clip boxes so the result would be to have overdrawn the unaligned clip
    box mask twice.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c
index b1ade5c..371393c 100644
--- a/src/cairo-traps-compositor.c
+++ b/src/cairo-traps-compositor.c
@@ -316,6 +316,32 @@ traps_get_clip_surface (const cairo_traps_compositor_t *compositor,
     return surface;
 }
 
+static void blt_unaligned_boxes(const cairo_traps_compositor_t *compositor,
+				cairo_surface_t *surface,
+				int dx, int dy,
+				cairo_box_t *boxes,
+				int num_boxes)
+{
+    struct blt_in info;
+    int i;
+
+    info.compositor = compositor;
+    info.dst = surface;
+    _cairo_boxes_init (&info.boxes);
+    info.boxes.num_boxes = 1;
+    for (i = 0; i < num_boxes; i++) {
+	cairo_box_t *b = &boxes[i];
+
+	if (! _cairo_fixed_is_integer (b->p1.x) ||
+	    ! _cairo_fixed_is_integer (b->p1.y) ||
+	    ! _cairo_fixed_is_integer (b->p2.x) ||
+	    ! _cairo_fixed_is_integer (b->p2.y))
+	{
+	    do_unaligned_box(blt_in, &info, b, dx, dy);
+	}
+    }
+}
+
 static cairo_surface_t *
 create_composite_mask (const cairo_traps_compositor_t *compositor,
 		       cairo_surface_t		*dst,
@@ -326,9 +352,7 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
 {
     cairo_surface_t *surface, *src;
     cairo_int_status_t status;
-    struct blt_in info;
     int src_x, src_y;
-    int i;
 
     TRACE ((stderr, "%s\n", __FUNCTION__));
 
@@ -369,6 +393,8 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
 					 &clear);
 	if (unlikely (status))
 	    goto error;
+
+	surface->is_clear = TRUE;
     }
 
     if (mask_func) {
@@ -376,8 +402,10 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
 			    CAIRO_OPERATOR_SOURCE, src, src_x, src_y,
 			    extents->bounded.x, extents->bounded.y,
 			    &extents->bounded, extents->clip);
-	if (likely (status == CAIRO_INT_STATUS_SUCCESS))
+	if (likely (status == CAIRO_INT_STATUS_SUCCESS)) {
+	    surface->is_clear = FALSE;
 	    goto out;
+	}
 	if (unlikely (status != CAIRO_INT_STATUS_UNSUPPORTED))
 	    goto error;
     }
@@ -390,24 +418,7 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
     if (unlikely (status))
 	goto error;
 
-    info.compositor = compositor;
-    info.dst = surface;
-    _cairo_boxes_init (&info.boxes);
-    info.boxes.num_boxes = 1;
-    for (i = 0; i < extents->clip->num_boxes; i++) {
-	cairo_box_t *b = &extents->clip->boxes[i];
-
-	if (! _cairo_fixed_is_integer (b->p1.x) ||
-	    ! _cairo_fixed_is_integer (b->p1.y) ||
-	    ! _cairo_fixed_is_integer (b->p2.x) ||
-	    ! _cairo_fixed_is_integer (b->p2.y))
-	{
-	    do_unaligned_box(blt_in, &info, b,
-			     extents->bounded.x,
-			     extents->bounded.y);
-	}
-    }
-
+    surface->is_clear = FALSE;
     if (extents->clip->path != NULL) {
 	status = combine_clip_as_traps (compositor, surface,
 					extents->clip, &extents->bounded);
@@ -418,12 +429,16 @@ create_composite_mask (const cairo_traps_compositor_t *compositor,
 	}
 	if (unlikely (status))
 	    goto error;
+    } else if (extents->clip->boxes) {
+	blt_unaligned_boxes(compositor, surface,
+			    extents->bounded.x, extents->bounded.y,
+			    extents->clip->boxes, extents->clip->num_boxes);
+
     }
 
 out:
     compositor->release (surface);
     cairo_surface_destroy (src);
-    surface->is_clear = FALSE;
     return surface;
 
 error:
commit d40b90a577f3dd159d3871185ed8d649a03a2a4e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 6 14:59:44 2012 +0000

    clip: Use the boxes-intersection routine for computing the clip polygon
    
    If we have more than a single box, run the boxes intersection as a
    post-processing step on the clip polygon, as it should be faster than
    doing it inline.
    
    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 0e1968d..db0298f 100644
--- a/src/cairo-clip-polygon.c
+++ b/src/cairo-clip-polygon.c
@@ -88,15 +88,23 @@ _cairo_clip_get_polygon (const cairo_clip_t *clip,
     if (! can_convert_to_polygon (clip))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    _cairo_polygon_init_with_clip (polygon, clip);
+    if (clip->num_boxes < 2)
+	_cairo_polygon_init_with_clip (polygon, clip);
+    else
+	_cairo_polygon_init_with_clip (polygon, NULL);
 
     clip_path = clip->path;
     status = _cairo_path_fixed_fill_to_polygon (&clip_path->path,
 						clip_path->tolerance,
 						polygon);
-    if (unlikely (status)) {
-	_cairo_polygon_fini (polygon);
-	return status;
+    if (unlikely (status))
+	goto err;
+
+    if (clip->num_boxes > 1) {
+	status = _cairo_polygon_intersect_with_boxes (polygon, fill_rule,
+						      clip->boxes, clip->num_boxes);
+	if (unlikely (status))
+	    goto err;
     }
 
     polygon->limits = NULL;
@@ -115,15 +123,17 @@ _cairo_clip_get_polygon (const cairo_clip_t *clip,
 		status = _cairo_polygon_intersect (polygon, *fill_rule,
 						   &next, clip_path->fill_rule);
 	_cairo_polygon_fini (&next);
-	if (unlikely (status)) {
-	    _cairo_polygon_fini (polygon);
-	    return status;
-	}
+	if (unlikely (status))
+	    goto err;
 
 	*fill_rule = CAIRO_FILL_RULE_WINDING;
     }
 
     return CAIRO_STATUS_SUCCESS;
+
+err:
+    _cairo_polygon_fini (polygon);
+    return status;
 }
 
 cairo_bool_t
commit f8f0510f8929980f9b8da7ef0f39d231dfe24686
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 6 14:42:19 2012 +0000

    image: Add unbounded support to the mono rasteriser fast-paths
    
    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 fdbe2de..8db8250 100644
--- a/src/cairo-image-compositor.c
+++ b/src/cairo-image-compositor.c
@@ -1484,8 +1484,10 @@ _fill8_spans (void *abstract_renderer, int y, int h,
 	    if (spans[0].coverage) {
 		int len = spans[1].x - spans[0].x;
 		uint8_t *d = r->u.fill.data + r->u.fill.stride*y + spans[0].x;
-		while (len--)
-		    *d++ = r->u.fill.pixel;
+		if (len == 1)
+		    *d = r->u.fill.pixel;
+		else
+		    memset(d, r->u.fill.pixel, len);
 	    }
 	    spans++;
 	} while (--num_spans > 1);
@@ -1496,8 +1498,10 @@ _fill8_spans (void *abstract_renderer, int y, int h,
 		do {
 		    int len = spans[1].x - spans[0].x;
 		    uint8_t *d = r->u.fill.data + r->u.fill.stride*yy + spans[0].x;
-		    while (len--)
-			*d++ = r->u.fill.pixel;
+		    if (len == 1)
+			*d = r->u.fill.pixel;
+		    else
+			memset(d, r->u.fill.pixel, len);
 		    yy++;
 		} while (--hh);
 	    }
@@ -1721,6 +1725,83 @@ _mono_spans (void *abstract_renderer, int y, int h,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_mono_unbounded_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;
+
+    if (num_spans == 0) {
+	pixman_image_composite32 (PIXMAN_OP_CLEAR,
+				  r->src, NULL, r->u.composite.dst,
+				  spans[0].x + r->u.composite.src_x,  y + r->u.composite.src_y,
+				  0, 0,
+				  r->composite->unbounded.x, y,
+				  r->composite->unbounded.width, h);
+	r->u.composite.mask_y = y + h;
+	return CAIRO_STATUS_SUCCESS;
+    }
+
+    if (y != r->u.composite.mask_y) {
+	pixman_image_composite32 (PIXMAN_OP_CLEAR,
+				  r->src, NULL, r->u.composite.dst,
+				  spans[0].x + r->u.composite.src_x,  y + r->u.composite.src_y,
+				  0, 0,
+				  r->composite->unbounded.x, r->u.composite.mask_y,
+				  r->composite->unbounded.width, y - r->u.composite.mask_y);
+    }
+
+    if (spans[0].x != r->composite->unbounded.x) {
+	    pixman_image_composite32 (PIXMAN_OP_CLEAR,
+				      r->src, NULL, r->u.composite.dst,
+				      spans[0].x + r->u.composite.src_x,  y + r->u.composite.src_y,
+				      0, 0,
+				      r->composite->unbounded.x, y,
+				      spans[0].x - r->composite->unbounded.x, h);
+    }
+
+    do {
+	int op = spans[0].coverage ? r->op : PIXMAN_OP_CLEAR;
+	pixman_image_composite32 (op,
+				  r->src, NULL, r->u.composite.dst,
+				  spans[0].x + r->u.composite.src_x,  y + r->u.composite.src_y,
+				  0, 0,
+				  spans[0].x, y,
+				  spans[1].x - spans[0].x, h);
+	spans++;
+    } while (--num_spans > 1);
+
+    if (spans[0].x != r->composite->unbounded.x + r->composite->unbounded.width) {
+	    pixman_image_composite32 (PIXMAN_OP_CLEAR,
+				      r->src, NULL, r->u.composite.dst,
+				      spans[0].x + r->u.composite.src_x,  y + r->u.composite.src_y,
+				      0, 0,
+				      spans[0].x, y,
+				      r->composite->unbounded.x + r->composite->unbounded.width - spans[0].x, h);
+    }
+
+    r->u.composite.mask_y = y + h;
+    return CAIRO_STATUS_SUCCESS;
+}
+
+static cairo_status_t
+_mono_finish_unbounded_spans (void *abstract_renderer)
+{
+    cairo_image_span_renderer_t *r = abstract_renderer;
+
+    if (r->u.composite.mask_y < r->composite->unbounded.y + r->composite->unbounded.height) {
+	pixman_image_composite32 (PIXMAN_OP_CLEAR,
+				  r->src, NULL, r->u.composite.dst,
+				  r->composite->unbounded.x + r->u.composite.src_x,  r->u.composite.mask_y + r->u.composite.src_y,
+				  0, 0,
+				  r->composite->unbounded.x, r->u.composite.mask_y,
+				  r->composite->unbounded.width,
+				  r->composite->unbounded.y + r->composite->unbounded.height - r->u.composite.mask_y);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_int_status_t
 mono_renderer_init (cairo_image_span_renderer_t	*r,
 		    const cairo_composite_rectangles_t *composite,
@@ -1785,23 +1866,22 @@ mono_renderer_init (cairo_image_span_renderer_t	*r,
     }
 
     if (r->base.render_rows == NULL) {
-	if (1) { /* XXX calling pixman_image_composite per span is too slow */
-	    r->src = _pixman_image_for_pattern (dst, &composite->source_pattern.base, FALSE,
-						&composite->unbounded,
-						&composite->source_sample_area,
-						&r->u.composite.src_x, &r->u.composite.src_y);
-	    if (unlikely (r->src == NULL))
-		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
-
-	    r->u.composite.dst = to_pixman_image (composite->surface);
-	    r->op = _pixman_operator (composite->op);
+	r->src = _pixman_image_for_pattern (dst, &composite->source_pattern.base, FALSE,
+					    &composite->unbounded,
+					    &composite->source_sample_area,
+					    &r->u.composite.src_x, &r->u.composite.src_y);
+	if (unlikely (r->src == NULL))
+	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+
+	r->u.composite.dst = to_pixman_image (composite->surface);
+	r->op = _pixman_operator (composite->op);
+	if (composite->is_bounded == 0) {
+	    r->base.render_rows = _mono_unbounded_spans;
+	    r->base.finish = _mono_finish_unbounded_spans;
+	    r->u.composite.mask_y = composite->unbounded.y;
+	} else
 	    r->base.render_rows = _mono_spans;
-	} else{
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-	}
     }
-    r->base.finish = NULL;
-
     r->bpp = PIXMAN_FORMAT_BPP(dst->pixman_format);
 
     return CAIRO_INT_STATUS_SUCCESS;
@@ -2316,7 +2396,6 @@ inplace_renderer_init (cairo_image_span_renderer_t	*r,
 	r->base.render_rows = _inplace_spans;
     }
 
-    r->base.finish = NULL;
     r->bpp = PIXMAN_FORMAT_BPP(dst->pixman_format);
 
     return CAIRO_INT_STATUS_SUCCESS;
@@ -2342,6 +2421,7 @@ span_renderer_init (cairo_abstract_span_renderer_t	*_r,
     r->composite = composite;
     r->mask = NULL;
     r->src = NULL;
+    r->base.finish = NULL;
 
     status = mono_renderer_init (r, composite, antialias, needs_clip);
     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
commit 5bd29eda63ee54daecfdfe36b12a1b6c4b592740
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Mar 6 14:11:49 2012 +0000

    surface-wrapper: Only apply the wrapped transform to the scaled-font
    
    And not the device_transform of the target. This smells fishy, but
    appears to make the test suite happy.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c
index 52d250c..fe9c42a 100644
--- a/src/cairo-surface-wrapper.c
+++ b/src/cairo-surface-wrapper.c
@@ -436,11 +436,13 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper,
 
 	_cairo_surface_wrapper_get_transform (wrapper, &m);
 
-	if (! _cairo_matrix_is_translation (&m)) {
+	if (! _cairo_matrix_is_translation (&wrapper->transform)) {
 	    cairo_matrix_t ctm;
 
-	    _cairo_matrix_multiply (&ctm, &m, &scaled_font->ctm);
-
+	    /* XXX No device-transform? A bug in the tangle of layers? */
+	    _cairo_matrix_multiply (&ctm,
+				    &wrapper->transform,
+				    &scaled_font->ctm);
 	    dev_scaled_font = cairo_scaled_font_create (scaled_font->font_face,
 							&scaled_font->font_matrix,
 							&ctm, &options);


More information about the cairo-commit mailing list