1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
|
Author: Jeff Muizelaar <jmuizelaar@mozilla.com>
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 8278694..12f6242 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -1530,6 +1530,70 @@ _cairo_recording_surface_clone_similar (cairo_surface_t *surface,
return CAIRO_STATUS_SUCCESS;
}
+struct acquire_source_image_data
+{
+ cairo_surface_t *src;
+ cairo_image_surface_t *image;
+ void *image_extra;
+};
+
+static void
+_wrap_release_source_image (void *data)
+{
+ struct acquire_source_image_data *acquire_data = data;
+ _cairo_surface_release_source_image (acquire_data->src,
+ acquire_data->image,
+ acquire_data->image_extra);
+ free(data);
+}
+
+static cairo_status_t
+_wrap_image (cairo_surface_t *src,
+ cairo_image_surface_t *image,
+ void *image_extra,
+ cairo_image_surface_t **out)
+{
+ static cairo_user_data_key_t wrap_image_key;
+ cairo_image_surface_t *surface;
+ cairo_status_t status;
+
+ struct acquire_source_image_data *data = malloc (sizeof (*data));
+ if (unlikely (data == NULL))
+ return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+ data->src = src;
+ data->image = image;
+ data->image_extra = image_extra;
+
+ surface = (cairo_image_surface_t *)
+ _cairo_image_surface_create_with_pixman_format (image->data,
+ image->pixman_format,
+ image->width,
+ image->height,
+ image->stride);
+ status = surface->base.status;
+ if (status) {
+ free (data);
+ return status;
+ }
+
+ status = _cairo_user_data_array_set_data (&surface->base.user_data,
+ &wrap_image_key,
+ data,
+ _wrap_release_source_image);
+ if (status) {
+ cairo_surface_destroy (&surface->base);
+ free (data);
+ return status;
+ }
+
+ pixman_image_set_component_alpha (
+ surface->pixman_image,
+ pixman_image_get_component_alpha (surface->pixman_image));
+
+ *out = surface;
+ return CAIRO_STATUS_SUCCESS;
+}
+
/**
* _cairo_surface_clone_similar:
* @surface: a #cairo_surface_t
@@ -1606,15 +1670,19 @@ _cairo_surface_clone_similar (cairo_surface_t *surface,
/* If we failed, try again with an image surface */
status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
if (status == CAIRO_STATUS_SUCCESS) {
- status =
- surface->backend->clone_similar (surface, &image->base,
- src_x, src_y,
- width, height,
- clone_offset_x,
- clone_offset_y,
- clone_out);
-
- _cairo_surface_release_source_image (src, image, image_extra);
+ status = _wrap_image(src, image, image_extra, &image);
+ if (status != CAIRO_STATUS_SUCCESS) {
+ _cairo_surface_release_source_image (src, image, image_extra);
+ } else {
+ status =
+ surface->backend->clone_similar (surface, &image->base,
+ src_x, src_y,
+ width, height,
+ clone_offset_x,
+ clone_offset_y,
+ clone_out);
+ cairo_surface_destroy(&image->base);
+ }
}
}
}
|