[cairo-commit] src/cairo-analysis-surface.c src/cairo-cogl-surface.c src/cairo-directfb-surface.c src/cairo-gl-surface.c src/cairo-image-source.c src/cairo-image-surface.c src/cairo-image-surface-private.h src/cairo-mask-compositor.c src/cairo-os2-surface.c src/cairo-paginated-surface.c src/cairo-pattern-private.h src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-qt-surface.cpp src/cairo-quartz-image-surface.c src/cairo-recording-surface.c src/cairo-script-surface.c src/cairo-spans-compositor.c src/cairo-surface-backend-private.h src/cairo-surface.c src/cairo-surface-observer.c src/cairo-surface-private.h src/cairo-surface-snapshot.c src/cairo-surface-subsurface.c src/cairo-svg-surface.c src/cairo-tee-surface.c src/cairo-traps-compositor.c src/cairo-type3-glyph-surface.c src/cairo-vg-surface.c src/cairo-win32-printing-surface.c src/cairo-win32-surface.c src/cairo-xcb-surface.c src/cairo-xlib-source.c src/cairo-xlib-surface.c src/cairo-xlib-xcb-surface.c src/cairo-xml-surface .c src/drm src/test-compositor-surface.c src/test-null-compositor-surface.c src/test-paginated-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Thu Feb 9 05:10:33 PST 2012


 src/cairo-analysis-surface.c        |    2 ++
 src/cairo-cogl-surface.c            |    1 +
 src/cairo-directfb-surface.c        |    1 +
 src/cairo-gl-surface.c              |   14 ++++++++++++++
 src/cairo-image-source.c            |   12 +++---------
 src/cairo-image-surface-private.h   |    5 +++++
 src/cairo-image-surface.c           |   14 ++++++++++++++
 src/cairo-mask-compositor.c         |   25 ++++++++-----------------
 src/cairo-os2-surface.c             |    1 +
 src/cairo-paginated-surface.c       |    9 +++++++++
 src/cairo-pattern-private.h         |    8 ++++++++
 src/cairo-pdf-surface.c             |    1 +
 src/cairo-ps-surface.c              |    1 +
 src/cairo-qt-surface.cpp            |    1 +
 src/cairo-quartz-image-surface.c    |    1 +
 src/cairo-recording-surface.c       |    2 ++
 src/cairo-script-surface.c          |   14 ++++++++++++++
 src/cairo-spans-compositor.c        |   18 ++++++------------
 src/cairo-surface-backend-private.h |    8 ++++++++
 src/cairo-surface-observer.c        |    9 +++++++++
 src/cairo-surface-private.h         |    4 ++++
 src/cairo-surface-snapshot.c        |    9 +++++++++
 src/cairo-surface-subsurface.c      |   14 ++++++++++++++
 src/cairo-surface.c                 |   16 ++++++++++++++++
 src/cairo-svg-surface.c             |    1 +
 src/cairo-tee-surface.c             |    9 +++++++++
 src/cairo-traps-compositor.c        |   26 +++++++++-----------------
 src/cairo-type3-glyph-surface.c     |    1 +
 src/cairo-vg-surface.c              |    1 +
 src/cairo-win32-printing-surface.c  |    1 +
 src/cairo-win32-surface.c           |    1 +
 src/cairo-xcb-surface.c             |   14 ++++++++++++++
 src/cairo-xlib-source.c             |   17 +++++------------
 src/cairo-xlib-surface.c            |   14 ++++++++++++++
 src/cairo-xlib-xcb-surface.c        |    9 +++++++++
 src/cairo-xml-surface.c             |    1 +
 src/drm/cairo-drm-gallium-surface.c |    1 +
 src/drm/cairo-drm-i915-surface.c    |    2 ++
 src/drm/cairo-drm-i965-surface.c    |    2 ++
 src/drm/cairo-drm-intel-surface.c   |    3 +++
 src/drm/cairo-drm-radeon-surface.c  |    3 +++
 src/test-compositor-surface.c       |    1 +
 src/test-null-compositor-surface.c  |    1 +
 src/test-paginated-surface.c        |    1 +
 44 files changed, 232 insertions(+), 67 deletions(-)

