mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-01 06:48:01 +02:00
Add tag functions to recording surface and surface-wrapper
This commit is contained in:
parent
4e70815b34
commit
3bd5efa1b6
4 changed files with 257 additions and 1 deletions
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
@ -1341,6 +1434,63 @@ err:
|
|||
return status;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue