mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-04-21 15:50:48 +02:00
[surface] Separate the mime-data from the user-data.
Move the mime-data into its own array so that it cannot be confused with user-data and we do not need to hard-code the copy list during snapshotting. The copy-on-snapshotting code becomes far simpler and will accommodate all future mime-types. Keeping mime-data separate from user-data is important due to the principle of least surprise - the API is different and so it would be surprising if you queried for user-data and were returned an opaque mime-data pointer, and vice versa. (Note this should have been prevented by using interned strings, but conceptually it is cleaner to make the separation.) Also it aides in trimming the user data arrays which are linearly searched. Based on the original patch by Adrian Johnson: http://cgit.freedesktop.org/~ajohnson/cairo/commit/?h=metadata&id=37e607cc777523ad12a2d214708d79ecbca5b380
This commit is contained in:
parent
2280de9d02
commit
adaf70a93f
5 changed files with 77 additions and 43 deletions
|
|
@ -494,3 +494,39 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array,
|
|||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_user_data_array_copy (cairo_user_data_array_t *dst,
|
||||
cairo_user_data_array_t *src)
|
||||
{
|
||||
/* discard any existing user-data */
|
||||
if (dst->num_elements != 0) {
|
||||
_cairo_user_data_array_fini (dst);
|
||||
_cairo_user_data_array_init (dst);
|
||||
}
|
||||
|
||||
if (src->num_elements == 0)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
return _cairo_array_append_multiple (dst,
|
||||
_cairo_array_index (src, 0),
|
||||
src->num_elements);
|
||||
}
|
||||
|
||||
void
|
||||
_cairo_user_data_array_foreach (cairo_user_data_array_t *array,
|
||||
void (*func) (void *key,
|
||||
void *elt,
|
||||
void *closure),
|
||||
void *closure)
|
||||
{
|
||||
cairo_user_data_slot_t *slots;
|
||||
int i, num_slots;
|
||||
|
||||
num_slots = array->num_elements;
|
||||
slots = _cairo_array_index (array, 0);
|
||||
for (i = 0; i < num_slots; i++) {
|
||||
if (slots[i].user_data != NULL)
|
||||
func (slots[i].key, slots[i].user_data, closure);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1121,12 +1121,6 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
cairo_surface_pattern_t pattern;
|
||||
cairo_image_surface_t *image;
|
||||
void *image_extra;
|
||||
const char *mime_types[] = {
|
||||
CAIRO_MIME_TYPE_JPEG,
|
||||
CAIRO_MIME_TYPE_PNG,
|
||||
CAIRO_MIME_TYPE_JP2,
|
||||
NULL
|
||||
}, **mime_type;
|
||||
|
||||
status = _cairo_surface_acquire_source_image (surface,
|
||||
&image, &image_extra);
|
||||
|
|
@ -1137,13 +1131,11 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
image->width,
|
||||
image->height);
|
||||
if (cairo_surface_status (snapshot)) {
|
||||
_cairo_surface_release_source_image (surface,
|
||||
image, image_extra);
|
||||
_cairo_surface_release_source_image (surface, image, image_extra);
|
||||
return snapshot;
|
||||
}
|
||||
|
||||
_cairo_pattern_init_for_surface (&pattern, &image->base);
|
||||
|
||||
status = _cairo_surface_composite (CAIRO_OPERATOR_SOURCE,
|
||||
&pattern.base,
|
||||
NULL,
|
||||
|
|
@ -1153,11 +1145,14 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
0, 0,
|
||||
image->width,
|
||||
image->height);
|
||||
|
||||
_cairo_pattern_fini (&pattern.base);
|
||||
_cairo_surface_release_source_image (surface,
|
||||
image, image_extra);
|
||||
_cairo_surface_release_source_image (surface, image, image_extra);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (snapshot);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
status = _cairo_surface_copy_mime_data (snapshot, surface);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (snapshot);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
|
|
@ -1166,14 +1161,6 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
snapshot->device_transform = surface->device_transform;
|
||||
snapshot->device_transform_inverse = surface->device_transform_inverse;
|
||||
|
||||
for (mime_type = mime_types; *mime_type; mime_type++) {
|
||||
status = _cairo_surface_copy_mime_data (snapshot, surface, *mime_type);
|
||||
if (unlikely (status)) {
|
||||
cairo_surface_destroy (snapshot);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
}
|
||||
|
||||
snapshot->is_snapshot = TRUE;
|
||||
|
||||
return snapshot;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ struct _cairo_surface {
|
|||
cairo_status_t status;
|
||||
cairo_bool_t finished;
|
||||
cairo_user_data_array_t user_data;
|
||||
cairo_user_data_array_t mime_data;
|
||||
|
||||
cairo_matrix_t device_transform;
|
||||
cairo_matrix_t device_transform_inverse;
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ const cairo_surface_t name = { \
|
|||
status, /* status */ \
|
||||
FALSE, /* finished */ \
|
||||
{ 0, 0, 0, NULL, }, /* user_data */ \
|
||||
{ 0, 0, 0, NULL, }, /* mime_data */ \
|
||||
{ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform */ \
|
||||
{ 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 }, /* device_transform_inverse */ \
|
||||
0.0, /* x_resolution */ \
|
||||
|
|
@ -194,6 +195,7 @@ _cairo_surface_init (cairo_surface_t *surface,
|
|||
surface->finished = FALSE;
|
||||
|
||||
_cairo_user_data_array_init (&surface->user_data);
|
||||
_cairo_user_data_array_init (&surface->mime_data);
|
||||
|
||||
cairo_matrix_init_identity (&surface->device_transform);
|
||||
cairo_matrix_init_identity (&surface->device_transform_inverse);
|
||||
|
|
@ -437,6 +439,7 @@ cairo_surface_destroy (cairo_surface_t *surface)
|
|||
cairo_surface_finish (surface);
|
||||
|
||||
_cairo_user_data_array_fini (&surface->user_data);
|
||||
_cairo_user_data_array_fini (&surface->mime_data);
|
||||
|
||||
free (surface);
|
||||
}
|
||||
|
|
@ -459,6 +462,7 @@ _cairo_surface_reset (cairo_surface_t *surface)
|
|||
assert (CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count) == 1);
|
||||
|
||||
_cairo_user_data_array_fini (&surface->user_data);
|
||||
_cairo_user_data_array_fini (&surface->mime_data);
|
||||
|
||||
if (surface->backend->reset != NULL) {
|
||||
cairo_status_t status = surface->backend->reset (surface);
|
||||
|
|
@ -620,7 +624,7 @@ cairo_surface_get_mime_data (cairo_surface_t *surface,
|
|||
return;
|
||||
}
|
||||
|
||||
mime_data = _cairo_user_data_array_get_data (&surface->user_data,
|
||||
mime_data = _cairo_user_data_array_get_data (&surface->mime_data,
|
||||
(cairo_user_data_key_t *) mime_type);
|
||||
if (mime_data == NULL)
|
||||
return;
|
||||
|
|
@ -696,7 +700,7 @@ cairo_surface_set_mime_data (cairo_surface_t *surface,
|
|||
} else
|
||||
mime_data = NULL;
|
||||
|
||||
status = _cairo_user_data_array_set_data (&surface->user_data,
|
||||
status = _cairo_user_data_array_set_data (&surface->mime_data,
|
||||
(cairo_user_data_key_t *) mime_type,
|
||||
mime_data,
|
||||
_cairo_mime_data_destroy);
|
||||
|
|
@ -711,13 +715,19 @@ cairo_surface_set_mime_data (cairo_surface_t *surface,
|
|||
}
|
||||
slim_hidden_def (cairo_surface_set_mime_data);
|
||||
|
||||
static void
|
||||
_cairo_mime_data_reference (void *key, void *elt, void *closure)
|
||||
{
|
||||
cairo_mime_data_t *mime_data = elt;
|
||||
|
||||
_cairo_reference_count_inc (&mime_data->ref_count);
|
||||
}
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_copy_mime_data (cairo_surface_t *dst,
|
||||
cairo_surface_t *src,
|
||||
const char *mime_type)
|
||||
cairo_surface_t *src)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_mime_data_t *mime_data;
|
||||
|
||||
if (dst->status)
|
||||
return dst->status;
|
||||
|
|
@ -725,25 +735,15 @@ _cairo_surface_copy_mime_data (cairo_surface_t *dst,
|
|||
if (src->status)
|
||||
return _cairo_surface_set_error (dst, src->status);
|
||||
|
||||
status = _cairo_intern_string (&mime_type, -1);
|
||||
/* first copy the mime-data, discarding any already set on dst */
|
||||
status = _cairo_user_data_array_copy (&dst->mime_data, &src->mime_data);
|
||||
if (unlikely (status))
|
||||
return _cairo_surface_set_error (dst, status);
|
||||
|
||||
mime_data = _cairo_user_data_array_get_data (&src->user_data,
|
||||
(cairo_user_data_key_t *) mime_type);
|
||||
if (mime_data == NULL)
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
|
||||
_cairo_reference_count_inc (&mime_data->ref_count);
|
||||
|
||||
status = _cairo_user_data_array_set_data (&dst->user_data,
|
||||
(cairo_user_data_key_t *) mime_type,
|
||||
mime_data,
|
||||
_cairo_mime_data_destroy);
|
||||
if (unlikely (status)) {
|
||||
_cairo_mime_data_destroy (mime_data);
|
||||
return _cairo_surface_set_error (dst, status);
|
||||
}
|
||||
/* now increment the reference counters for the copies */
|
||||
_cairo_user_data_array_foreach (&dst->mime_data,
|
||||
_cairo_mime_data_reference,
|
||||
NULL);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -330,6 +330,17 @@ _cairo_user_data_array_set_data (cairo_user_data_array_t *array,
|
|||
void *user_data,
|
||||
cairo_destroy_func_t destroy);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_user_data_array_copy (cairo_user_data_array_t *dst,
|
||||
cairo_user_data_array_t *src);
|
||||
|
||||
cairo_private void
|
||||
_cairo_user_data_array_foreach (cairo_user_data_array_t *array,
|
||||
void (*func) (void *key,
|
||||
void *elt,
|
||||
void *closure),
|
||||
void *closure);
|
||||
|
||||
#define _CAIRO_HASH_INIT_VALUE 5381
|
||||
|
||||
cairo_private unsigned long
|
||||
|
|
@ -1742,8 +1753,7 @@ _cairo_surface_create_in_error (cairo_status_t status);
|
|||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_copy_mime_data (cairo_surface_t *dst,
|
||||
cairo_surface_t *src,
|
||||
const char *mime_type);
|
||||
cairo_surface_t *src);
|
||||
|
||||
cairo_private cairo_status_t
|
||||
_cairo_surface_set_error (cairo_surface_t *surface,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue