[cairo-commit] 2 commits - src/cairo-image-surface.c src/cairoint.h src/cairo-surface-fallback.c src/test-paginated-surface.c test/cairo-test.c

Carl Worth cworth at kemper.freedesktop.org
Fri Apr 14 11:13:16 PDT 2006


 src/cairo-image-surface.c    |    2 
 src/cairo-surface-fallback.c |    4 
 src/cairoint.h               |   13 ++
 src/test-paginated-surface.c |  219 ++++++++++++++++++++++++++++++++++++++++---
 test/cairo-test.c            |    4 
 5 files changed, 226 insertions(+), 16 deletions(-)

New commits:
diff-tree 5461f25df9888aa5fd79e1e371cd1af2cf8964ab (from c81569d2f1b8c396f789f4c49d87772a596862d9)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Apr 14 11:01:39 2006 -0700

    Fix _composite_trap_region to restore the original clip when done.

diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c
index 9b6cfd6..a5c723f 100644
--- a/src/cairo-surface-fallback.c
+++ b/src/cairo-surface-fallback.c
@@ -451,6 +451,10 @@ _composite_trap_region (cairo_clip_t    
 				       extents->x, extents->y,
 				       extents->width, extents->height);
 
+    /* Restore the original clip if we modified it temporarily. */
+    if (num_rects >1)
+	_cairo_surface_set_clip (dst, clip);
+
     if (clip_surface)
       _cairo_pattern_fini (&mask.base);
 
diff-tree c81569d2f1b8c396f789f4c49d87772a596862d9 (from 41dc06d7111d246d4b5802c700a83e4be9091449)
Author: Carl Worth <cworth at cworth.org>
Date:   Fri Apr 14 10:38:11 2006 -0700

    Flesh test-paginated-surface out into a complete surface.
    
    This adds an aactual test_paginated_surface_backend rather than just
    having this test surface create a paginated surface around an image
    surface. This is a more realistic test of what a paginated surface is
    and should be more useful as an example of how to use the paginated
    surface, (and in particular the analysis portions).

diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 0621946..e095aa0 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -861,7 +861,7 @@ _cairo_image_surface_composite_trapezoid
     return status;
 }
 
-static cairo_int_status_t
+cairo_int_status_t
 _cairo_image_surface_set_clip_region (void *abstract_surface,
 				      pixman_region16_t *region)
 {
diff --git a/src/cairoint.h b/src/cairoint.h
index 13880cb..51829c9 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1862,6 +1862,19 @@ _cairo_image_surface_create_for_data_wit
 cairo_private void
 _cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface);
 
+/* XXX: It's a nasty kludge that this appears here. Backend functions
+ * like this should really be static. But we're doing this to work
+ * around some general defects in the backend clipping interfaces,
+ * (see some notes in test-paginated-surface.c).
+ *
+ * I want to fix the real defects, but it's "hard" as they touch many
+ * backends, so doing that will require synchronizing several backend
+ * maintainers.
+ */
+cairo_private cairo_int_status_t
+_cairo_image_surface_set_clip_region (void *abstract_surface,
+				      pixman_region16_t *region);
+
 cairo_private cairo_bool_t
 _cairo_surface_is_image (const cairo_surface_t *surface);
 
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index d07ac37..e42f6a7 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -51,20 +51,21 @@
 
 #include "cairo-paginated-surface-private.h"
 
+typedef struct _test_paginated_surface {
+    cairo_surface_t base;
+    cairo_surface_t *target;
+    cairo_paginated_mode_t paginated_mode;
+} test_paginated_surface_t;
+
+static const cairo_surface_backend_t test_paginated_surface_backend;
+
 static void
