diff options
author | Adrian Johnson <ajohnson@redneon.com> | 2016-10-01 17:26:16 +0930 |
---|---|---|
committer | Adrian Johnson <ajohnson@redneon.com> | 2016-10-01 17:26:16 +0930 |
commit | 3bd5efa1b651503ed9f175f9ea62fff53f0b2882 (patch) | |
tree | 4c10bd4c6dbf8e65100951e581127b5f15943071 | |
parent | 4e70815b349309e0a82bc8c52663e030c24a1add (diff) |
Add tag functions to recording surface and surface-wrapper
-rw-r--r-- | src/cairo-recording-surface-private.h | 15 | ||||
-rw-r--r-- | src/cairo-recording-surface.c | 185 | ||||
-rw-r--r-- | src/cairo-surface-wrapper-private.h | 11 | ||||
-rw-r--r-- | src/cairo-surface-wrapper.c | 47 |
4 files changed, 257 insertions, 1 deletions
diff --git a/src/cairo-recording-surface-private.h b/src/cairo-recording-surface-private.h index 021b73c08..c1827f5b3 100644 --- a/src/cairo-recording-surface-private.h +++ b/src/cairo-recording-surface-private.h @@ -49,6 +49,9 @@ typedef enum { CAIRO_COMMAND_STROKE, CAIRO_COMMAND_FILL, CAIRO_COMMAND_SHOW_TEXT_GLYPHS, + + /* cairo_tag_begin()/cairo_tag_end() */ + CAIRO_COMMAND_TAG, } cairo_command_type_t; typedef enum { @@ -112,6 +115,17 @@ typedef struct _cairo_command_show_text_glyphs { cairo_scaled_font_t *scaled_font; } cairo_command_show_text_glyphs_t; +typedef struct _cairo_command_tag { + cairo_command_header_t header; + cairo_bool_t begin; + char *tag_name; + char *attributes; + cairo_pattern_union_t source; + cairo_stroke_style_t style; + cairo_matrix_t ctm; + cairo_matrix_t ctm_inverse; +} cairo_command_tag_t; + typedef union _cairo_command { cairo_command_header_t header; @@ -120,6 +134,7 @@ typedef union _cairo_command { cairo_command_stroke_t stroke; cairo_command_fill_t fill; cairo_command_show_text_glyphs_t show_text_glyphs; + cairo_command_tag_t tag; } cairo_command_t; typedef struct _cairo_recording_surface { diff --git a/src/cairo-recording-surface.c b/src/cairo-recording-surface.c index 65913138c..84449522d 100644 --- a/src/cairo-recording-surface.c +++ b/src/cairo-recording-surface.c @@ -483,7 +483,16 @@ _cairo_recording_surface_finish (void *abstract_surface) cairo_scaled_font_destroy (command->show_text_glyphs.scaled_font); break; - default: + case CAIRO_COMMAND_TAG: + free (command->tag.tag_name); + if (command->tag.begin) { + free (command->tag.attributes); + _cairo_pattern_fini (&command->tag.source.base); + _cairo_stroke_style_fini (&command->tag.style); + } + break; + + default: ASSERT_NOT_REACHED; } @@ -1076,6 +1085,90 @@ CLEANUP_COMPOSITE: return status; } +static cairo_int_status_t +_cairo_recording_surface_tag (void *abstract_surface, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip) +{ + cairo_status_t status; + cairo_recording_surface_t *surface = abstract_surface; + cairo_command_tag_t *command; + cairo_composite_rectangles_t composite; + + TRACE ((stderr, "%s: surface=%d\n", __FUNCTION__, surface->base.unique_id)); + + status = _cairo_composite_rectangles_init_for_paint (&composite, + &surface->base, + CAIRO_OPERATOR_SOURCE, + source ? source : &_cairo_pattern_black.base, + clip); + if (unlikely (status)) + return status; + + command = calloc (1, sizeof (cairo_command_tag_t)); + if (unlikely (command == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto CLEANUP_COMPOSITE; + } + + status = _command_init (surface, + &command->header, CAIRO_COMMAND_TAG, CAIRO_OPERATOR_SOURCE, + &composite); + if (unlikely (status)) + goto CLEANUP_COMMAND; + + command->begin = begin; + command->tag_name = strdup (tag_name); + if (begin) { + if (attributes) + command->attributes = strdup (attributes); + + status = _cairo_pattern_init_snapshot (&command->source.base, source); + if (unlikely (status)) + goto CLEANUP_STRINGS; + + status = _cairo_stroke_style_init_copy (&command->style, style); + if (unlikely (status)) + goto CLEANUP_SOURCE; + + command->ctm = *ctm; + command->ctm_inverse = *ctm_inverse; + } + + status = _cairo_recording_surface_commit (surface, &command->header); + if (unlikely (status)) { + if (begin) + goto CLEANUP_STRINGS; + else + goto CLEANUP_STYLE; + } + + _cairo_recording_surface_destroy_bbtree (surface); + + _cairo_composite_rectangles_fini (&composite); + return CAIRO_STATUS_SUCCESS; + + CLEANUP_STYLE: + _cairo_stroke_style_fini (&command->style); + CLEANUP_SOURCE: + _cairo_pattern_fini (&command->source.base); + CLEANUP_STRINGS: + free (command->tag_name); + free (command->attributes); + CLEANUP_COMMAND: + _cairo_clip_destroy (command->header.clip); + free (command); + CLEANUP_COMPOSITE: + _cairo_composite_rectangles_fini (&composite); + return status; +} + static void _command_init_copy (cairo_recording_surface_t *surface, cairo_command_header_t *dst, @@ -1342,6 +1435,63 @@ err: } static cairo_status_t +_cairo_recording_surface_copy__tag (cairo_recording_surface_t *surface, + const cairo_command_t *src) +{ + cairo_command_tag_t *command; + cairo_status_t status; + + command = calloc (1, sizeof (*command)); + if (unlikely (command == NULL)) { + status = _cairo_error (CAIRO_STATUS_NO_MEMORY); + goto err; + } + + _command_init_copy (surface, &command->header, &src->header); + + command->begin = src->tag.begin; + command->tag_name = strdup (src->tag.tag_name); + if (src->tag.begin) { + if (src->tag.attributes) + command->attributes = strdup (src->tag.attributes); + + status = _cairo_pattern_init_copy (&command->source.base, + &src->stroke.source.base); + if (unlikely (status)) + goto err_command; + + status = _cairo_stroke_style_init_copy (&command->style, + &src->stroke.style); + if (unlikely (status)) + goto err_source; + + command->ctm = src->stroke.ctm; + command->ctm_inverse = src->stroke.ctm_inverse; + } + + status = _cairo_recording_surface_commit (surface, &command->header); + if (unlikely (status)) { + if (src->tag.begin) + goto err_command; + else + goto err_style; + } + + return CAIRO_STATUS_SUCCESS; + +err_style: + _cairo_stroke_style_fini (&command->style); +err_source: + _cairo_pattern_fini (&command->source.base); +err_command: + free(command->tag_name); + free(command->attributes); + free(command); +err: + return status; +} + +static cairo_status_t _cairo_recording_surface_copy (cairo_recording_surface_t *dst, cairo_recording_surface_t *src) { @@ -1375,6 +1525,10 @@ _cairo_recording_surface_copy (cairo_recording_surface_t *dst, status = _cairo_recording_surface_copy__glyphs (dst, command); break; + case CAIRO_COMMAND_TAG: + status = _cairo_recording_surface_copy__tag (dst, command); + break; + default: ASSERT_NOT_REACHED; } @@ -1490,6 +1644,8 @@ static const cairo_surface_backend_t cairo_recording_surface_backend = { NULL, _cairo_recording_surface_has_show_text_glyphs, _cairo_recording_surface_show_text_glyphs, + NULL, /* get_supported_mime_types */ + _cairo_recording_surface_tag, }; cairo_int_status_t @@ -1554,6 +1710,9 @@ _cairo_recording_surface_get_path (cairo_surface_t *abstract_surface, break; } + case CAIRO_COMMAND_TAG: + break; + default: ASSERT_NOT_REACHED; } @@ -1851,6 +2010,18 @@ _cairo_recording_surface_replay_internal (cairo_recording_surface_t *surface, } break; + case CAIRO_COMMAND_TAG: + status = _cairo_surface_wrapper_tag (&wrapper, + command->tag.begin, + command->tag.tag_name, + command->tag.attributes, + &command->tag.source.base, + &command->tag.style, + &command->tag.ctm, + &command->tag.ctm_inverse, + command->header.clip); + break; + default: ASSERT_NOT_REACHED; } @@ -1958,6 +2129,18 @@ _cairo_recording_surface_replay_one (cairo_recording_surface_t *surface, command->header.clip); break; + case CAIRO_COMMAND_TAG: + status = _cairo_surface_wrapper_tag (&wrapper, + command->tag.begin, + command->tag.tag_name, + command->tag.attributes, + &command->tag.source.base, + &command->tag.style, + &command->tag.ctm, + &command->tag.ctm_inverse, + command->header.clip); + break; + default: ASSERT_NOT_REACHED; } diff --git a/src/cairo-surface-wrapper-private.h b/src/cairo-surface-wrapper-private.h index e412fc65c..fd22bd7e6 100644 --- a/src/cairo-surface-wrapper-private.h +++ b/src/cairo-surface-wrapper-private.h @@ -159,6 +159,17 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, cairo_scaled_font_t *scaled_font, const cairo_clip_t *clip); +cairo_private cairo_status_t +_cairo_surface_wrapper_tag (cairo_surface_wrapper_t *wrapper, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip); + cairo_private cairo_surface_t * _cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper, cairo_content_t content, diff --git a/src/cairo-surface-wrapper.c b/src/cairo-surface-wrapper.c index b9b4b44a5..47155c3f7 100644 --- a/src/cairo-surface-wrapper.c +++ b/src/cairo-surface-wrapper.c @@ -501,6 +501,53 @@ _cairo_surface_wrapper_show_text_glyphs (cairo_surface_wrapper_t *wrapper, return status; } +cairo_status_t +_cairo_surface_wrapper_tag (cairo_surface_wrapper_t *wrapper, + cairo_bool_t begin, + const char *tag_name, + const char *attributes, + const cairo_pattern_t *source, + const cairo_stroke_style_t *stroke_style, + const cairo_matrix_t *ctm, + const cairo_matrix_t *ctm_inverse, + const cairo_clip_t *clip) +{ + cairo_status_t status; + cairo_clip_t *dev_clip; + cairo_matrix_t dev_ctm = *ctm; + cairo_matrix_t dev_ctm_inverse = *ctm_inverse; + cairo_pattern_union_t source_copy; + + if (unlikely (wrapper->target->status)) + return wrapper->target->status; + + dev_clip = _cairo_surface_wrapper_get_clip (wrapper, clip); + if (wrapper->needs_transform) { + cairo_matrix_t m; + + _cairo_surface_wrapper_get_transform (wrapper, &m); + + cairo_matrix_multiply (&dev_ctm, &dev_ctm, &m); + + status = cairo_matrix_invert (&m); + assert (status == CAIRO_STATUS_SUCCESS); + + cairo_matrix_multiply (&dev_ctm_inverse, &m, &dev_ctm_inverse); + + _copy_transformed_pattern (&source_copy.base, source, &m); + source = &source_copy.base; + } + + status = _cairo_surface_tag (wrapper->target, + begin, tag_name, attributes, + source, stroke_style, + &dev_ctm, &dev_ctm_inverse, + dev_clip); + + _cairo_clip_destroy (dev_clip); + return status; +} + cairo_surface_t * _cairo_surface_wrapper_create_similar (cairo_surface_wrapper_t *wrapper, cairo_content_t content, |