[cairo] [patch] quartz: fix crash in recordxx-xxx cases

Henry (Yu) Song - SISA hsong at sisa.samsung.com
Mon Jul 23 09:28:28 PDT 2012


commit c7b6c6e7c163a7f7a8ee6005951bdc4f4c5294cb
Author: Henry Song <henry.song at samsung.com>
Date:   Mon Jul 23 09:00:17 2012 -0700

    quartz: we need to replay if the source/mask surface is recording surface
    otherwise, the source/mask surface can be unbounded.

diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 7c8c453..28bdae6 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -47,6 +47,7 @@
 #include "cairo-pattern-private.h"
 #include "cairo-surface-backend-private.h"
 #include "cairo-surface-clipper-private.h"
+#include "cairo-recording-surface-private.h"
 
 #include <dlfcn.h>
 
@@ -782,11 +783,15 @@ DataProviderReleaseCallback (void *info, const void *data, size_t size)
 }
 
 static cairo_status_t
-_cairo_surface_to_cgimage (cairo_surface_t *source,
-			   CGImageRef *image_out)
+_cairo_surface_to_cgimage (cairo_surface_t	 *source,
+			   cairo_rectangle_int_t *extents,
+			   cairo_format_t	 format,
+			   const cairo_clip_t 	 *clip, 
+			   CGImageRef		 *image_out)
 {
     cairo_status_t status;
     quartz_source_image_t *source_img;
+    cairo_image_surface_t *image_surface;
 
     if (source->backend && source->backend->type == CAIRO_SURFACE_TYPE_QUARTZ_IMAGE) {
 	cairo_quartz_image_surface_t *surface = (cairo_quartz_image_surface_t *) source;
@@ -814,10 +819,37 @@ _cairo_surface_to_cgimage (cairo_surface_t *source,
 
     source_img->surface = source;
 
-    status = _cairo_surface_acquire_source_image (source_img->surface, &source_img->image_out, &source_img->image_extra);
-    if (unlikely (status)) {
-	free (source_img);
-	return status;
+    if (source->type == CAIRO_SURFACE_TYPE_RECORDING) {
+	image_surface = (cairo_image_surface_t *) 
+	    cairo_image_surface_create (format, extents->width, extents->height);
+	if (unlikely (image_surface->base.status)) {
+	    status = image_surface->base.status;
+	    cairo_surface_destroy (&image_surface->base);
+	    free (source_img);
+	    return status;
+	}
+
+	status = _cairo_recording_surface_replay_with_clip (source, 
+							    NULL,
+							    &image_surface->base,
+							    NULL);
+	if (unlikely (status)) {
+	    cairo_surface_destroy (&image_surface->base);
+	    free (source_img);
+	    return status;
+	}
+ 	
+	source_img->image_out = image_surface;
+	source_img->image_extra = NULL;
+    } 
+    else {
+	status = _cairo_surface_acquire_source_image (source_img->surface, 
+						      &source_img->image_out, 
+						      &source_img->image_extra);
+	if (unlikely (status)) {
+	    free (source_img);
+	    return status;
+	}
     }
 
     if (source_img->image_out->width == 0 || source_img->image_out->height == 0) {
@@ -897,11 +929,13 @@ SurfacePatternReleaseInfoFunc (void *ainfo)
 static cairo_int_status_t
 _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t *dest,
 							 const cairo_pattern_t *apattern,
+							 const cairo_clip_t *clip,
 							 CGPatternRef *cgpat)
 {
     cairo_surface_pattern_t *spattern;
     cairo_surface_t *pat_surf;
     cairo_rectangle_int_t extents;
+    cairo_format_t format = _cairo_format_from_content (dest->base.content);
 
     CGImageRef image;
     CGRect pbounds;
@@ -922,10 +956,15 @@ _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (cairo_quartz_surface_t
     spattern = (cairo_surface_pattern_t *) apattern;
     pat_surf = spattern->surface;
 
-    is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
-    assert (is_bounded);
+    if (pat_surf->type != CAIRO_SURFACE_TYPE_RECORDING) {
+	is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
+	assert (is_bounded);
+    }
+    else
+	_cairo_surface_get_extents (&dest->base, &extents);
 
-    status = _cairo_surface_to_cgimage (pat_surf, &image);
+    status = _cairo_surface_to_cgimage (pat_surf, &extents, format, 
+					clip, &image);
     if (unlikely (status))
 	return status;
 
@@ -1084,14 +1123,15 @@ _cairo_quartz_setup_gradient_source (cairo_quartz_drawing_state_t *state,
 
 static cairo_int_status_t
 _cairo_quartz_setup_state (cairo_quartz_drawing_state_t *state,
-			   cairo_composite_rectangles_t *extents)
+			   cairo_composite_rectangles_t *composite)
 {
-    cairo_quartz_surface_t       *surface = (cairo_quartz_surface_t *) extents->surface;
-    cairo_operator_t              op = extents->op;
-    const cairo_pattern_t        *source = &extents->source_pattern.base;
-    const cairo_clip_t           *clip = extents->clip;
+    cairo_quartz_surface_t       *surface = (cairo_quartz_surface_t *) composite->surface;
+    cairo_operator_t              op = composite->op;
+    const cairo_pattern_t        *source = &composite->source_pattern.base;
+    const cairo_clip_t           *clip = composite->clip;
     cairo_bool_t needs_temp;
     cairo_status_t status;
+    cairo_format_t format = _cairo_format_from_content (composite->surface->content);
 
     state->layer = NULL;
     state->image = NULL;
@@ -1205,7 +1245,9 @@ _cairo_quartz_setup_state (cairo_quartz_drawing_state_t *state,
 	cairo_fixed_t fw, fh;
 	cairo_bool_t is_bounded;
 
-	status = _cairo_surface_to_cgimage (pat_surf, &img);
+	_cairo_surface_get_extents (composite->surface, &extents);
+	status = _cairo_surface_to_cgimage (pat_surf, &extents, format,  
+					    clip, &img);
 	if (unlikely (status))
 	    return status;
 
@@ -1220,8 +1262,10 @@ _cairo_quartz_setup_state (cairo_quartz_drawing_state_t *state,
 
 	_cairo_quartz_cairo_matrix_to_quartz (&m, &state->transform);
 
-	is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
-	assert (is_bounded);
+	if (pat_surf->type != CAIRO_SURFACE_TYPE_RECORDING) {
+	    is_bounded = _cairo_surface_get_extents (pat_surf, &extents);
+	    assert (is_bounded);
+	}
 
 	srcRect = CGRectMake (0, 0, extents.width, extents.height);
 
@@ -1291,7 +1335,7 @@ _cairo_quartz_setup_state (cairo_quartz_drawing_state_t *state,
 	CGPatternRef pattern = NULL;
 	cairo_int_status_t status;
 
-	status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, &pattern);
+	status = _cairo_quartz_cairo_repeating_surface_pattern_to_quartz (surface, source, clip, &pattern);
 	if (unlikely (status))
 	    return status;
 
@@ -1604,8 +1648,12 @@ _cairo_quartz_cg_mask_with_surface (cairo_composite_rectangles_t *extents,
     cairo_status_t status;
     CGAffineTransform mask_matrix;
     cairo_quartz_drawing_state_t state;
+    cairo_format_t format = _cairo_format_from_content (extents->surface->content);
+    cairo_rectangle_int_t dest_extents;
 
-    status = _cairo_surface_to_cgimage (mask_surf, &img);
+    _cairo_surface_get_extents (extents->surface, &dest_extents);
+    status = _cairo_surface_to_cgimage (mask_surf, &dest_extents, format, 
+					extents->clip, &img);
     if (unlikely (status))
 	return status;
 


More information about the cairo mailing list