summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAdrian Johnson <ajohnson@redneon.com>2016-10-01 17:26:16 +0930
committerAdrian Johnson <ajohnson@redneon.com>2016-10-01 17:26:16 +0930
commit3bd5efa1b651503ed9f175f9ea62fff53f0b2882 (patch)
tree4c10bd4c6dbf8e65100951e581127b5f15943071
parent4e70815b349309e0a82bc8c52663e030c24a1add (diff)
Add tag functions to recording surface and surface-wrapper
-rw-r--r--src/cairo-recording-surface-private.h15
-rw-r--r--src/cairo-recording-surface.c185
-rw-r--r--src/cairo-surface-wrapper-private.h11
-rw-r--r--src/cairo-surface-wrapper.c47
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,