Rev 14952 | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
14952 | fschmid | 1 | /* cairo - a vector graphics library with display and print output |
2 | * |
||
3 | * Copyright © 2005 Red Hat, Inc |
||
4 | * Copyright © 2009 Chris Wilson |
||
5 | * |
||
6 | * This library is free software; you can redistribute it and/or |
||
7 | * modify it either under the terms of the GNU Lesser General Public |
||
8 | * License version 2.1 as published by the Free Software Foundation |
||
9 | * (the "LGPL") or, at your option, under the terms of the Mozilla |
||
10 | * Public License Version 1.1 (the "MPL"). If you do not alter this |
||
11 | * notice, a recipient may use your version of this file under either |
||
12 | * the MPL or the LGPL. |
||
13 | * |
||
14 | * You should have received a copy of the LGPL along with this library |
||
15 | * in the file COPYING-LGPL-2.1; if not, write to the Free Software |
||
18122 | mrdocs | 16 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
14952 | fschmid | 17 | * You should have received a copy of the MPL along with this library |
18 | * in the file COPYING-MPL-1.1 |
||
19 | * |
||
20 | * The contents of this file are subject to the Mozilla Public License |
||
21 | * Version 1.1 (the "License"); you may not use this file except in |
||
22 | * compliance with the License. You may obtain a copy of the License at |
||
23 | * http://www.mozilla.org/MPL/ |
||
24 | * |
||
25 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY |
||
26 | * OF ANY KIND, either express or implied. See the LGPL or the MPL for |
||
27 | * the specific language governing rights and limitations. |
||
28 | * |
||
29 | * The Original Code is the cairo graphics library. |
||
30 | * |
||
31 | * The Initial Developer of the Original Code is Red Hat, Inc. |
||
32 | * |
||
33 | * Contributor(s): |
||
34 | * Carl Worth <cworth@cworth.org> |
||
35 | * Chris Wilson <chris@chris-wilson.co.uk> |
||
36 | */ |
||
37 | |||
38 | /* This surface supports redirecting all its input to multiple surfaces. |
||
39 | */ |
||
40 | |||
41 | #include "cairoint.h" |
||
42 | |||
43 | #include "cairo-tee-surface-private.h" |
||
44 | #include "cairo-surface-wrapper-private.h" |
||
45 | |||
46 | typedef struct _cairo_tee_surface { |
||
47 | cairo_surface_t base; |
||
48 | |||
49 | cairo_surface_wrapper_t master; |
||
50 | cairo_array_t slaves; |
||
51 | } cairo_tee_surface_t; |
||
52 | |||
53 | slim_hidden_proto (cairo_tee_surface_create); |
||
54 | slim_hidden_proto (cairo_tee_surface_add); |
||
55 | |||
56 | static cairo_surface_t * |
||
57 | _cairo_tee_surface_create_similar (void *abstract_surface, |
||
58 | cairo_content_t content, |
||
59 | int width, |
||
60 | int height) |
||
61 | { |
||
62 | |||
63 | cairo_tee_surface_t *other = abstract_surface; |
||
64 | cairo_surface_t *similar; |
||
65 | cairo_surface_t *surface; |
||
66 | cairo_surface_wrapper_t *slaves; |
||
67 | int n, num_slaves; |
||
68 | |||
69 | similar = _cairo_surface_wrapper_create_similar (&other->master, |
||
70 | content, width, height); |
||
71 | surface = cairo_tee_surface_create (similar); |
||
72 | cairo_surface_destroy (similar); |
||
73 | if (unlikely (surface->status)) |
||
74 | return surface; |
||
75 | |||
76 | num_slaves = _cairo_array_num_elements (&other->slaves); |
||
77 | slaves = _cairo_array_index (&other->slaves, 0); |
||
78 | for (n = 0; n < num_slaves; n++) { |
||
79 | |||
80 | similar = _cairo_surface_wrapper_create_similar (&slaves[n], |
||
81 | content, |
||
82 | width, height); |
||
83 | cairo_tee_surface_add (surface, similar); |
||
84 | cairo_surface_destroy (similar); |
||
85 | } |
||
86 | |||
87 | if (unlikely (surface->status)) { |
||
88 | cairo_status_t status = surface->status; |
||
89 | cairo_surface_destroy (surface); |
||
90 | surface = _cairo_surface_create_in_error (status); |
||
91 | } |
||
92 | |||
93 | return surface; |
||
94 | } |
||
95 | |||
96 | static cairo_status_t |
||
97 | _cairo_tee_surface_finish (void *abstract_surface) |
||
98 | { |
||
99 | cairo_tee_surface_t *surface = abstract_surface; |
||
100 | cairo_surface_wrapper_t *slaves; |
||
101 | int n, num_slaves; |
||
102 | |||
103 | _cairo_surface_wrapper_fini (&surface->master); |
||
104 | |||
105 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
106 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
107 | for (n = 0; n < num_slaves; n++) |
||
108 | _cairo_surface_wrapper_fini (&slaves[n]); |
||
109 | |||
110 | _cairo_array_fini (&surface->slaves); |
||
111 | |||
112 | return CAIRO_STATUS_SUCCESS; |
||
113 | } |
||
114 | |||
115 | static cairo_status_t |
||
116 | _cairo_tee_surface_acquire_source_image (void *abstract_surface, |
||
117 | cairo_image_surface_t **image_out, |
||
118 | void **image_extra) |
||
119 | { |
||
120 | cairo_tee_surface_t *surface = abstract_surface; |
||
121 | cairo_surface_wrapper_t *slaves; |
||
122 | int num_slaves, n; |
||
123 | |||
124 | /* we prefer to use a real image surface if available */ |
||
125 | if (_cairo_surface_is_image (surface->master.target)) { |
||
126 | return _cairo_surface_wrapper_acquire_source_image (&surface->master, |
||
127 | image_out, image_extra); |
||
128 | } |
||
129 | |||
130 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
131 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
132 | for (n = 0; n < num_slaves; n++) { |
||
133 | if (_cairo_surface_is_image (slaves[n].target)) { |
||
134 | return _cairo_surface_wrapper_acquire_source_image (&slaves[n], |
||
135 | image_out, |
||
136 | image_extra); |
||
137 | } |
||
138 | } |
||
139 | |||
140 | return _cairo_surface_wrapper_acquire_source_image (&surface->master, |
||
141 | image_out, image_extra); |
||
142 | } |
||
143 | |||
144 | static void |
||
145 | _cairo_tee_surface_release_source_image (void *abstract_surface, |
||
146 | cairo_image_surface_t *image, |
||
147 | void *image_extra) |
||
148 | { |
||
149 | cairo_tee_surface_t *surface = abstract_surface; |
||
150 | |||
151 | _cairo_surface_wrapper_release_source_image (&surface->master, |
||
152 | image, image_extra); |
||
153 | } |
||
154 | |||
155 | static cairo_surface_t * |
||
156 | _cairo_tee_surface_snapshot (void *abstract_surface) |
||
157 | { |
||
158 | cairo_tee_surface_t *surface = abstract_surface; |
||
159 | cairo_surface_wrapper_t *slaves; |
||
160 | int num_slaves, n; |
||
161 | |||
162 | /* we prefer to use a meta surface for our snapshots */ |
||
163 | if (_cairo_surface_is_meta (surface->master.target)) |
||
164 | return _cairo_surface_wrapper_snapshot (&surface->master); |
||
165 | |||
166 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
167 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
168 | for (n = 0; n < num_slaves; n++) { |
||
169 | if (_cairo_surface_is_meta (slaves[n].target)) |
||
170 | return _cairo_surface_wrapper_snapshot (&slaves[n]); |
||
171 | } |
||
172 | |||
173 | return _cairo_surface_wrapper_snapshot (&surface->master); |
||
174 | } |
||
175 | |||
176 | static cairo_bool_t |
||
177 | _cairo_tee_surface_get_extents (void *abstract_surface, |
||
178 | cairo_rectangle_int_t *rectangle) |
||
179 | { |
||
180 | cairo_tee_surface_t *surface = abstract_surface; |
||
181 | |||
182 | return _cairo_surface_wrapper_get_extents (&surface->master, rectangle); |
||
183 | } |
||
184 | |||
185 | static void |
||
186 | _cairo_tee_surface_get_font_options (void *abstract_surface, |
||
187 | cairo_font_options_t *options) |
||
188 | { |
||
189 | cairo_tee_surface_t *surface = abstract_surface; |
||
190 | |||
191 | _cairo_surface_wrapper_get_font_options (&surface->master, options); |
||
192 | } |
||
193 | |||
194 | static cairo_int_status_t |
||
195 | _cairo_tee_surface_paint (void *abstract_surface, |
||
196 | cairo_operator_t op, |
||
197 | const cairo_pattern_t *source, |
||
198 | cairo_clip_t *clip) |
||
199 | { |
||
200 | cairo_tee_surface_t *surface = abstract_surface; |
||
201 | cairo_surface_wrapper_t *slaves; |
||
202 | int n, num_slaves; |
||
203 | cairo_status_t status; |
||
204 | |||
205 | status = _cairo_surface_wrapper_paint (&surface->master, op, source, clip); |
||
206 | if (unlikely (status)) |
||
207 | return status; |
||
208 | |||
209 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
210 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
211 | for (n = 0; n < num_slaves; n++) { |
||
212 | status = _cairo_surface_wrapper_paint (&slaves[n], op, source, clip); |
||
213 | if (unlikely (status)) |
||
214 | return status; |
||
215 | } |
||
216 | |||
217 | return CAIRO_STATUS_SUCCESS; |
||
218 | } |
||
219 | |||
220 | static cairo_int_status_t |
||
221 | _cairo_tee_surface_mask (void *abstract_surface, |
||
222 | cairo_operator_t op, |
||
223 | const cairo_pattern_t *source, |
||
224 | const cairo_pattern_t *mask, |
||
225 | cairo_clip_t *clip) |
||
226 | { |
||
227 | cairo_tee_surface_t *surface = abstract_surface; |
||
228 | cairo_surface_wrapper_t *slaves; |
||
229 | int n, num_slaves; |
||
230 | cairo_status_t status; |
||
231 | |||
232 | status = _cairo_surface_wrapper_mask (&surface->master, |
||
233 | op, source, mask, clip); |
||
234 | if (unlikely (status)) |
||
235 | return status; |
||
236 | |||
237 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
238 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
239 | for (n = 0; n < num_slaves; n++) { |
||
240 | status = _cairo_surface_wrapper_mask (&slaves[n], |
||
241 | op, source, mask, clip); |
||
242 | if (unlikely (status)) |
||
243 | return status; |
||
244 | } |
||
245 | |||
246 | return CAIRO_STATUS_SUCCESS; |
||
247 | } |
||
248 | |||
249 | static cairo_int_status_t |
||
250 | _cairo_tee_surface_stroke (void *abstract_surface, |
||
251 | cairo_operator_t op, |
||
252 | const cairo_pattern_t *source, |
||
253 | cairo_path_fixed_t *path, |
||
254 | cairo_stroke_style_t *style, |
||
255 | cairo_matrix_t *ctm, |
||
256 | cairo_matrix_t *ctm_inverse, |
||
257 | double tolerance, |
||
258 | cairo_antialias_t antialias, |
||
259 | cairo_clip_t *clip) |
||
260 | { |
||
261 | cairo_tee_surface_t *surface = abstract_surface; |
||
262 | cairo_surface_wrapper_t *slaves; |
||
263 | int n, num_slaves; |
||
264 | cairo_status_t status; |
||
265 | |||
266 | status = _cairo_surface_wrapper_stroke (&surface->master, |
||
267 | op, source, |
||
268 | path, style, |
||
269 | ctm, ctm_inverse, |
||
270 | tolerance, antialias, |
||
271 | clip); |
||
272 | if (unlikely (status)) |
||
273 | return status; |
||
274 | |||
275 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
276 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
277 | for (n = 0; n < num_slaves; n++) { |
||
278 | status = _cairo_surface_wrapper_stroke (&slaves[n], |
||
279 | op, source, |
||
280 | path, style, |
||
281 | ctm, ctm_inverse, |
||
282 | tolerance, antialias, |
||
283 | clip); |
||
284 | if (unlikely (status)) |
||
285 | return status; |
||
286 | } |
||
287 | |||
288 | return CAIRO_STATUS_SUCCESS; |
||
289 | } |
||
290 | |||
291 | static cairo_int_status_t |
||
292 | _cairo_tee_surface_fill (void *abstract_surface, |
||
293 | cairo_operator_t op, |
||
294 | const cairo_pattern_t *source, |
||
295 | cairo_path_fixed_t *path, |
||
296 | cairo_fill_rule_t fill_rule, |
||
297 | double tolerance, |
||
298 | cairo_antialias_t antialias, |
||
299 | cairo_clip_t *clip) |
||
300 | { |
||
301 | cairo_tee_surface_t *surface = abstract_surface; |
||
302 | cairo_surface_wrapper_t *slaves; |
||
303 | int n, num_slaves; |
||
304 | cairo_status_t status; |
||
305 | |||
306 | status = _cairo_surface_wrapper_fill (&surface->master, |
||
307 | op, source, |
||
308 | path, fill_rule, |
||
309 | tolerance, antialias, |
||
310 | clip); |
||
311 | if (unlikely (status)) |
||
312 | return status; |
||
313 | |||
314 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
315 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
316 | for (n = 0; n < num_slaves; n++) { |
||
317 | status = _cairo_surface_wrapper_fill (&slaves[n], |
||
318 | op, source, |
||
319 | path, fill_rule, |
||
320 | tolerance, antialias, |
||
321 | clip); |
||
322 | if (unlikely (status)) |
||
323 | return status; |
||
324 | } |
||
325 | |||
326 | return CAIRO_STATUS_SUCCESS; |
||
327 | } |
||
328 | |||
329 | static cairo_bool_t |
||
330 | _cairo_tee_surface_has_show_text_glyphs (void *abstract_surface) |
||
331 | { |
||
332 | return TRUE; |
||
333 | } |
||
334 | |||
335 | static cairo_int_status_t |
||
336 | _cairo_tee_surface_show_text_glyphs (void *abstract_surface, |
||
337 | cairo_operator_t op, |
||
338 | const cairo_pattern_t *source, |
||
339 | const char *utf8, |
||
340 | int utf8_len, |
||
341 | cairo_glyph_t *glyphs, |
||
342 | int num_glyphs, |
||
343 | const cairo_text_cluster_t *clusters, |
||
344 | int num_clusters, |
||
345 | cairo_text_cluster_flags_t cluster_flags, |
||
346 | cairo_scaled_font_t *scaled_font, |
||
347 | cairo_clip_t *clip) |
||
348 | { |
||
349 | cairo_tee_surface_t *surface = abstract_surface; |
||
350 | cairo_surface_wrapper_t *slaves; |
||
351 | int n, num_slaves; |
||
352 | cairo_status_t status; |
||
353 | cairo_glyph_t *glyphs_copy; |
||
354 | |||
355 | /* XXX: This copying is ugly. */ |
||
356 | glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); |
||
357 | if (unlikely (glyphs_copy == NULL)) |
||
358 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
||
359 | |||
360 | memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); |
||
361 | status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, op, |
||
362 | source, |
||
363 | utf8, utf8_len, |
||
364 | glyphs_copy, num_glyphs, |
||
365 | clusters, num_clusters, |
||
366 | cluster_flags, |
||
367 | scaled_font, |
||
368 | clip); |
||
369 | if (unlikely (status)) |
||
370 | goto CLEANUP; |
||
371 | |||
372 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
373 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
374 | for (n = 0; n < num_slaves; n++) { |
||
375 | memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); |
||
376 | status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op, |
||
377 | source, |
||
378 | utf8, utf8_len, |
||
379 | glyphs_copy, num_glyphs, |
||
380 | clusters, num_clusters, |
||
381 | cluster_flags, |
||
382 | scaled_font, |
||
383 | clip); |
||
384 | if (unlikely (status)) |
||
385 | goto CLEANUP; |
||
386 | } |
||
387 | |||
388 | CLEANUP: |
||
389 | free (glyphs_copy); |
||
390 | return status; |
||
391 | } |
||
392 | |||
393 | static const cairo_surface_backend_t cairo_tee_surface_backend = { |
||
394 | CAIRO_SURFACE_TYPE_TEE, |
||
395 | _cairo_tee_surface_create_similar, |
||
396 | _cairo_tee_surface_finish, |
||
397 | _cairo_tee_surface_acquire_source_image, |
||
398 | _cairo_tee_surface_release_source_image, |
||
399 | NULL, NULL, /* dest_image */ |
||
400 | NULL, /* clone_similar */ |
||
401 | NULL, /* composite */ |
||
402 | NULL, /* fill_rectangles */ |
||
403 | NULL, /* composite_trapezoids */ |
||
404 | NULL, /* create_span_renderer */ |
||
405 | NULL, /* check_span_renderer */ |
||
406 | NULL, /* copy_page */ |
||
407 | NULL, /* show_page */ |
||
408 | _cairo_tee_surface_get_extents, |
||
409 | NULL, /* old_show_glyphs */ |
||
410 | _cairo_tee_surface_get_font_options, |
||
411 | NULL, /* flush */ |
||
412 | NULL, /* mark_dirty_rectangle */ |
||
413 | NULL, /* scaled_font_fini */ |
||
414 | NULL, /* scaled_glyph_fini */ |
||
415 | |||
416 | _cairo_tee_surface_paint, |
||
417 | _cairo_tee_surface_mask, |
||
418 | _cairo_tee_surface_stroke, |
||
419 | _cairo_tee_surface_fill, |
||
420 | NULL, /* replaced by show_text_glyphs */ |
||
421 | |||
422 | _cairo_tee_surface_snapshot, |
||
423 | NULL, /* is_similar */ |
||
424 | NULL, /* fill_stroke */ |
||
425 | NULL, /* create_solid_pattern_surface */ |
||
426 | NULL, /* can_repaint_solid_pattern_surface */ |
||
427 | |||
428 | _cairo_tee_surface_has_show_text_glyphs, |
||
429 | _cairo_tee_surface_show_text_glyphs |
||
430 | }; |
||
431 | |||
432 | cairo_surface_t * |
||
433 | cairo_tee_surface_create (cairo_surface_t *master) |
||
434 | { |
||
435 | cairo_tee_surface_t *surface; |
||
436 | |||
437 | if (unlikely (master->status)) |
||
438 | return _cairo_surface_create_in_error (master->status); |
||
439 | |||
440 | surface = malloc (sizeof (cairo_tee_surface_t)); |
||
441 | if (unlikely (surface == NULL)) |
||
442 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
||
443 | |||
444 | _cairo_surface_init (&surface->base, |
||
445 | &cairo_tee_surface_backend, |
||
446 | master->content); |
||
447 | |||
448 | _cairo_surface_wrapper_init (&surface->master, master); |
||
449 | /* we trust that these are already set and remain constant */ |
||
450 | surface->base.device_transform = master->device_transform; |
||
451 | surface->base.device_transform_inverse = master->device_transform_inverse; |
||
452 | |||
453 | _cairo_array_init (&surface->slaves, sizeof (cairo_surface_wrapper_t)); |
||
454 | |||
455 | return &surface->base; |
||
456 | } |
||
457 | slim_hidden_def (cairo_tee_surface_create); |
||
458 | |||
459 | void |
||
460 | cairo_tee_surface_add (cairo_surface_t *abstract_surface, |
||
461 | cairo_surface_t *target) |
||
462 | { |
||
463 | cairo_tee_surface_t *surface; |
||
464 | cairo_surface_wrapper_t slave; |
||
465 | cairo_status_t status; |
||
466 | |||
467 | if (unlikely (abstract_surface->status)) |
||
468 | return; |
||
469 | |||
470 | if (abstract_surface->backend != &cairo_tee_surface_backend) { |
||
471 | status = _cairo_surface_set_error (abstract_surface, |
||
472 | _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); |
||
473 | return; |
||
474 | } |
||
475 | |||
476 | if (unlikely (target->status)) { |
||
477 | status = _cairo_surface_set_error (abstract_surface, target->status); |
||
478 | return; |
||
479 | } |
||
480 | |||
481 | surface = (cairo_tee_surface_t *) abstract_surface; |
||
482 | |||
483 | _cairo_surface_wrapper_init (&slave, target); |
||
484 | status = _cairo_array_append (&surface->slaves, &slave); |
||
485 | if (unlikely (status)) { |
||
486 | _cairo_surface_wrapper_fini (&slave); |
||
487 | status = _cairo_surface_set_error (&surface->base, status); |
||
488 | } |
||
489 | } |
||
490 | slim_hidden_def (cairo_tee_surface_add); |
||
491 | |||
492 | void |
||
493 | cairo_tee_surface_remove (cairo_surface_t *abstract_surface, |
||
494 | cairo_surface_t *target) |
||
495 | { |
||
496 | cairo_tee_surface_t *surface; |
||
497 | cairo_surface_wrapper_t *slaves; |
||
498 | int n, num_slaves; |
||
499 | cairo_status_t status; |
||
500 | |||
501 | if (abstract_surface->backend != &cairo_tee_surface_backend) { |
||
502 | status = _cairo_surface_set_error (abstract_surface, |
||
503 | _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); |
||
504 | return; |
||
505 | } |
||
506 | |||
507 | surface = (cairo_tee_surface_t *) abstract_surface; |
||
508 | if (target == surface->master.target) { |
||
509 | status = _cairo_surface_set_error (abstract_surface, |
||
510 | _cairo_error (CAIRO_STATUS_INVALID_INDEX)); |
||
511 | return; |
||
512 | } |
||
513 | |||
514 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
515 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
516 | for (n = 0; n < num_slaves; n++) { |
||
517 | if (slaves[n].target == target) |
||
518 | break; |
||
519 | } |
||
520 | |||
521 | if (n == num_slaves) { |
||
522 | status = _cairo_surface_set_error (abstract_surface, |
||
523 | _cairo_error (CAIRO_STATUS_INVALID_INDEX)); |
||
524 | return; |
||
525 | } |
||
526 | |||
527 | _cairo_surface_wrapper_fini (&slaves[n]); |
||
528 | for (n++; n < num_slaves; n++) |
||
529 | slaves[n-1] = slaves[n]; |
||
530 | surface->slaves.num_elements--; /* XXX: cairo_array_remove()? */ |
||
531 | } |
||
532 | |||
533 | cairo_surface_t * |
||
534 | cairo_tee_surface_index (cairo_surface_t *abstract_surface, |
||
535 | int index) |
||
536 | { |
||
537 | cairo_tee_surface_t *surface; |
||
538 | |||
539 | if (unlikely (abstract_surface->status)) |
||
540 | return _cairo_surface_create_in_error (abstract_surface->status); |
||
541 | |||
542 | if (abstract_surface->backend != &cairo_tee_surface_backend) |
||
543 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); |
||
544 | |||
545 | surface = (cairo_tee_surface_t *) abstract_surface; |
||
546 | if (index == 0) { |
||
547 | return surface->master.target; |
||
548 | } else { |
||
549 | cairo_surface_wrapper_t *slave; |
||
550 | |||
551 | index--; |
||
552 | |||
553 | if (index >= _cairo_array_num_elements (&surface->slaves)) |
||
554 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX)); |
||
555 | |||
556 | slave = _cairo_array_index (&surface->slaves, index); |
||
557 | return slave->target; |
||
558 | } |
||
559 | } |
||
560 | |||
561 | cairo_surface_t * |
||
562 | _cairo_tee_surface_find_match (void *abstract_surface, |
||
563 | const cairo_surface_backend_t *backend, |
||
564 | cairo_content_t content) |
||
565 | { |
||
566 | cairo_tee_surface_t *surface = abstract_surface; |
||
567 | cairo_surface_wrapper_t *slaves; |
||
568 | int num_slaves, n; |
||
569 | |||
570 | /* exact match first */ |
||
571 | if (surface->master.target->backend == backend && |
||
572 | surface->master.target->content == content) |
||
573 | { |
||
574 | return surface->master.target; |
||
575 | } |
||
576 | |||
577 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
578 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
579 | for (n = 0; n < num_slaves; n++) { |
||
580 | if (slaves[n].target->backend == backend && |
||
581 | slaves[n].target->content == content) |
||
582 | { |
||
583 | return slaves[n].target; |
||
584 | } |
||
585 | } |
||
586 | |||
587 | /* matching backend? */ |
||
588 | if (surface->master.target->backend == backend) |
||
589 | return surface->master.target; |
||
590 | |||
591 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
592 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
593 | for (n = 0; n < num_slaves; n++) { |
||
594 | if (slaves[n].target->backend == backend) |
||
595 | return slaves[n].target; |
||
596 | } |
||
597 | |||
598 | return NULL; |
||
599 | } |