Git init
[framework/graphics/cairo.git] / src / cairo-tee-surface.c
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 <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.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-private.h"
49 #include "cairo-surface-wrapper-private.h"
50 #include "cairo-array-private.h"
51 #include "cairo-image-surface-private.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_status_t
123 _cairo_tee_surface_acquire_source_image (void        *abstract_surface,
124                                          cairo_image_surface_t **image_out,
125                                          void            **image_extra)
126 {
127     cairo_tee_surface_t *surface = abstract_surface;
128     cairo_surface_wrapper_t *slaves;
129     int num_slaves, n;
130
131     /* we prefer to use a real image surface if available */
132     if (_cairo_surface_is_image (surface->master.target)) {
133         return _cairo_surface_wrapper_acquire_source_image (&surface->master,
134                                                             image_out, image_extra);
135     }
136
137     num_slaves = _cairo_array_num_elements (&surface->slaves);
138     slaves = _cairo_array_index (&surface->slaves, 0);
139     for (n = 0; n < num_slaves; n++) {
140         if (_cairo_surface_is_image (slaves[n].target)) {
141             return _cairo_surface_wrapper_acquire_source_image (&slaves[n],
142                                                                 image_out,
143                                                                 image_extra);
144         }
145     }
146
147     return _cairo_surface_wrapper_acquire_source_image (&surface->master,
148                                                         image_out, image_extra);
149 }
150
151 static void
152 _cairo_tee_surface_release_source_image (void        *abstract_surface,
153                                          cairo_image_surface_t  *image,
154                                          void             *image_extra)
155 {
156     cairo_tee_surface_t *surface = abstract_surface;
157
158     _cairo_surface_wrapper_release_source_image (&surface->master,
159                                                  image, image_extra);
160 }
161
162 static cairo_surface_t *
163 _cairo_tee_surface_snapshot (void *abstract_surface)
164 {
165     cairo_tee_surface_t *surface = abstract_surface;
166     cairo_surface_wrapper_t *slaves;
167     int num_slaves, n;
168
169     /* we prefer to use a recording surface for our snapshots */
170     if (_cairo_surface_is_recording (surface->master.target))
171         return _cairo_surface_wrapper_snapshot (&surface->master);
172
173     num_slaves = _cairo_array_num_elements (&surface->slaves);
174     slaves = _cairo_array_index (&surface->slaves, 0);
175     for (n = 0; n < num_slaves; n++) {
176         if (_cairo_surface_is_recording (slaves[n].target))
177             return _cairo_surface_wrapper_snapshot (&slaves[n]);
178     }
179
180     return _cairo_surface_wrapper_snapshot (&surface->master);
181 }
182
183 static cairo_bool_t
184 _cairo_tee_surface_get_extents (void                    *abstract_surface,
185                                 cairo_rectangle_int_t   *rectangle)
186 {
187     cairo_tee_surface_t *surface = abstract_surface;
188
189     return _cairo_surface_wrapper_get_extents (&surface->master, rectangle);
190 }
191
192 static void
193 _cairo_tee_surface_get_font_options (void                  *abstract_surface,
194                                      cairo_font_options_t  *options)
195 {
196     cairo_tee_surface_t *surface = abstract_surface;
197
198     _cairo_surface_wrapper_get_font_options (&surface->master, options);
199 }
200
201 static cairo_int_status_t
202 _cairo_tee_surface_paint (void                  *abstract_surface,
203                           cairo_operator_t       op,
204                           const cairo_pattern_t *source,
205                           const cairo_clip_t    *clip)
206 {
207     cairo_tee_surface_t *surface = abstract_surface;
208     cairo_surface_wrapper_t *slaves;
209     int n, num_slaves;
210     cairo_int_status_t status;
211
212     num_slaves = _cairo_array_num_elements (&surface->slaves);
213     slaves = _cairo_array_index (&surface->slaves, 0);
214     for (n = 0; n < num_slaves; n++) {
215         status = _cairo_surface_wrapper_paint (&slaves[n], op, source, clip);
216         if (unlikely (status))
217             return status;
218     }
219
220     return _cairo_surface_wrapper_paint (&surface->master, op, source, clip);
221 }
222
223 static cairo_int_status_t
224 _cairo_tee_surface_mask (void                   *abstract_surface,
225                          cairo_operator_t        op,
226                          const cairo_pattern_t  *source,
227                          const cairo_pattern_t  *mask,
228                          const cairo_clip_t     *clip)
229 {
230     cairo_tee_surface_t *surface = abstract_surface;
231     cairo_surface_wrapper_t *slaves;
232     cairo_int_status_t status;
233     int n, num_slaves;
234
235     num_slaves = _cairo_array_num_elements (&surface->slaves);
236     slaves = _cairo_array_index (&surface->slaves, 0);
237     for (n = 0; n < num_slaves; n++) {
238         status = _cairo_surface_wrapper_mask (&slaves[n],
239                                               op, source, mask, clip);
240         if (unlikely (status))
241             return status;
242     }
243
244     return _cairo_surface_wrapper_mask (&surface->master,
245                                         op, source, mask, clip);
246 }
247
248 static cairo_int_status_t
249 _cairo_tee_surface_stroke (void                         *abstract_surface,
250                            cairo_operator_t              op,
251                            const cairo_pattern_t        *source,
252                            const cairo_path_fixed_t     *path,
253                            const cairo_stroke_style_t   *style,
254                            const cairo_matrix_t         *ctm,
255                            const cairo_matrix_t         *ctm_inverse,
256                            double                        tolerance,
257                            cairo_antialias_t             antialias,
258                            const cairo_clip_t           *clip)
259 {
260     cairo_tee_surface_t *surface = abstract_surface;
261     cairo_surface_wrapper_t *slaves;
262     cairo_int_status_t status;
263     int n, num_slaves;
264
265     num_slaves = _cairo_array_num_elements (&surface->slaves);
266     slaves = _cairo_array_index (&surface->slaves, 0);
267     for (n = 0; n < num_slaves; n++) {
268         status = _cairo_surface_wrapper_stroke (&slaves[n],
269                                                 op, source,
270                                                 path, style,
271                                                 ctm, ctm_inverse,
272                                                 tolerance, antialias,
273                                                 clip);
274         if (unlikely (status))
275             return status;
276     }
277
278     return _cairo_surface_wrapper_stroke (&surface->master,
279                                           op, source,
280                                           path, style,
281                                           ctm, ctm_inverse,
282                                           tolerance, antialias,
283                                           clip);
284 }
285
286 static cairo_int_status_t
287 _cairo_tee_surface_fill (void                           *abstract_surface,
288                          cairo_operator_t                op,
289                          const cairo_pattern_t          *source,
290                          const cairo_path_fixed_t       *path,
291                          cairo_fill_rule_t               fill_rule,
292                          double                          tolerance,
293                          cairo_antialias_t               antialias,
294                          const cairo_clip_t             *clip)
295 {
296     cairo_tee_surface_t *surface = abstract_surface;
297     cairo_surface_wrapper_t *slaves;
298     cairo_int_status_t status;
299     int n, num_slaves;
300
301     num_slaves = _cairo_array_num_elements (&surface->slaves);
302     slaves = _cairo_array_index (&surface->slaves, 0);
303     for (n = 0; n < num_slaves; n++) {
304         status = _cairo_surface_wrapper_fill (&slaves[n],
305                                               op, source,
306                                               path, fill_rule,
307                                               tolerance, antialias,
308                                               clip);
309         if (unlikely (status))
310             return status;
311     }
312
313     return _cairo_surface_wrapper_fill (&surface->master,
314                                         op, source,
315                                         path, fill_rule,
316                                         tolerance, antialias,
317                                         clip);
318 }
319
320 static cairo_bool_t
321 _cairo_tee_surface_has_show_text_glyphs (void *abstract_surface)
322 {
323     return TRUE;
324 }
325
326 static cairo_int_status_t
327 _cairo_tee_surface_show_text_glyphs (void                   *abstract_surface,
328                                      cairo_operator_t        op,
329                                      const cairo_pattern_t  *source,
330                                      const char             *utf8,
331                                      int                     utf8_len,
332                                      cairo_glyph_t          *glyphs,
333                                      int                     num_glyphs,
334                                      const cairo_text_cluster_t *clusters,
335                                      int                     num_clusters,
336                                      cairo_text_cluster_flags_t cluster_flags,
337                                      cairo_scaled_font_t    *scaled_font,
338                                      const cairo_clip_t     *clip)
339 {
340     cairo_tee_surface_t *surface = abstract_surface;
341     cairo_surface_wrapper_t *slaves;
342     cairo_int_status_t status;
343     int n, num_slaves;
344     cairo_glyph_t *glyphs_copy;
345
346     /* XXX: This copying is ugly. */
347     glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
348     if (unlikely (glyphs_copy == NULL))
349         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
350
351     num_slaves = _cairo_array_num_elements (&surface->slaves);
352     slaves = _cairo_array_index (&surface->slaves, 0);
353     for (n = 0; n < num_slaves; n++) {
354         memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
355         status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op,
356                                                           source,
357                                                           utf8, utf8_len,
358                                                           glyphs_copy, num_glyphs,
359                                                           clusters, num_clusters,
360                                                           cluster_flags,
361                                                           scaled_font,
362                                                           clip);
363         if (unlikely (status))
364             goto CLEANUP;
365     }
366
367     memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
368     status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, op,
369                                                       source,
370                                                       utf8, utf8_len,
371                                                       glyphs_copy, num_glyphs,
372                                                       clusters, num_clusters,
373                                                       cluster_flags,
374                                                       scaled_font,
375                                                       clip);
376 CLEANUP:
377     free (glyphs_copy);
378     return status;
379 }
380
381 static const cairo_surface_backend_t cairo_tee_surface_backend = {
382     CAIRO_SURFACE_TYPE_TEE,
383     _cairo_tee_surface_finish,
384
385     _cairo_default_context_create, /* XXX */
386
387     _cairo_tee_surface_create_similar,
388     NULL, /* create similar image */
389     NULL, /* map to image */
390     NULL, /* unmap image */
391
392     _cairo_tee_surface_acquire_source_image,
393     _cairo_tee_surface_release_source_image,
394     _cairo_tee_surface_snapshot,
395     NULL, /* copy_page */
396     NULL, /* show_page */
397     _cairo_tee_surface_get_extents,
398     _cairo_tee_surface_get_font_options,
399     NULL, /* flush */
400     NULL, /* mark_dirty_rectangle */
401
402     _cairo_tee_surface_paint,
403     _cairo_tee_surface_mask,
404     _cairo_tee_surface_stroke,
405     _cairo_tee_surface_fill,
406     NULL, /* fill_stroke */
407
408     NULL, /* show_glyphs */
409
410     _cairo_tee_surface_has_show_text_glyphs,
411     _cairo_tee_surface_show_text_glyphs
412 };
413
414 cairo_surface_t *
415 cairo_tee_surface_create (cairo_surface_t *master)
416 {
417     cairo_tee_surface_t *surface;
418
419     if (unlikely (master->status))
420         return _cairo_surface_create_in_error (master->status);
421
422     surface = malloc (sizeof (cairo_tee_surface_t));
423     if (unlikely (surface == NULL))
424         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
425
426     _cairo_surface_init (&surface->base,
427                          &cairo_tee_surface_backend,
428                          master->device,
429                          master->content);
430
431     _cairo_surface_wrapper_init (&surface->master, master);
432
433     _cairo_array_init (&surface->slaves, sizeof (cairo_surface_wrapper_t));
434
435     return &surface->base;
436 }
437 slim_hidden_def (cairo_tee_surface_create);
438
439 void
440 cairo_tee_surface_add (cairo_surface_t *abstract_surface,
441                        cairo_surface_t *target)
442 {
443     cairo_tee_surface_t *surface;
444     cairo_surface_wrapper_t slave;
445     cairo_status_t status;
446
447     if (unlikely (abstract_surface->status))
448         return;
449     if (unlikely (abstract_surface->finished)) {
450         status = _cairo_surface_set_error (abstract_surface,
451                                            _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
452         return;
453     }
454
455     if (abstract_surface->backend != &cairo_tee_surface_backend) {
456         status = _cairo_surface_set_error (abstract_surface,
457                                            _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
458         return;
459     }
460
461     if (unlikely (target->status)) {
462         status = _cairo_surface_set_error (abstract_surface, target->status);
463         return;
464     }
465
466     surface = (cairo_tee_surface_t *) abstract_surface;
467
468     _cairo_surface_wrapper_init (&slave, target);
469     status = _cairo_array_append (&surface->slaves, &slave);
470     if (unlikely (status)) {
471         _cairo_surface_wrapper_fini (&slave);
472         status = _cairo_surface_set_error (&surface->base, status);
473     }
474 }
475 slim_hidden_def (cairo_tee_surface_add);
476
477 void
478 cairo_tee_surface_remove (cairo_surface_t *abstract_surface,
479                           cairo_surface_t *target)
480 {
481     cairo_tee_surface_t *surface;
482     cairo_surface_wrapper_t *slaves;
483     int n, num_slaves;
484
485     if (unlikely (abstract_surface->status))
486         return;
487     if (unlikely (abstract_surface->finished)) {
488         _cairo_surface_set_error (abstract_surface,
489                                   _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
490         return;
491     }
492
493     if (abstract_surface->backend != &cairo_tee_surface_backend) {
494         _cairo_surface_set_error (abstract_surface,
495                                   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
496         return;
497     }
498
499     surface = (cairo_tee_surface_t *) abstract_surface;
500     if (target == surface->master.target) {
501         _cairo_surface_set_error (abstract_surface,
502                                   _cairo_error (CAIRO_STATUS_INVALID_INDEX));
503         return;
504     }
505
506     num_slaves = _cairo_array_num_elements (&surface->slaves);
507     slaves = _cairo_array_index (&surface->slaves, 0);
508     for (n = 0; n < num_slaves; n++) {
509         if (slaves[n].target == target)
510             break;
511     }
512
513     if (n == num_slaves) {
514         _cairo_surface_set_error (abstract_surface,
515                                   _cairo_error (CAIRO_STATUS_INVALID_INDEX));
516         return;
517     }
518
519     _cairo_surface_wrapper_fini (&slaves[n]);
520     for (n++; n < num_slaves; n++)
521         slaves[n-1] = slaves[n];
522     surface->slaves.num_elements--; /* XXX: cairo_array_remove()? */
523 }
524
525 cairo_surface_t *
526 cairo_tee_surface_index (cairo_surface_t *abstract_surface,
527                          unsigned int index)
528 {
529     cairo_tee_surface_t *surface;
530
531     if (unlikely (abstract_surface->status))
532         return _cairo_surface_create_in_error (abstract_surface->status);
533     if (unlikely (abstract_surface->finished))
534         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
535
536     if (abstract_surface->backend != &cairo_tee_surface_backend)
537         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
538
539     surface = (cairo_tee_surface_t *) abstract_surface;
540     if (index == 0) {
541         return surface->master.target;
542     } else {
543         cairo_surface_wrapper_t *slave;
544
545         index--;
546
547         if (index >= _cairo_array_num_elements (&surface->slaves))
548             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
549
550         slave = _cairo_array_index (&surface->slaves, index);
551         return slave->target;
552     }
553 }
554
555 cairo_surface_t *
556 _cairo_tee_surface_find_match (void *abstract_surface,
557                                const cairo_surface_backend_t *backend,
558                                cairo_content_t content)
559 {
560     cairo_tee_surface_t *surface = abstract_surface;
561     cairo_surface_wrapper_t *slaves;
562     int num_slaves, n;
563
564     /* exact match first */
565     if (surface->master.target->backend == backend &&
566         surface->master.target->content == content)
567     {
568         return surface->master.target;
569     }
570
571     num_slaves = _cairo_array_num_elements (&surface->slaves);
572     slaves = _cairo_array_index (&surface->slaves, 0);
573     for (n = 0; n < num_slaves; n++) {
574         if (slaves[n].target->backend == backend &&
575             slaves[n].target->content == content)
576         {
577             return slaves[n].target;
578         }
579     }
580
581     /* matching backend? */
582     if (surface->master.target->backend == backend)
583         return surface->master.target;
584
585     num_slaves = _cairo_array_num_elements (&surface->slaves);
586     slaves = _cairo_array_index (&surface->slaves, 0);
587     for (n = 0; n < num_slaves; n++) {
588         if (slaves[n].target->backend == backend)
589             return slaves[n].target;
590     }
591
592     return NULL;
593 }