[cairo-commit] 2 commits - src/cairo-clip.c src/cairoint.h src/cairo-recording-surface.c src/cairo-recording-surface-private.h src/cairo-rectangle.c src/cairo-surface-wrapper.c src/cairo-surface-wrapper-private.h

Chris Wilson ickle at kemper.freedesktop.org
Tue Jul 26 00:58:49 PDT 2011


 src/cairo-clip.c                      |    7 
 src/cairo-recording-surface-private.h |    3 
 src/cairo-recording-surface.c         |  306 +++++++++++++++++++++++-----------
 src/cairo-rectangle.c                 |    7 
 src/cairo-surface-wrapper-private.h   |    4 
 src/cairo-surface-wrapper.c           |   44 ++++
 src/cairoint.h                        |   20 ++
 7 files changed, 285 insertions(+), 106 deletions(-)

New commits:
commit c596483f854a14840ee591304ce08dee3f0edeee
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jul 26 08:33:09 2011 +0100

    record: Check the operation against the target device extents.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index f304645..16cc5c1 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -939,8 +939,9 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t	*surface,
 	type == CAIRO_RECORDING_REPLAY &&
 	region != CAIRO_RECORDING_REGION_ALL;
     int i, num_elements;
-    cairo_int_status_t status;
+    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_surface_wrapper_t wrapper;
+    cairo_rectangle_int_t extents;
 
     if (unlikely (surface->base.status))
 	return surface->base.status;
@@ -967,7 +968,9 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t	*surface,
     _cairo_surface_wrapper_set_inverse_transform (&wrapper, surface_transform);
     _cairo_surface_wrapper_set_clip (&wrapper, target_clip);
 
-    status = CAIRO_STATUS_SUCCESS;
+    /* Compute the extents of the target clip in recorded device space */
+    if (! _cairo_surface_wrapper_get_target_extents (&wrapper, &extents))
+	goto done;
 
     num_elements = surface->commands.num_elements;
     elements = _cairo_array_index (&surface->commands, 0);
@@ -978,6 +981,9 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t	*surface,
 	if (! replay_all && command->header.region != region)
 	    continue;
 
+	if (! _cairo_rectangle_intersects (&extents, &command->header.extents))
+	    continue;
+
 	switch (command->header.type) {
 	case CAIRO_COMMAND_PAINT:
 	    status = _cairo_surface_wrapper_paint (&wrapper,
@@ -1090,6 +1096,7 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t	*surface,
 	    break;
     }
 
+done:
     _cairo_surface_wrapper_fini (&wrapper);
     return _cairo_surface_set_error (&surface->base, status);
 }
diff --git a/src/cairo-surface-wrapper-private.h b/src/cairo-surface-wrapper-private.h
index e2e46b3..cce08e1 100644
--- a/src/cairo-surface-wrapper-private.h
+++ b/src/cairo-surface-wrapper-private.h
@@ -182,6 +182,10 @@ _cairo_surface_wrapper_is_active (cairo_surface_wrapper_t *wrapper)
     return wrapper->target != (cairo_surface_t *) 0;
 }
 
+cairo_private cairo_bool_t
+_cairo_surface_wrapper_get_target_extents (cairo_surface_wrapper_t *wrapper,
+					   cairo_rectangle_int_t *extents);
+
 CAIRO_END_DECLS
 
 #endif /* CAIRO_SURFACE_WRAPPER_PRIVATE_H */
diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c
index 59c87da..2a3f4b3 100644
--- a/src/cairo-surface-wrapper.c
+++ b/src/cairo-surface-wrapper.c
@@ -573,3 +573,47 @@ _cairo_surface_wrapper_fini (cairo_surface_wrapper_t *wrapper)
 {
     cairo_surface_destroy (wrapper->target);
 }
