[cairo-commit] 3 commits - src/cairo-surface.c src/cairo-surface-fallback.c src/cairo-xlib-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Mon Sep 21 05:57:16 PDT 2009


 src/cairo-surface-fallback.c |   42 ++++++++++++++++++++++++++++++++
 src/cairo-surface.c          |   23 +++++++----------
 src/cairo-xlib-surface.c     |   55 +++++++++++++++++++------------------------
 3 files changed, 77 insertions(+), 43 deletions(-)

New commits:
commit e00d0627494a4b15ed3b74a704695ca8b81a350e
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 21 13:50:00 2009 +0100

    [xlib] Fix recent bug in unbounded trapezoids
    
    Gah! I had believed that the dst extents and the clip were correct to
    enable unbounded fixup for the unbounded trapezoids. I was wrong, so I
    need to requery the trapezoid extents. As this information is already
    known, I should update the interface to pass along all relevant
    information.

diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 25ce0b9..d66e930 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2631,7 +2631,7 @@ _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t         *dst,
 
     /* Now compute the area that is in dst but not drawn */
     status = cairo_region_subtract_rectangle (&clear_region, &dst_rectangle);
-    if (unlikely (status))
+    if (unlikely (status) || cairo_region_is_empty (&clear_region))
         goto CLEANUP_REGIONS;
 
   EMPTY:
@@ -2767,9 +2767,8 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t            *dst,
 						unsigned int		    height,
 						cairo_region_t	    *clip_region)
 {
-    cairo_rectangle_int_t src_tmp, mask_tmp;
-    cairo_rectangle_int_t *src_rectangle = NULL;
-    cairo_rectangle_int_t *mask_rectangle = NULL;
+    cairo_rectangle_int_t src_tmp, *src= NULL;
+    cairo_rectangle_int_t mask;
 
     if (dst->status)
 	return dst->status;
@@ -2784,20 +2783,18 @@ _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t            *dst,
     {
 	src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
 	src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
-	src_tmp.width = src_width;
+	src_tmp.width  = src_width;
 	src_tmp.height = src_height;
 
-	src_rectangle = &src_tmp;
+	src = &src_tmp;
     }
 
-    mask_tmp.x = dst_x - mask_x;
-    mask_tmp.y = dst_y - mask_y;
-    mask_tmp.width = mask_width;
-    mask_tmp.height = mask_height;
+    mask.x = dst_x - mask_x;
+    mask.y = dst_y - mask_y;
+    mask.width  = mask_width;
+    mask.height = mask_height;
 
-    mask_rectangle = &mask_tmp;
-
-    return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
+    return _cairo_surface_composite_fixup_unbounded_internal (dst, src, &mask,
 							      dst_x, dst_y, width, height,
 							      clip_region);
 }
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 0352ed7..2b8d31a 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2576,26 +2576,32 @@ _cairo_xlib_surface_composite_trapezoids (cairo_operator_t	op,
 				xtraps, num_traps);
 
     if (xtraps != xtraps_stack)