New commits:
commit 2061cd81f26c04deb5a7092744295caab7bac077
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Thu Feb 9 13:01:17 2012 +0000

    Replace the ad-hoc surface unwrappers with a function pointer
    
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index d9edcd7..895d82b 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -702,6 +702,7 @@ static const cairo_surface_backend_t cairo_analysis_surface_backend = {
     NULL, /* map_to_image */
     NULL, /* unmap */
 
+    NULL, /* source */
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* snapshot */
@@ -895,6 +896,7 @@ static const cairo_surface_backend_t cairo_null_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image*/
 
+    NULL, /* source */
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* snapshot */
diff --git a/src/cairo-cogl-surface.c b/src/cairo-cogl-surface.c
index 3f9a782..7326284 100644
--- a/src/cairo-cogl-surface.c
+++ b/src/cairo-cogl-surface.c
@@ -2463,6 +2463,7 @@ const cairo_surface_backend_t _cairo_cogl_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     _cairo_cogl_surface_acquire_source_image,
     _cairo_cogl_surface_release_source_image,
     NULL, /* snapshot */
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index 46c0960..dd830f0 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -1835,6 +1835,7 @@ _cairo_directfb_surface_backend = {
 	NULL, /* map to image */
 	NULL, /* unmap image */
 
+	_cairo_surface_default_source,
         _cairo_directfb_surface_acquire_source_image,/*acquire_source_image*/
         _cairo_directfb_surface_release_source_image,/*release_source_image*/
         _cairo_directfb_surface_acquire_dest_image,/*acquire_dest_image*/
diff --git a/src/cairo-gl-surface.c b/src/cairo-gl-surface.c
index 7601b6a..c0d768a 100644
--- a/src/cairo-gl-surface.c
+++ b/src/cairo-gl-surface.c
@@ -1078,6 +1078,19 @@ _cairo_gl_surface_map_to_image (void      *abstract_surface,
     return &image->base;
 }
 
+static cairo_surface_t *
+_cairo_gl_surface_source (void		       *abstract_surface,
+			  cairo_rectangle_int_t *extents)
+{
+    cairo_gl_surface_t *surface = abstract_surface;
+
+    extents->x = extents->y = 0;
+    extents->width  = surface->width;
+    extents->height = surface->height;
+
+    return &surface->base;
+}
+
 static cairo_status_t
 _cairo_gl_surface_acquire_source_image (void		       *abstract_surface,
 					cairo_image_surface_t **image_out,
@@ -1249,6 +1262,7 @@ static const cairo_surface_backend_t _cairo_gl_surface_backend = {
     _cairo_gl_surface_map_to_image,
     _cairo_gl_surface_unmap_image,
 
+    _cairo_gl_surface_source,
     _cairo_gl_surface_acquire_source_image,
     _cairo_gl_surface_release_source_image,
     NULL, /* snapshot */
diff --git a/src/cairo-image-source.c b/src/cairo-image-source.c
index 047a049..2c94379 100644
--- a/src/cairo-image-source.c
+++ b/src/cairo-image-source.c
@@ -609,15 +609,9 @@ _pixman_image_for_recording (cairo_image_surface_t *dst,
 
     *ix = *iy = 0;
 
-    source = pattern->surface;
-    if (_cairo_surface_is_subsurface (source))
-	source = _cairo_surface_subsurface_get_target_with_offset (source, &tx, &ty);
-    if (_cairo_surface_is_snapshot (source))
-	source = _cairo_surface_snapshot_get_target (source);
-    if (_cairo_surface_is_observer (source))
-	source = _cairo_surface_observer_get_target (source);
-    if (_cairo_surface_is_paginated (source))
-	source = _cairo_paginated_surface_get_target (source);
+    source = _cairo_pattern_get_source (pattern, &limit);
+    tx = limit.x;
+    ty = limit.y;
 
     extend = pattern->base.extend;
     if (_cairo_surface_get_extents (source, &limit)) {
diff --git a/src/cairo-image-surface-private.h b/src/cairo-image-surface-private.h
index 2777e2f..d580d89 100644
--- a/src/cairo-image-surface-private.h
+++ b/src/cairo-image-surface-private.h
@@ -97,6 +97,11 @@ _cairo_image_surface_map_to_image (void *abstract_other,
 cairo_private cairo_int_status_t
 _cairo_image_surface_unmap_image (void *abstract_surface,
 				  cairo_image_surface_t *image);
+
+cairo_private cairo_surface_t *
+_cairo_image_surface_source (void			*abstract_surface,
+			     cairo_rectangle_int_t	*extents);
+
 cairo_private cairo_status_t
 _cairo_image_surface_acquire_source_image (void                    *abstract_surface,
 					   cairo_image_surface_t  **image_out,
diff --git a/src/cairo-image-surface.c b/src/cairo-image-surface.c
index 6adbdd6..212e2b5 100644
--- a/src/cairo-image-surface.c
+++ b/src/cairo-image-surface.c
@@ -819,6 +819,19 @@ _cairo_image_surface_assume_ownership_of_data (cairo_image_surface_t *surface)
     surface->owns_data = TRUE;
 }
 
+cairo_surface_t *
+_cairo_image_surface_source (void			*abstract_surface,
+			     cairo_rectangle_int_t	*extents)
+{
+    cairo_image_surface_t *surface = abstract_surface;
+
+    extents->x = extents->y = 0;
+    extents->width = surface->width;
+    extents->height = surface->height;
+
+    return &surface->base;
+}
+
 cairo_status_t
 _cairo_image_surface_acquire_source_image (void                    *abstract_surface,
 					   cairo_image_surface_t  **image_out,
@@ -948,6 +961,7 @@ const cairo_surface_backend_t _cairo_image_surface_backend = {
     _cairo_image_surface_map_to_image,
     _cairo_image_surface_unmap_image,
 
+    _cairo_image_surface_source,
     _cairo_image_surface_acquire_source_image,
     _cairo_image_surface_release_source_image,
     _cairo_image_surface_snapshot,
diff --git a/src/cairo-mask-compositor.c b/src/cairo-mask-compositor.c
index b34ffa2..807ba99 100644
--- a/src/cairo-mask-compositor.c
+++ b/src/cairo-mask-compositor.c
@@ -778,39 +778,30 @@ upload_boxes (const cairo_mask_compositor_t *compositor,
 {
     cairo_surface_t *dst = extents->surface;
     const cairo_pattern_t *source = &extents->source_pattern.base;
-    const cairo_surface_pattern_t *pattern;
     cairo_surface_t *src;
     cairo_rectangle_int_t limit;
     cairo_int_status_t status;
     int tx, ty;
 
-    pattern = (const cairo_surface_pattern_t *) source;
-    src = pattern->surface;
+    src = _cairo_pattern_get_source ((cairo_surface_pattern_t *)source, &limit);
     if (!(src->type == CAIRO_SURFACE_TYPE_IMAGE || src->type == dst->type))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (_cairo_surface_is_snapshot (src))
-	src = _cairo_surface_snapshot_get_target (src);
-    if (_cairo_surface_is_observer (src))
-	src = _cairo_surface_observer_get_target (src);
-    if (_cairo_surface_is_subsurface (src)) {
-	_cairo_surface_subsurface_offset (src, &tx, &ty);
-	src = _cairo_surface_subsurface_get_target (src);
-    }
-
     /* Check that the data is entirely within the image */
-    if (extents->bounded.x + tx < 0 || extents->bounded.y + ty < 0)
+    if (extents->bounded.x + tx < limit.x || extents->bounded.y + ty < limit.y)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    _cairo_surface_get_extents (pattern->surface, &limit);
-    if (extents->bounded.x + extents->bounded.width  + tx > limit.width ||
-	extents->bounded.y + extents->bounded.height + ty > limit.height)
+    if (extents->bounded.x + extents->bounded.width  + tx > limit.x + limit.width ||
+	extents->bounded.y + extents->bounded.height + ty > limit.y + limit.height)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE)
+    tx += limit.x;
+    ty += limit.y;
+
+    if (src->type == CAIRO_SURFACE_TYPE_IMAGE)
 	status = compositor->draw_image_boxes (dst,
 					       (cairo_image_surface_t *)src,
 					       boxes, tx, ty);
diff --git a/src/cairo-os2-surface.c b/src/cairo-os2-surface.c
index 51171fa..3b83d0f 100644
--- a/src/cairo-os2-surface.c
+++ b/src/cairo-os2-surface.c
@@ -1394,6 +1394,7 @@ static const cairo_surface_backend_t cairo_os2_surface_backend = {
     _cairo_os2_surface_map_to_image,
     _cairo_os2_surface_unmap_image,
 
+    _cairo_surface_default_source,
     _cairo_os2_surface_acquire_source_image,
     _cairo_os2_surface_release_source_image,
     NULL, /* snapshot */
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index e872e39..957cf7b 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -242,6 +242,14 @@ _cairo_paginated_surface_create_image_surface (void	       *abstract_surface,
     return image;
 }
 
+static cairo_surface_t *
+_cairo_paginated_surface_source (void	       *abstract_surface,
+				 cairo_rectangle_int_t *extents)
+{
+    cairo_paginated_surface_t *surface = abstract_surface;
+    return _cairo_surface_get_source (surface->target, extents);
+}
+
 static cairo_status_t
 _cairo_paginated_surface_acquire_source_image (void	       *abstract_surface,
 					       cairo_image_surface_t **image_out,
@@ -682,6 +690,7 @@ static const cairo_surface_backend_t cairo_paginated_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_paginated_surface_source,
     _cairo_paginated_surface_acquire_source_image,
     _cairo_paginated_surface_release_source_image,
     _cairo_paginated_surface_snapshot,
diff --git a/src/cairo-pattern-private.h b/src/cairo-pattern-private.h
index 9b2f875..761fce3 100644
--- a/src/cairo-pattern-private.h
+++ b/src/cairo-pattern-private.h
@@ -39,6 +39,7 @@
 #include "cairo-error-private.h"
 #include "cairo-types-private.h"
 #include "cairo-list-private.h"
+#include "cairo-surface-private.h"
 
 #include <stdio.h> /* FILE* */
 
@@ -370,6 +371,13 @@ _cairo_raster_source_pattern_finish (cairo_pattern_t *abstract_pattern);
 cairo_private void
 _cairo_debug_print_pattern (FILE *file, const cairo_pattern_t *pattern);
 
+static inline cairo_surface_t *
+_cairo_pattern_get_source (const cairo_surface_pattern_t *pattern,
+			   cairo_rectangle_int_t *extents)
+{
+    return _cairo_surface_get_source (pattern->surface, extents);
+}
+
 CAIRO_END_DECLS
 
 #endif /* CAIRO_PATTERN_PRIVATE */
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index cf8aab4..dff5a3a 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -7274,6 +7274,7 @@ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* snapshot */
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 8c861cb..07155e7 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -4538,6 +4538,7 @@ static const cairo_surface_backend_t cairo_ps_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* snapshot */
diff --git a/src/cairo-qt-surface.cpp b/src/cairo-qt-surface.cpp
index aaed90c..467a389 100644
--- a/src/cairo-qt-surface.cpp
+++ b/src/cairo-qt-surface.cpp
@@ -1561,6 +1561,7 @@ static const cairo_surface_backend_t cairo_qt_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     _cairo_qt_surface_acquire_source_image,
     _cairo_qt_surface_release_source_image,
     _cairo_qt_surface_acquire_dest_image,
diff --git a/src/cairo-quartz-image-surface.c b/src/cairo-quartz-image-surface.c
index b5f8612..19cd424 100644
--- a/src/cairo-quartz-image-surface.c
+++ b/src/cairo-quartz-image-surface.c
@@ -260,6 +260,7 @@ static const cairo_surface_backend_t cairo_quartz_image_surface_backend = {
     _cairo_quartz_image_surface_map_to_image,
     _cairo_quartz_image_surface_unmap_image,
 
+    _cairo_surface_default_source,
     _cairo_quartz_image_surface_acquire_source_image,
     NULL, /* release_source_image */
     NULL, /* snapshot */
diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c
index 5316a10..3b626cc 100644
--- a/src/cairo-recording-surface.c
+++ b/src/cairo-recording-surface.c
@@ -535,6 +535,7 @@ static const cairo_surface_backend_t proxy_backend  = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     proxy_acquire_source_image,
     proxy_release_source_image,
 };
@@ -1135,6 +1136,7 @@ static const cairo_surface_backend_t cairo_recording_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     _cairo_recording_surface_acquire_source_image,
     _cairo_recording_surface_release_source_image,
     _cairo_recording_surface_snapshot,
diff --git a/src/cairo-script-surface.c b/src/cairo-script-surface.c
index 8851a9e..a779780 100644
--- a/src/cairo-script-surface.c
+++ b/src/cairo-script-surface.c
@@ -2090,6 +2090,19 @@ _device_destroy (void *abstract_device)
     free (ctx);
 }
 
+static cairo_surface_t *
+_cairo_script_surface_source (void                    *abstract_surface,
+			      cairo_rectangle_int_t	*extents)
+{
+    cairo_script_surface_t *surface = abstract_surface;
+
+    extents->x = extents->y = 0;
+    extents->width  = surface->width;
+    extents->height = surface->height;
+
+    return &surface->base;
+}
+
 static cairo_status_t
 _cairo_script_surface_acquire_source_image (void                    *abstract_surface,
 					    cairo_image_surface_t  **image_out,
@@ -3557,6 +3570,7 @@ _cairo_script_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_script_surface_source,
     _cairo_script_surface_acquire_source_image,
     _cairo_script_surface_release_source_image,
     _cairo_script_surface_snapshot,
diff --git a/src/cairo-spans-compositor.c b/src/cairo-spans-compositor.c
index 0e94be8..0abb505 100644
--- a/src/cairo-spans-compositor.c
+++ b/src/cairo-spans-compositor.c
@@ -379,18 +379,12 @@ error:
 }
 
 static cairo_surface_t *
-unwrap_surface (const cairo_pattern_t *pattern)
+unwrap_source (const cairo_pattern_t *pattern)
 {
-    cairo_surface_t *surface;
+    cairo_rectangle_int_t limit;
 
-    surface = ((const cairo_surface_pattern_t *) pattern)->surface;
-    if (_cairo_surface_is_paginated (surface))
-	surface = _cairo_paginated_surface_get_recording (surface);
-    if (_cairo_surface_is_snapshot (surface))
-	surface = _cairo_surface_snapshot_get_target (surface);
-    if (_cairo_surface_is_observer (surface))
-	surface = _cairo_surface_observer_get_target (surface);
-    return surface;
+    return _cairo_pattern_get_source ((cairo_surface_pattern_t *)pattern,
+				      &limit);
 }
 
 static cairo_bool_t
@@ -417,7 +411,7 @@ recording_pattern_contains_sample (const cairo_pattern_t *pattern,
     if (pattern->extend == CAIRO_EXTEND_NONE)
 	return TRUE;
 
-    surface = (cairo_recording_surface_t *) unwrap_surface (pattern);
+    surface = (cairo_recording_surface_t *) unwrap_source (pattern);
     if (surface->unbounded)
 	return TRUE;
 
@@ -482,7 +476,7 @@ composite_aligned_boxes (const cairo_spans_compositor_t		*compositor,
 					     boxes);
 
 	recording_clip = _cairo_clip_from_boxes (boxes);
-	status = _cairo_recording_surface_replay_with_clip (unwrap_surface (source),
+	status = _cairo_recording_surface_replay_with_clip (unwrap_source (source),
 							    &source->matrix,
 							    dst, recording_clip);
 	_cairo_clip_destroy (recording_clip);
diff --git a/src/cairo-surface-backend-private.h b/src/cairo-surface-backend-private.h
index 1f076e2..f7bfbd7 100644
--- a/src/cairo-surface-backend-private.h
+++ b/src/cairo-surface-backend-private.h
@@ -70,6 +70,10 @@ struct _cairo_surface_backend {
     (*unmap_image)		(void			*surface,
 				 cairo_image_surface_t	*image);
 
+    cairo_surface_t *
+    (*source)			(void                    *abstract_surface,
+				 cairo_rectangle_int_t  *extents);
+
     cairo_warn cairo_status_t
     (*acquire_source_image)	(void                    *abstract_surface,
 				 cairo_image_surface_t  **image_out,
@@ -197,6 +201,10 @@ struct _cairo_surface_backend {
     (*get_supported_mime_types)	(void			    *surface);
 };
 
+cairo_private cairo_surface_t *
+_cairo_surface_default_source (void *surface,
+			       cairo_rectangle_int_t *extents);
+
 CAIRO_END_DECLS
 
 #endif /* CAIRO_SURFACE_BACKEND_PRIVATE_H */
diff --git a/src/cairo-surface-observer.c b/src/cairo-surface-observer.c
index c70c0cc..e5d3371 100644
--- a/src/cairo-surface-observer.c
+++ b/src/cairo-surface-observer.c
@@ -1276,6 +1276,14 @@ _cairo_surface_observer_get_font_options (void *abstract_surface,
 	surface->target->backend->get_font_options (surface->target, options);
 }
 
+static cairo_surface_t *
+_cairo_surface_observer_source (void                    *abstract_surface,
+				cairo_rectangle_int_t	*extents)
+{
+    cairo_surface_observer_t *surface = abstract_surface;
+    return _cairo_surface_get_source (surface->target, extents);
+}
+
 static cairo_status_t
 _cairo_surface_observer_acquire_source_image (void                    *abstract_surface,
 						cairo_image_surface_t  **image_out,
@@ -1339,6 +1347,7 @@ static const cairo_surface_backend_t _cairo_surface_observer_backend = {
     _cairo_surface_observer_map_to_image,
     _cairo_surface_observer_unmap_image,
 
+    _cairo_surface_observer_source,
     _cairo_surface_observer_acquire_source_image,
     _cairo_surface_observer_release_source_image,
     _cairo_surface_observer_snapshot,
diff --git a/src/cairo-surface-private.h b/src/cairo-surface-private.h
index 5a66480..af24e25 100644
--- a/src/cairo-surface-private.h
+++ b/src/cairo-surface-private.h
@@ -105,4 +105,8 @@ struct _cairo_surface {
 cairo_private cairo_surface_t *
 _cairo_int_surface_create_in_error (cairo_int_status_t status);
 
+cairo_private cairo_surface_t *
+_cairo_surface_get_source (cairo_surface_t *surface,
+			   cairo_rectangle_int_t *extents);
+
 #endif /* CAIRO_SURFACE_PRIVATE_H */
diff --git a/src/cairo-surface-snapshot.c b/src/cairo-surface-snapshot.c
index 4bc40e7..6952374 100644
--- a/src/cairo-surface-snapshot.c
+++ b/src/cairo-surface-snapshot.c
@@ -68,6 +68,14 @@ _cairo_surface_snapshot_flush (void *abstract_surface)
     return surface->target->status;
 }
 
+static cairo_surface_t *
+_cairo_surface_snapshot_source (void                    *abstract_surface,
+				cairo_rectangle_int_t *extents)
+{
+    cairo_surface_snapshot_t *surface = abstract_surface;
+    return _cairo_surface_get_source (surface->target, extents);
+}
+
 static cairo_status_t
 _cairo_surface_snapshot_acquire_source_image (void                    *abstract_surface,
 					      cairo_image_surface_t  **image_out,
@@ -107,6 +115,7 @@ static const cairo_surface_backend_t _cairo_surface_snapshot_backend = {
     NULL, /* map to image */
     NULL, /* unmap image  */
 
+    _cairo_surface_snapshot_source,
     _cairo_surface_snapshot_acquire_source_image,
     _cairo_surface_snapshot_release_source_image,
     NULL, /* snapshot */
diff --git a/src/cairo-surface-subsurface.c b/src/cairo-surface-subsurface.c
index b2f7e0a..4d80cfd 100644
--- a/src/cairo-surface-subsurface.c
+++ b/src/cairo-surface-subsurface.c
@@ -293,6 +293,19 @@ _cairo_surface_subsurface_get_font_options (void *abstract_surface,
 	surface->target->backend->get_font_options (surface->target, options);
 }
 
+static cairo_surface_t *
+_cairo_surface_subsurface_source (void *abstract_surface,
+				  cairo_rectangle_int_t *extents)
+{
+    cairo_surface_subsurface_t *surface = abstract_surface;
+    cairo_surface_t *source;
+
+    source = _cairo_surface_get_source (surface->target, extents);
+    *extents = surface->extents;
+
+    return source;
+}
+
 static cairo_status_t
 _cairo_surface_subsurface_acquire_source_image (void                    *abstract_surface,
 						cairo_image_surface_t  **image_out,
@@ -386,6 +399,7 @@ static const cairo_surface_backend_t _cairo_surface_subsurface_backend = {
     _cairo_surface_subsurface_map_to_image,
     _cairo_surface_subsurface_unmap_image,
 
+    _cairo_surface_subsurface_source,
     _cairo_surface_subsurface_acquire_source_image,
     _cairo_surface_subsurface_release_source_image,
     _cairo_surface_subsurface_snapshot,
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 99a0777..9a4b88d 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1714,6 +1714,22 @@ _cairo_surface_release_source_image (cairo_surface_t        *surface,
 	surface->backend->release_source_image (surface, image, image_extra);
 }
 
+cairo_surface_t *
+_cairo_surface_get_source (cairo_surface_t *surface,
+			   cairo_rectangle_int_t *extents)
+{
+    assert (surface->backend->source);
+    return surface->backend->source (surface, extents);
+}
+
+cairo_surface_t *
+_cairo_surface_default_source (void *surface,
+			       cairo_rectangle_int_t *extents)
+{
+    _cairo_surface_get_extents(surface, extents);
+    return surface;
+}
+
 static cairo_status_t
 _pattern_has_error (const cairo_pattern_t *pattern)
 {
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index c5a02c2..7f87c93 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -2603,6 +2603,7 @@ static const cairo_surface_backend_t cairo_svg_surface_backend = {
 	NULL, /* map to image */
 	NULL, /* unmap image */
 
+	_cairo_surface_default_source,
 	NULL, /* acquire_source_image */
 	NULL, /* release_source_image */
 	NULL, /* snapshot */
diff --git a/src/cairo-tee-surface.c b/src/cairo-tee-surface.c
index 4930a0b..d26ea9e 100644
--- a/src/cairo-tee-surface.c
+++ b/src/cairo-tee-surface.c
@@ -119,6 +119,14 @@ _cairo_tee_surface_finish (void *abstract_surface)
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_surface_t *
+_cairo_tee_surface_source (void	     *abstract_surface,
+			   cairo_rectangle_int_t *extents)
+{
+    cairo_tee_surface_t *surface = abstract_surface;
+    return _cairo_surface_get_source (surface->master.target, extents);
+}
+
 static cairo_status_t
 _cairo_tee_surface_acquire_source_image (void	     *abstract_surface,
 					 cairo_image_surface_t **image_out,
@@ -389,6 +397,7 @@ static const cairo_surface_backend_t cairo_tee_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_tee_surface_source,
     _cairo_tee_surface_acquire_source_image,
     _cairo_tee_surface_release_source_image,
     _cairo_tee_surface_snapshot,
diff --git a/src/cairo-traps-compositor.c b/src/cairo-traps-compositor.c
index ac0a56f..4c05e80 100644
--- a/src/cairo-traps-compositor.c
+++ b/src/cairo-traps-compositor.c
@@ -1102,39 +1102,31 @@ upload_boxes (const cairo_traps_compositor_t *compositor,
 {
     cairo_surface_t *dst = extents->surface;
     const cairo_pattern_t *source = &extents->source_pattern.base;
-    const cairo_surface_pattern_t *pattern;
     cairo_surface_t *src;
     cairo_rectangle_int_t limit;
     cairo_int_status_t status;
     int tx, ty;
 
-    pattern = (const cairo_surface_pattern_t *) source;
-    src = pattern->surface;
+    src = _cairo_pattern_get_source((cairo_surface_pattern_t *)source,
+				    &limit);
     if (!(src->type == CAIRO_SURFACE_TYPE_IMAGE || src->type == dst->type))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
     if (! _cairo_matrix_is_integer_translation (&source->matrix, &tx, &ty))
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (_cairo_surface_is_snapshot (src))
-	src = _cairo_surface_snapshot_get_target (src);
-    if (_cairo_surface_is_observer (src))
-	src = _cairo_surface_observer_get_target (src);
-    if (_cairo_surface_is_subsurface (src)) {
-	_cairo_surface_subsurface_offset (src, &tx, &ty);
-	src = _cairo_surface_subsurface_get_target (src);
-    }
-
     /* Check that the data is entirely within the image */
-    if (extents->bounded.x + tx < 0 || extents->bounded.y + ty < 0)
+    if (extents->bounded.x + tx < limit.x || extents->bounded.y + ty < limit.y)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    _cairo_surface_get_extents (pattern->surface, &limit);
-    if (extents->bounded.x + extents->bounded.width  + tx > limit.width ||
-	extents->bounded.y + extents->bounded.height + ty > limit.height)
+    if (extents->bounded.x + extents->bounded.width  + tx > limit.x + limit.width ||
+	extents->bounded.y + extents->bounded.height + ty > limit.y + limit.height)
 	return CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (pattern->surface->type == CAIRO_SURFACE_TYPE_IMAGE)
+    tx += limit.x;
+    ty += limit.y;
+
+    if (src->type == CAIRO_SURFACE_TYPE_IMAGE)
 	status = compositor->draw_image_boxes (dst,
 					       (cairo_image_surface_t *)src,
 					       boxes, tx, ty);
diff --git a/src/cairo-type3-glyph-surface.c b/src/cairo-type3-glyph-surface.c
index ee2d0e3..5bb6bfc 100644
--- a/src/cairo-type3-glyph-surface.c
+++ b/src/cairo-type3-glyph-surface.c
@@ -331,6 +331,7 @@ static const cairo_surface_backend_t cairo_type3_glyph_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    NULL, /* source */
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* snapshot */
diff --git a/src/cairo-vg-surface.c b/src/cairo-vg-surface.c
index e285d6b..afbf7a0 100644
--- a/src/cairo-vg-surface.c
+++ b/src/cairo-vg-surface.c
@@ -1487,6 +1487,7 @@ static const cairo_surface_backend_t cairo_vg_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     _vg_surface_acquire_source_image,
     _vg_surface_release_source_image,
     NULL, /* snapshot */
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 931ae0f..17a68f7 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -1881,6 +1881,7 @@ static const cairo_surface_backend_t cairo_win32_printing_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* snapshot */
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index c7d3216..244abc0 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1937,6 +1937,7 @@ static const cairo_surface_backend_t cairo_win32_surface_backend = {
     _cairo_win32_surface_map_to_image,
     _cairo_win32_surface_unmap_image,
 
+    _cairo_surface_default_source,
     _cairo_win32_surface_acquire_source_image,
     _cairo_win32_surface_release_source_image,
     NULL,  /* snapshot */
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index aa2bbbf..9e2c665 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -457,6 +457,19 @@ FAIL:
     return _cairo_surface_create_in_error (status);
 }
 
+static cairo_surface_t *
+_cairo_xcb_surface_source (void *abstract_surface,
+			   cairo_rectangle_int_t *extents)
+{
+    cairo_xcb_surface_t *surface = abstract_surface;
+
+    extents->x = extents->y = 0;
+    extents->width  = surface->width;
+    extents->height = surface->height;
+
+    return &surface->base;
+}
+
 static cairo_status_t
 _cairo_xcb_surface_acquire_source_image (void *abstract_surface,
 					 cairo_image_surface_t **image_out,
@@ -1052,6 +1065,7 @@ const cairo_surface_backend_t _cairo_xcb_surface_backend = {
     _cairo_xcb_surface_map_to_image,
     _cairo_xcb_surface_unmap,
 
+    _cairo_xcb_surface_source,
     _cairo_xcb_surface_acquire_source_image,
     _cairo_xcb_surface_release_source_image,
     NULL, /* snapshot */
diff --git a/src/cairo-xlib-source.c b/src/cairo-xlib-source.c
index a098cf2..5498794 100644
--- a/src/cairo-xlib-source.c
+++ b/src/cairo-xlib-source.c
@@ -59,17 +59,10 @@
 #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
 
 static cairo_xlib_surface_t *
-unwrap_surface (cairo_surface_t *surface)
+unwrap_source (const cairo_surface_pattern_t *pattern)
 {
-    if (_cairo_surface_is_paginated (surface))
-	surface = _cairo_paginated_surface_get_recording (surface);
-    if (_cairo_surface_is_snapshot (surface))
-	surface = _cairo_surface_snapshot_get_target (surface);
-    if (_cairo_surface_is_subsurface (surface))
-	surface = _cairo_surface_subsurface_get_target (surface);
-    if (_cairo_surface_is_observer (surface))
-	surface = _cairo_surface_observer_get_target (surface);
-    return (cairo_xlib_surface_t *)surface;
+    cairo_rectangle_int_t limits;
+    return (cairo_xlib_surface_t *)_cairo_pattern_get_source (pattern, &limits);
 }
 
 static cairo_status_t
@@ -760,7 +753,7 @@ native_source (cairo_xlib_surface_t *dst,
 				  extents, sample,
 				  src_x, src_y);
 
-    src = unwrap_surface (pattern->surface);
+    src = unwrap_source (pattern);
 
     if (pattern->base.filter == CAIRO_FILTER_NEAREST &&
 	sample->x >= 0 && sample->y >= 0 &&
@@ -1037,7 +1030,7 @@ _cairo_xlib_source_create_for_pattern (cairo_surface_t *_dst,
 	    cairo_surface_pattern_t *spattern = (cairo_surface_pattern_t *)pattern;
 	    if (spattern->surface->type == CAIRO_SURFACE_TYPE_XLIB &&
 		_cairo_xlib_surface_same_screen (dst,
-						 unwrap_surface (spattern->surface)))
+						 unwrap_source (spattern)))
 		return native_source (dst, spattern, is_mask,
 				      extents, sample,
 				      src_x, src_y);
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index 5fb9185..71ddafb 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1224,6 +1224,19 @@ _cairo_xlib_surface_draw_image (cairo_xlib_surface_t   *surface,
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_surface_t *
+_cairo_xlib_surface_source(void                    *abstract_surface,
+			   cairo_rectangle_int_t *extents)
+{
+    cairo_xlib_surface_t *surface = abstract_surface;
+
+    extents->x = extents->y = 0;
+    extents->width  = surface->width;
+    extents->height = surface->height;
+
+    return &surface->base;
+}
+
 static cairo_status_t
 _cairo_xlib_surface_acquire_source_image (void                    *abstract_surface,
 					  cairo_image_surface_t  **image_out,
@@ -1400,6 +1413,7 @@ static const cairo_surface_backend_t cairo_xlib_surface_backend = {
     _cairo_xlib_surface_map_to_image,
     _cairo_xlib_surface_unmap_image,
 
+    _cairo_xlib_surface_source,
     _cairo_xlib_surface_acquire_source_image,
     _cairo_xlib_surface_release_source_image,
     _cairo_xlib_surface_snapshot,
diff --git a/src/cairo-xlib-xcb-surface.c b/src/cairo-xlib-xcb-surface.c
index 5021cfc..2002fc3 100644
--- a/src/cairo-xlib-xcb-surface.c
+++ b/src/cairo-xlib-xcb-surface.c
@@ -137,6 +137,14 @@ _cairo_xlib_xcb_surface_unmap (void *abstract_surface,
     return cairo_surface_status (&surface->xcb->base);
 }
 
+static cairo_surface_t *
+_cairo_xlib_xcb_surface_source (void *abstract_surface,
+				cairo_rectangle_int_t *extents)
+{
+    cairo_xlib_xcb_surface_t *surface = abstract_surface;
+    return _cairo_surface_get_source (&surface->cb->base, extents);
+}
+
 static cairo_status_t
 _cairo_xlib_xcb_surface_acquire_source_image (void *abstract_surface,
 					      cairo_image_surface_t **image_out,
@@ -275,6 +283,7 @@ static const cairo_surface_backend_t _cairo_xlib_xcb_surface_backend = {
     _cairo_xlib_xcb_surface_map_to_image,
     _cairo_xlib_xcb_surface_unmap,
 
+    _cairo_xlib_xcb_surface_source,
     _cairo_xlib_xcb_surface_acquire_source_image,
     _cairo_xlib_xcb_surface_release_source_image,
     NULL, /* snapshot */
diff --git a/src/cairo-xml-surface.c b/src/cairo-xml-surface.c
index dd9d3f6..a2e6a9f 100644
--- a/src/cairo-xml-surface.c
+++ b/src/cairo-xml-surface.c
@@ -1002,6 +1002,7 @@ _cairo_xml_surface_backend = {
     NULL, /* map_to_image */
     NULL, /* unmap_image */
 
+    _cairo_surface_default_source,
     NULL, /* acquire source image */
     NULL, /* release source image */
     NULL, /* snapshot */
diff --git a/src/drm/cairo-drm-gallium-surface.c b/src/drm/cairo-drm-gallium-surface.c
index b489753..aa3f45e 100644
--- a/src/drm/cairo-drm-gallium-surface.c
+++ b/src/drm/cairo-drm-gallium-surface.c
@@ -468,6 +468,7 @@ static const cairo_surface_backend_t gallium_surface_backend = {
     gallium_surface_create_similar,
     gallium_surface_finish,
 
+    NULL,
     gallium_surface_acquire_source_image,
     gallium_surface_release_source_image,
 
diff --git a/src/drm/cairo-drm-i915-surface.c b/src/drm/cairo-drm-i915-surface.c
index 2a55889..0200121 100644
--- a/src/drm/cairo-drm-i915-surface.c
+++ b/src/drm/cairo-drm-i915-surface.c
@@ -2343,6 +2343,8 @@ static const cairo_surface_backend_t i915_surface_backend = {
 
     i915_surface_create_similar,
     i915_surface_finish,
+
+    NULL,
     intel_surface_acquire_source_image,
     intel_surface_release_source_image,
 
diff --git a/src/drm/cairo-drm-i965-surface.c b/src/drm/cairo-drm-i965-surface.c
index 71061a0..0891c95 100644
--- a/src/drm/cairo-drm-i965-surface.c
+++ b/src/drm/cairo-drm-i965-surface.c
@@ -1495,6 +1495,8 @@ static const cairo_surface_backend_t i965_surface_backend = {
 
     i965_surface_create_similar,
     i965_surface_finish,
+
+    NULL,
     intel_surface_acquire_source_image,
     intel_surface_release_source_image,
 
diff --git a/src/drm/cairo-drm-intel-surface.c b/src/drm/cairo-drm-intel-surface.c
index f28c750..fe98759 100644
--- a/src/drm/cairo-drm-intel-surface.c
+++ b/src/drm/cairo-drm-intel-surface.c
@@ -253,8 +253,11 @@ static const cairo_surface_backend_t intel_surface_backend = {
 
     intel_surface_create_similar,
     intel_surface_finish,
+
+    NULL,
     intel_surface_acquire_source_image,
     intel_surface_release_source_image,
+
     NULL, NULL, NULL,
     NULL, /* composite */
     NULL, /* fill */
diff --git a/src/drm/cairo-drm-radeon-surface.c b/src/drm/cairo-drm-radeon-surface.c
index 9335d7b..9f46ca1 100644
--- a/src/drm/cairo-drm-radeon-surface.c
+++ b/src/drm/cairo-drm-radeon-surface.c
@@ -257,8 +257,11 @@ static const cairo_surface_backend_t radeon_surface_backend = {
 
     radeon_surface_create_similar,
     radeon_surface_finish,
+
+    NULL,
     radeon_surface_acquire_source_image,
     radeon_surface_release_source_image,
+
     NULL, NULL, NULL,
     NULL, /* composite */
     NULL, /* fill */
diff --git a/src/test-compositor-surface.c b/src/test-compositor-surface.c
index 356c16c..ddee06f 100644
--- a/src/test-compositor-surface.c
+++ b/src/test-compositor-surface.c
@@ -195,6 +195,7 @@ static const cairo_surface_backend_t test_compositor_surface_backend = {
     _cairo_image_surface_map_to_image,
     _cairo_image_surface_unmap_image,
 
+    _cairo_image_surface_source,
     _cairo_image_surface_acquire_source_image,
     _cairo_image_surface_release_source_image,
     _cairo_image_surface_snapshot,
diff --git a/src/test-null-compositor-surface.c b/src/test-null-compositor-surface.c
index e94c8a7..9516155 100644
--- a/src/test-null-compositor-surface.c
+++ b/src/test-null-compositor-surface.c
@@ -198,6 +198,7 @@ static const cairo_surface_backend_t test_compositor_surface_backend = {
     _cairo_image_surface_map_to_image,
     _cairo_image_surface_unmap_image,
 
+    _cairo_image_surface_source,
     _cairo_image_surface_acquire_source_image,
     _cairo_image_surface_release_source_image,
     NULL, /* snapshot */
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index e3c8a91..0a7c79b 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -253,6 +253,7 @@ static const cairo_surface_backend_t test_paginated_surface_backend = {
     NULL, /* map to image */
     NULL, /* unmap image */
 
+    _cairo_surface_default_source,
     NULL, /* acquire_source_image */
     NULL, /* release_source_image */
     NULL, /* snapshot */


More information about the cairo-commit mailing list