Bug 593604. cairo patch for changeset bacc54d452a9l a=NPOTB
authorRobert O'Callahan <robert@ocallahan.org>
Wed, 19 Jan 2011 21:27:54 +1300
changeset 60854 2cd4d1dfc0a5af0b2828589699c5853c2fd4e098
parent 60853 756269dfadeeb9111420453220e79c2dc8fc7072
child 60855 8b3806faa4b69c8ea87bbb5afa3ae8959067d4fe
push idunknown
push userunknown
push dateunknown
reviewersNPOTB
bugs593604
milestone2.0b10pre
Bug 593604. cairo patch for changeset bacc54d452a9l a=NPOTB
gfx/cairo/README
gfx/cairo/tee-surfaces-pointwise.patch
--- a/gfx/cairo/README
+++ b/gfx/cairo/README
@@ -153,16 +153,18 @@ quartz-mask-non-OVER.patch: Don't use CG
 quartz-layers-content.patch: Store cairo content type in CGLayer surfaces
 
 quartz-optimize-OVER.patch: Optimize OVER to SOURCE for opaque patterns
 
 quartz-check-imageSurfaceEquiv.patch: Drop cairo_quartz_surface_t's "imageSurfaceEquiv" member variable if we have problems creating it
 
 disable-subpixel-antialiasing.patch: Add API to disable subpixel antialiasing completely for a target surface
 
+tee-surfaces-pointwise.patch: Composite tee subsurfaces pointwise if possible
+
 ==== pixman patches ====
 
 pixman-android-cpu-detect.patch: Add CPU detection support for Android, where we can't reliably access /proc/self/auxv.
 
 pixman-rename-and-endian.patch: include cairo-platform.h for renaming of external symbols and endian macros
 
 NOTE: we previously supported ARM assembler on MSVC, this has been removed because of the maintenance burden
 
