michael@0: # HG changeset patch michael@0: # User Robert O'Callahan michael@0: # Date 1294019288 -46800 michael@0: # Node ID bacc54d452a9fddb5a0d6a1442ec7be4de81ffa7 michael@0: # Parent ccba8826be1451d0e61d0df38363dadffb20ba48 michael@0: Bug 593604. Part 2: When compositing a tee surface into another tee surface, try to compose the subsurfaces pointwise. r=jrmuizel,a=blocking michael@0: michael@0: diff --git a/gfx/cairo/cairo/src/cairo-tee-surface.c b/gfx/cairo/cairo/src/cairo-tee-surface.c michael@0: --- a/gfx/cairo/cairo/src/cairo-tee-surface.c michael@0: +++ b/gfx/cairo/cairo/src/cairo-tee-surface.c michael@0: @@ -186,35 +186,72 @@ static void michael@0: _cairo_tee_surface_get_font_options (void *abstract_surface, michael@0: cairo_font_options_t *options) michael@0: { michael@0: cairo_tee_surface_t *surface = abstract_surface; michael@0: michael@0: _cairo_surface_wrapper_get_font_options (&surface->master, options); michael@0: } michael@0: michael@0: +static const cairo_pattern_t * michael@0: +_cairo_tee_surface_match_source (cairo_tee_surface_t *surface, michael@0: + const cairo_pattern_t *source, michael@0: + int index, michael@0: + cairo_surface_wrapper_t *dest, michael@0: + cairo_surface_pattern_t *temp) michael@0: +{ michael@0: + cairo_surface_t *s; michael@0: + cairo_status_t status = cairo_pattern_get_surface ((cairo_pattern_t *)source, &s); michael@0: + if (status == CAIRO_STATUS_SUCCESS && michael@0: + cairo_surface_get_type (s) == CAIRO_SURFACE_TYPE_TEE) { michael@0: + cairo_surface_t *tee_surf = cairo_tee_surface_index (s, index); michael@0: + if (tee_surf->status == CAIRO_STATUS_SUCCESS && michael@0: + tee_surf->backend == dest->target->backend) { michael@0: + status = _cairo_pattern_init_copy (&temp->base, source); michael@0: + if (status == CAIRO_STATUS_SUCCESS) { michael@0: + cairo_surface_destroy (temp->surface); michael@0: + temp->surface = tee_surf; michael@0: + cairo_surface_reference (temp->surface); michael@0: + return &temp->base; michael@0: + } michael@0: + } michael@0: + } michael@0: + michael@0: + return source; michael@0: +} michael@0: + michael@0: static cairo_int_status_t michael@0: _cairo_tee_surface_paint (void *abstract_surface, michael@0: cairo_operator_t op, michael@0: const cairo_pattern_t *source, michael@0: cairo_clip_t *clip) michael@0: { michael@0: cairo_tee_surface_t *surface = abstract_surface; michael@0: cairo_surface_wrapper_t *slaves; michael@0: int n, num_slaves; michael@0: cairo_status_t status; michael@0: + const cairo_pattern_t *matched_source; michael@0: + cairo_surface_pattern_t temp; michael@0: michael@0: - status = _cairo_surface_wrapper_paint (&surface->master, op, source, clip); michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp); michael@0: + status = _cairo_surface_wrapper_paint (&surface->master, op, matched_source, clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: return status; michael@0: michael@0: num_slaves = _cairo_array_num_elements (&surface->slaves); michael@0: slaves = _cairo_array_index (&surface->slaves, 0); michael@0: for (n = 0; n < num_slaves; n++) { michael@0: - status = _cairo_surface_wrapper_paint (&slaves[n], op, source, clip); michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp); michael@0: + status = _cairo_surface_wrapper_paint (&slaves[n], op, matched_source, clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: return status; michael@0: } michael@0: michael@0: return CAIRO_STATUS_SUCCESS; michael@0: } michael@0: michael@0: static cairo_int_status_t michael@0: @@ -223,27 +260,37 @@ _cairo_tee_surface_mask (void *abstrac michael@0: const cairo_pattern_t *source, michael@0: const cairo_pattern_t *mask, michael@0: cairo_clip_t *clip) michael@0: { michael@0: cairo_tee_surface_t *surface = abstract_surface; michael@0: cairo_surface_wrapper_t *slaves; michael@0: int n, num_slaves; michael@0: cairo_status_t status; michael@0: + const cairo_pattern_t *matched_source; michael@0: + cairo_surface_pattern_t temp; michael@0: michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp); michael@0: status = _cairo_surface_wrapper_mask (&surface->master, michael@0: - op, source, mask, clip); michael@0: + op, matched_source, mask, clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: return status; michael@0: michael@0: num_slaves = _cairo_array_num_elements (&surface->slaves); michael@0: slaves = _cairo_array_index (&surface->slaves, 0); michael@0: for (n = 0; n < num_slaves; n++) { michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp); michael@0: status = _cairo_surface_wrapper_mask (&slaves[n], michael@0: - op, source, mask, clip); michael@0: + op, matched_source, mask, clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: return status; michael@0: } michael@0: michael@0: return CAIRO_STATUS_SUCCESS; michael@0: } michael@0: michael@0: static cairo_int_status_t michael@0: @@ -257,35 +304,45 @@ _cairo_tee_surface_stroke (void *abst michael@0: double tolerance, michael@0: cairo_antialias_t antialias, michael@0: cairo_clip_t *clip) michael@0: { michael@0: cairo_tee_surface_t *surface = abstract_surface; michael@0: cairo_surface_wrapper_t *slaves; michael@0: int n, num_slaves; michael@0: cairo_status_t status; michael@0: + const cairo_pattern_t *matched_source; michael@0: + cairo_surface_pattern_t temp; michael@0: michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp); michael@0: status = _cairo_surface_wrapper_stroke (&surface->master, michael@0: - op, source, michael@0: + op, matched_source, michael@0: path, style, michael@0: ctm, ctm_inverse, michael@0: tolerance, antialias, michael@0: clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: return status; michael@0: michael@0: num_slaves = _cairo_array_num_elements (&surface->slaves); michael@0: slaves = _cairo_array_index (&surface->slaves, 0); michael@0: for (n = 0; n < num_slaves; n++) { michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp); michael@0: status = _cairo_surface_wrapper_stroke (&slaves[n], michael@0: - op, source, michael@0: + op, matched_source, michael@0: path, style, michael@0: ctm, ctm_inverse, michael@0: tolerance, antialias, michael@0: clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: return status; michael@0: } michael@0: michael@0: return CAIRO_STATUS_SUCCESS; michael@0: } michael@0: michael@0: static cairo_int_status_t michael@0: @@ -297,33 +354,43 @@ _cairo_tee_surface_fill (void *abstra michael@0: double tolerance, michael@0: cairo_antialias_t antialias, michael@0: cairo_clip_t *clip) michael@0: { michael@0: cairo_tee_surface_t *surface = abstract_surface; michael@0: cairo_surface_wrapper_t *slaves; michael@0: int n, num_slaves; michael@0: cairo_status_t status; michael@0: + const cairo_pattern_t *matched_source; michael@0: + cairo_surface_pattern_t temp; michael@0: michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp); michael@0: status = _cairo_surface_wrapper_fill (&surface->master, michael@0: - op, source, michael@0: + op, matched_source, michael@0: path, fill_rule, michael@0: tolerance, antialias, michael@0: clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: return status; michael@0: michael@0: num_slaves = _cairo_array_num_elements (&surface->slaves); michael@0: slaves = _cairo_array_index (&surface->slaves, 0); michael@0: for (n = 0; n < num_slaves; n++) { michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp); michael@0: status = _cairo_surface_wrapper_fill (&slaves[n], michael@0: - op, source, michael@0: + op, matched_source, michael@0: path, fill_rule, michael@0: tolerance, antialias, michael@0: clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: return status; michael@0: } michael@0: michael@0: return CAIRO_STATUS_SUCCESS; michael@0: } michael@0: michael@0: static cairo_bool_t michael@0: @@ -346,46 +413,56 @@ _cairo_tee_surface_show_text_glyphs (voi michael@0: cairo_scaled_font_t *scaled_font, michael@0: cairo_clip_t *clip) michael@0: { michael@0: cairo_tee_surface_t *surface = abstract_surface; michael@0: cairo_surface_wrapper_t *slaves; michael@0: int n, num_slaves; michael@0: cairo_status_t status; michael@0: cairo_glyph_t *glyphs_copy; michael@0: + const cairo_pattern_t *matched_source; michael@0: + cairo_surface_pattern_t temp; michael@0: michael@0: /* XXX: This copying is ugly. */ michael@0: glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); michael@0: if (unlikely (glyphs_copy == NULL)) michael@0: return _cairo_error (CAIRO_STATUS_NO_MEMORY); michael@0: michael@0: memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp); michael@0: status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, op, michael@0: - source, michael@0: + matched_source, michael@0: utf8, utf8_len, michael@0: glyphs_copy, num_glyphs, michael@0: clusters, num_clusters, michael@0: cluster_flags, michael@0: scaled_font, michael@0: clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: goto CLEANUP; michael@0: michael@0: num_slaves = _cairo_array_num_elements (&surface->slaves); michael@0: slaves = _cairo_array_index (&surface->slaves, 0); michael@0: for (n = 0; n < num_slaves; n++) { michael@0: memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); michael@0: + matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp); michael@0: status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op, michael@0: - source, michael@0: + matched_source, michael@0: utf8, utf8_len, michael@0: glyphs_copy, num_glyphs, michael@0: clusters, num_clusters, michael@0: cluster_flags, michael@0: scaled_font, michael@0: clip); michael@0: + if (matched_source == &temp.base) { michael@0: + _cairo_pattern_fini (&temp.base); michael@0: + } michael@0: if (unlikely (status)) michael@0: goto CLEANUP; michael@0: } michael@0: michael@0: CLEANUP: michael@0: free (glyphs_copy); michael@0: return status; michael@0: }