+
+cairo_bool_t
+_cairo_surface_wrapper_get_target_extents (cairo_surface_wrapper_t *wrapper,
+					   cairo_rectangle_int_t *extents)
+{
+    cairo_rectangle_int_t tmp;
+
+    if (wrapper->clip) {
+	const cairo_rectangle_int_t *r = _cairo_clip_get_extents (wrapper->clip);
+	if (wrapper->needs_transform) {
+	    cairo_matrix_t m;
+	    double x1, y1, x2, y2;
+
+	    _cairo_surface_wrapper_get_transform (wrapper, &m);
+
+	    x1 = r->x;
+	    y1 = r->y;
+	    x2 = r->x + r->width;
+	    y2 = r->y + r->height;
+
+	    _cairo_matrix_transform_bounding_box (&m, &x1, &y1, &x2, &y2, NULL);
+
+	    tmp.x = floor (x1);
+	    tmp.y = floor (y1);
+	    tmp.width  = ceil (x2) - tmp.x;
+	    tmp.height = ceil (y2) - tmp.y;
+	    r = &tmp;
+	}
+
+	if (wrapper->has_extents) {
+	    *extents = wrapper->extents;
+	    return _cairo_rectangle_intersect (extents, r);
+	} else {
+	    *extents = *r;
+	    return TRUE;
+	}
+    } else if (wrapper->has_extents) {
+	*extents = wrapper->extents;
+	return TRUE;
+    } else {
+	_cairo_unbounded_rectangle_init (extents);
+	return TRUE;
+    }
+}
diff --git a/src/cairoint.h b/src/cairoint.h
index 0d7dfaa..d31d62a 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -300,6 +300,24 @@ cairo_private_no_warn cairo_bool_t
 _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,
 			    const cairo_rectangle_int_t *src);
 
+static inline cairo_bool_t
+_cairo_rectangle_intersects (const cairo_rectangle_int_t *dst,
+			     const cairo_rectangle_int_t *src)
+{
+    int v1, v2;
+
+    v1 = MAX (dst->x, src->x);
+    v2 = MIN (dst->x + (int) dst->width,  src->x + (int) src->width);
+
+    if (v1 >= v2)
+	return FALSE;
+
+    v1 = MAX (dst->y, src->y);
+    v2 = MIN (dst->y + (int) dst->height, src->y + (int) src->height);
+
+    return v1 < v2;
+}
+
 /* Extends the dst rectangle to also contain src.
  * If one of the rectangles is empty, the result is undefined
  */
commit 8ba8534d6225a4340acd1469858067e40f48acc3
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Jul 26 08:02:59 2011 +0100

    record: Store the untransformed operation extents along with the command
    
    This allows us to actually clip out the geometry before we record it, as
    suggested by allowing the user to supply an extents... But it will be
    advantageous in later patches for reducing the amount of work we need to
    perform to replay.
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-clip.c b/src/cairo-clip.c
index 7e4f8c5..a90c698 100644
--- a/src/cairo-clip.c
+++ b/src/cairo-clip.c
@@ -54,13 +54,6 @@ static freed_pool_t clip_pool;
 
 const cairo_clip_t __cairo_clip_all;
 