-_test_paginated_surface_set_paginated_mode (cairo_surface_t *target,
+_test_paginated_surface_set_paginated_mode (cairo_surface_t *abstract_surface,
 					    cairo_paginated_mode_t mode)
 {
-    /* XXX: We don't do anything to save the paginated mode here. This
-     * means that all the rendering will hit the image surface
-     * twice. This will work (but less efficiently) for all tests that
-     * explicitly initialize all pixels. Tests that expect the
-     * background to initially be transparent and leave it that way in
-     * spots will likely fail.
-     *
-     * If we see this as worth fixing, it will just require shoving
-     * some set_paginated_mode support into cairo_image_surface_t.
-     */
+    test_paginated_surface_t *surface = (test_paginated_surface_t *) abstract_surface;
+
+    surface->paginated_mode = mode;
 }
 
 cairo_surface_t *
@@ -74,12 +75,204 @@ _test_paginated_surface_create_for_data 
 					 int		 	 height,
 					 int		 	 stride)
 {
+    cairo_status_t status;
     cairo_surface_t *target;
+    test_paginated_surface_t *surface;
 
-    target = _cairo_image_surface_create_for_data_with_content (data, content,
+    target =  _cairo_image_surface_create_for_data_with_content (data, content,
 								width, height,
 								stride);
+    status = cairo_surface_status (target);
+    if (status) {
+	_cairo_error (status);
+	return (cairo_surface_t *) &_cairo_surface_nil;
+    }
+
+    surface = malloc (sizeof (test_paginated_surface_t));
+    if (surface == NULL) {
+	_cairo_error (CAIRO_STATUS_NO_MEMORY);
+	return (cairo_surface_t *) &_cairo_surface_nil;
+    }
 
-    return _cairo_paginated_surface_create (target, content, width, height,
+    _cairo_surface_init (&surface->base, &test_paginated_surface_backend);
+
+    surface->target = target;
+
+    return _cairo_paginated_surface_create (&surface->base, content, width, height,
 					    _test_paginated_surface_set_paginated_mode);
 }
+
+static cairo_int_status_t
+_test_paginated_surface_set_clip_region (void *abstract_surface,
+					 pixman_region16_t *region)
+{
+    test_paginated_surface_t *surface = abstract_surface;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_STATUS_SUCCESS;
+
+    /* XXX: The whole surface backend clipping interface is a giant
+     * disaster right now. In particular, its uncleanness shows up
+     * when trying to implement one surface that wraps another one (as
+     * we are doing here).
+     *
+     * Here are two of the problems that show up:
+     *
+     * 1. The most critical piece of information in all this stuff,
+     * the "clip" isn't getting passed to the backend
+     * functions. Instead the generic surface layer is caching that as
+     * surface->clip. This is a problem for surfaces like this one
+     * that do wrapping. Our base surface will have the clip set, but
+     * our target's surface will not.
+     *
+     * 2. We're here in our backend's set_clip_region function, and we
+     * want to call into our target surface's set_clip_region.
+     * Generally, we would do this by calling an equivalent
+     * _cairo_surface function, but _cairo_surface_set_clip_region
+     * does not have the same signature/semantics, (it has the
+     * clip_serial stuff as well).
+     *
+     * We kludge around each of these by manually copying the clip
+     * object from our base surface into the target's base surface
+     * (yuck!) and by reaching directly into the image surface's
+     * set_clip_region instead of calling into the generic
+     * _cairo_surface_set_clip_region (double yuck!).
+     */
+
+    surface->target->clip = surface->base.clip;
+
+    return _cairo_image_surface_set_clip_region (surface->target, region);
+}
+
+static cairo_int_status_t
+_test_paginated_surface_get_extents (void	       *abstract_surface,
+				     cairo_rectangle_t *rectangle)
+{
+    test_paginated_surface_t *surface = abstract_surface;
+
+    return _cairo_surface_get_extents (surface->target, rectangle);
+}
+
+static cairo_int_status_t
+_test_paginated_surface_paint (void		*abstract_surface,
+			       cairo_operator_t	 op,
+			       cairo_pattern_t	*source)
+{
+    test_paginated_surface_t *surface = abstract_surface;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_STATUS_SUCCESS;
+
+    return _cairo_surface_paint (surface->target, op, source);
+}
+
+static cairo_int_status_t
+_test_paginated_surface_mask (void		*abstract_surface,
+			      cairo_operator_t	 op,
+			      cairo_pattern_t	*source,
+			      cairo_pattern_t	*mask)
+{
+    test_paginated_surface_t *surface = abstract_surface;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_STATUS_SUCCESS;
+
+    return _cairo_surface_mask (surface->target, op, source, mask);
+}
+
+static cairo_int_status_t
+_test_paginated_surface_stroke (void			*abstract_surface,
+				cairo_operator_t	 op,
+				cairo_pattern_t		*source,
+				cairo_path_fixed_t	*path,
+				cairo_stroke_style_t	*style,
+				cairo_matrix_t		*ctm,
+				cairo_matrix_t		*ctm_inverse,
+				double			 tolerance,
+				cairo_antialias_t	 antialias)
+{
+    test_paginated_surface_t *surface = abstract_surface;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_STATUS_SUCCESS;
+
+    return _cairo_surface_stroke (surface->target, op, source,
+				  path, style,
+				  ctm, ctm_inverse,
+				  tolerance, antialias);
+}
+
+static cairo_int_status_t
+_test_paginated_surface_fill (void			*abstract_surface,
+			      cairo_operator_t		 op,
+			      cairo_pattern_t		*source,
+			      cairo_path_fixed_t	*path,
+			      cairo_fill_rule_t		 fill_rule,
+			      double			 tolerance,
+			      cairo_antialias_t		 antialias)
+{
+    test_paginated_surface_t *surface = abstract_surface;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_STATUS_SUCCESS;
+
+    return _cairo_surface_fill (surface->target, op, source,
+				path, fill_rule,
+				tolerance, antialias);
+}
+
+static cairo_int_status_t
+_test_paginated_surface_show_glyphs (void			*abstract_surface,
+				     cairo_operator_t		 op,
+				     cairo_pattern_t		*source,
+				     const cairo_glyph_t	*glyphs,
+				     int			 num_glyphs,
+				     cairo_scaled_font_t	*scaled_font)
+{
+    test_paginated_surface_t *surface = abstract_surface;
+
+    if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+	return CAIRO_STATUS_SUCCESS;
+
+    return _cairo_surface_show_glyphs (surface->target, op, source,
+				       glyphs, num_glyphs, scaled_font);
+}
+
+static const cairo_surface_backend_t test_paginated_surface_backend = {
+    CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
+
+    /* Since we are a paginated user, we get to regard most of the
+     * surface backend interface as historical cruft and ignore it. */
+
+    NULL, /* create_similar */
+    NULL, /* finish */
+    NULL, /* acquire_source_image */
+    NULL, /* release_source_image */
+    NULL, /* acquire_dest_image */
+    NULL, /* release_dest_image */
+    NULL, /* clone_similar */
+    NULL, /* composite */
+    NULL, /* fill_rectangles */
+    NULL, /* composite_trapezoids */
+    NULL, /* copy_page */
+    NULL, /* show_page */
+    _test_paginated_surface_set_clip_region,
+    NULL, /* intersect_clip_path */
+    _test_paginated_surface_get_extents,
+    NULL, /* old_show_glyphs */
+    NULL, /* get_font_options */
+    NULL, /* flush */
+    NULL, /* mark_dirty_rectangle */
+    NULL, /* scaled_font_fini */
+    NULL, /* scaled_glyph_fini */
+
+    /* Here is the more "modern" section of the surface backend
+     * interface which is mostly just drawing functions */
+
+    _test_paginated_surface_paint,
+    _test_paginated_surface_mask,
+    _test_paginated_surface_stroke,
+    _test_paginated_surface_fill,
+    _test_paginated_surface_show_glyphs,
+    NULL /* snapshot */
+};
diff --git a/test/cairo-test.c b/test/cairo-test.c
index b937fe6..c200bf7 100644
--- a/test/cairo-test.c
+++ b/test/cairo-test.c
@@ -1502,12 +1502,12 @@ cairo_test_expecting (cairo_test_t *test
 	    { "test-meta", CAIRO_INTERNAL_SURFACE_TYPE_TEST_META,
 	      CAIRO_CONTENT_COLOR,
 	      create_test_meta_surface, cairo_surface_write_to_png, NULL },
-	    { "test-paginated", CAIRO_SURFACE_TYPE_IMAGE,
+	    { "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
 	      CAIRO_CONTENT_COLOR_ALPHA,
 	      create_test_paginated_surface,
 	      test_paginated_write_to_png,
 	      cleanup_test_paginated },
-	    { "test-paginated", CAIRO_SURFACE_TYPE_IMAGE,
+	    { "test-paginated", CAIRO_INTERNAL_SURFACE_TYPE_TEST_PAGINATED,
 	      CAIRO_CONTENT_COLOR,
 	      create_test_paginated_surface,
 	      test_paginated_write_to_png,


More information about the cairo-commit mailing list