diff options
author | Chris Wilson <chris@chris-wilson.co.uk> | 2010-04-28 14:26:21 +0100 |
---|---|---|
committer | Chris Wilson <chris@chris-wilson.co.uk> | 2010-04-30 10:16:24 +0100 |
commit | 8ded35fd69ed0bbb07359c0278071a25af66571c (patch) | |
tree | e6b44acf234b3399306240600c29f470e6045e92 /src/cairo-surface-wrapper.c | |
parent | 5fc04bba9fa8ddda8cf7d7a97015f21a21429172 (diff) | |
download | cairo-8ded35fd69ed0bbb07359c0278071a25af66571c.tar.gz |
ps: Enable native encoding of subsurface patterns.
Carefully handle subsurfaces of a recording surface through the analysis
and paginated surfaces so that we can generate a native pattern for the
vector backends, demonstrated by the PostScript backend.
Nothing remarkable, just a lot of bookkeeping to track the wrapped
surface types and to apply the correct offsets when generating the
subsurface pattern.
Diffstat (limited to 'src/cairo-surface-wrapper.c')
-rw-r--r-- | src/cairo-surface-wrapper.c | 314 |
1 files changed, 257 insertions, 57 deletions
diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c index c0d9672bb..39e90f08f 100644 --- a/src/cairo-surface-wrapper.c +++ b/src/cairo-surface-wrapper.c @@ -71,6 +71,12 @@ _cairo_surface_wrapper_needs_device_transform (cairo_surface_wrapper_t *wrapper) return ! _cairo_matrix_is_identity (&wrapper->target->device_transform); } +static cairo_bool_t +_cairo_surface_wrapper_needs_extents_transform (cairo_surface_wrapper_t *wrapper) +{ + return wrapper->has_extents && (wrapper->extents.x | wrapper->extents.y); +} + cairo_status_t _cairo_surface_wrapper_acquire_source_image (cairo_surface_wrapper_t *wrapper, cairo_image_surface_t **image_out, @@ -100,30 +106,58 @@ _cairo_surface_wrapper_paint (cairo_surface_wrapper_t *wrapper, cairo_status_t status; cairo_clip_t clip_copy, *dev_clip = clip; cairo_pattern_union_t source_copy; + cairo_clip_t target_clip; if (unlikely (wrapper->target->status)) return wrapper->target->status; - if (clip && clip->all_clipped) - return CAIRO_STATUS_SUCCESS; + if (wrapper->has_extents) { + _cairo_clip_init_copy (&target_clip, clip); + status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); + if (unlikely (status)) + goto FINISH; + + dev_clip = clip = &target_clip; + } + + if (clip && clip->all_clipped) { + status = CAIRO_STATUS_SUCCESS; + goto FINISH; + } + + if (_cairo_surface_wrapper_needs_device_transform (wrapper) || + _cairo_surface_wrapper_needs_extents_transform (wrapper)) + { + cairo_matrix_t m; + + cairo_matrix_init_identity (&m); + + if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) + cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); + + if (_cairo_surface_wrapper_needs_device_transform (wrapper)) + cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) { if (clip != NULL) { - status = _cairo_clip_init_copy_transformed (&clip_copy, clip, - &wrapper->target->device_transform); + status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); if (unlikely (status)) goto FINISH; dev_clip = &clip_copy; } - _copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse); + status = cairo_matrix_invert (&m); + assert (status == CAIRO_STATUS_SUCCESS); + + _copy_transformed_pattern (&source_copy.base, source, &m); source = &source_copy.base; } status = _cairo_surface_paint (wrapper->target, op, source, dev_clip); FINISH: + if (wrapper->has_extents) + _cairo_clip_reset (&target_clip); if (dev_clip != clip) _cairo_clip_reset (dev_clip); return status; @@ -140,33 +174,61 @@ _cairo_surface_wrapper_mask (cairo_surface_wrapper_t *wrapper, cairo_clip_t clip_copy, *dev_clip = clip; cairo_pattern_union_t source_copy; cairo_pattern_union_t mask_copy; + cairo_clip_t target_clip; if (unlikely (wrapper->target->status)) return wrapper->target->status; - if (clip && clip->all_clipped) - return CAIRO_STATUS_SUCCESS; + if (wrapper->has_extents) { + _cairo_clip_init_copy (&target_clip, clip); + status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); + if (unlikely (status)) + goto FINISH; + + dev_clip = clip = &target_clip; + } + + if (clip && clip->all_clipped) { + status = CAIRO_STATUS_SUCCESS; + goto FINISH; + } + + if (_cairo_surface_wrapper_needs_device_transform (wrapper) || + _cairo_surface_wrapper_needs_extents_transform (wrapper)) + { + cairo_matrix_t m; + + cairo_matrix_init_identity (&m); + + if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) + cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); + + if (_cairo_surface_wrapper_needs_device_transform (wrapper)) + cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) { if (clip != NULL) { - status = _cairo_clip_init_copy_transformed (&clip_copy, clip, - &wrapper->target->device_transform); + status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); if (unlikely (status)) goto FINISH; dev_clip = &clip_copy; } - _copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse); + status = cairo_matrix_invert (&m); + assert (status == CAIRO_STATUS_SUCCESS); + + _copy_transformed_pattern (&source_copy.base, source, &m); source = &source_copy.base; - _copy_transformed_pattern (&mask_copy.base, mask, &wrapper->target->device_transform_inverse); + _copy_transformed_pattern (&mask_copy.base, mask, &m); mask = &mask_copy.base; } status = _cairo_surface_mask (wrapper->target, op, source, mask, dev_clip); FINISH: + if (wrapper->has_extents) + _cairo_clip_reset (&target_clip); if (dev_clip != clip) _cairo_clip_reset (dev_clip); return status; @@ -190,38 +252,65 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, cairo_matrix_t dev_ctm = *ctm; cairo_matrix_t dev_ctm_inverse = *ctm_inverse; cairo_pattern_union_t source_copy; + cairo_clip_t target_clip; if (unlikely (wrapper->target->status)) return wrapper->target->status; - if (clip && clip->all_clipped) - return CAIRO_STATUS_SUCCESS; + if (wrapper->has_extents) { + _cairo_clip_init_copy (&target_clip, clip); + status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); + if (unlikely (status)) + goto FINISH; + + dev_clip = clip = &target_clip; + } + + if (clip && clip->all_clipped) { + status = CAIRO_STATUS_SUCCESS; + goto FINISH; + } + + if (_cairo_surface_wrapper_needs_device_transform (wrapper) || + _cairo_surface_wrapper_needs_extents_transform (wrapper)) + { + cairo_matrix_t m; + + cairo_matrix_init_identity (&m); + + if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) + cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); + + if (_cairo_surface_wrapper_needs_device_transform (wrapper)) + cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) { status = _cairo_path_fixed_init_copy (&path_copy, dev_path); if (unlikely (status)) goto FINISH; - _cairo_path_fixed_transform (&path_copy, &wrapper->target->device_transform); + _cairo_path_fixed_transform (&path_copy, &m); dev_path = &path_copy; if (clip != NULL) { - status = _cairo_clip_init_copy_transformed (&clip_copy, clip, - &wrapper->target->device_transform); + status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); if (unlikely (status)) goto FINISH; dev_clip = &clip_copy; } - cairo_matrix_multiply (&dev_ctm, &dev_ctm, &wrapper->target->device_transform); - cairo_matrix_multiply (&dev_ctm_inverse, - &wrapper->target->device_transform_inverse, - &dev_ctm_inverse); + cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); + + status = cairo_matrix_invert (&m); + assert (status == CAIRO_STATUS_SUCCESS); - _copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse); + cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); + + _copy_transformed_pattern (&source_copy.base, source, &m); source = &source_copy.base; - } else { + } + else + { if (clip != NULL) { dev_clip = &clip_copy; _cairo_clip_init_copy (&clip_copy, clip); @@ -237,6 +326,8 @@ _cairo_surface_wrapper_stroke (cairo_surface_wrapper_t *wrapper, FINISH: if (dev_path != path) _cairo_path_fixed_fini (dev_path); + if (wrapper->has_extents) + _cairo_clip_reset (&target_clip); if (dev_clip != clip) _cairo_clip_reset (dev_clip); return status; @@ -266,41 +357,68 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse; cairo_pattern_union_t stroke_source_copy; cairo_pattern_union_t fill_source_copy; + cairo_clip_t target_clip; if (unlikely (wrapper->target->status)) return wrapper->target->status; - if (clip && clip->all_clipped) - return CAIRO_STATUS_SUCCESS; + if (wrapper->has_extents) { + _cairo_clip_init_copy (&target_clip, clip); + status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); + if (unlikely (status)) + goto FINISH; + + dev_clip = clip = &target_clip; + } + + if (clip && clip->all_clipped) { + status = CAIRO_STATUS_SUCCESS; + goto FINISH; + } + + if (_cairo_surface_wrapper_needs_device_transform (wrapper) || + _cairo_surface_wrapper_needs_extents_transform (wrapper)) + { + cairo_matrix_t m; + + cairo_matrix_init_identity (&m); + + if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) + cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); + + if (_cairo_surface_wrapper_needs_device_transform (wrapper)) + cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) { status = _cairo_path_fixed_init_copy (&path_copy, dev_path); if (unlikely (status)) goto FINISH; - _cairo_path_fixed_transform (&path_copy, &wrapper->target->device_transform); + _cairo_path_fixed_transform (&path_copy, &m); dev_path = &path_copy; if (clip != NULL) { - status = _cairo_clip_init_copy_transformed (&clip_copy, clip, - &wrapper->target->device_transform); + status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); if (unlikely (status)) goto FINISH; dev_clip = &clip_copy; } - cairo_matrix_multiply (&dev_ctm, &dev_ctm, &wrapper->target->device_transform); - cairo_matrix_multiply (&dev_ctm_inverse, - &wrapper->target->device_transform_inverse, - &dev_ctm_inverse); + cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); - _copy_transformed_pattern (&stroke_source_copy.base, stroke_source, &wrapper->target->device_transform_inverse); + status = cairo_matrix_invert (&m); + assert (status == CAIRO_STATUS_SUCCESS); + + cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); + + _copy_transformed_pattern (&stroke_source_copy.base, stroke_source, &m); stroke_source = &stroke_source_copy.base; - _copy_transformed_pattern (&fill_source_copy.base, fill_source, &wrapper->target->device_transform_inverse); + _copy_transformed_pattern (&fill_source_copy.base, fill_source, &m); fill_source = &fill_source_copy.base; - } else { + } + else + { if (clip != NULL) { dev_clip = &clip_copy; _cairo_clip_init_copy (&clip_copy, clip); @@ -320,6 +438,8 @@ _cairo_surface_wrapper_fill_stroke (cairo_surface_wrapper_t *wrapper, FINISH: if (dev_path != path) _cairo_path_fixed_fini (dev_path); + if (wrapper->has_extents) + _cairo_clip_reset (&target_clip); if (dev_clip != clip) _cairo_clip_reset (dev_clip); return status; @@ -339,33 +459,61 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, cairo_path_fixed_t path_copy, *dev_path = path; cairo_clip_t clip_copy, *dev_clip = clip; cairo_pattern_union_t source_copy; + cairo_clip_t target_clip; if (unlikely (wrapper->target->status)) return wrapper->target->status; - if (clip && clip->all_clipped) - return CAIRO_STATUS_SUCCESS; + if (wrapper->has_extents) { + _cairo_clip_init_copy (&target_clip, clip); + status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); + if (unlikely (status)) + goto FINISH; + + dev_clip = clip = &target_clip; + } + + if (clip && clip->all_clipped) { + status = CAIRO_STATUS_SUCCESS; + goto FINISH; + } + + if (_cairo_surface_wrapper_needs_device_transform (wrapper) || + _cairo_surface_wrapper_needs_extents_transform (wrapper)) + { + cairo_matrix_t m; + + cairo_matrix_init_identity (&m); + + if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) + cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); + + if (_cairo_surface_wrapper_needs_device_transform (wrapper)) + cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) { status = _cairo_path_fixed_init_copy (&path_copy, dev_path); if (unlikely (status)) goto FINISH; - _cairo_path_fixed_transform (&path_copy, &wrapper->target->device_transform); + _cairo_path_fixed_transform (&path_copy, &m); dev_path = &path_copy; if (clip != NULL) { - status = _cairo_clip_init_copy_transformed (&clip_copy, clip, - &wrapper->target->device_transform); + status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); if (unlikely (status)) goto FINISH; dev_clip = &clip_copy; } - _copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse); + status = cairo_matrix_invert (&m); + assert (status == CAIRO_STATUS_SUCCESS); + + _copy_transformed_pattern (&source_copy.base, source, &m); source = &source_copy.base; - } else { + } + else + { if (clip != NULL) { dev_clip = &clip_copy; _cairo_clip_init_copy (&clip_copy, clip); @@ -380,6 +528,8 @@ _cairo_surface_wrapper_fill (cairo_surface_wrapper_t *wrapper, FINISH: if (dev_path != path) _cairo_path_fixed_fini (dev_path); + if (wrapper->has_extents) + _cairo_clip_reset (&target_clip); if (dev_clip != clip) _cairo_clip_reset (dev_clip); return status; @@ -403,6 +553,7 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, cairo_clip_t clip_copy, *dev_clip = clip; cairo_glyph_t *dev_glyphs = glyphs; cairo_pattern_union_t source_copy; + cairo_clip_t target_clip; if (unlikely (wrapper->target->status)) return wrapper->target->status; @@ -410,15 +561,36 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, if (glyphs == NULL || num_glyphs == 0) return CAIRO_STATUS_SUCCESS; - if (clip && clip->all_clipped) - return CAIRO_STATUS_SUCCESS; + if (wrapper->has_extents) { + _cairo_clip_init_copy (&target_clip, clip); + status = _cairo_clip_rectangle (&target_clip, &wrapper->extents); + if (unlikely (status)) + goto FINISH; + + dev_clip = clip = &target_clip; + } + + if (clip && clip->all_clipped) { + status = CAIRO_STATUS_SUCCESS; + goto FINISH; + } - if (_cairo_surface_wrapper_needs_device_transform (wrapper)) { + if (_cairo_surface_wrapper_needs_device_transform (wrapper) || + _cairo_surface_wrapper_needs_extents_transform (wrapper)) + { + cairo_matrix_t m; int i; + cairo_matrix_init_identity (&m); + + if (_cairo_surface_wrapper_needs_extents_transform (wrapper)) + cairo_matrix_translate (&m, -wrapper->extents.x, -wrapper->extents.y); + + if (_cairo_surface_wrapper_needs_device_transform (wrapper)) + cairo_matrix_multiply (&m, &wrapper->target->device_transform, &m); + if (clip != NULL) { - status = _cairo_clip_init_copy_transformed (&clip_copy, clip, - &wrapper->target->device_transform); + status = _cairo_clip_init_copy_transformed (&clip_copy, clip, &m); if (unlikely (status)) goto FINISH; @@ -433,14 +605,17 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, for (i = 0; i < num_glyphs; i++) { dev_glyphs[i] = glyphs[i]; - cairo_matrix_transform_point (&wrapper->target->device_transform, - &dev_glyphs[i].x, - &dev_glyphs[i].y); + cairo_matrix_transform_point (&m, &dev_glyphs[i].x, &dev_glyphs[i].y); } - _copy_transformed_pattern (&source_copy.base, source, &wrapper->target->device_transform_inverse); + status = cairo_matrix_invert (&m); + assert (status == CAIRO_STATUS_SUCCESS); + + _copy_transformed_pattern (&source_copy.base, source, &m); source = &source_copy.base; - } else { + } + else + { if (clip != NULL) { dev_clip = &clip_copy; _cairo_clip_init_copy (&clip_copy, clip); @@ -454,9 +629,12 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, cluster_flags, scaled_font, dev_clip); + FINISH: if (dev_clip != clip) _cairo_clip_reset (dev_clip); + if (wrapper->has_extents) + _cairo_clip_reset (&target_clip); if (dev_glyphs != glyphs) free (dev_glyphs); return status; @@ -476,7 +654,28 @@ cairo_bool_t _cairo_surface_wrapper_get_extents (cairo_surface_wrapper_t *wrapper, cairo_rectangle_int_t *extents) { - return _cairo_surface_get_extents (wrapper->target, extents); + if (wrapper->has_extents) { + if (_cairo_surface_get_extents (wrapper->target, extents)) + _cairo_rectangle_intersect (extents, &wrapper->extents); + else + *extents = wrapper->extents; + + return TRUE; + } else { + return _cairo_surface_get_extents (wrapper->target, extents); + } +} + +void +_cairo_surface_wrapper_set_extents (cairo_surface_wrapper_t *wrapper, + const cairo_rectangle_int_t *extents) +{ + if (extents != NULL) { + wrapper->extents = *extents; + wrapper->has_extents = TRUE; + } else { + wrapper->has_extents = FALSE; + } } void @@ -503,6 +702,7 @@ _cairo_surface_wrapper_init (cairo_surface_wrapper_t *wrapper, cairo_surface_t *target) { wrapper->target = cairo_surface_reference (target); + wrapper->has_extents = FALSE; } void |