Upload Tizen2.0 source
[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-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 }