new file mode 100644
--- /dev/null
+++ b/gfx/cairo/tee-surfaces-pointwise.patch
@@ -0,0 +1,278 @@
+# HG changeset patch
+# User Robert O'Callahan <robert@ocallahan.org>
+# Date 1294019288 -46800
+# Node ID bacc54d452a9fddb5a0d6a1442ec7be4de81ffa7
+# Parent  ccba8826be1451d0e61d0df38363dadffb20ba48
+Bug 593604. Part 2: When compositing a tee surface into another tee surface, try to compose the subsurfaces pointwise. r=jrmuizel,a=blocking
+
+diff --git a/gfx/cairo/cairo/src/cairo-tee-surface.c b/gfx/cairo/cairo/src/cairo-tee-surface.c
+--- a/gfx/cairo/cairo/src/cairo-tee-surface.c
++++ b/gfx/cairo/cairo/src/cairo-tee-surface.c
+@@ -186,35 +186,72 @@ static void
+ _cairo_tee_surface_get_font_options (void                  *abstract_surface,
+ 				     cairo_font_options_t  *options)
+ {
+     cairo_tee_surface_t *surface = abstract_surface;
+ 
+     _cairo_surface_wrapper_get_font_options (&surface->master, options);
+ }
+ 
++static const cairo_pattern_t *
++_cairo_tee_surface_match_source (cairo_tee_surface_t *surface,
++                                 const cairo_pattern_t *source,
++                                 int index,
++                                 cairo_surface_wrapper_t *dest,
++                                 cairo_surface_pattern_t *temp)
++{
++    cairo_surface_t *s;
++    cairo_status_t status = cairo_pattern_get_surface ((cairo_pattern_t *)source, &s);
++    if (status == CAIRO_STATUS_SUCCESS &&
++        cairo_surface_get_type (s) == CAIRO_SURFACE_TYPE_TEE) {
++        cairo_surface_t *tee_surf = cairo_tee_surface_index (s, index);
++        if (tee_surf->status == CAIRO_STATUS_SUCCESS &&
++            tee_surf->backend == dest->target->backend) {
++            status = _cairo_pattern_init_copy (&temp->base, source);
++            if (status == CAIRO_STATUS_SUCCESS) {
++                cairo_surface_destroy (temp->surface);
++                temp->surface = tee_surf;
++                cairo_surface_reference (temp->surface);
++                return &temp->base;
++            }
++        }
++    }
++
++    return source;
++}
++
+ static cairo_int_status_t
+ _cairo_tee_surface_paint (void			*abstract_surface,
+ 			  cairo_operator_t	 op,
+ 			  const cairo_pattern_t	*source,
+ 			  cairo_clip_t		*clip)
+ {
+     cairo_tee_surface_t *surface = abstract_surface;
+     cairo_surface_wrapper_t *slaves;
+     int n, num_slaves;
+     cairo_status_t status;
++    const cairo_pattern_t *matched_source;
++    cairo_surface_pattern_t temp;
+ 
+-    status = _cairo_surface_wrapper_paint (&surface->master, op, source, clip);
++    matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
++    status = _cairo_surface_wrapper_paint (&surface->master, op, matched_source, clip);
++    if (matched_source == &temp.base) {
++        _cairo_pattern_fini (&temp.base);
++    }
+     if (unlikely (status))
+ 	return status;
+ 
+     num_slaves = _cairo_array_num_elements (&surface->slaves);
+     slaves = _cairo_array_index (&surface->slaves, 0);
+     for (n = 0; n < num_slaves; n++) {
+-	status = _cairo_surface_wrapper_paint (&slaves[n], op, source, clip);
++        matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
++	status = _cairo_surface_wrapper_paint (&slaves[n], op, matched_source, clip);
++        if (matched_source == &temp.base) {
++            _cairo_pattern_fini (&temp.base);
++        }
+ 	if (unlikely (status))
+ 	    return status;
+     }
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_int_status_t
+@@ -223,27 +260,37 @@ _cairo_tee_surface_mask (void			*abstrac
+ 			 const cairo_pattern_t	*source,
+ 			 const cairo_pattern_t	*mask,
+ 			 cairo_clip_t		*clip)
+ {
+     cairo_tee_surface_t *surface = abstract_surface;
+     cairo_surface_wrapper_t *slaves;
+     int n, num_slaves;
+     cairo_status_t status;
++    const cairo_pattern_t *matched_source;
++    cairo_surface_pattern_t temp;
+ 
++    matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
+     status = _cairo_surface_wrapper_mask (&surface->master,
+-					  op, source, mask, clip);
++					  op, matched_source, mask, clip);
++    if (matched_source == &temp.base) {
++        _cairo_pattern_fini (&temp.base);
++    }
+     if (unlikely (status))
+ 	return status;
+ 
+     num_slaves = _cairo_array_num_elements (&surface->slaves);
+     slaves = _cairo_array_index (&surface->slaves, 0);
+     for (n = 0; n < num_slaves; n++) {
++        matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
+ 	status = _cairo_surface_wrapper_mask (&slaves[n],
+-					      op, source, mask, clip);
++					      op, matched_source, mask, clip);
++        if (matched_source == &temp.base) {
++            _cairo_pattern_fini (&temp.base);
++        }
+ 	if (unlikely (status))
+ 	    return status;
+     }
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_int_status_t
+@@ -257,35 +304,45 @@ _cairo_tee_surface_stroke (void				*abst
+ 			   double			 tolerance,
+ 			   cairo_antialias_t		 antialias,
+ 			   cairo_clip_t			*clip)
+ {
+     cairo_tee_surface_t *surface = abstract_surface;
+     cairo_surface_wrapper_t *slaves;
+     int n, num_slaves;
+     cairo_status_t status;
++    const cairo_pattern_t *matched_source;
++    cairo_surface_pattern_t temp;
+ 
++    matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
+     status = _cairo_surface_wrapper_stroke (&surface->master,
+-					    op, source,
++					    op, matched_source,
+ 					    path, style,
+ 					    ctm, ctm_inverse,
+ 					    tolerance, antialias,
+ 					    clip);
++    if (matched_source == &temp.base) {
++        _cairo_pattern_fini (&temp.base);
++    }
+     if (unlikely (status))
+ 	return status;
+ 
+     num_slaves = _cairo_array_num_elements (&surface->slaves);
+     slaves = _cairo_array_index (&surface->slaves, 0);
+     for (n = 0; n < num_slaves; n++) {
++        matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
+ 	status = _cairo_surface_wrapper_stroke (&slaves[n],
+-						op, source,
++						op, matched_source,
+ 						path, style,
+ 						ctm, ctm_inverse,
+ 						tolerance, antialias,
+ 						clip);
++        if (matched_source == &temp.base) {
++            _cairo_pattern_fini (&temp.base);
++        }
+ 	if (unlikely (status))
+ 	    return status;
+     }
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_int_status_t
+@@ -297,33 +354,43 @@ _cairo_tee_surface_fill (void				*abstra
+ 			 double				 tolerance,
+ 			 cairo_antialias_t		 antialias,
+ 			 cairo_clip_t			*clip)
+ {
+     cairo_tee_surface_t *surface = abstract_surface;
+     cairo_surface_wrapper_t *slaves;
+     int n, num_slaves;
+     cairo_status_t status;
++    const cairo_pattern_t *matched_source;
++    cairo_surface_pattern_t temp;
+ 
++    matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
+     status = _cairo_surface_wrapper_fill (&surface->master,
+-					  op, source,
++					  op, matched_source,
+ 					  path, fill_rule,
+ 					  tolerance, antialias,
+ 					  clip);
++    if (matched_source == &temp.base) {
++        _cairo_pattern_fini (&temp.base);
++    }
+     if (unlikely (status))
+ 	return status;
+ 
+     num_slaves = _cairo_array_num_elements (&surface->slaves);
+     slaves = _cairo_array_index (&surface->slaves, 0);
+     for (n = 0; n < num_slaves; n++) {
++        matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
+ 	status = _cairo_surface_wrapper_fill (&slaves[n],
+-					      op, source,
++					      op, matched_source,
+ 					      path, fill_rule,
+ 					      tolerance, antialias,
+ 					      clip);
++        if (matched_source == &temp.base) {
++            _cairo_pattern_fini (&temp.base);
++        }
+ 	if (unlikely (status))
+ 	    return status;
+     }
+ 
+     return CAIRO_STATUS_SUCCESS;
+ }
+ 
+ static cairo_bool_t
+@@ -346,46 +413,56 @@ _cairo_tee_surface_show_text_glyphs (voi
+ 				     cairo_scaled_font_t    *scaled_font,
+ 				     cairo_clip_t	    *clip)
+ {
+     cairo_tee_surface_t *surface = abstract_surface;
+     cairo_surface_wrapper_t *slaves;
+     int n, num_slaves;
+     cairo_status_t status;
+     cairo_glyph_t *glyphs_copy;
++    const cairo_pattern_t *matched_source;
++    cairo_surface_pattern_t temp;
+ 
+     /* XXX: This copying is ugly. */
+     glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
+     if (unlikely (glyphs_copy == NULL))
+ 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ 
+     memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
++    matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
+     status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, op,
+-						      source,
++                              matched_source,
+ 						      utf8, utf8_len,
+ 						      glyphs_copy, num_glyphs,
+ 						      clusters, num_clusters,
+ 						      cluster_flags,
+ 						      scaled_font,
+ 						      clip);
++    if (matched_source == &temp.base) {
++        _cairo_pattern_fini (&temp.base);
++    }
+     if (unlikely (status))
+ 	goto CLEANUP;
+ 
+     num_slaves = _cairo_array_num_elements (&surface->slaves);
+     slaves = _cairo_array_index (&surface->slaves, 0);
+     for (n = 0; n < num_slaves; n++) {
+ 	memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
++      matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
+ 	status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op,
+-							  source,
++	                          matched_source,
+ 							  utf8, utf8_len,
+ 							  glyphs_copy, num_glyphs,
+ 							  clusters, num_clusters,
+ 							  cluster_flags,
+ 							  scaled_font,
+ 							  clip);
++        if (matched_source == &temp.base) {
++            _cairo_pattern_fini (&temp.base);
++        }
+ 	if (unlikely (status))
+ 	    goto CLEANUP;
+     }
+ 
+   CLEANUP:
+     free (glyphs_copy);
+     return status;
+ }