-	free(xtraps);
+	free (xtraps);
+
+    if (! _cairo_operator_bounded_by_mask (op)) {
+	cairo_traps_t _traps;
+	cairo_box_t box;
+	cairo_rectangle_int_t extents;
 
-    if (!_cairo_operator_bounded_by_mask (op)) {
 	/* XRenderCompositeTrapezoids() creates a mask only large enough for the
 	 * trapezoids themselves, but if the operator is unbounded, then we need
-	 * to actually composite all the way out to the bounds, so we create
-	 * the mask and composite ourselves. There actually would
-	 * be benefit to doing this in all cases, since RENDER implementations
-	 * will frequently create a too temporary big mask, ignoring destination
-	 * bounds and clip. (XRenderAddTraps() could be used to make creating
-	 * the mask somewhat cheaper.)
+	 * to actually composite all the way out to the bounds.
 	 */
+	/* XXX: update the interface to pass composite rects */
+	_traps.traps = traps;
+	_traps.num_traps = num_traps;
+	_cairo_traps_extents (&_traps, &box);
+	_cairo_box_round_to_rectangle (&box, &extents);
+
 	status = _cairo_surface_composite_shape_fixup_unbounded (&dst->base,
-								 &attributes, src->width, src->height,
-								 width, height,
+								 &attributes,
+								 src->width, src->height,
+								 extents.width, extents.height,
 								 src_x, src_y,
-								 0, 0,
-								 dst_x, dst_y, width, height,
+								 -extents.x + dst_x, -extents.y + dst_y,
+								 dst_x, dst_y,
+								 width, height,
 								 clip_region);
-
     }
 
  BAIL:
commit 378b1e73d9f27e9b54ea01b10e588b361848d0cd
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 21 03:10:53 2009 +0100

    [fallback] Special case single composite rectangle
    
    Avoid the overhead of region-from-traps extraction for the very frequent
    case of using a single (possibly clipped) rectangle with a pattern source.

diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 35befa5..77ae0ed 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -715,6 +715,44 @@ _fill_rectangles (cairo_surface_t *dst,
     return status;
 }
 
+/* fast-path for very common composite of a single rectangle */
+static cairo_status_t
+_composite_rectangle (cairo_surface_t *dst,
+		      cairo_operator_t op,
+		      const cairo_pattern_t *src,
+		      cairo_traps_t *traps,
+		      cairo_clip_t *clip)
+{
+    cairo_rectangle_int_t rect;
+
+    if (clip != NULL)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (traps->num_traps > 1 || ! traps->is_rectilinear || ! traps->maybe_region)
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
+    if (! _cairo_fixed_is_integer (traps->traps[0].top)          ||
+	! _cairo_fixed_is_integer (traps->traps[0].bottom)       ||
+	! _cairo_fixed_is_integer (traps->traps[0].left.p1.x)    ||
+	! _cairo_fixed_is_integer (traps->traps[0].right.p1.x))
+    {
+	traps->maybe_region = FALSE;
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
+    rect.x = _cairo_fixed_integer_part (traps->traps[0].left.p1.x);
+    rect.y = _cairo_fixed_integer_part (traps->traps[0].top);
+    rect.width  = _cairo_fixed_integer_part (traps->traps[0].right.p1.x) - rect.x;
+    rect.height = _cairo_fixed_integer_part (traps->traps[0].bottom) - rect.y;
+
+    return _cairo_surface_composite (op, src, NULL, dst,
+				     rect.x, rect.y,
+				     0, 0,
+				     rect.x, rect.y,
+				     rect.width, rect.height,
+				     NULL);
+}
+
 /* Warning: This call modifies the coordinates of traps */
 static cairo_status_t
 _clip_and_composite_trapezoids (const cairo_pattern_t *src,
@@ -756,6 +794,10 @@ _clip_and_composite_trapezoids (const cairo_pattern_t *src,
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	    return status;
 
+	status = _composite_rectangle (dst, op, src, traps, clip);
+	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
+	    return status;
+
 	status = _cairo_traps_extract_region (traps, &trap_region);
 	if (unlikely (_cairo_status_is_error (status)))
 	    return status;
commit 35daf95db8aa4f0c254891f180aa4996dd464a60
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Mon Sep 21 03:31:22 2009 +0100

    [xlib] Trim a few redundant steps when uploading glyphs
    
    Cleanup the glyph coercion routines to avoid the temporary cairo_t (as
    we can just cairo_surface_paint() directly).

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 88bad87..0352ed7 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -3764,7 +3764,6 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
      * a clear 1x1 surface, to avoid various X server bugs.
      */
     if (glyph_surface->width == 0 || glyph_surface->height == 0) {
-	cairo_t *cr;
 	cairo_surface_t *tmp_surface;
 
 	tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1);
@@ -3772,19 +3771,10 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
 	if (unlikely (status))
 	    goto BAIL;
 
-	cr = cairo_create (tmp_surface);
-	cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
-	cairo_paint (cr);
-	status = cairo_status (cr);
-	cairo_destroy (cr);
-
 	tmp_surface->device_transform = glyph_surface->base.device_transform;
 	tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
 
 	glyph_surface = (cairo_image_surface_t *) tmp_surface;
-
-	if (unlikely (status))
-	    goto BAIL;
     }
 
     /* If the glyph format does not match the font format, then we
@@ -3792,7 +3782,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
      * format.
      */
     if (glyph_surface->format != glyphset_info->format) {
-	cairo_t *cr;
+	cairo_surface_pattern_t pattern;
 	cairo_surface_t *tmp_surface;
 
 	tmp_surface = cairo_image_surface_create (glyphset_info->format,
@@ -3805,12 +3795,11 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
 	tmp_surface->device_transform = glyph_surface->base.device_transform;
 	tmp_surface->device_transform_inverse = glyph_surface->base.device_transform_inverse;
 
-	cr = cairo_create (tmp_surface);
-	cairo_set_source_surface (cr, &glyph_surface->base, 0, 0);
-	cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
-	cairo_paint (cr);
-	status = cairo_status (cr);
-	cairo_destroy (cr);
+	_cairo_pattern_init_for_surface (&pattern, &glyph_surface->base);
+	status = _cairo_surface_paint (tmp_surface,
+				       CAIRO_OPERATOR_SOURCE, &pattern.base,
+				       NULL);
+	_cairo_pattern_fini (&pattern.base);
 
 	glyph_surface = (cairo_image_surface_t *) tmp_surface;
 


More information about the cairo-commit mailing list