[cairo-commit] cairo/src cairo-meta-surface.c, 1.10, 1.11 cairo-surface.c, 1.102, 1.103 cairoint.h, 1.215, 1.216

Carl Worth commit at pdx.freedesktop.org
Thu Oct 13 21:00:54 PDT 2005


Committed by: cworth

Update of /cvs/cairo/cairo/src
In directory gabe:/tmp/cvs-serv9830/src

Modified Files:
	cairo-meta-surface.c cairo-surface.c cairoint.h 
Log Message:

2005-10-13  Carl Worth  <cworth at cworth.org>

        Reviewed by: keithp, otaylor

        * src/cairo-meta-surface.c: (_init_pattern_with_snapshot): New
        function to create a snapshot copy of a pattern.

        * src/cairo-meta-surface.c: (_cairo_meta_surface_composite),
        (_cairo_meta_surface_composite_trapezoids),
        (_cairo_meta_surface_show_glyphs),
        (_cairo_meta_surface_fill_path): Port code to use
        _init_pattern_with_snapshot rather than _cairo_pattern_init_copy
        for all source and mask patterns.

        * src/cairo-surface.c: (_cairo_surface_snapshot): New function to
        create a snapshot copy of a surface (still preliminary---no
        support for meta-surfaces or any other surface for which
        acquire_source_surface will fail).

        * src/cairoint.h:
        * src/cairo-surface.c: (_cairo_surface_init): Add new
        surface->is_snapshot and initialize to FALSE.

        * src/cairo-surface.c: (cairo_surface_mark_dirty),
        (cairo_surface_mark_dirty_rectangle),
        (cairo_surface_set_device_offset), (_cairo_surface_clone_similar),
        (_cairo_surface_composite),
        (_cairo_surface_fill_rectangle), (_cairo_surface_fill_region),
        (_fallback_fill_rectangles), (_cairo_surface_fill_rectangles),
        (_cairo_surface_fill_path), (_cairo_surface_composite_trapezoids),
        (_cairo_surface_copy_page), (_cairo_surface_show_page),
        (_cairo_surface_show_glyphs),
        (_cairo_surface_composite_fixup_unbounded),
        (_cairo_surface_composite_shape_fixup_unbounded): Assert that none
        of these surface-modifying functions are ever called with a
        snapshot surface.


