beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-tee-surface.c
blob294e5f162e22b18af59bc89da93adda13ddd8d00
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2005 Red Hat, Inc
4 * Copyright © 2009 Chris Wilson
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.
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
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/
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.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Red Hat, Inc.
33 * Contributor(s):
34 * Carl Worth <cworth@cworth.org>
35 * Chris Wilson <chris@chris-wilson.co.uk>
38 /* This surface supports redirecting all its input to multiple surfaces.
41 #include "cairoint.h"
43 #include "cairo-tee.h"
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"
53 typedef struct _cairo_tee_surface {
54 cairo_surface_t base;
56 cairo_surface_wrapper_t master;
57 cairo_array_t slaves;
58 } cairo_tee_surface_t;
60 slim_hidden_proto (cairo_tee_surface_create);
61 slim_hidden_proto (cairo_tee_surface_add);
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)
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;
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;
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++) {
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);
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);
100 return surface;
103 static cairo_status_t
104 _cairo_tee_surface_finish (void *abstract_surface)
106 cairo_tee_surface_t *surface = abstract_surface;
107 cairo_surface_wrapper_t *slaves;
108 int n, num_slaves;
110 _cairo_surface_wrapper_fini (&surface->master);
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]);
117 _cairo_array_fini (&surface->slaves);
119 return CAIRO_STATUS_SUCCESS;
122 static cairo_surface_t *
123 _cairo_tee_surface_source (void *abstract_surface,
124 cairo_rectangle_int_t *extents)
126 cairo_tee_surface_t *surface = abstract_surface;
127 return _cairo_surface_get_source (surface->master.target, extents);
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)
135 cairo_tee_surface_t *surface = abstract_surface;
136 cairo_surface_wrapper_t *slaves;
137 int num_slaves, n;
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);
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);
155 return _cairo_surface_wrapper_acquire_source_image (&surface->master,
156 image_out, image_extra);
159 static void
160 _cairo_tee_surface_release_source_image (void *abstract_surface,
161 cairo_image_surface_t *image,
162 void *image_extra)
164 cairo_tee_surface_t *surface = abstract_surface;
166 _cairo_surface_wrapper_release_source_image (&surface->master,
167 image, image_extra);
170 static cairo_surface_t *
171 _cairo_tee_surface_snapshot (void *abstract_surface)
173 cairo_tee_surface_t *surface = abstract_surface;
174 cairo_surface_wrapper_t *slaves;
175 int num_slaves, n;
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);
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]);
188 return _cairo_surface_wrapper_snapshot (&surface->master);
191 static cairo_bool_t
192 _cairo_tee_surface_get_extents (void *abstract_surface,
193 cairo_rectangle_int_t *rectangle)
195 cairo_tee_surface_t *surface = abstract_surface;
197 return _cairo_surface_wrapper_get_extents (&surface->master, rectangle);
200 static void
201 _cairo_tee_surface_get_font_options (void *abstract_surface,
202 cairo_font_options_t *options)
204 cairo_tee_surface_t *surface = abstract_surface;
206 _cairo_surface_wrapper_get_font_options (&surface->master, options);
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)
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;
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;
228 return _cairo_surface_wrapper_paint (&surface->master, op, source, clip);
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)
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;
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;
252 return _cairo_surface_wrapper_mask (&surface->master,
253 op, source, mask, clip);
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)
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;
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;
286 return _cairo_surface_wrapper_stroke (&surface->master,
287 op, source,
288 path, style,
289 ctm, ctm_inverse,
290 tolerance, antialias,
291 clip);
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)
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;
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;
321 return _cairo_surface_wrapper_fill (&surface->master,
322 op, source,
323 path, fill_rule,
324 tolerance, antialias,
325 clip);
328 static cairo_bool_t
329 _cairo_tee_surface_has_show_text_glyphs (void *abstract_surface)
331 return TRUE;
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)
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;
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);
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;
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;
389 static const cairo_surface_backend_t cairo_tee_surface_backend = {
390 CAIRO_SURFACE_TYPE_TEE,
391 _cairo_tee_surface_finish,
393 _cairo_default_context_create, /* XXX */
395 _cairo_tee_surface_create_similar,
396 NULL, /* create similar image */
397 NULL, /* map to image */
398 NULL, /* unmap image */
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 */
411 _cairo_tee_surface_paint,
412 _cairo_tee_surface_mask,
413 _cairo_tee_surface_stroke,
414 _cairo_tee_surface_fill,
415 NULL, /* fill_stroke */
417 NULL, /* show_glyphs */
419 _cairo_tee_surface_has_show_text_glyphs,
420 _cairo_tee_surface_show_text_glyphs
423 cairo_surface_t *
424 cairo_tee_surface_create (cairo_surface_t *master)
426 cairo_tee_surface_t *surface;
428 if (unlikely (master->status))
429 return _cairo_surface_create_in_error (master->status);
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));
435 _cairo_surface_init (&surface->base,
436 &cairo_tee_surface_backend,
437 master->device,
438 master->content);
440 _cairo_surface_wrapper_init (&surface->master, master);
442 _cairo_array_init (&surface->slaves, sizeof (cairo_surface_wrapper_t));
444 return &surface->base;
446 slim_hidden_def (cairo_tee_surface_create);
448 void
449 cairo_tee_surface_add (cairo_surface_t *abstract_surface,
450 cairo_surface_t *target)
452 cairo_tee_surface_t *surface;
453 cairo_surface_wrapper_t slave;
454 cairo_status_t status;
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;
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;
470 if (unlikely (target->status)) {
471 status = _cairo_surface_set_error (abstract_surface, target->status);
472 return;
475 surface = (cairo_tee_surface_t *) abstract_surface;
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);
484 slim_hidden_def (cairo_tee_surface_add);
486 void
487 cairo_tee_surface_remove (cairo_surface_t *abstract_surface,
488 cairo_surface_t *target)
490 cairo_tee_surface_t *surface;
491 cairo_surface_wrapper_t *slaves;
492 int n, num_slaves;
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;
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;
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;
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;
522 if (n == num_slaves) {
523 _cairo_surface_set_error (abstract_surface,
524 _cairo_error (CAIRO_STATUS_INVALID_INDEX));
525 return;
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()? */
534 cairo_surface_t *
535 cairo_tee_surface_index (cairo_surface_t *abstract_surface,
536 unsigned int index)
538 cairo_tee_surface_t *surface;
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));
545 if (abstract_surface->backend != &cairo_tee_surface_backend)
546 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
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;
554 index--;
556 if (index >= _cairo_array_num_elements (&surface->slaves))
557 return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
559 slave = _cairo_array_index (&surface->slaves, index);
560 return slave->target;
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)
569 cairo_tee_surface_t *surface = abstract_surface;
570 cairo_surface_wrapper_t *slaves;
571 int num_slaves, n;
573 /* exact match first */
574 if (surface->master.target->backend == backend &&
575 surface->master.target->content == content)
577 return surface->master.target;
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)
586 return slaves[n].target;
590 /* matching backend? */
591 if (surface->master.target->backend == backend)
592 return surface->master.target;
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;
601 return NULL;