-static const cairo_rectangle_int_t _cairo_empty_rectangle = { 0, 0, 0, 0 };
-static const cairo_rectangle_int_t _cairo_unbounded_rectangle = {
-     CAIRO_RECT_INT_MIN, CAIRO_RECT_INT_MIN,
-     CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN,
-     CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN,
-};
-
 static cairo_clip_path_t *
 _cairo_clip_path_create (cairo_clip_t *clip)
 {
diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h
index cc23d80..3408a06 100644
--- a/src/cairo-recording-surface-private.h
+++ b/src/cairo-recording-surface-private.h
@@ -58,8 +58,9 @@ typedef enum {
 
 typedef struct _cairo_command_header {
     cairo_command_type_t	 type;
-    cairo_recording_region_type_t     region;
+    cairo_recording_region_type_t region;
     cairo_operator_t		 op;
+    cairo_rectangle_int_t	 extents;
     cairo_clip_t		*clip;
 } cairo_command_header_t;
 
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index f711344..f304645 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -79,6 +79,7 @@
 #include "cairoint.h"
 #include "cairo-analysis-surface-private.h"
 #include "cairo-clip-private.h"
+#include "cairo-composite-rectangles-private.h"
 #include "cairo-default-context-private.h"
 #include "cairo-error-private.h"
 #include "cairo-recording-surface-private.h"
@@ -135,40 +136,40 @@ cairo_surface_t *
 cairo_recording_surface_create (cairo_content_t		 content,
 				const cairo_rectangle_t	*extents)
 {
-    cairo_recording_surface_t *recording_surface;
+    cairo_recording_surface_t *surface;
 
-    recording_surface = malloc (sizeof (cairo_recording_surface_t));
-    if (unlikely (recording_surface == NULL))
+    surface = malloc (sizeof (cairo_recording_surface_t));
+    if (unlikely (surface == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
-    _cairo_surface_init (&recording_surface->base,
+    _cairo_surface_init (&surface->base,
 			 &cairo_recording_surface_backend,
 			 NULL, /* device */
 			 content);
 
-    recording_surface->content = content;
+    surface->content = content;
 
-    recording_surface->unbounded = TRUE;
+    surface->unbounded = TRUE;
 
     /* unbounded -> 'infinite' extents */
     if (extents != NULL) {
-	recording_surface->extents_pixels = *extents;
+	surface->extents_pixels = *extents;
 
 	/* XXX check for overflow */
-	recording_surface->extents.x = floor (extents->x);
-	recording_surface->extents.y = floor (extents->y);
-	recording_surface->extents.width = ceil (extents->x + extents->width) - recording_surface->extents.x;
-	recording_surface->extents.height = ceil (extents->y + extents->height) - recording_surface->extents.y;
+	surface->extents.x = floor (extents->x);
+	surface->extents.y = floor (extents->y);
+	surface->extents.width = ceil (extents->x + extents->width) - surface->extents.x;
+	surface->extents.height = ceil (extents->y + extents->height) - surface->extents.y;
 
-	recording_surface->unbounded = FALSE;
+	surface->unbounded = FALSE;
     }
 
-    _cairo_array_init (&recording_surface->commands, sizeof (cairo_command_t *));
+    _cairo_array_init (&surface->commands, sizeof (cairo_command_t *));
 
-    recording_surface->replay_start_idx = 0;
-    recording_surface->base.is_clear = TRUE;
+    surface->replay_start_idx = 0;
+    surface->base.is_clear = TRUE;
 
-    return &recording_surface->base;
+    return &surface->base;
 }
 slim_hidden_def (cairo_recording_surface_create);
 
@@ -188,12 +189,12 @@ _cairo_recording_surface_create_similar (void		       *abstract_surface,
 static cairo_status_t
 _cairo_recording_surface_finish (void *abstract_surface)
 {
-    cairo_recording_surface_t *recording_surface = abstract_surface;
+    cairo_recording_surface_t *surface = abstract_surface;
     cairo_command_t **elements;
     int i, num_elements;
 
-    num_elements = recording_surface->commands.num_elements;
-    elements = _cairo_array_index (&recording_surface->commands, 0);
+    num_elements = surface->commands.num_elements;
+    elements = _cairo_array_index (&surface->commands, 0);
     for (i = 0; i < num_elements; i++) {
 	cairo_command_t *command = elements[i];
 
@@ -234,7 +235,7 @@ _cairo_recording_surface_finish (void *abstract_surface)
 	free (command);
     }
 
-    _cairo_array_fini (&recording_surface->commands);
+    _cairo_array_fini (&surface->commands);
 
     return CAIRO_STATUS_SUCCESS;
 }
@@ -315,38 +316,66 @@ _cairo_recording_surface_release_source_image (void			*abstract_surface,
 }
 
 static cairo_status_t
-_command_init (cairo_recording_surface_t *recording_surface,
+_command_init (cairo_recording_surface_t *surface,
 	       cairo_command_header_t *command,
 	       cairo_command_type_t type,
 	       cairo_operator_t op,
-	       const cairo_clip_t *clip)
+	       cairo_composite_rectangles_t *composite)
 {
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
 
     command->type = type;
     command->op = op;
     command->region = CAIRO_RECORDING_REGION_ALL;
-    command->clip = _cairo_clip_copy (clip);
+
+    command->extents = composite->unbounded;
+
+    /* steal the clip */
+    command->clip = composite->clip;
+    composite->clip = NULL;
 
     return status;
 }
 
+static const cairo_rectangle_int_t *
+_cairo_recording_surface_extents (cairo_recording_surface_t *surface)
+{
+    if (surface->unbounded)
+	return &_cairo_unbounded_rectangle;
+
+    return &surface->extents;
+}
+
 static cairo_int_status_t
 _cairo_recording_surface_paint (void			  *abstract_surface,
 				cairo_operator_t	   op,
 				const cairo_pattern_t	  *source,
-				const cairo_clip_t		  *clip)
+				const cairo_clip_t	  *clip)
 {
     cairo_status_t status;
-    cairo_recording_surface_t *recording_surface = abstract_surface;
+    cairo_recording_surface_t *surface = abstract_surface;
     cairo_command_paint_t *command;
+    cairo_composite_rectangles_t composite;
+    const cairo_rectangle_int_t *extents;
+
+    extents = _cairo_recording_surface_extents (surface);
+    status = _cairo_composite_rectangles_init_for_paint (&composite,
+							 extents->width,
+							 extents->height,
+							 op, source,
+							 clip);
+    if (unlikely (status))
+	return status;
 
     command = malloc (sizeof (cairo_command_paint_t));
-    if (unlikely (command == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (unlikely (command == NULL)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto CLEANUP_COMPOSITE;
+    }
 
-    status = _command_init (recording_surface,
-			    &command->header, CAIRO_COMMAND_PAINT, op, clip);
+    status = _command_init (surface,
+			    &command->header, CAIRO_COMMAND_PAINT, op,
+			    &composite);
     if (unlikely (status))
 	goto CLEANUP_COMMAND;
 
@@ -354,7 +383,7 @@ _cairo_recording_surface_paint (void			  *abstract_surface,
     if (unlikely (status))
 	goto CLEANUP_COMMAND;
 
-    status = _cairo_array_append (&recording_surface->commands, &command);
+    status = _cairo_array_append (&surface->commands, &command);
     if (unlikely (status))
 	goto CLEANUP_SOURCE;
 
@@ -362,8 +391,9 @@ _cairo_recording_surface_paint (void			  *abstract_surface,
      * before surface is cleared. We don't erase recorded commands
      * since we may have earlier snapshots of this surface. */
     if (op == CAIRO_OPERATOR_CLEAR && clip == NULL)
-	recording_surface->replay_start_idx = recording_surface->commands.num_elements;
+	surface->replay_start_idx = surface->commands.num_elements;
 
+    _cairo_composite_rectangles_fini (&composite);
     return CAIRO_STATUS_SUCCESS;
 
   CLEANUP_SOURCE:
@@ -371,6 +401,8 @@ _cairo_recording_surface_paint (void			  *abstract_surface,
   CLEANUP_COMMAND:
     _cairo_clip_destroy (command->header.clip);
     free (command);
+CLEANUP_COMPOSITE:
+    _cairo_composite_rectangles_fini (&composite);
     return status;
 }
 
@@ -382,15 +414,29 @@ _cairo_recording_surface_mask (void			*abstract_surface,
 			       const cairo_clip_t	*clip)
 {
     cairo_status_t status;
-    cairo_recording_surface_t *recording_surface = abstract_surface;
+    cairo_recording_surface_t *surface = abstract_surface;
     cairo_command_mask_t *command;
+    cairo_composite_rectangles_t composite;
+    const cairo_rectangle_int_t *extents;
+
+    extents = _cairo_recording_surface_extents (surface);
+    status = _cairo_composite_rectangles_init_for_mask (&composite,
+							extents->width,
+							extents->height,
+							op, source, mask,
+							clip);
+    if (unlikely (status))
+	return status;
 
     command = malloc (sizeof (cairo_command_mask_t));
-    if (unlikely (command == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (unlikely (command == NULL)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto CLEANUP_COMPOSITE;
+    }
 
-    status = _command_init (recording_surface,
-			    &command->header, CAIRO_COMMAND_MASK, op, clip);
+    status = _command_init (surface,
+			    &command->header, CAIRO_COMMAND_MASK, op,
+			    &composite);
     if (unlikely (status))
 	goto CLEANUP_COMMAND;
 
@@ -402,10 +448,11 @@ _cairo_recording_surface_mask (void			*abstract_surface,
     if (unlikely (status))
 	goto CLEANUP_SOURCE;
 
-    status = _cairo_array_append (&recording_surface->commands, &command);
+    status = _cairo_array_append (&surface->commands, &command);
     if (unlikely (status))
 	goto CLEANUP_MASK;
 
+    _cairo_composite_rectangles_fini (&composite);
     return CAIRO_STATUS_SUCCESS;
 
   CLEANUP_MASK:
@@ -415,6 +462,8 @@ _cairo_recording_surface_mask (void			*abstract_surface,
   CLEANUP_COMMAND:
     _cairo_clip_destroy (command->header.clip);
     free (command);
+CLEANUP_COMPOSITE:
+    _cairo_composite_rectangles_fini (&composite);
     return status;
 }
 
@@ -431,15 +480,30 @@ _cairo_recording_surface_stroke (void			*abstract_surface,
 				 const cairo_clip_t	*clip)
 {
     cairo_status_t status;
-    cairo_recording_surface_t *recording_surface = abstract_surface;
+    cairo_recording_surface_t *surface = abstract_surface;
     cairo_command_stroke_t *command;
+    cairo_composite_rectangles_t composite;
+    const cairo_rectangle_int_t *extents;
+
+    extents = _cairo_recording_surface_extents (surface);
+    status = _cairo_composite_rectangles_init_for_stroke (&composite,
+							  extents->width,
+							  extents->height,
+							  op, source,
+							  path, style, ctm,
+							  clip);
+    if (unlikely (status))
+	return status;
 
     command = malloc (sizeof (cairo_command_stroke_t));
-    if (unlikely (command == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (unlikely (command == NULL)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto CLEANUP_COMPOSITE;
+    }
 
-    status = _command_init (recording_surface,
-			    &command->header, CAIRO_COMMAND_STROKE, op, clip);
+    status = _command_init (surface,
+			    &command->header, CAIRO_COMMAND_STROKE, op,
+			    &composite);
     if (unlikely (status))
 	goto CLEANUP_COMMAND;
 
@@ -460,10 +524,11 @@ _cairo_recording_surface_stroke (void			*abstract_surface,
     command->tolerance = tolerance;
     command->antialias = antialias;
 
-    status = _cairo_array_append (&recording_surface->commands, &command);
+    status = _cairo_array_append (&surface->commands, &command);
     if (unlikely (status))
 	goto CLEANUP_STYLE;
 
+    _cairo_composite_rectangles_fini (&composite);
     return CAIRO_STATUS_SUCCESS;
 
   CLEANUP_STYLE:
@@ -475,6 +540,8 @@ _cairo_recording_surface_stroke (void			*abstract_surface,
   CLEANUP_COMMAND:
     _cairo_clip_destroy (command->header.clip);
     free (command);
+CLEANUP_COMPOSITE:
+    _cairo_composite_rectangles_fini (&composite);
     return status;
 }
 
@@ -489,15 +556,29 @@ _cairo_recording_surface_fill (void			*abstract_surface,
 			       const cairo_clip_t	*clip)
 {
     cairo_status_t status;
-    cairo_recording_surface_t *recording_surface = abstract_surface;
+    cairo_recording_surface_t *surface = abstract_surface;
     cairo_command_fill_t *command;
+    cairo_composite_rectangles_t composite;
+    const cairo_rectangle_int_t *extents;
+
+    extents = _cairo_recording_surface_extents (surface);
+    status = _cairo_composite_rectangles_init_for_fill (&composite,
+							extents->width,
+							extents->height,
+							op, source, path,
+							clip);
+    if (unlikely (status))
+	return status;
 
     command = malloc (sizeof (cairo_command_fill_t));
-    if (unlikely (command == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (unlikely (command == NULL)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto CLEANUP_COMPOSITE;
+    }
 
-    status =_command_init (recording_surface,
-			   &command->header, CAIRO_COMMAND_FILL, op, clip);
+    status =_command_init (surface,
+			   &command->header, CAIRO_COMMAND_FILL, op,
+			   &composite);
     if (unlikely (status))
 	goto CLEANUP_COMMAND;
 
@@ -513,10 +594,11 @@ _cairo_recording_surface_fill (void			*abstract_surface,
     command->tolerance = tolerance;
     command->antialias = antialias;
 
-    status = _cairo_array_append (&recording_surface->commands, &command);
+    status = _cairo_array_append (&surface->commands, &command);
     if (unlikely (status))
 	goto CLEANUP_PATH;
 
+    _cairo_composite_rectangles_fini (&composite);
     return CAIRO_STATUS_SUCCESS;
 
   CLEANUP_PATH:
@@ -526,6 +608,8 @@ _cairo_recording_surface_fill (void			*abstract_surface,
   CLEANUP_COMMAND:
     _cairo_clip_destroy (command->header.clip);
     free (command);
+CLEANUP_COMPOSITE:
+    _cairo_composite_rectangles_fini (&composite);
     return status;
 }
 
@@ -550,16 +634,32 @@ _cairo_recording_surface_show_text_glyphs (void				*abstract_surface,
 					   const cairo_clip_t		*clip)
 {
     cairo_status_t status;
-    cairo_recording_surface_t *recording_surface = abstract_surface;
+    cairo_recording_surface_t *surface = abstract_surface;
     cairo_command_show_text_glyphs_t *command;
+    cairo_composite_rectangles_t composite;
+    const cairo_rectangle_int_t *extents;
+
+    extents = _cairo_recording_surface_extents (surface);
+    status = _cairo_composite_rectangles_init_for_glyphs (&composite,
+							  extents->width,
+							  extents->height,
+							  op, source,
+							  scaled_font,
+							  glyphs, num_glyphs,
+							  clip,
+							  NULL);
+    if (unlikely (status))
+	return status;
 
     command = malloc (sizeof (cairo_command_show_text_glyphs_t));
-    if (unlikely (command == NULL))
-	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+    if (unlikely (command == NULL)) {
+	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	goto CLEANUP_COMPOSITE;
+    }
 
-    status = _command_init (recording_surface,
+    status = _command_init (surface,
 			    &command->header, CAIRO_COMMAND_SHOW_TEXT_GLYPHS,
-			    op, clip);
+			    op, &composite);
     if (unlikely (status))
 	goto CLEANUP_COMMAND;
 
@@ -603,10 +703,11 @@ _cairo_recording_surface_show_text_glyphs (void				*abstract_surface,
 
     command->scaled_font = cairo_scaled_font_reference (scaled_font);
 
-    status = _cairo_array_append (&recording_surface->commands, &command);
+    status = _cairo_array_append (&surface->commands, &command);
     if (unlikely (status))
 	goto CLEANUP_SCALED_FONT;
 
+    _cairo_composite_rectangles_fini (&composite);
     return CAIRO_STATUS_SUCCESS;
 
   CLEANUP_SCALED_FONT:
@@ -620,6 +721,8 @@ _cairo_recording_surface_show_text_glyphs (void				*abstract_surface,
   CLEANUP_COMMAND:
     _cairo_clip_destroy (command->header.clip);
     free (command);
+CLEANUP_COMPOSITE:
+    _cairo_composite_rectangles_fini (&composite);
     return status;
 }
 
@@ -640,37 +743,37 @@ static cairo_surface_t *
 _cairo_recording_surface_snapshot (void *abstract_other)
 {
     cairo_recording_surface_t *other = abstract_other;
-    cairo_recording_surface_t *recording_surface;
+    cairo_recording_surface_t *surface;
     cairo_status_t status;
 
-    recording_surface = malloc (sizeof (cairo_recording_surface_t));
-    if (unlikely (recording_surface == NULL))
+    surface = malloc (sizeof (cairo_recording_surface_t));
+    if (unlikely (surface == NULL))
 	return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
 
-    _cairo_surface_init (&recording_surface->base,
+    _cairo_surface_init (&surface->base,
 			 &cairo_recording_surface_backend,
 			 NULL, /* device */
 			 other->base.content);
 
-    recording_surface->extents_pixels = other->extents_pixels;
-    recording_surface->extents = other->extents;
-    recording_surface->unbounded = other->unbounded;
-    recording_surface->content = other->content;
+    surface->extents_pixels = other->extents_pixels;
+    surface->extents = other->extents;
+    surface->unbounded = other->unbounded;
+    surface->content = other->content;
 
     /* XXX We should in theory be able to reuse the original array, but we
      * need to handle reference cycles during subsurface and self-copy.
      */
-    recording_surface->replay_start_idx = 0;
-    recording_surface->base.is_clear = TRUE;
+    surface->replay_start_idx = 0;
+    surface->base.is_clear = TRUE;
 
-    _cairo_array_init (&recording_surface->commands, sizeof (cairo_command_t *));
-    status = _cairo_recording_surface_replay (&other->base, &recording_surface->base);
+    _cairo_array_init (&surface->commands, sizeof (cairo_command_t *));
+    status = _cairo_recording_surface_replay (&other->base, &surface->base);
     if (unlikely (status)) {
-	cairo_surface_destroy (&recording_surface->base);
+	cairo_surface_destroy (&surface->base);
 	return _cairo_surface_create_in_error (status);
     }
 
-    return &recording_surface->base;
+    return &surface->base;
 }
 
 static cairo_bool_t
@@ -750,23 +853,23 @@ static const cairo_surface_backend_t cairo_recording_surface_backend = {
 };
 
 cairo_int_status_t
-_cairo_recording_surface_get_path (cairo_surface_t    *surface,
+_cairo_recording_surface_get_path (cairo_surface_t    *abstract_surface,
 				   cairo_path_fixed_t *path)
 {
-    cairo_recording_surface_t *recording_surface;
+    cairo_recording_surface_t *surface;
     cairo_command_t **elements;
     int i, num_elements;
     cairo_int_status_t status;
 
-    if (surface->status)
-	return surface->status;
+    if (unlikely (abstract_surface->status))
+	return abstract_surface->status;
 
-    recording_surface = (cairo_recording_surface_t *) surface;
+    surface = (cairo_recording_surface_t *) abstract_surface;
     status = CAIRO_STATUS_SUCCESS;
 
-    num_elements = recording_surface->commands.num_elements;
-    elements = _cairo_array_index (&recording_surface->commands, 0);
-    for (i = recording_surface->replay_start_idx; i < num_elements; i++) {
+    num_elements = surface->commands.num_elements;
+    elements = _cairo_array_index (&surface->commands, 0);
+    for (i = surface->replay_start_idx; i < num_elements; i++) {
 	cairo_command_t *command = elements[i];
 
 	switch (command->header.type) {
@@ -819,11 +922,11 @@ _cairo_recording_surface_get_path (cairo_surface_t    *surface,
 	    break;
     }
 
-    return _cairo_surface_set_error (surface, status);
+    return _cairo_surface_set_error (&surface->base, status);
 }
 
 static cairo_status_t
-_cairo_recording_surface_replay_internal (cairo_surface_t	     *surface,
+_cairo_recording_surface_replay_internal (cairo_recording_surface_t	*surface,
 					  const cairo_rectangle_int_t *surface_extents,
 					  const cairo_matrix_t *surface_transform,
 					  cairo_surface_t	     *target,
@@ -831,7 +934,6 @@ _cairo_recording_surface_replay_internal (cairo_surface_t	     *surface,
 					  cairo_recording_replay_type_t type,
 					  cairo_recording_region_type_t region)
 {
-    cairo_recording_surface_t *recording_surface;
     cairo_command_t **elements;
     cairo_bool_t replay_all =
 	type == CAIRO_RECORDING_REPLAY &&
@@ -840,37 +942,37 @@ _cairo_recording_surface_replay_internal (cairo_surface_t	     *surface,
     cairo_int_status_t status;
     cairo_surface_wrapper_t wrapper;
 
-    if (unlikely (surface->status))
-	return surface->status;
+    if (unlikely (surface->base.status))
+	return surface->base.status;
 
     if (unlikely (target->status))
 	return target->status;
 
-    if (unlikely (surface->finished))
+    if (unlikely (surface->base.finished))
 	return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
 
-    if (surface->is_clear)
+    if (surface->base.is_clear)
 	return CAIRO_STATUS_SUCCESS;
 
-    assert (_cairo_surface_is_recording (surface));
-    recording_surface = (cairo_recording_surface_t *) surface;
+    assert (_cairo_surface_is_recording (&surface->base));
+    surface = (cairo_recording_surface_t *) surface;
 
     _cairo_surface_wrapper_init (&wrapper, target);
     if (surface_extents)
 	_cairo_surface_wrapper_intersect_extents (&wrapper,
 						  surface_extents);
-    if (! recording_surface->unbounded)
+    if (! surface->unbounded)
 	_cairo_surface_wrapper_intersect_extents (&wrapper,
-						  &recording_surface->extents);
+						  &surface->extents);
     _cairo_surface_wrapper_set_inverse_transform (&wrapper, surface_transform);
     _cairo_surface_wrapper_set_clip (&wrapper, target_clip);
 
     status = CAIRO_STATUS_SUCCESS;
 
-    num_elements = recording_surface->commands.num_elements;
-    elements = _cairo_array_index (&recording_surface->commands, 0);
+    num_elements = surface->commands.num_elements;
+    elements = _cairo_array_index (&surface->commands, 0);
 
-    for (i = recording_surface->replay_start_idx; i < num_elements; i++) {
+    for (i = surface->replay_start_idx; i < num_elements; i++) {
 	cairo_command_t *command = elements[i];
 
 	if (! replay_all && command->header.region != region)
@@ -989,7 +1091,7 @@ _cairo_recording_surface_replay_internal (cairo_surface_t	     *surface,
     }
 
     _cairo_surface_wrapper_fini (&wrapper);
-    return _cairo_surface_set_error (surface, status);
+    return _cairo_surface_set_error (&surface->base, status);
 }
 
 /**
@@ -1008,7 +1110,7 @@ cairo_status_t
 _cairo_recording_surface_replay (cairo_surface_t *surface,
 				 cairo_surface_t *target)
 {
-    return _cairo_recording_surface_replay_internal (surface, NULL, NULL,
+    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL,
 						     target, NULL,
 						     CAIRO_RECORDING_REPLAY,
 						     CAIRO_RECORDING_REGION_ALL);
@@ -1020,7 +1122,7 @@ _cairo_recording_surface_replay_with_clip (cairo_surface_t *surface,
 					   cairo_surface_t *target,
 					   const cairo_clip_t *target_clip)
 {
-    return _cairo_recording_surface_replay_internal (surface, NULL, surface_transform,
+    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, surface_transform,
 						     target, target_clip,
 						     CAIRO_RECORDING_REPLAY,
 						     CAIRO_RECORDING_REGION_ALL);
@@ -1036,7 +1138,7 @@ cairo_status_t
 _cairo_recording_surface_replay_and_create_regions (cairo_surface_t *surface,
 						    cairo_surface_t *target)
 {
-    return _cairo_recording_surface_replay_internal (surface, NULL, NULL,
+    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface, NULL, NULL,
 						     target, NULL,
 						     CAIRO_RECORDING_CREATE_REGIONS,
 						     CAIRO_RECORDING_REGION_ALL);
@@ -1048,7 +1150,8 @@ _cairo_recording_surface_replay_region (cairo_surface_t          *surface,
 					cairo_surface_t          *target,
 					cairo_recording_region_type_t  region)
 {
-    return _cairo_recording_surface_replay_internal (surface, surface_extents, NULL,
+    return _cairo_recording_surface_replay_internal ((cairo_recording_surface_t *) surface,
+						     surface_extents, NULL,
 						     target, NULL,
 						     CAIRO_RECORDING_REPLAY,
 						     region);
diff --git a/src/cairo-rectangle.c b/src/cairo-rectangle.c
index 3a541eb..b0b6d9e 100644
--- a/src/cairo-rectangle.c
+++ b/src/cairo-rectangle.c
@@ -41,6 +41,13 @@
 
 #include "cairo-box-private.h"
 
+const cairo_rectangle_int_t _cairo_empty_rectangle = { 0, 0, 0, 0 };
+const cairo_rectangle_int_t _cairo_unbounded_rectangle = {
+     CAIRO_RECT_INT_MIN, CAIRO_RECT_INT_MIN,
+     CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN,
+     CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN,
+};
+
 cairo_private void
 _cairo_box_from_doubles (cairo_box_t *box,
 			 double *x1, double *y1,
diff --git a/src/cairoint.h b/src/cairoint.h
index b3ee61e..0d7dfaa 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -293,6 +293,8 @@ _cairo_unbounded_rectangle_init (cairo_rectangle_int_t *rect)
     rect->width = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
     rect->height = CAIRO_RECT_INT_MAX - CAIRO_RECT_INT_MIN;
 }
+cairo_private extern const cairo_rectangle_int_t _cairo_empty_rectangle;
+cairo_private extern const cairo_rectangle_int_t _cairo_unbounded_rectangle;
 
 cairo_private_no_warn cairo_bool_t
 _cairo_rectangle_intersect (cairo_rectangle_int_t *dst,


More information about the cairo-commit mailing list