mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-05-05 15:48:00 +02:00
[mime-data] Copy a reference to the mime-data on snapshotting.
Instead of doing a full-copy of the mime data (which can be 10K-100K, or even larger) just copy a reference to the original mime to the snapshot surface (as suggested by Behdad).
This commit is contained in:
parent
4f032ca35a
commit
9021755012
4 changed files with 65 additions and 46 deletions
|
|
@ -1035,8 +1035,6 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
cairo_status_t status;
|
||||
cairo_surface_pattern_t pattern;
|
||||
cairo_image_surface_t *image;
|
||||
const unsigned char *mime_data;
|
||||
unsigned int mime_data_length;
|
||||
void *image_extra;
|
||||
|
||||
status = _cairo_surface_acquire_source_image (surface,
|
||||
|
|
@ -1081,28 +1079,11 @@ _cairo_surface_fallback_snapshot (cairo_surface_t *surface)
|
|||
* For now, just copy "image/jpeg", but in future we should construct
|
||||
* an array of known types and iterate.
|
||||
*/
|
||||
cairo_surface_get_mime_data (surface, CAIRO_MIME_TYPE_JPEG,
|
||||
&mime_data, &mime_data_length);
|
||||
if (mime_data != NULL) {
|
||||
unsigned char *mime_data_copy;
|
||||
|
||||
mime_data_copy = malloc (mime_data_length);
|
||||
if (mime_data == NULL) {
|
||||
cairo_surface_destroy (snapshot);
|
||||
return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
}
|
||||
memcpy (mime_data_copy, mime_data, mime_data_length);
|
||||
|
||||
status = cairo_surface_set_mime_data (snapshot,
|
||||
CAIRO_MIME_TYPE_JPEG,
|
||||
mime_data_copy,
|
||||
mime_data_length,
|
||||
free);
|
||||
if (status) {
|
||||
free (mime_data_copy);
|
||||
cairo_surface_destroy (snapshot);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
status = _cairo_surface_copy_mime_data (snapshot, surface,
|
||||
CAIRO_MIME_TYPE_JPEG);
|
||||
if (status) {
|
||||
cairo_surface_destroy (snapshot);
|
||||
return _cairo_surface_create_in_error (status);
|
||||
}
|
||||
|
||||
snapshot->is_snapshot = TRUE;
|
||||
|
|
|
|||
|
|
@ -637,6 +637,9 @@ _cairo_mime_data_destroy (void *ptr)
|
|||
{
|
||||
cairo_mime_data_t *mime_data = ptr;
|
||||
|
||||
if (! _cairo_reference_count_dec_and_test (&mime_data->ref_count))
|
||||
return;
|
||||
|
||||
if (mime_data->destroy && mime_data->data)
|
||||
mime_data->destroy (mime_data->data);
|
||||
|
||||
|
|
@ -679,36 +682,64 @@ cairo_surface_set_mime_data (cairo_surface_t *surface,
|
|||
if (status)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
mime_data = _cairo_user_data_array_get_data (&surface->user_data,
|
||||
(cairo_user_data_key_t *) mime_type);
|
||||
if (mime_data != NULL) {
|
||||
if (mime_data->destroy && mime_data->data)
|
||||
mime_data->destroy (mime_data->data);
|
||||
mime_data = malloc (sizeof (cairo_mime_data_t));
|
||||
if (mime_data == NULL)
|
||||
return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
|
||||
mime_data->data = (unsigned char *) data;
|
||||
mime_data->length = length;
|
||||
mime_data->destroy = destroy;
|
||||
} else {
|
||||
mime_data = malloc (sizeof (cairo_mime_data_t));
|
||||
if (mime_data == NULL)
|
||||
return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_NO_MEMORY));
|
||||
CAIRO_REFERENCE_COUNT_INIT (&mime_data->ref_count, 1);
|
||||
|
||||
mime_data->data = (unsigned char *) data;
|
||||
mime_data->length = length;
|
||||
mime_data->destroy = destroy;
|
||||
mime_data->data = (unsigned char *) data;
|
||||
mime_data->length = length;
|
||||
mime_data->destroy = destroy;
|
||||
|
||||
status = _cairo_user_data_array_set_data (&surface->user_data,
|
||||
(cairo_user_data_key_t *) mime_type,
|
||||
mime_data,
|
||||
_cairo_mime_data_destroy);
|
||||
if (status)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
}
|
||||
status = _cairo_user_data_array_set_data (&surface->user_data,
|
||||
(cairo_user_data_key_t *) mime_type,
|
||||
mime_data,
|
||||
_cairo_mime_data_destroy);
|
||||
if (status)
|
||||
return _cairo_surface_set_error (surface, status);
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
slim_hidden_def (cairo_surface_set_mime_data);
|
||||
|
||||
cairo_status_t
|
||||
_cairo_surface_copy_mime_data (cairo_surface_t *dst,
|
||||
cairo_surface_t *src,
|
||||
const char *mime_type)
|
||||
{
|
||||
cairo_status_t status;
|
||||
cairo_mime_data_t *mime_data;
|
||||
|
||||
if (dst->status)
|
||||
return dst->status;
|
||||
|
||||
if (src->status)
|
||||
return _cairo_surface_set_error (dst, src->status);
|
||||
|
||||
status = _cairo_intern_string (&mime_type, -1);
|
||||
if (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 (status) {
|
||||
_cairo_mime_data_destroy (mime_data);
|
||||
return _cairo_surface_set_error (dst, status);
|
||||
}
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* _cairo_surface_set_font_options:
|
||||
* @surface: a #cairo_surface_t
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "cairo.h"
|
||||
#include "cairo-fixed-type-private.h"
|
||||
#include "cairo-reference-count-private.h"
|
||||
|
||||
typedef struct _cairo_array cairo_array_t;
|
||||
typedef struct _cairo_cache cairo_cache_t;
|
||||
|
|
@ -344,6 +345,7 @@ typedef enum _cairo_image_transparency {
|
|||
} cairo_image_transparency_t;
|
||||
|
||||
struct _cairo_mime_data {
|
||||
cairo_reference_count_t ref_count;
|
||||
unsigned char *data;
|
||||
unsigned int length;
|
||||
cairo_destroy_func_t destroy;
|
||||
|
|
|
|||
|
|
@ -1665,6 +1665,11 @@ _cairo_stroke_style_max_distance_from_path (const cairo_stroke_style_t *style,
|
|||
cairo_private cairo_surface_t *
|
||||
_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_private cairo_status_t
|
||||
_cairo_surface_set_error (cairo_surface_t *surface,
|
||||
cairo_status_t status);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue