Rev 1892 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1892 | Rev 3959 | ||
---|---|---|---|
1 | /* cairo - a vector graphics library with display and print output |
1 | /* cairo - a vector graphics library with display and print output |
2 | * |
2 | * |
3 | * Copyright © 2009 Intel Corporation |
3 | * Copyright © 2009 Intel Corporation |
4 | * |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it either under the terms of the GNU Lesser General Public |
6 | * modify it either under the terms of the GNU Lesser General Public |
7 | * License version 2.1 as published by the Free Software Foundation |
7 | * License version 2.1 as published by the Free Software Foundation |
8 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
8 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
9 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
9 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
10 | * notice, a recipient may use your version of this file under either |
10 | * notice, a recipient may use your version of this file under either |
11 | * the MPL or the LGPL. |
11 | * the MPL or the LGPL. |
12 | * |
12 | * |
13 | * You should have received a copy of the LGPL along with this library |
13 | * You should have received a copy of the LGPL along with this library |
14 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
14 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
15 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
15 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
16 | * You should have received a copy of the MPL along with this library |
16 | * You should have received a copy of the MPL along with this library |
17 | * in the file COPYING-MPL-1.1 |
17 | * in the file COPYING-MPL-1.1 |
18 | * |
18 | * |
19 | * The contents of this file are subject to the Mozilla Public License |
19 | * The contents of this file are subject to the Mozilla Public License |
20 | * Version 1.1 (the "License"); you may not use this file except in |
20 | * Version 1.1 (the "License"); you may not use this file except in |
21 | * compliance with the License. You may obtain a copy of the License at |
21 | * compliance with the License. You may obtain a copy of the License at |
22 | * http://www.mozilla.org/MPL/ |
22 | * http://www.mozilla.org/MPL/ |
23 | * |
23 | * |
24 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
24 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
25 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
25 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
26 | * the specific language governing rights and limitations. |
26 | * the specific language governing rights and limitations. |
27 | * |
27 | * |
28 | * The Original Code is the cairo graphics library. |
28 | * The Original Code is the cairo graphics library. |
29 | * |
29 | * |
30 | * The Initial Developer of the Original Code is Intel Corporation. |
30 | * The Initial Developer of the Original Code is Intel Corporation. |
31 | * |
31 | * |
32 | * Contributor(s): |
32 | * Contributor(s): |
33 | * Chris Wilson |
33 | * Chris Wilson |
34 | */ |
34 | */ |
35 | 35 | ||
36 | #include "cairoint.h" |
36 | #include "cairoint.h" |
- | 37 | ||
37 | 38 | #include "cairo-clip-inline.h" |
|
- | 39 | #include "cairo-error-private.h" |
|
38 | #include "cairo-error-private.h" |
40 | #include "cairo-image-surface-private.h" |
39 | #include "cairo-recording-surface-private.h" |
41 | #include "cairo-recording-surface-private.h" |
- | 42 | #include "cairo-surface-offset-private.h" |
|
40 | #include "cairo-surface-offset-private.h" |
43 | #include "cairo-surface-snapshot-private.h" |
41 | #include "cairo-surface-subsurface-private.h" |
44 | #include "cairo-surface-subsurface-private.h" |
42 | 45 | ||
43 | static const cairo_surface_backend_t _cairo_surface_subsurface_backend; |
46 | static const cairo_surface_backend_t _cairo_surface_subsurface_backend; |
44 | 47 | ||
45 | static cairo_status_t |
48 | static cairo_status_t |
46 | _cairo_surface_subsurface_finish (void *abstract_surface) |
49 | _cairo_surface_subsurface_finish (void *abstract_surface) |
47 | { |
50 | { |
48 | cairo_surface_subsurface_t *surface = abstract_surface; |
51 | cairo_surface_subsurface_t *surface = abstract_surface; |
49 | 52 | ||
50 | cairo_surface_destroy (surface->target); |
53 | cairo_surface_destroy (surface->target); |
- | 54 | cairo_surface_destroy (surface->snapshot); |
|
51 | 55 | ||
52 | return CAIRO_STATUS_SUCCESS; |
56 | return CAIRO_STATUS_SUCCESS; |
53 | } |
57 | } |
54 | 58 | ||
55 | static cairo_surface_t * |
59 | static cairo_surface_t * |
56 | _cairo_surface_subsurface_create_similar (void *other, |
60 | _cairo_surface_subsurface_create_similar (void *other, |
57 | cairo_content_t content, |
61 | cairo_content_t content, |
58 | int width, int height) |
62 | int width, int height) |
59 | { |
63 | { |
60 | cairo_surface_subsurface_t *surface = other; |
64 | cairo_surface_subsurface_t *surface = other; |
- | 65 | ||
- | 66 | if (surface->target->backend->create_similar == NULL) |
|
- | 67 | return NULL; |
|
- | 68 | ||
61 | return surface->target->backend->create_similar (surface->target, content, width, height); |
69 | return surface->target->backend->create_similar (surface->target, content, width, height); |
62 | } |
70 | } |
- | 71 | ||
- | 72 | static cairo_surface_t * |
|
- | 73 | _cairo_surface_subsurface_create_similar_image (void *other, |
|
- | 74 | cairo_format_t format, |
|
- | 75 | int width, int height) |
|
- | 76 | { |
|
- | 77 | cairo_surface_subsurface_t *surface = other; |
|
- | 78 | ||
- | 79 | if (surface->target->backend->create_similar_image == NULL) |
|
- | 80 | return NULL; |
|
- | 81 | ||
- | 82 | return surface->target->backend->create_similar_image (surface->target, |
|
- | 83 | format, |
|
- | 84 | width, height); |
|
- | 85 | } |
|
- | 86 | ||
- | 87 | static cairo_image_surface_t * |
|
- | 88 | _cairo_surface_subsurface_map_to_image (void *abstract_surface, |
|
- | 89 | const cairo_rectangle_int_t *extents) |
|
- | 90 | { |
|
- | 91 | cairo_surface_subsurface_t *surface = abstract_surface; |
|
- | 92 | cairo_rectangle_int_t target_extents; |
|
- | 93 | ||
- | 94 | target_extents.x = extents->x + surface->extents.x; |
|
- | 95 | target_extents.y = extents->y + surface->extents.y; |
|
- | 96 | target_extents.width = extents->width; |
|
- | 97 | target_extents.height = extents->height; |
|
- | 98 | ||
- | 99 | return _cairo_surface_map_to_image (surface->target, &target_extents); |
|
- | 100 | } |
|
- | 101 | ||
- | 102 | static cairo_int_status_t |
|
- | 103 | _cairo_surface_subsurface_unmap_image (void *abstract_surface, |
|
- | 104 | cairo_image_surface_t *image) |
|
- | 105 | { |
|
- | 106 | cairo_surface_subsurface_t *surface = abstract_surface; |
|
- | 107 | return _cairo_surface_unmap_image (surface->target, image); |
|
- | 108 | } |
|
63 | 109 | ||
64 | static cairo_int_status_t |
110 | static cairo_int_status_t |
65 | _cairo_surface_subsurface_paint (void *abstract_surface, |
111 | _cairo_surface_subsurface_paint (void *abstract_surface, |
66 | cairo_operator_t op, |
112 | cairo_operator_t op, |
67 | const cairo_pattern_t *source, |
113 | const cairo_pattern_t *source, |
68 | cairo_clip_t *clip) |
114 | const cairo_clip_t *clip) |
69 | { |
115 | { |
70 | cairo_surface_subsurface_t *surface = abstract_surface; |
116 | cairo_surface_subsurface_t *surface = abstract_surface; |
71 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
117 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
72 | cairo_status_t status; |
118 | cairo_status_t status; |
73 | cairo_clip_t target_clip; |
119 | cairo_clip_t *target_clip; |
74 | - | ||
75 | _cairo_clip_init_copy (&target_clip, clip); |
- | |
76 | status = _cairo_clip_rectangle (&target_clip, &rect); |
- | |
77 | if (unlikely (status)) |
- | |
78 | goto CLEANUP; |
- | |
- | 120 | ||
79 | 121 | target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect); |
|
80 | status = _cairo_surface_offset_paint (surface->target, |
122 | status = _cairo_surface_offset_paint (surface->target, |
81 | -surface->extents.x, -surface->extents.y, |
123 | -surface->extents.x, -surface->extents.y, |
82 | op, source, &target_clip); |
- | |
83 | CLEANUP: |
124 | op, source, target_clip); |
84 | _cairo_clip_fini (&target_clip); |
125 | _cairo_clip_destroy (target_clip); |
85 | return status; |
126 | return status; |
86 | } |
127 | } |
87 | 128 | ||
88 | static cairo_int_status_t |
129 | static cairo_int_status_t |
89 | _cairo_surface_subsurface_mask (void *abstract_surface, |
130 | _cairo_surface_subsurface_mask (void *abstract_surface, |
90 | cairo_operator_t op, |
131 | cairo_operator_t op, |
91 | const cairo_pattern_t *source, |
132 | const cairo_pattern_t *source, |
92 | const cairo_pattern_t *mask, |
133 | const cairo_pattern_t *mask, |
93 | cairo_clip_t *clip) |
134 | const cairo_clip_t *clip) |
94 | { |
135 | { |
95 | cairo_surface_subsurface_t *surface = abstract_surface; |
136 | cairo_surface_subsurface_t *surface = abstract_surface; |
96 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
137 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
97 | cairo_status_t status; |
138 | cairo_status_t status; |
98 | cairo_clip_t target_clip; |
139 | cairo_clip_t *target_clip; |
99 | - | ||
100 | _cairo_clip_init_copy (&target_clip, clip); |
- | |
101 | status = _cairo_clip_rectangle (&target_clip, &rect); |
- | |
102 | if (unlikely (status)) |
- | |
103 | goto CLEANUP; |
- | |
- | 140 | ||
104 | 141 | target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect); |
|
105 | status = _cairo_surface_offset_mask (surface->target, |
142 | status = _cairo_surface_offset_mask (surface->target, |
106 | -surface->extents.x, -surface->extents.y, |
143 | -surface->extents.x, -surface->extents.y, |
107 | op, source, mask, &target_clip); |
- | |
108 | CLEANUP: |
144 | op, source, mask, target_clip); |
109 | _cairo_clip_fini (&target_clip); |
145 | _cairo_clip_destroy (target_clip); |
110 | return status; |
146 | return status; |
111 | } |
147 | } |
112 | 148 | ||
113 | static cairo_int_status_t |
149 | static cairo_int_status_t |
114 | _cairo_surface_subsurface_fill (void *abstract_surface, |
150 | _cairo_surface_subsurface_fill (void *abstract_surface, |
115 | cairo_operator_t op, |
151 | cairo_operator_t op, |
116 | const cairo_pattern_t *source, |
152 | const cairo_pattern_t *source, |
117 | cairo_path_fixed_t *path, |
153 | const cairo_path_fixed_t *path, |
118 | cairo_fill_rule_t fill_rule, |
154 | cairo_fill_rule_t fill_rule, |
119 | double tolerance, |
155 | double tolerance, |
120 | cairo_antialias_t antialias, |
156 | cairo_antialias_t antialias, |
121 | cairo_clip_t *clip) |
157 | const cairo_clip_t *clip) |
122 | { |
158 | { |
123 | cairo_surface_subsurface_t *surface = abstract_surface; |
159 | cairo_surface_subsurface_t *surface = abstract_surface; |
124 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
160 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
125 | cairo_status_t status; |
161 | cairo_status_t status; |
126 | cairo_clip_t target_clip; |
162 | cairo_clip_t *target_clip; |
127 | - | ||
128 | _cairo_clip_init_copy (&target_clip, clip); |
- | |
129 | status = _cairo_clip_rectangle (&target_clip, &rect); |
- | |
130 | if (unlikely (status)) |
- | |
131 | goto CLEANUP; |
- | |
- | 163 | ||
132 | 164 | target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect); |
|
133 | status = _cairo_surface_offset_fill (surface->target, |
165 | status = _cairo_surface_offset_fill (surface->target, |
134 | -surface->extents.x, -surface->extents.y, |
166 | -surface->extents.x, -surface->extents.y, |
135 | op, source, path, fill_rule, tolerance, antialias, |
167 | op, source, path, fill_rule, tolerance, antialias, |
136 | &target_clip); |
168 | target_clip); |
137 | CLEANUP: |
- | |
138 | _cairo_clip_fini (&target_clip); |
169 | _cairo_clip_destroy (target_clip); |
139 | return status; |
170 | return status; |
140 | } |
171 | } |
141 | 172 | ||
142 | static cairo_int_status_t |
173 | static cairo_int_status_t |
143 | _cairo_surface_subsurface_stroke (void *abstract_surface, |
174 | _cairo_surface_subsurface_stroke (void *abstract_surface, |
144 | cairo_operator_t op, |
175 | cairo_operator_t op, |
145 | const cairo_pattern_t *source, |
176 | const cairo_pattern_t *source, |
146 | cairo_path_fixed_t *path, |
177 | const cairo_path_fixed_t *path, |
147 | const cairo_stroke_style_t *stroke_style, |
178 | const cairo_stroke_style_t *stroke_style, |
148 | const cairo_matrix_t *ctm, |
179 | const cairo_matrix_t *ctm, |
149 | const cairo_matrix_t *ctm_inverse, |
180 | const cairo_matrix_t *ctm_inverse, |
150 | double tolerance, |
181 | double tolerance, |
151 | cairo_antialias_t antialias, |
182 | cairo_antialias_t antialias, |
152 | cairo_clip_t *clip) |
183 | const cairo_clip_t *clip) |
153 | { |
184 | { |
154 | cairo_surface_subsurface_t *surface = abstract_surface; |
185 | cairo_surface_subsurface_t *surface = abstract_surface; |
155 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
186 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
156 | cairo_status_t status; |
187 | cairo_status_t status; |
157 | cairo_clip_t target_clip; |
188 | cairo_clip_t *target_clip; |
158 | - | ||
159 | _cairo_clip_init_copy (&target_clip, clip); |
- | |
160 | status = _cairo_clip_rectangle (&target_clip, &rect); |
- | |
161 | if (unlikely (status)) |
- | |
162 | goto CLEANUP; |
- | |
- | 189 | ||
163 | 190 | target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect); |
|
164 | status = _cairo_surface_offset_stroke (surface->target, |
191 | status = _cairo_surface_offset_stroke (surface->target, |
165 | -surface->extents.x, -surface->extents.y, |
192 | -surface->extents.x, -surface->extents.y, |
166 | op, source, path, stroke_style, ctm, ctm_inverse, |
193 | op, source, path, stroke_style, ctm, ctm_inverse, |
167 | tolerance, antialias, |
194 | tolerance, antialias, |
168 | &target_clip); |
195 | target_clip); |
169 | CLEANUP: |
- | |
170 | _cairo_clip_fini (&target_clip); |
196 | _cairo_clip_destroy (target_clip); |
171 | return status; |
197 | return status; |
172 | } |
198 | } |
173 | 199 | ||
174 | static cairo_int_status_t |
200 | static cairo_int_status_t |
175 | _cairo_surface_subsurface_glyphs (void *abstract_surface, |
201 | _cairo_surface_subsurface_glyphs (void *abstract_surface, |
176 | cairo_operator_t op, |
202 | cairo_operator_t op, |
177 | const cairo_pattern_t *source, |
203 | const cairo_pattern_t *source, |
178 | cairo_glyph_t *glyphs, |
204 | cairo_glyph_t *glyphs, |
179 | int num_glyphs, |
205 | int num_glyphs, |
180 | cairo_scaled_font_t *scaled_font, |
206 | cairo_scaled_font_t *scaled_font, |
181 | cairo_clip_t *clip, |
207 | const cairo_clip_t *clip) |
182 | int *remaining_glyphs) |
- | |
183 | { |
208 | { |
184 | cairo_surface_subsurface_t *surface = abstract_surface; |
209 | cairo_surface_subsurface_t *surface = abstract_surface; |
185 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
210 | cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height }; |
186 | cairo_status_t status; |
211 | cairo_status_t status; |
187 | cairo_clip_t target_clip; |
212 | cairo_clip_t *target_clip; |
188 | - | ||
189 | _cairo_clip_init_copy (&target_clip, clip); |
- | |
190 | status = _cairo_clip_rectangle (&target_clip, &rect); |
- | |
191 | if (unlikely (status)) |
- | |
192 | goto CLEANUP; |
- | |
- | 213 | ||
193 | 214 | target_clip = _cairo_clip_copy_intersect_rectangle (clip, &rect); |
|
194 | status = _cairo_surface_offset_glyphs (surface->target, |
215 | status = _cairo_surface_offset_glyphs (surface->target, |
195 | -surface->extents.x, -surface->extents.y, |
216 | -surface->extents.x, -surface->extents.y, |
196 | op, source, |
217 | op, source, |
197 | scaled_font, glyphs, num_glyphs, |
218 | scaled_font, glyphs, num_glyphs, |
198 | &target_clip); |
219 | target_clip); |
199 | *remaining_glyphs = 0; |
- | |
200 | CLEANUP: |
- | |
201 | _cairo_clip_fini (&target_clip); |
220 | _cairo_clip_destroy (target_clip); |
202 | return status; |
221 | return status; |
203 | } |
222 | } |
204 | 223 | ||
205 | static cairo_status_t |
224 | static cairo_status_t |
206 | _cairo_surface_subsurface_flush (void *abstract_surface) |
225 | _cairo_surface_subsurface_flush (void *abstract_surface, unsigned flags) |
207 | { |
226 | { |
208 | cairo_surface_subsurface_t *surface = abstract_surface; |
227 | cairo_surface_subsurface_t *surface = abstract_surface; |
209 | cairo_status_t status; |
- | |
210 | - | ||
211 | status = CAIRO_STATUS_SUCCESS; |
- | |
212 | if (surface->target->backend->flush != NULL) |
- | |
213 | status = surface->target->backend->flush (surface->target); |
228 | return _cairo_surface_flush (surface->target, flags); |
214 | - | ||
215 | return status; |
- | |
216 | } |
229 | } |
217 | 230 | ||
218 | static cairo_status_t |
231 | static cairo_status_t |
219 | _cairo_surface_subsurface_mark_dirty (void *abstract_surface, |
232 | _cairo_surface_subsurface_mark_dirty (void *abstract_surface, |
220 | int x, int y, |
233 | int x, int y, |
221 | int width, int height) |
234 | int width, int height) |
222 | { |
235 | { |
223 | cairo_surface_subsurface_t *surface = abstract_surface; |
236 | cairo_surface_subsurface_t *surface = abstract_surface; |
224 | cairo_status_t status; |
237 | cairo_status_t status; |
225 | 238 | ||
226 | status = CAIRO_STATUS_SUCCESS; |
239 | status = CAIRO_STATUS_SUCCESS; |
227 | if (surface->target->backend->mark_dirty_rectangle != NULL) { |
240 | if (surface->target->backend->mark_dirty_rectangle != NULL) { |
228 | cairo_rectangle_int_t rect, extents; |
241 | cairo_rectangle_int_t rect, extents; |
229 | 242 | ||
230 | rect.x = x; |
243 | rect.x = x; |
231 | rect.y = y; |
244 | rect.y = y; |
232 | rect.width = width; |
245 | rect.width = width; |
233 | rect.height = height; |
246 | rect.height = height; |
234 | 247 | ||
235 | extents.x = extents.y = 0; |
248 | extents.x = extents.y = 0; |
236 | extents.width = surface->extents.width; |
249 | extents.width = surface->extents.width; |
237 | extents.height = surface->extents.height; |
250 | extents.height = surface->extents.height; |
238 | 251 | ||
239 | if (_cairo_rectangle_intersect (&rect, &extents)) { |
252 | if (_cairo_rectangle_intersect (&rect, &extents)) { |
240 | status = surface->target->backend->mark_dirty_rectangle (surface->target, |
253 | status = surface->target->backend->mark_dirty_rectangle (surface->target, |
241 | rect.x + surface->extents.x, |
254 | rect.x + surface->extents.x, |
242 | rect.y + surface->extents.y, |
255 | rect.y + surface->extents.y, |
243 | rect.width, rect.height); |
256 | rect.width, rect.height); |
244 | } |
257 | } |
245 | } |
258 | } |
246 | 259 | ||
247 | return status; |
260 | return status; |
248 | } |
261 | } |
249 | 262 | ||
250 | static cairo_bool_t |
263 | static cairo_bool_t |
251 | _cairo_surface_subsurface_get_extents (void *abstract_surface, |
264 | _cairo_surface_subsurface_get_extents (void *abstract_surface, |
252 | cairo_rectangle_int_t *extents) |
265 | cairo_rectangle_int_t *extents) |
253 | { |
266 | { |
254 | cairo_surface_subsurface_t *surface = abstract_surface; |
267 | cairo_surface_subsurface_t *surface = abstract_surface; |
255 | 268 | ||
256 | extents->x = 0; |
269 | extents->x = 0; |
257 | extents->y = 0; |
270 | extents->y = 0; |
258 | extents->width = surface->extents.width; |
271 | extents->width = surface->extents.width; |
259 | extents->height = surface->extents.height; |
272 | extents->height = surface->extents.height; |
260 | 273 | ||
261 | return TRUE; |
274 | return TRUE; |
262 | } |
275 | } |
263 | 276 | ||
264 | static void |
277 | static void |
265 | _cairo_surface_subsurface_get_font_options (void *abstract_surface, |
278 | _cairo_surface_subsurface_get_font_options (void *abstract_surface, |
266 | cairo_font_options_t *options) |
279 | cairo_font_options_t *options) |
267 | { |
280 | { |
268 | cairo_surface_subsurface_t *surface = abstract_surface; |
281 | cairo_surface_subsurface_t *surface = abstract_surface; |
269 | 282 | ||
270 | if (surface->target->backend->get_font_options != NULL) |
283 | if (surface->target->backend->get_font_options != NULL) |
271 | surface->target->backend->get_font_options (surface->target, options); |
284 | surface->target->backend->get_font_options (surface->target, options); |
272 | } |
285 | } |
273 | - | ||
274 | struct extra { |
286 | |
275 | cairo_image_surface_t *image; |
- | |
276 | void *image_extra; |
- | |
277 | }; |
- | |
278 | - | ||
279 | static void |
287 | static cairo_surface_t * |
280 | cairo_surface_paint_to_target (cairo_surface_t *target, |
288 | _cairo_surface_subsurface_source (void *abstract_surface, |
281 | cairo_surface_subsurface_t *subsurface) |
289 | cairo_rectangle_int_t *extents) |
282 | { |
290 | { |
283 | cairo_t *cr; |
- | |
284 | 291 | cairo_surface_subsurface_t *surface = abstract_surface; |
|
285 | cr = cairo_create (target); |
- | |
286 | 292 | cairo_surface_t *source; |
|
287 | cairo_set_source_surface (cr, |
293 | |
288 | subsurface->target, |
294 | source = _cairo_surface_get_source (surface->target, extents); |
289 | - subsurface->extents.x, |
- | |
290 | - subsurface->extents.y); |
- | |
291 | cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); |
295 | if (extents) |
292 | cairo_paint (cr); |
296 | *extents = surface->extents; |
293 | 297 | ||
294 | cairo_destroy (cr); |
298 | return source; |
295 | } |
299 | } |
296 | 300 | ||
297 | static cairo_status_t |
301 | static cairo_status_t |
298 | _cairo_surface_subsurface_acquire_source_image (void *abstract_surface, |
302 | _cairo_surface_subsurface_acquire_source_image (void *abstract_surface, |
299 | cairo_image_surface_t **image_out, |
303 | cairo_image_surface_t **image_out, |
300 | void **extra_out) |
304 | void **extra_out) |
301 | { |
305 | { |
302 | cairo_rectangle_int_t target_extents; |
- | |
303 | cairo_surface_subsurface_t *surface = abstract_surface; |
306 | cairo_surface_subsurface_t *surface = abstract_surface; |
- | 307 | cairo_surface_pattern_t pattern; |
|
304 | cairo_image_surface_t *image; |
308 | cairo_surface_t *image; |
305 | cairo_status_t status; |
309 | cairo_status_t status; |
306 | struct extra *extra; |
- | |
307 | uint8_t *data; |
- | |
308 | cairo_bool_t ret; |
- | |
309 | - | ||
310 | if (surface->target->type == CAIRO_SURFACE_TYPE_RECORDING) { |
- | |
311 | cairo_recording_surface_t *meta = (cairo_recording_surface_t *) surface->target; |
- | |
312 | cairo_surface_t *snapshot; |
- | |
313 | - | ||
314 | snapshot = _cairo_surface_has_snapshot (&surface->base, |
- | |
315 | &_cairo_image_surface_backend); |
- | |
316 | if (snapshot != NULL) { |
- | |
317 | *image_out = (cairo_image_surface_t *) cairo_surface_reference (snapshot); |
- | |
318 | *extra_out = NULL; |
- | |
319 | return CAIRO_STATUS_SUCCESS; |
- | |
320 | } |
- | |
321 | - | ||
322 | if (! _cairo_surface_has_snapshot (&meta->base, |
- | |
323 | &_cairo_image_surface_backend)) |
- | |
324 | { |
- | |
325 | image = (cairo_image_surface_t *) |
310 | |
326 | _cairo_image_surface_create_with_content (meta->content, |
311 | image = _cairo_image_surface_create_with_content (surface->base.content, |
327 | surface->extents.width, |
312 | surface->extents.width, |
328 | surface->extents.height); |
313 | surface->extents.height); |
329 | if (unlikely (image->base.status)) |
314 | if (unlikely (image->status)) |
330 | return image->base.status; |
- | |
331 | - | ||
332 | cairo_surface_paint_to_target (&image->base, surface); |
- | |
333 | - | ||
334 | _cairo_surface_attach_snapshot (&surface->base, &image->base, NULL); |
- | |
335 | - | ||
336 | *image_out = image; |
- | |
337 | *extra_out = NULL; |
- | |
338 | return CAIRO_STATUS_SUCCESS; |
- | |
339 | } |
- | |
340 | } |
- | |
341 | - | ||
342 | extra = malloc (sizeof (struct extra)); |
- | |
343 | if (unlikely (extra == NULL)) |
- | |
344 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
- | |
345 | - | ||
346 | status = _cairo_surface_acquire_source_image (surface->target, &extra->image, &extra->image_extra); |
- | |
347 | if (unlikely (status)) |
- | |
348 | goto CLEANUP; |
- | |
349 | - | ||
350 | ret = _cairo_surface_get_extents (&extra->image->base, &target_extents); |
- | |
351 | assert (ret); |
- | |
352 | - | ||
353 | /* only copy if we need to perform sub-byte manipulation */ |
- | |
354 | if (PIXMAN_FORMAT_BPP (extra->image->pixman_format) >= 8 && |
- | |
355 | target_extents.x <= surface->extents.x && |
- | |
356 | target_extents.y <= surface->extents.y && |
- | |
357 | surface->extents.x + surface->extents.width <= target_extents.x + target_extents.width && |
- | |
358 | surface->extents.y + surface->extents.height <= target_extents.y + target_extents.height) { |
- | |
359 | - | ||
360 | assert ((PIXMAN_FORMAT_BPP (extra->image->pixman_format) % 8) == 0); |
- | |
361 | - | ||
362 | data = extra->image->data + surface->extents.y * extra->image->stride; |
- | |
363 | data += PIXMAN_FORMAT_BPP (extra->image->pixman_format) / 8 * surface->extents.x; |
- | |
364 | - | ||
365 | image = (cairo_image_surface_t *) |
- | |
366 | _cairo_image_surface_create_with_pixman_format (data, |
- | |
367 | extra->image->pixman_format, |
- | |
368 | surface->extents.width, |
- | |
369 | surface->extents.height, |
- | |
370 | extra->image->stride); |
- | |
371 | if (unlikely ((status = image->base.status))) |
- | |
372 | goto CLEANUP_IMAGE; |
- | |
373 | - | ||
374 | image->base.is_clear = FALSE; |
- | |
375 | } else { |
- | |
376 | image = (cairo_image_surface_t *) |
- | |
377 | _cairo_image_surface_create_with_pixman_format (NULL, |
- | |
378 | extra->image->pixman_format, |
- | |
379 | surface->extents.width, |
- | |
380 | surface->extents.height, |
- | |
381 | 0); |
- | |
382 | if (unlikely ((status = image->base.status))) |
- | |
383 | goto CLEANUP_IMAGE; |
315 | return image->status; |
- | 316 | ||
- | 317 | _cairo_pattern_init_for_surface (&pattern, surface->target); |
|
- | 318 | cairo_matrix_init_translate (&pattern.base.matrix, |
|
- | 319 | surface->extents.x, |
|
- | 320 | surface->extents.y); |
|
- | 321 | pattern.base.filter = CAIRO_FILTER_NEAREST; |
|
- | 322 | status = _cairo_surface_paint (image, |
|
- | 323 | CAIRO_OPERATOR_SOURCE, |
|
- | 324 | &pattern.base, NULL); |
|
- | 325 | _cairo_pattern_fini (&pattern.base); |
|
- | 326 | if (unlikely (status)) { |
|
384 | 327 | cairo_surface_destroy (image); |
|
385 | cairo_surface_paint_to_target (&image->base, surface); |
328 | return status; |
386 | } |
329 | } |
387 | 330 | ||
388 | *image_out = image; |
- | |
389 | *extra_out = extra; |
- | |
390 | return CAIRO_STATUS_SUCCESS; |
- | |
391 | - | ||
392 | CLEANUP_IMAGE: |
- | |
393 | _cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra); |
- | |
394 | CLEANUP: |
331 | *image_out = (cairo_image_surface_t *)image; |
395 | free (extra); |
332 | *extra_out = NULL; |
396 | return status; |
333 | return CAIRO_STATUS_SUCCESS; |
397 | } |
334 | } |
398 | 335 | ||
399 | static void |
336 | static void |
400 | _cairo_surface_subsurface_release_source_image (void *abstract_surface, |
337 | _cairo_surface_subsurface_release_source_image (void *abstract_surface, |
401 | cairo_image_surface_t *image, |
338 | cairo_image_surface_t *image, |
402 | void *abstract_extra) |
339 | void *abstract_extra) |
403 | { |
340 | { |
404 | cairo_surface_subsurface_t *surface = abstract_surface; |
- | |
405 | - | ||
406 | if (abstract_extra != NULL) { |
- | |
407 | struct extra *extra = abstract_extra; |
- | |
408 | - | ||
409 | _cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra); |
- | |
410 | free (extra); |
- | |
411 | } |
- | |
412 | - | ||
413 | cairo_surface_destroy (&image->base); |
341 | cairo_surface_destroy (&image->base); |
414 | } |
342 | } |
415 | 343 | ||
416 | static cairo_surface_t * |
344 | static cairo_surface_t * |
417 | _cairo_surface_subsurface_snapshot (void *abstract_surface) |
345 | _cairo_surface_subsurface_snapshot (void *abstract_surface) |
418 | { |
346 | { |
419 | cairo_surface_subsurface_t *surface = abstract_surface; |
347 | cairo_surface_subsurface_t *surface = abstract_surface; |
420 | cairo_surface_subsurface_t *snapshot; |
348 | cairo_surface_pattern_t pattern; |
- | 349 | cairo_surface_t *clone; |
|
- | 350 | cairo_status_t status; |
|
421 | 351 | ||
422 | snapshot = malloc (sizeof (cairo_surface_subsurface_t)); |
- | |
423 | if (unlikely (snapshot == NULL)) |
- | |
424 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
352 | TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, surface->target->unique_id)); |
425 | 353 | ||
426 | _cairo_surface_init (&snapshot->base, |
354 | clone = _cairo_surface_create_similar_scratch (surface->target, |
427 | &_cairo_surface_subsurface_backend, |
355 | surface->target->content, |
428 | NULL, /* device */ |
- | |
429 | surface->target->content); |
356 | surface->extents.width, |
430 | snapshot->target = _cairo_surface_snapshot (surface->target); |
357 | surface->extents.height); |
- | 358 | if (unlikely (clone->status)) |
|
- | 359 | return clone; |
|
- | 360 | ||
- | 361 | _cairo_pattern_init_for_surface (&pattern, surface->target); |
|
431 | if (unlikely (snapshot->target->status)) { |
362 | cairo_matrix_init_translate (&pattern.base.matrix, |
- | 363 | surface->extents.x, surface->extents.y); |
|
- | 364 | pattern.base.filter = CAIRO_FILTER_NEAREST; |
|
- | 365 | status = _cairo_surface_paint (clone, |
|
- | 366 | CAIRO_OPERATOR_SOURCE, |
|
432 | cairo_status_t status; |
367 | &pattern.base, NULL); |
- | 368 | _cairo_pattern_fini (&pattern.base); |
|
433 | 369 | ||
434 | status = snapshot->target->status; |
370 | if (unlikely (status)) { |
435 | free (snapshot); |
- | |
436 | return _cairo_surface_create_in_error (status); |
371 | cairo_surface_destroy (clone); |
- | 372 | clone = _cairo_surface_create_in_error (status); |
|
- | 373 | } |
|
- | 374 | ||
- | 375 | return clone; |
|
437 | } |
376 | } |
- | 377 | ||
438 | 378 | static cairo_t * |
|
439 | snapshot->base.type = snapshot->target->type; |
379 | _cairo_surface_subsurface_create_context(void *target) |
440 | snapshot->extents = surface->extents; |
380 | { |
441 | 381 | cairo_surface_subsurface_t *surface = target; |
|
442 | return &snapshot->base; |
382 | return surface->target->backend->create_context (&surface->base); |
443 | } |
383 | } |
444 | 384 | ||
445 | static const cairo_surface_backend_t _cairo_surface_subsurface_backend = { |
385 | static const cairo_surface_backend_t _cairo_surface_subsurface_backend = { |
446 | CAIRO_SURFACE_TYPE_SUBSURFACE, |
386 | CAIRO_SURFACE_TYPE_SUBSURFACE, |
447 | _cairo_surface_subsurface_create_similar, |
- | |
448 | _cairo_surface_subsurface_finish, |
387 | _cairo_surface_subsurface_finish, |
- | 388 | ||
- | 389 | _cairo_surface_subsurface_create_context, |
|
- | 390 | ||
- | 391 | _cairo_surface_subsurface_create_similar, |
|
- | 392 | _cairo_surface_subsurface_create_similar_image, |
|
- | 393 | _cairo_surface_subsurface_map_to_image, |
|
- | 394 | _cairo_surface_subsurface_unmap_image, |
|
- | 395 | ||
449 | 396 | _cairo_surface_subsurface_source, |
|
450 | _cairo_surface_subsurface_acquire_source_image, |
397 | _cairo_surface_subsurface_acquire_source_image, |
451 | _cairo_surface_subsurface_release_source_image, |
- | |
452 | NULL, NULL, /* acquire, release dest */ |
- | |
453 | NULL, /* clone similar */ |
- | |
454 | NULL, /* composite */ |
- | |
455 | NULL, /* fill rectangles */ |
- | |
456 | NULL, /* composite trapezoids */ |
398 | _cairo_surface_subsurface_release_source_image, |
457 | NULL, /* create span renderer */ |
- | |
- | 399 | _cairo_surface_subsurface_snapshot, |
|
458 | NULL, /* check span renderer */ |
400 | |
459 | NULL, /* copy_page */ |
401 | NULL, /* copy_page */ |
- | 402 | NULL, /* show_page */ |
|
460 | NULL, /* show_page */ |
403 | |
461 | _cairo_surface_subsurface_get_extents, |
- | |
462 | NULL, /* old_show_glyphs */ |
404 | _cairo_surface_subsurface_get_extents, |
- | 405 | _cairo_surface_subsurface_get_font_options, |
|
463 | _cairo_surface_subsurface_get_font_options, |
406 | |
464 | _cairo_surface_subsurface_flush, |
407 | _cairo_surface_subsurface_flush, |
465 | _cairo_surface_subsurface_mark_dirty, |
- | |
466 | NULL, /* font_fini */ |
- | |
467 | NULL, /* glyph_fini */ |
408 | _cairo_surface_subsurface_mark_dirty, |
468 | 409 | ||
469 | _cairo_surface_subsurface_paint, |
410 | _cairo_surface_subsurface_paint, |
470 | _cairo_surface_subsurface_mask, |
411 | _cairo_surface_subsurface_mask, |
471 | _cairo_surface_subsurface_stroke, |
412 | _cairo_surface_subsurface_stroke, |
472 | _cairo_surface_subsurface_fill, |
413 | _cairo_surface_subsurface_fill, |
- | 414 | NULL, /* fill/stroke */ |
|
473 | _cairo_surface_subsurface_glyphs, |
415 | _cairo_surface_subsurface_glyphs, |
474 | - | ||
475 | _cairo_surface_subsurface_snapshot, |
- | |
476 | }; |
416 | }; |
477 | 417 | ||
478 | /** |
418 | /** |
479 | * cairo_surface_create_for_rectangle: |
419 | * cairo_surface_create_for_rectangle: |
480 | * @target: an existing surface for which the sub-surface will point to |
420 | * @target: an existing surface for which the sub-surface will point to |
481 | * @x: the x-origin of the sub-surface from the top-left of the target surface (in device-space units) |
421 | * @x: the x-origin of the sub-surface from the top-left of the target surface (in device-space units) |
482 | * @y: the y-origin of the sub-surface from the top-left of the target surface (in device-space units) |
422 | * @y: the y-origin of the sub-surface from the top-left of the target surface (in device-space units) |
483 | * @width: width of the sub-surface (in device-space units) |
423 | * @width: width of the sub-surface (in device-space units) |
484 | * @height: height of the sub-surface (in device-space units) |
424 | * @height: height of the sub-surface (in device-space units) |
485 | * |
425 | * |
486 | * Create a new surface that is a rectangle within the target surface. |
426 | * Create a new surface that is a rectangle within the target surface. |
487 | * All operations drawn to this surface are then clipped and translated |
427 | * All operations drawn to this surface are then clipped and translated |
488 | * onto the target surface. Nothing drawn via this sub-surface outside of |
428 | * onto the target surface. Nothing drawn via this sub-surface outside of |
489 | * its bounds is drawn onto the target surface, making this a useful method |
429 | * its bounds is drawn onto the target surface, making this a useful method |
490 | * for passing constrained child surfaces to library routines that draw |
430 | * for passing constrained child surfaces to library routines that draw |
491 | * directly onto the parent surface, i.e. with no further backend allocations, |
431 | * directly onto the parent surface, i.e. with no further backend allocations, |
492 | * double buffering or copies. |
432 | * double buffering or copies. |
493 | * |
433 | * |
494 | * |
434 | * |
495 | * unless the rectangle is in full device units, is contained within |
435 | * unless the rectangle is in full device units, is contained within |
496 | * the extents of the target surface, and the target or subsurface's |
436 | * the extents of the target surface, and the target or subsurface's |
497 | * device transforms are not changed. |
437 | * device transforms are not changed. |
498 | * |
438 | * |
499 | * Return value: a pointer to the newly allocated surface. The caller |
439 | * Return value: a pointer to the newly allocated surface. The caller |
500 | * owns the surface and should call cairo_surface_destroy() when done |
440 | * owns the surface and should call cairo_surface_destroy() when done |
501 | * with it. |
441 | * with it. |
502 | * |
442 | * |
503 | * This function always returns a valid pointer, but it will return a |
443 | * This function always returns a valid pointer, but it will return a |
504 | * pointer to a "nil" surface if @other is already in an error state |
444 | * pointer to a "nil" surface if @other is already in an error state |
505 | * or any other error occurs. |
445 | * or any other error occurs. |
506 | * |
446 | * |
507 | * Since: 1.10 |
447 | * Since: 1.10 |
508 | **/ |
448 | **/ |
509 | cairo_surface_t * |
449 | cairo_surface_t * |
510 | cairo_surface_create_for_rectangle (cairo_surface_t *target, |
450 | cairo_surface_create_for_rectangle (cairo_surface_t *target, |
511 | double x, double y, |
451 | double x, double y, |
512 | double width, double height) |
452 | double width, double height) |
513 | { |
453 | { |
514 | cairo_surface_subsurface_t *surface; |
454 | cairo_surface_subsurface_t *surface; |
- | 455 | ||
- | 456 | if (unlikely (width < 0 || height < 0)) |
|
- | 457 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_SIZE)); |
|
515 | 458 | ||
516 | if (unlikely (target->status)) |
459 | if (unlikely (target->status)) |
517 | return _cairo_surface_create_in_error (target->status); |
460 | return _cairo_surface_create_in_error (target->status); |
518 | if (unlikely (target->finished)) |
461 | if (unlikely (target->finished)) |
519 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); |
462 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); |
520 | 463 | ||
521 | surface = malloc (sizeof (cairo_surface_subsurface_t)); |
464 | surface = malloc (sizeof (cairo_surface_subsurface_t)); |
522 | if (unlikely (surface == NULL)) |
465 | if (unlikely (surface == NULL)) |
523 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
466 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
524 | 467 | ||
525 | assert (_cairo_matrix_is_translation (&target->device_transform)); |
468 | assert (_cairo_matrix_is_translation (&target->device_transform)); |
526 | x += target->device_transform.x0; |
469 | x += target->device_transform.x0; |
527 | y += target->device_transform.y0; |
470 | y += target->device_transform.y0; |
528 | 471 | ||
529 | _cairo_surface_init (&surface->base, |
472 | _cairo_surface_init (&surface->base, |
530 | &_cairo_surface_subsurface_backend, |
473 | &_cairo_surface_subsurface_backend, |
531 | NULL, /* device */ |
474 | NULL, /* device */ |
532 | target->content); |
475 | target->content); |
533 | 476 | ||
534 | /* XXX forced integer alignment */ |
477 | /* XXX forced integer alignment */ |
535 | surface->extents.x = ceil (x); |
478 | surface->extents.x = ceil (x); |
536 | surface->extents.y = ceil (y); |
479 | surface->extents.y = ceil (y); |
537 | surface->extents.width = floor (x + width) - surface->extents.x; |
480 | surface->extents.width = floor (x + width) - surface->extents.x; |
538 | surface->extents.height = floor (y + height) - surface->extents.y; |
481 | surface->extents.height = floor (y + height) - surface->extents.y; |
- | 482 | if ((surface->extents.width | surface->extents.height) < 0) |
|
- | 483 | surface->extents.width = surface->extents.height = 0; |
|
539 | 484 | ||
540 | if (target->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { |
485 | if (target->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) { |
541 | /* Maintain subsurfaces as 1-depth */ |
486 | /* Maintain subsurfaces as 1-depth */ |
542 | cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) target; |
487 | cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) target; |
543 | surface->extents.x += sub->extents.x; |
488 | surface->extents.x += sub->extents.x; |
544 | surface->extents.y += sub->extents.y; |
489 | surface->extents.y += sub->extents.y; |
545 | target = sub->target; |
490 | target = sub->target; |
546 | } |
491 | } |
547 | 492 | ||
548 | surface->target = cairo_surface_reference (target); |
493 | surface->target = cairo_surface_reference (target); |
- | 494 | surface->base.type = surface->target->type; |
|
- | 495 | ||
- | 496 | surface->snapshot = NULL; |
|
- | 497 | ||
- | 498 | return &surface->base; |
|
- | 499 | } |
|
- | 500 | ||
- | 501 | cairo_surface_t * |
|
- | 502 | _cairo_surface_create_for_rectangle_int (cairo_surface_t *target, |
|
- | 503 | const cairo_rectangle_int_t *extents) |
|
- | 504 | { |
|
- | 505 | cairo_surface_subsurface_t *surface; |
|
- | 506 | ||
- | 507 | if (unlikely (target->status)) |
|
- | 508 | return _cairo_surface_create_in_error (target->status); |
|
- | 509 | if (unlikely (target->finished)) |
|
- | 510 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); |
|
- | 511 | ||
- | 512 | assert (target->backend->type != CAIRO_SURFACE_TYPE_SUBSURFACE); |
|
- | 513 | ||
- | 514 | surface = malloc (sizeof (cairo_surface_subsurface_t)); |
|
- | 515 | if (unlikely (surface == NULL)) |
|
- | 516 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
|
- | 517 | ||
- | 518 | assert (_cairo_matrix_is_translation (&target->device_transform)); |
|
- | 519 | ||
- | 520 | _cairo_surface_init (&surface->base, |
|
- | 521 | &_cairo_surface_subsurface_backend, |
|
- | 522 | NULL, /* device */ |
|
- | 523 | target->content); |
|
- | 524 | ||
- | 525 | surface->extents = *extents; |
|
- | 526 | surface->extents.x += target->device_transform.x0; |
|
- | 527 | surface->extents.y += target->device_transform.y0; |
|
- | 528 | ||
- | 529 | surface->target = cairo_surface_reference (target); |
|
- | 530 | surface->base.type = surface->target->type; |
|
- | 531 | ||
- | 532 | surface->snapshot = NULL; |
|
549 | 533 | ||
550 | return &surface->base; |
534 | return &surface->base; |
551 | } |
535 | } |
552 | /* XXX observe mark-dirty */=>=>=>=> |
536 | /* XXX observe mark-dirty */ |
- | 537 | ||
- | 538 | static void |
|
- | 539 | _cairo_surface_subsurface_detach_snapshot (cairo_surface_t *surface) |
|
- | 540 | { |
|
- | 541 | cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface; |
|
- | 542 | ||
- | 543 | TRACE ((stderr, "%s: target=%d\n", __FUNCTION__, ss->target->unique_id)); |
|
- | 544 | ||
- | 545 | cairo_surface_destroy (ss->snapshot); |
|
- | 546 | ss->snapshot = NULL; |
|
- | 547 | } |
|
- | 548 | ||
- | 549 | void |
|
- | 550 | _cairo_surface_subsurface_set_snapshot (cairo_surface_t *surface, |
|
- | 551 | cairo_surface_t *snapshot) |
|
- | 552 | { |
|
- | 553 | cairo_surface_subsurface_t *ss = (cairo_surface_subsurface_t *) surface; |
|
- | 554 | ||
- | 555 | TRACE ((stderr, "%s: target=%d, snapshot=%d\n", __FUNCTION__, |
|
- | 556 | ss->target->unique_id, snapshot->unique_id)); |
|
- | 557 | ||
- | 558 | /* FIXME: attaching the subsurface as a snapshot to its target creates |
|
- | 559 | * a reference cycle. Let's make this call as a no-op until that bug |
|
- | 560 | * is fixed. |
|
- | 561 | */ |
|
- | 562 | return; |
|
- | 563 | ||
- | 564 | if (ss->snapshot) |
|
- | 565 | _cairo_surface_detach_snapshot (ss->snapshot); |
|
- | 566 | ||
- | 567 | ss->snapshot = cairo_surface_reference (snapshot); |
|
- | 568 | ||
- | 569 | _cairo_surface_attach_snapshot (ss->target, &ss->base, |
|
- | 570 | _cairo_surface_subsurface_detach_snapshot); |
|
- | 571 | }>>> |