Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
3959 | Serge | 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 |
||
16 | * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA |
||
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 |
||
35 | * Chris Wilson |
||
36 | */ |
||
37 | |||
38 | /* This surface supports redirecting all its input to multiple surfaces. |
||
39 | */ |
||
40 | |||
41 | #include "cairoint.h" |
||
42 | |||
43 | #include "cairo-tee.h" |
||
44 | |||
45 | #include "cairo-default-context-private.h" |
||
46 | #include "cairo-error-private.h" |
||
47 | #include "cairo-tee-surface-private.h" |
||
48 | #include "cairo-recording-surface-inline.h" |
||
49 | #include "cairo-surface-wrapper-private.h" |
||
50 | #include "cairo-array-private.h" |
||
51 | #include "cairo-image-surface-inline.h" |
||
52 | |||
53 | typedef struct _cairo_tee_surface { |
||
54 | cairo_surface_t base; |
||
55 | |||
56 | cairo_surface_wrapper_t master; |
||
57 | cairo_array_t slaves; |
||
58 | } cairo_tee_surface_t; |
||
59 | |||
60 | slim_hidden_proto (cairo_tee_surface_create); |
||
61 | slim_hidden_proto (cairo_tee_surface_add); |
||
62 | |||
63 | static cairo_surface_t * |
||
64 | _cairo_tee_surface_create_similar (void *abstract_surface, |
||
65 | cairo_content_t content, |
||
66 | int width, |
||
67 | int height) |
||
68 | { |
||
69 | |||
70 | cairo_tee_surface_t *other = abstract_surface; |
||
71 | cairo_surface_t *similar; |
||
72 | cairo_surface_t *surface; |
||
73 | cairo_surface_wrapper_t *slaves; |
||
74 | int n, num_slaves; |
||
75 | |||
76 | similar = _cairo_surface_wrapper_create_similar (&other->master, |
||
77 | content, width, height); |
||
78 | surface = cairo_tee_surface_create (similar); |
||
79 | cairo_surface_destroy (similar); |
||
80 | if (unlikely (surface->status)) |
||
81 | return surface; |
||
82 | |||
83 | num_slaves = _cairo_array_num_elements (&other->slaves); |
||
84 | slaves = _cairo_array_index (&other->slaves, 0); |
||
85 | for (n = 0; n < num_slaves; n++) { |
||
86 | |||
87 | similar = _cairo_surface_wrapper_create_similar (&slaves[n], |
||
88 | content, |
||
89 | width, height); |
||
90 | cairo_tee_surface_add (surface, similar); |
||
91 | cairo_surface_destroy (similar); |
||
92 | } |
||
93 | |||
94 | if (unlikely (surface->status)) { |
||
95 | cairo_status_t status = surface->status; |
||
96 | cairo_surface_destroy (surface); |
||
97 | surface = _cairo_surface_create_in_error (status); |
||
98 | } |
||
99 | |||
100 | return surface; |
||
101 | } |
||
102 | |||
103 | static cairo_status_t |
||
104 | _cairo_tee_surface_finish (void *abstract_surface) |
||
105 | { |
||
106 | cairo_tee_surface_t *surface = abstract_surface; |
||
107 | cairo_surface_wrapper_t *slaves; |
||
108 | int n, num_slaves; |
||
109 | |||
110 | _cairo_surface_wrapper_fini (&surface->master); |
||
111 | |||
112 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
113 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
114 | for (n = 0; n < num_slaves; n++) |
||
115 | _cairo_surface_wrapper_fini (&slaves[n]); |
||
116 | |||
117 | _cairo_array_fini (&surface->slaves); |
||
118 | |||
119 | return CAIRO_STATUS_SUCCESS; |
||
120 | } |
||
121 | |||
122 | static cairo_surface_t * |
||
123 | _cairo_tee_surface_source (void *abstract_surface, |
||
124 | cairo_rectangle_int_t *extents) |
||
125 | { |
||
126 | cairo_tee_surface_t *surface = abstract_surface; |
||
127 | return _cairo_surface_get_source (surface->master.target, extents); |
||
128 | } |
||
129 | |||
130 | static cairo_status_t |
||
131 | _cairo_tee_surface_acquire_source_image (void *abstract_surface, |
||
132 | cairo_image_surface_t **image_out, |
||
133 | void **image_extra) |
||
134 | { |
||
135 | cairo_tee_surface_t *surface = abstract_surface; |
||
136 | cairo_surface_wrapper_t *slaves; |
||
137 | int num_slaves, n; |
||
138 | |||
139 | /* we prefer to use a real image surface if available */ |
||
140 | if (_cairo_surface_is_image (surface->master.target)) { |
||
141 | return _cairo_surface_wrapper_acquire_source_image (&surface->master, |
||
142 | image_out, image_extra); |
||
143 | } |
||
144 | |||
145 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
146 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
147 | for (n = 0; n < num_slaves; n++) { |
||
148 | if (_cairo_surface_is_image (slaves[n].target)) { |
||
149 | return _cairo_surface_wrapper_acquire_source_image (&slaves[n], |
||
150 | image_out, |
||
151 | image_extra); |
||
152 | } |
||
153 | } |
||
154 | |||
155 | return _cairo_surface_wrapper_acquire_source_image (&surface->master, |
||
156 | image_out, image_extra); |
||
157 | } |
||
158 | |||
159 | static void |
||
160 | _cairo_tee_surface_release_source_image (void *abstract_surface, |
||
161 | cairo_image_surface_t *image, |
||
162 | void *image_extra) |
||
163 | { |
||
164 | cairo_tee_surface_t *surface = abstract_surface; |
||
165 | |||
166 | _cairo_surface_wrapper_release_source_image (&surface->master, |
||
167 | image, image_extra); |
||
168 | } |
||
169 | |||
170 | static cairo_surface_t * |
||
171 | _cairo_tee_surface_snapshot (void *abstract_surface) |
||
172 | { |
||
173 | cairo_tee_surface_t *surface = abstract_surface; |
||
174 | cairo_surface_wrapper_t *slaves; |
||
175 | int num_slaves, n; |
||
176 | |||
177 | /* we prefer to use a recording surface for our snapshots */ |
||
178 | if (_cairo_surface_is_recording (surface->master.target)) |
||
179 | return _cairo_surface_wrapper_snapshot (&surface->master); |
||
180 | |||
181 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
182 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
183 | for (n = 0; n < num_slaves; n++) { |
||
184 | if (_cairo_surface_is_recording (slaves[n].target)) |
||
185 | return _cairo_surface_wrapper_snapshot (&slaves[n]); |
||
186 | } |
||
187 | |||
188 | return _cairo_surface_wrapper_snapshot (&surface->master); |
||
189 | } |
||
190 | |||
191 | static cairo_bool_t |
||
192 | _cairo_tee_surface_get_extents (void *abstract_surface, |
||
193 | cairo_rectangle_int_t *rectangle) |
||
194 | { |
||
195 | cairo_tee_surface_t *surface = abstract_surface; |
||
196 | |||
197 | return _cairo_surface_wrapper_get_extents (&surface->master, rectangle); |
||
198 | } |
||
199 | |||
200 | static void |
||
201 | _cairo_tee_surface_get_font_options (void *abstract_surface, |
||
202 | cairo_font_options_t *options) |
||
203 | { |
||
204 | cairo_tee_surface_t *surface = abstract_surface; |
||
205 | |||
206 | _cairo_surface_wrapper_get_font_options (&surface->master, options); |
||
207 | } |
||
208 | |||
209 | static cairo_int_status_t |
||
210 | _cairo_tee_surface_paint (void *abstract_surface, |
||
211 | cairo_operator_t op, |
||
212 | const cairo_pattern_t *source, |
||
213 | const cairo_clip_t *clip) |
||
214 | { |
||
215 | cairo_tee_surface_t *surface = abstract_surface; |
||
216 | cairo_surface_wrapper_t *slaves; |
||
217 | int n, num_slaves; |
||
218 | cairo_int_status_t status; |
||
219 | |||
220 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
221 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
222 | for (n = 0; n < num_slaves; n++) { |
||
223 | status = _cairo_surface_wrapper_paint (&slaves[n], op, source, clip); |
||
224 | if (unlikely (status)) |
||
225 | return status; |
||
226 | } |
||
227 | |||
228 | return _cairo_surface_wrapper_paint (&surface->master, op, source, clip); |
||
229 | } |
||
230 | |||
231 | static cairo_int_status_t |
||
232 | _cairo_tee_surface_mask (void *abstract_surface, |
||
233 | cairo_operator_t op, |
||
234 | const cairo_pattern_t *source, |
||
235 | const cairo_pattern_t *mask, |
||
236 | const cairo_clip_t *clip) |
||
237 | { |
||
238 | cairo_tee_surface_t *surface = abstract_surface; |
||
239 | cairo_surface_wrapper_t *slaves; |
||
240 | cairo_int_status_t status; |
||
241 | int n, num_slaves; |
||
242 | |||
243 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
244 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
245 | for (n = 0; n < num_slaves; n++) { |
||
246 | status = _cairo_surface_wrapper_mask (&slaves[n], |
||
247 | op, source, mask, clip); |
||
248 | if (unlikely (status)) |
||
249 | return status; |
||
250 | } |
||
251 | |||
252 | return _cairo_surface_wrapper_mask (&surface->master, |
||
253 | op, source, mask, clip); |
||
254 | } |
||
255 | |||
256 | static cairo_int_status_t |
||
257 | _cairo_tee_surface_stroke (void *abstract_surface, |
||
258 | cairo_operator_t op, |
||
259 | const cairo_pattern_t *source, |
||
260 | const cairo_path_fixed_t *path, |
||
261 | const cairo_stroke_style_t *style, |
||
262 | const cairo_matrix_t *ctm, |
||
263 | const cairo_matrix_t *ctm_inverse, |
||
264 | double tolerance, |
||
265 | cairo_antialias_t antialias, |
||
266 | const cairo_clip_t *clip) |
||
267 | { |
||
268 | cairo_tee_surface_t *surface = abstract_surface; |
||
269 | cairo_surface_wrapper_t *slaves; |
||
270 | cairo_int_status_t status; |
||
271 | int n, num_slaves; |
||
272 | |||
273 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
274 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
275 | for (n = 0; n < num_slaves; n++) { |
||
276 | status = _cairo_surface_wrapper_stroke (&slaves[n], |
||
277 | op, source, |
||
278 | path, style, |
||
279 | ctm, ctm_inverse, |
||
280 | tolerance, antialias, |
||
281 | clip); |
||
282 | if (unlikely (status)) |
||
283 | return status; |
||
284 | } |
||
285 | |||
286 | return _cairo_surface_wrapper_stroke (&surface->master, |
||
287 | op, source, |
||
288 | path, style, |
||
289 | ctm, ctm_inverse, |
||
290 | tolerance, antialias, |
||
291 | clip); |
||
292 | } |
||
293 | |||
294 | static cairo_int_status_t |
||
295 | _cairo_tee_surface_fill (void *abstract_surface, |
||
296 | cairo_operator_t op, |
||
297 | const cairo_pattern_t *source, |
||
298 | const cairo_path_fixed_t *path, |
||
299 | cairo_fill_rule_t fill_rule, |
||
300 | double tolerance, |
||
301 | cairo_antialias_t antialias, |
||
302 | const cairo_clip_t *clip) |
||
303 | { |
||
304 | cairo_tee_surface_t *surface = abstract_surface; |
||
305 | cairo_surface_wrapper_t *slaves; |
||
306 | cairo_int_status_t status; |
||
307 | int n, num_slaves; |
||
308 | |||
309 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
310 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
311 | for (n = 0; n < num_slaves; n++) { |
||
312 | status = _cairo_surface_wrapper_fill (&slaves[n], |
||
313 | op, source, |
||
314 | path, fill_rule, |
||
315 | tolerance, antialias, |
||
316 | clip); |
||
317 | if (unlikely (status)) |
||
318 | return status; |
||
319 | } |
||
320 | |||
321 | return _cairo_surface_wrapper_fill (&surface->master, |
||
322 | op, source, |
||
323 | path, fill_rule, |
||
324 | tolerance, antialias, |
||
325 | clip); |
||
326 | } |
||
327 | |||
328 | static cairo_bool_t |
||
329 | _cairo_tee_surface_has_show_text_glyphs (void *abstract_surface) |
||
330 | { |
||
331 | return TRUE; |
||
332 | } |
||
333 | |||
334 | static cairo_int_status_t |
||
335 | _cairo_tee_surface_show_text_glyphs (void *abstract_surface, |
||
336 | cairo_operator_t op, |
||
337 | const cairo_pattern_t *source, |
||
338 | const char *utf8, |
||
339 | int utf8_len, |
||
340 | cairo_glyph_t *glyphs, |
||
341 | int num_glyphs, |
||
342 | const cairo_text_cluster_t *clusters, |
||
343 | int num_clusters, |
||
344 | cairo_text_cluster_flags_t cluster_flags, |
||
345 | cairo_scaled_font_t *scaled_font, |
||
346 | const cairo_clip_t *clip) |
||
347 | { |
||
348 | cairo_tee_surface_t *surface = abstract_surface; |
||
349 | cairo_surface_wrapper_t *slaves; |
||
350 | cairo_int_status_t status; |
||
351 | int n, num_slaves; |
||
352 | cairo_glyph_t *glyphs_copy; |
||
353 | |||
354 | /* XXX: This copying is ugly. */ |
||
355 | glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t)); |
||
356 | if (unlikely (glyphs_copy == NULL)) |
||
357 | return _cairo_error (CAIRO_STATUS_NO_MEMORY); |
||
358 | |||
359 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
360 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
361 | for (n = 0; n < num_slaves; n++) { |
||
362 | memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); |
||
363 | status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op, |
||
364 | source, |
||
365 | utf8, utf8_len, |
||
366 | glyphs_copy, num_glyphs, |
||
367 | clusters, num_clusters, |
||
368 | cluster_flags, |
||
369 | scaled_font, |
||
370 | clip); |
||
371 | if (unlikely (status)) |
||
372 | goto CLEANUP; |
||
373 | } |
||
374 | |||
375 | memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs); |
||
376 | status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, 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 | CLEANUP: |
||
385 | free (glyphs_copy); |
||
386 | return status; |
||
387 | } |
||
388 | |||
389 | static const cairo_surface_backend_t cairo_tee_surface_backend = { |
||
390 | CAIRO_SURFACE_TYPE_TEE, |
||
391 | _cairo_tee_surface_finish, |
||
392 | |||
393 | _cairo_default_context_create, /* XXX */ |
||
394 | |||
395 | _cairo_tee_surface_create_similar, |
||
396 | NULL, /* create similar image */ |
||
397 | NULL, /* map to image */ |
||
398 | NULL, /* unmap image */ |
||
399 | |||
400 | _cairo_tee_surface_source, |
||
401 | _cairo_tee_surface_acquire_source_image, |
||
402 | _cairo_tee_surface_release_source_image, |
||
403 | _cairo_tee_surface_snapshot, |
||
404 | NULL, /* copy_page */ |
||
405 | NULL, /* show_page */ |
||
406 | _cairo_tee_surface_get_extents, |
||
407 | _cairo_tee_surface_get_font_options, |
||
408 | NULL, /* flush */ |
||
409 | NULL, /* mark_dirty_rectangle */ |
||
410 | |||
411 | _cairo_tee_surface_paint, |
||
412 | _cairo_tee_surface_mask, |
||
413 | _cairo_tee_surface_stroke, |
||
414 | _cairo_tee_surface_fill, |
||
415 | NULL, /* fill_stroke */ |
||
416 | |||
417 | NULL, /* show_glyphs */ |
||
418 | |||
419 | _cairo_tee_surface_has_show_text_glyphs, |
||
420 | _cairo_tee_surface_show_text_glyphs |
||
421 | }; |
||
422 | |||
423 | cairo_surface_t * |
||
424 | cairo_tee_surface_create (cairo_surface_t *master) |
||
425 | { |
||
426 | cairo_tee_surface_t *surface; |
||
427 | |||
428 | if (unlikely (master->status)) |
||
429 | return _cairo_surface_create_in_error (master->status); |
||
430 | |||
431 | surface = malloc (sizeof (cairo_tee_surface_t)); |
||
432 | if (unlikely (surface == NULL)) |
||
433 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY)); |
||
434 | |||
435 | _cairo_surface_init (&surface->base, |
||
436 | &cairo_tee_surface_backend, |
||
437 | master->device, |
||
438 | master->content); |
||
439 | |||
440 | _cairo_surface_wrapper_init (&surface->master, master); |
||
441 | |||
442 | _cairo_array_init (&surface->slaves, sizeof (cairo_surface_wrapper_t)); |
||
443 | |||
444 | return &surface->base; |
||
445 | } |
||
446 | slim_hidden_def (cairo_tee_surface_create); |
||
447 | |||
448 | void |
||
449 | cairo_tee_surface_add (cairo_surface_t *abstract_surface, |
||
450 | cairo_surface_t *target) |
||
451 | { |
||
452 | cairo_tee_surface_t *surface; |
||
453 | cairo_surface_wrapper_t slave; |
||
454 | cairo_status_t status; |
||
455 | |||
456 | if (unlikely (abstract_surface->status)) |
||
457 | return; |
||
458 | if (unlikely (abstract_surface->finished)) { |
||
459 | status = _cairo_surface_set_error (abstract_surface, |
||
460 | _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); |
||
461 | return; |
||
462 | } |
||
463 | |||
464 | if (abstract_surface->backend != &cairo_tee_surface_backend) { |
||
465 | status = _cairo_surface_set_error (abstract_surface, |
||
466 | _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); |
||
467 | return; |
||
468 | } |
||
469 | |||
470 | if (unlikely (target->status)) { |
||
471 | status = _cairo_surface_set_error (abstract_surface, target->status); |
||
472 | return; |
||
473 | } |
||
474 | |||
475 | surface = (cairo_tee_surface_t *) abstract_surface; |
||
476 | |||
477 | _cairo_surface_wrapper_init (&slave, target); |
||
478 | status = _cairo_array_append (&surface->slaves, &slave); |
||
479 | if (unlikely (status)) { |
||
480 | _cairo_surface_wrapper_fini (&slave); |
||
481 | status = _cairo_surface_set_error (&surface->base, status); |
||
482 | } |
||
483 | } |
||
484 | slim_hidden_def (cairo_tee_surface_add); |
||
485 | |||
486 | void |
||
487 | cairo_tee_surface_remove (cairo_surface_t *abstract_surface, |
||
488 | cairo_surface_t *target) |
||
489 | { |
||
490 | cairo_tee_surface_t *surface; |
||
491 | cairo_surface_wrapper_t *slaves; |
||
492 | int n, num_slaves; |
||
493 | |||
494 | if (unlikely (abstract_surface->status)) |
||
495 | return; |
||
496 | if (unlikely (abstract_surface->finished)) { |
||
497 | _cairo_surface_set_error (abstract_surface, |
||
498 | _cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); |
||
499 | return; |
||
500 | } |
||
501 | |||
502 | if (abstract_surface->backend != &cairo_tee_surface_backend) { |
||
503 | _cairo_surface_set_error (abstract_surface, |
||
504 | _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); |
||
505 | return; |
||
506 | } |
||
507 | |||
508 | surface = (cairo_tee_surface_t *) abstract_surface; |
||
509 | if (target == surface->master.target) { |
||
510 | _cairo_surface_set_error (abstract_surface, |
||
511 | _cairo_error (CAIRO_STATUS_INVALID_INDEX)); |
||
512 | return; |
||
513 | } |
||
514 | |||
515 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
516 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
517 | for (n = 0; n < num_slaves; n++) { |
||
518 | if (slaves[n].target == target) |
||
519 | break; |
||
520 | } |
||
521 | |||
522 | if (n == num_slaves) { |
||
523 | _cairo_surface_set_error (abstract_surface, |
||
524 | _cairo_error (CAIRO_STATUS_INVALID_INDEX)); |
||
525 | return; |
||
526 | } |
||
527 | |||
528 | _cairo_surface_wrapper_fini (&slaves[n]); |
||
529 | for (n++; n < num_slaves; n++) |
||
530 | slaves[n-1] = slaves[n]; |
||
531 | surface->slaves.num_elements--; /* XXX: cairo_array_remove()? */ |
||
532 | } |
||
533 | |||
534 | cairo_surface_t * |
||
535 | cairo_tee_surface_index (cairo_surface_t *abstract_surface, |
||
536 | unsigned int index) |
||
537 | { |
||
538 | cairo_tee_surface_t *surface; |
||
539 | |||
540 | if (unlikely (abstract_surface->status)) |
||
541 | return _cairo_surface_create_in_error (abstract_surface->status); |
||
542 | if (unlikely (abstract_surface->finished)) |
||
543 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED)); |
||
544 | |||
545 | if (abstract_surface->backend != &cairo_tee_surface_backend) |
||
546 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH)); |
||
547 | |||
548 | surface = (cairo_tee_surface_t *) abstract_surface; |
||
549 | if (index == 0) { |
||
550 | return surface->master.target; |
||
551 | } else { |
||
552 | cairo_surface_wrapper_t *slave; |
||
553 | |||
554 | index--; |
||
555 | |||
556 | if (index >= _cairo_array_num_elements (&surface->slaves)) |
||
557 | return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX)); |
||
558 | |||
559 | slave = _cairo_array_index (&surface->slaves, index); |
||
560 | return slave->target; |
||
561 | } |
||
562 | } |
||
563 | |||
564 | cairo_surface_t * |
||
565 | _cairo_tee_surface_find_match (void *abstract_surface, |
||
566 | const cairo_surface_backend_t *backend, |
||
567 | cairo_content_t content) |
||
568 | { |
||
569 | cairo_tee_surface_t *surface = abstract_surface; |
||
570 | cairo_surface_wrapper_t *slaves; |
||
571 | int num_slaves, n; |
||
572 | |||
573 | /* exact match first */ |
||
574 | if (surface->master.target->backend == backend && |
||
575 | surface->master.target->content == content) |
||
576 | { |
||
577 | return surface->master.target; |
||
578 | } |
||
579 | |||
580 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
581 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
582 | for (n = 0; n < num_slaves; n++) { |
||
583 | if (slaves[n].target->backend == backend && |
||
584 | slaves[n].target->content == content) |
||
585 | { |
||
586 | return slaves[n].target; |
||
587 | } |
||
588 | } |
||
589 | |||
590 | /* matching backend? */ |
||
591 | if (surface->master.target->backend == backend) |
||
592 | return surface->master.target; |
||
593 | |||
594 | num_slaves = _cairo_array_num_elements (&surface->slaves); |
||
595 | slaves = _cairo_array_index (&surface->slaves, 0); |
||
596 | for (n = 0; n < num_slaves; n++) { |
||
597 | if (slaves[n].target->backend == backend) |
||
598 | return slaves[n].target; |
||
599 | } |
||
600 | |||
601 | return NULL; |
||
602 | }>>>>>>>>>>>>> |