Index: cairo-meta-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-meta-surface.c,v
retrieving revision 1.10
retrieving revision 1.11
diff -u -d -r1.10 -r1.11
--- cairo-meta-surface.c	13 Oct 2005 23:55:14 -0000	1.10
+++ cairo-meta-surface.c	14 Oct 2005 04:00:52 -0000	1.11
@@ -127,6 +127,29 @@
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_init_pattern_with_snapshot (cairo_pattern_t       *pattern,
+			     const cairo_pattern_t *other)
+{
+    cairo_status_t status;
+
+    _cairo_pattern_init_copy (pattern, other);
+
+    if (pattern->type == CAIRO_PATTERN_SURFACE) {
+	cairo_surface_pattern_t *surface_pattern = (cairo_surface_pattern_t *) pattern;
+	cairo_surface_t *surface = surface_pattern->surface;
+
+	surface_pattern->surface = _cairo_surface_snapshot (surface);
+
+	cairo_surface_destroy (surface);
+
+	if (status)
+	    return status;
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 static cairo_int_status_t
 _cairo_meta_surface_composite (cairo_operator_t	operator,
 			       cairo_pattern_t	*src_pattern,
@@ -150,9 +173,9 @@
 
     command->type = CAIRO_COMMAND_COMPOSITE;
     command->operator = operator;
-    _cairo_pattern_init_copy (&command->src_pattern.base, src_pattern);
+    _init_pattern_with_snapshot (&command->src_pattern.base, src_pattern);
     if (mask_pattern) {
-	_cairo_pattern_init_copy (&command->mask_pattern.base, mask_pattern);
+	_init_pattern_with_snapshot (&command->mask_pattern.base, mask_pattern);
 	command->mask_pattern_pointer = &command->mask_pattern.base;
     } else {
 	command->mask_pattern_pointer = NULL;
@@ -236,7 +259,7 @@
 
     command->type = CAIRO_COMMAND_COMPOSITE_TRAPEZOIDS;
     command->operator = operator;
-    _cairo_pattern_init_copy (&command->pattern.base, pattern);
+    _init_pattern_with_snapshot (&command->pattern.base, pattern);
     command->antialias = antialias;
     command->x_src = x_src;
     command->y_src = y_src;
@@ -349,7 +372,7 @@
     command->type = CAIRO_COMMAND_SHOW_GLYPHS;
     command->scaled_font = cairo_scaled_font_reference (scaled_font);
     command->operator = operator;
-    _cairo_pattern_init_copy (&command->pattern.base, pattern);
+    _init_pattern_with_snapshot (&command->pattern.base, pattern);
     command->source_x = source_x;
     command->source_y = source_y;
     command->dest_x = dest_x;
@@ -396,7 +419,7 @@
 
     command->type = CAIRO_COMMAND_FILL_PATH;
     command->operator = operator;
-    _cairo_pattern_init_copy (&command->pattern.base, pattern);
+    _init_pattern_with_snapshot (&command->pattern.base, pattern);
     status = _cairo_path_fixed_init_copy (&command->path, path);
     if (status) {
 	_cairo_pattern_fini (&command->pattern.base);

Index: cairo-surface.c
===================================================================
RCS file: /cvs/cairo/cairo/src/cairo-surface.c,v
retrieving revision 1.102
retrieving revision 1.103
diff -u -d -r1.102 -r1.103
--- cairo-surface.c	13 Oct 2005 23:55:14 -0000	1.102
+++ cairo-surface.c	14 Oct 2005 04:00:52 -0000	1.103
@@ -154,6 +154,8 @@
 
     surface->next_clip_serial = 0;
     surface->current_clip_serial = 0;
+
+    surface->is_snapshot = FALSE;
 }
 
 cairo_surface_t *
@@ -473,6 +475,8 @@
 void
 cairo_surface_mark_dirty (cairo_surface_t *surface)
 {
+    assert (! surface->is_snapshot);
+
     cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1);
 }
 
@@ -495,6 +499,8 @@
 				    int              width,
 				    int              height)
 {
+    assert (! surface->is_snapshot);
+
     if (surface->status)
 	return;
 
@@ -536,6 +542,8 @@
 				 double           x_offset,
 				 double           y_offset)
 {
+    assert (! surface->is_snapshot);
+
     if (surface->status)
 	return;
 
@@ -700,7 +708,7 @@
     status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
     if (status != CAIRO_STATUS_SUCCESS)
 	return status;
-    
+
     status = surface->backend->clone_similar (surface, &image->base, clone_out);
 
     /* If the above failed point, we could implement a full fallback
@@ -713,6 +721,67 @@
     return status;
 }
 
+/**
+ * _cairo_surface_snapshot
+ * @surface: a #cairo_surface_t
+ * @snapshot_out: return value surface---not necessarily of the same type as @surface
+ *
+ * Make an immutable copy of @surface. It is an error to call a
+ * surface-modifying function on the result of this function.
+ *
+ * The caller owns the return value and should call
+ * cairo_surface_destroy when finished with it. This function will not
+ * return NULL, but will return a nil surface instead.
+ **/
+cairo_surface_t *
+_cairo_surface_snapshot (cairo_surface_t *surface)
+
+{
+    cairo_surface_t *snapshot;
+    cairo_status_t status;
+    cairo_pattern_union_t pattern;
+    cairo_image_surface_t *image;
+    void *image_extra;
+
+    if (surface->finished)
+	return (cairo_surface_t *) &_cairo_surface_nil;
+
+    /* XXX: Will need to do something very different here to snapshot
+     * a meta-surface. */
+
+    status = _cairo_surface_acquire_source_image (surface,
+						  &image, &image_extra);
+    if (status != CAIRO_STATUS_SUCCESS)
+	return (cairo_surface_t *) &_cairo_surface_nil;
+
+    snapshot = cairo_image_surface_create (image->format,
+					   image->width,
+					   image->height);
+    if (cairo_surface_status (snapshot))
+	return snapshot;
+
+    _cairo_pattern_init_for_surface (&pattern.surface, &image->base);
+
+    _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
+			      &pattern.base,
+			      NULL,
+			      snapshot,
+			      0, 0,
+			      0, 0,
+			      0, 0,
+			      image->width,
+			      image->height);
+
+    _cairo_pattern_fini (&pattern.base);
+
+    _cairo_surface_release_source_image (surface,
+					 image, &image_extra);
+
+    snapshot->is_snapshot = TRUE;
+
+    return snapshot;
+}
+
 typedef struct {
     cairo_surface_t *dst;
     cairo_rectangle_t extents;
@@ -824,6 +893,8 @@
 {
     cairo_int_status_t status;
 
+    assert (! dst->is_snapshot);
+
     if (mask) {
 	/* These operators aren't interpreted the same way by the backends;
 	 * they are implemented in terms of other operators in cairo-gstate.c
@@ -882,6 +953,8 @@
 {
     cairo_rectangle_t rect;
 
+    assert (! surface->is_snapshot);
+
     if (surface->status)
 	return surface->status;
 
@@ -921,6 +994,8 @@
     cairo_status_t status;
     int i;
 
+    assert (! surface->is_snapshot);
+
     if (!num_rects)
 	return CAIRO_STATUS_SUCCESS;
     
@@ -956,6 +1031,8 @@
     int x1, y1, x2, y2;
     int i;
 
+    assert (! surface->is_snapshot);
+
     if (num_rects <= 0)
 	return CAIRO_STATUS_SUCCESS;
 
@@ -1042,6 +1119,8 @@
 {
     cairo_int_status_t status;
 
+    assert (! surface->is_snapshot);
+
     if (surface->status)
 	return surface->status;
 
@@ -1111,6 +1190,8 @@
 {
     cairo_status_t status;
 
+    assert (! dst->is_snapshot);
+
     if (dst->backend->fill_path) {
 	status = dst->backend->fill_path (operator, pattern, dst, path,
 					  fill_rule, tolerance, antialias);
@@ -1209,6 +1290,8 @@
 {
     cairo_int_status_t status;
 
+    assert (! dst->is_snapshot);
+
     /* These operators aren't interpreted the same way by the backends;
      * they are implemented in terms of other operators in cairo-gstate.c
      */
@@ -1243,6 +1326,8 @@
 cairo_status_t
 _cairo_surface_copy_page (cairo_surface_t *surface)
 {
+    assert (! surface->is_snapshot);
+
     if (surface->status)
 	return surface->status;
 
@@ -1259,6 +1344,8 @@
 cairo_status_t
 _cairo_surface_show_page (cairo_surface_t *surface)
 {
+    assert (! surface->is_snapshot);
+
     if (surface->status)
 	return surface->status;
 
@@ -1527,6 +1614,8 @@
 {
     cairo_status_t status;
 
+    assert (! dst->is_snapshot);
+
     if (dst->status)
 	return dst->status;
 
@@ -1647,6 +1736,8 @@
     cairo_rectangle_t src_tmp, mask_tmp;
     cairo_rectangle_t *src_rectangle = NULL;
     cairo_rectangle_t *mask_rectangle = NULL;
+
+    assert (! dst->is_snapshot);
   
     /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
      * non-repeating sources and masks. Other sources and masks can be ignored.
@@ -1720,6 +1811,8 @@
     cairo_rectangle_t src_tmp, mask_tmp;
     cairo_rectangle_t *src_rectangle = NULL;
     cairo_rectangle_t *mask_rectangle = NULL;
+
+    assert (! dst->is_snapshot);
   
     /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
      * non-repeating sources and masks. Other sources and masks can be ignored.

Index: cairoint.h
===================================================================
RCS file: /cvs/cairo/cairo/src/cairoint.h,v
retrieving revision 1.215
retrieving revision 1.216
diff -u -d -r1.215 -r1.216
--- cairoint.h	13 Oct 2005 23:55:15 -0000	1.215
+++ cairoint.h	14 Oct 2005 04:00:52 -0000	1.216
@@ -776,6 +776,9 @@
      * The special value '0' is reserved for the unclipped case.
      */
     unsigned int current_clip_serial;
+
+    /* A "snapshot" surface is immutable. See _cairo_surface_snapshot. */
+    cairo_bool_t is_snapshot;
 };
 
 struct _cairo_image_surface {
@@ -1612,6 +1615,9 @@
 			      cairo_surface_t  *src,
 			      cairo_surface_t **clone_out);
 
+cairo_private cairo_surface_t *
+_cairo_surface_snapshot (cairo_surface_t *surface);
+
 cairo_private unsigned int
 _cairo_surface_get_current_clip_serial (cairo_surface_t *surface);
 



More information about the cairo-commit mailing list