LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-tee-surface.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 271 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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-error-private.h"
      46             : #include "cairo-tee-surface-private.h"
      47             : #include "cairo-surface-wrapper-private.h"
      48             : 
      49             : typedef struct _cairo_tee_surface {
      50             :     cairo_surface_t base;
      51             : 
      52             :     cairo_surface_wrapper_t master;
      53             :     cairo_array_t slaves;
      54             : } cairo_tee_surface_t;
      55             : 
      56             : slim_hidden_proto (cairo_tee_surface_create);
      57             : slim_hidden_proto (cairo_tee_surface_add);
      58             : 
      59             : static cairo_surface_t *
      60           0 : _cairo_tee_surface_create_similar (void                 *abstract_surface,
      61             :                                    cairo_content_t       content,
      62             :                                    int                   width,
      63             :                                    int                   height)
      64             : {
      65             : 
      66           0 :     cairo_tee_surface_t *other = abstract_surface;
      67             :     cairo_surface_t *similar;
      68             :     cairo_surface_t *surface;
      69             :     cairo_surface_wrapper_t *slaves;
      70             :     int n, num_slaves;
      71             : 
      72           0 :     similar = _cairo_surface_wrapper_create_similar (&other->master,
      73             :                                                      content, width, height);
      74           0 :     surface = cairo_tee_surface_create (similar);
      75           0 :     cairo_surface_destroy (similar);
      76           0 :     if (unlikely (surface->status))
      77           0 :         return surface;
      78             : 
      79           0 :     num_slaves = _cairo_array_num_elements (&other->slaves);
      80           0 :     slaves = _cairo_array_index (&other->slaves, 0);
      81           0 :     for (n = 0; n < num_slaves; n++) {
      82             : 
      83           0 :         similar = _cairo_surface_wrapper_create_similar (&slaves[n],
      84             :                                                          content,
      85             :                                                          width, height);
      86           0 :         cairo_tee_surface_add (surface, similar);
      87           0 :         cairo_surface_destroy (similar);
      88             :     }
      89             : 
      90           0 :     if (unlikely (surface->status)) {
      91           0 :         cairo_status_t status = surface->status;
      92           0 :         cairo_surface_destroy (surface);
      93           0 :         surface = _cairo_surface_create_in_error (status);
      94             :     }
      95             : 
      96           0 :     return surface;
      97             : }
      98             : 
      99             : static cairo_status_t
     100           0 : _cairo_tee_surface_finish (void *abstract_surface)
     101             : {
     102           0 :     cairo_tee_surface_t *surface = abstract_surface;
     103             :     cairo_surface_wrapper_t *slaves;
     104             :     int n, num_slaves;
     105             : 
     106           0 :     _cairo_surface_wrapper_fini (&surface->master);
     107             : 
     108           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     109           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     110           0 :     for (n = 0; n < num_slaves; n++)
     111           0 :         _cairo_surface_wrapper_fini (&slaves[n]);
     112             : 
     113           0 :     _cairo_array_fini (&surface->slaves);
     114             : 
     115           0 :     return CAIRO_STATUS_SUCCESS;
     116             : }
     117             : 
     118             : static cairo_status_t
     119           0 : _cairo_tee_surface_acquire_source_image (void        *abstract_surface,
     120             :                                          cairo_image_surface_t **image_out,
     121             :                                          void            **image_extra)
     122             : {
     123           0 :     cairo_tee_surface_t *surface = abstract_surface;
     124             :     cairo_surface_wrapper_t *slaves;
     125             :     int num_slaves, n;
     126             : 
     127             :     /* we prefer to use a real image surface if available */
     128           0 :     if (_cairo_surface_is_image (surface->master.target)) {
     129           0 :         return _cairo_surface_wrapper_acquire_source_image (&surface->master,
     130             :                                                             image_out, image_extra);
     131             :     }
     132             : 
     133           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     134           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     135           0 :     for (n = 0; n < num_slaves; n++) {
     136           0 :         if (_cairo_surface_is_image (slaves[n].target)) {
     137           0 :             return _cairo_surface_wrapper_acquire_source_image (&slaves[n],
     138             :                                                                 image_out,
     139             :                                                                 image_extra);
     140             :         }
     141             :     }
     142             : 
     143           0 :     return _cairo_surface_wrapper_acquire_source_image (&surface->master,
     144             :                                                         image_out, image_extra);
     145             : }
     146             : 
     147             : static void
     148           0 : _cairo_tee_surface_release_source_image (void        *abstract_surface,
     149             :                                          cairo_image_surface_t  *image,
     150             :                                          void             *image_extra)
     151             : {
     152           0 :     cairo_tee_surface_t *surface = abstract_surface;
     153             : 
     154           0 :     _cairo_surface_wrapper_release_source_image (&surface->master,
     155             :                                                  image, image_extra);
     156           0 : }
     157             : 
     158             : static cairo_surface_t *
     159           0 : _cairo_tee_surface_snapshot (void *abstract_surface)
     160             : {
     161           0 :     cairo_tee_surface_t *surface = abstract_surface;
     162             :     cairo_surface_wrapper_t *slaves;
     163             :     int num_slaves, n;
     164             : 
     165             :     /* we prefer to use a recording surface for our snapshots */
     166           0 :     if (_cairo_surface_is_recording (surface->master.target))
     167           0 :         return _cairo_surface_wrapper_snapshot (&surface->master);
     168             : 
     169           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     170           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     171           0 :     for (n = 0; n < num_slaves; n++) {
     172           0 :         if (_cairo_surface_is_recording (slaves[n].target))
     173           0 :             return _cairo_surface_wrapper_snapshot (&slaves[n]);
     174             :     }
     175             : 
     176           0 :     return _cairo_surface_wrapper_snapshot (&surface->master);
     177             : }
     178             : 
     179             : static cairo_bool_t
     180           0 : _cairo_tee_surface_get_extents (void                    *abstract_surface,
     181             :                                 cairo_rectangle_int_t   *rectangle)
     182             : {
     183           0 :     cairo_tee_surface_t *surface = abstract_surface;
     184             : 
     185           0 :     return _cairo_surface_wrapper_get_extents (&surface->master, rectangle);
     186             : }
     187             : 
     188             : static void
     189           0 : _cairo_tee_surface_get_font_options (void                  *abstract_surface,
     190             :                                      cairo_font_options_t  *options)
     191             : {
     192           0 :     cairo_tee_surface_t *surface = abstract_surface;
     193             : 
     194           0 :     _cairo_surface_wrapper_get_font_options (&surface->master, options);
     195           0 : }
     196             : 
     197             : static const cairo_pattern_t *
     198           0 : _cairo_tee_surface_match_source (cairo_tee_surface_t *surface,
     199             :                                  const cairo_pattern_t *source,
     200             :                                  int index,
     201             :                                  cairo_surface_wrapper_t *dest,
     202             :                                  cairo_surface_pattern_t *temp)
     203             : {
     204             :     cairo_surface_t *s;
     205           0 :     cairo_status_t status = cairo_pattern_get_surface ((cairo_pattern_t *)source, &s);
     206           0 :     if (status == CAIRO_STATUS_SUCCESS &&
     207           0 :         cairo_surface_get_type (s) == CAIRO_SURFACE_TYPE_TEE) {
     208           0 :         cairo_surface_t *tee_surf = cairo_tee_surface_index (s, index);
     209           0 :         if (tee_surf->status == CAIRO_STATUS_SUCCESS &&
     210           0 :             tee_surf->backend == dest->target->backend) {
     211           0 :             status = _cairo_pattern_init_copy (&temp->base, source);
     212           0 :             if (status == CAIRO_STATUS_SUCCESS) {
     213           0 :                 cairo_surface_destroy (temp->surface);
     214           0 :                 temp->surface = tee_surf;
     215           0 :                 cairo_surface_reference (temp->surface);
     216           0 :                 return &temp->base;
     217             :             }
     218             :         }
     219             :     }
     220             : 
     221           0 :     return source;
     222             : }
     223             : 
     224             : static cairo_int_status_t
     225           0 : _cairo_tee_surface_paint (void                  *abstract_surface,
     226             :                           cairo_operator_t       op,
     227             :                           const cairo_pattern_t *source,
     228             :                           cairo_clip_t          *clip)
     229             : {
     230           0 :     cairo_tee_surface_t *surface = abstract_surface;
     231             :     cairo_surface_wrapper_t *slaves;
     232             :     int n, num_slaves;
     233             :     cairo_status_t status;
     234             :     const cairo_pattern_t *matched_source;
     235             :     cairo_surface_pattern_t temp;
     236             : 
     237           0 :     matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
     238           0 :     status = _cairo_surface_wrapper_paint (&surface->master, op, matched_source, clip);
     239           0 :     if (matched_source == &temp.base) {
     240           0 :         _cairo_pattern_fini (&temp.base);
     241             :     }
     242           0 :     if (unlikely (status))
     243           0 :         return status;
     244             : 
     245           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     246           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     247           0 :     for (n = 0; n < num_slaves; n++) {
     248           0 :         matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
     249           0 :         status = _cairo_surface_wrapper_paint (&slaves[n], op, matched_source, clip);
     250           0 :         if (matched_source == &temp.base) {
     251           0 :             _cairo_pattern_fini (&temp.base);
     252             :         }
     253           0 :         if (unlikely (status))
     254           0 :             return status;
     255             :     }
     256             : 
     257           0 :     return CAIRO_STATUS_SUCCESS;
     258             : }
     259             : 
     260             : static cairo_int_status_t
     261           0 : _cairo_tee_surface_mask (void                   *abstract_surface,
     262             :                          cairo_operator_t        op,
     263             :                          const cairo_pattern_t  *source,
     264             :                          const cairo_pattern_t  *mask,
     265             :                          cairo_clip_t           *clip)
     266             : {
     267           0 :     cairo_tee_surface_t *surface = abstract_surface;
     268             :     cairo_surface_wrapper_t *slaves;
     269             :     int n, num_slaves;
     270             :     cairo_status_t status;
     271             :     const cairo_pattern_t *matched_source;
     272             :     cairo_surface_pattern_t temp;
     273             : 
     274           0 :     matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
     275           0 :     status = _cairo_surface_wrapper_mask (&surface->master,
     276             :                                           op, matched_source, mask, clip);
     277           0 :     if (matched_source == &temp.base) {
     278           0 :         _cairo_pattern_fini (&temp.base);
     279             :     }
     280           0 :     if (unlikely (status))
     281           0 :         return status;
     282             : 
     283           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     284           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     285           0 :     for (n = 0; n < num_slaves; n++) {
     286           0 :         matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
     287           0 :         status = _cairo_surface_wrapper_mask (&slaves[n],
     288             :                                               op, matched_source, mask, clip);
     289           0 :         if (matched_source == &temp.base) {
     290           0 :             _cairo_pattern_fini (&temp.base);
     291             :         }
     292           0 :         if (unlikely (status))
     293           0 :             return status;
     294             :     }
     295             : 
     296           0 :     return CAIRO_STATUS_SUCCESS;
     297             : }
     298             : 
     299             : static cairo_int_status_t
     300           0 : _cairo_tee_surface_stroke (void                         *abstract_surface,
     301             :                            cairo_operator_t              op,
     302             :                            const cairo_pattern_t        *source,
     303             :                            cairo_path_fixed_t           *path,
     304             :                            const cairo_stroke_style_t   *style,
     305             :                            const cairo_matrix_t         *ctm,
     306             :                            const cairo_matrix_t         *ctm_inverse,
     307             :                            double                        tolerance,
     308             :                            cairo_antialias_t             antialias,
     309             :                            cairo_clip_t                 *clip)
     310             : {
     311           0 :     cairo_tee_surface_t *surface = abstract_surface;
     312             :     cairo_surface_wrapper_t *slaves;
     313             :     int n, num_slaves;
     314             :     cairo_status_t status;
     315             :     const cairo_pattern_t *matched_source;
     316             :     cairo_surface_pattern_t temp;
     317             : 
     318           0 :     matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
     319           0 :     status = _cairo_surface_wrapper_stroke (&surface->master,
     320             :                                             op, matched_source,
     321             :                                             path, style,
     322             :                                             ctm, ctm_inverse,
     323             :                                             tolerance, antialias,
     324             :                                             clip);
     325           0 :     if (matched_source == &temp.base) {
     326           0 :         _cairo_pattern_fini (&temp.base);
     327             :     }
     328           0 :     if (unlikely (status))
     329           0 :         return status;
     330             : 
     331           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     332           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     333           0 :     for (n = 0; n < num_slaves; n++) {
     334           0 :         matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
     335           0 :         status = _cairo_surface_wrapper_stroke (&slaves[n],
     336             :                                                 op, matched_source,
     337             :                                                 path, style,
     338             :                                                 ctm, ctm_inverse,
     339             :                                                 tolerance, antialias,
     340             :                                                 clip);
     341           0 :         if (matched_source == &temp.base) {
     342           0 :             _cairo_pattern_fini (&temp.base);
     343             :         }
     344           0 :         if (unlikely (status))
     345           0 :             return status;
     346             :     }
     347             : 
     348           0 :     return CAIRO_STATUS_SUCCESS;
     349             : }
     350             : 
     351             : static cairo_int_status_t
     352           0 : _cairo_tee_surface_fill (void                           *abstract_surface,
     353             :                          cairo_operator_t                op,
     354             :                          const cairo_pattern_t          *source,
     355             :                          cairo_path_fixed_t             *path,
     356             :                          cairo_fill_rule_t               fill_rule,
     357             :                          double                          tolerance,
     358             :                          cairo_antialias_t               antialias,
     359             :                          cairo_clip_t                   *clip)
     360             : {
     361           0 :     cairo_tee_surface_t *surface = abstract_surface;
     362             :     cairo_surface_wrapper_t *slaves;
     363             :     int n, num_slaves;
     364             :     cairo_status_t status;
     365             :     const cairo_pattern_t *matched_source;
     366             :     cairo_surface_pattern_t temp;
     367             : 
     368           0 :     matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
     369           0 :     status = _cairo_surface_wrapper_fill (&surface->master,
     370             :                                           op, matched_source,
     371             :                                           path, fill_rule,
     372             :                                           tolerance, antialias,
     373             :                                           clip);
     374           0 :     if (matched_source == &temp.base) {
     375           0 :         _cairo_pattern_fini (&temp.base);
     376             :     }
     377           0 :     if (unlikely (status))
     378           0 :         return status;
     379             : 
     380           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     381           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     382           0 :     for (n = 0; n < num_slaves; n++) {
     383           0 :         matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
     384           0 :         status = _cairo_surface_wrapper_fill (&slaves[n],
     385             :                                               op, matched_source,
     386             :                                               path, fill_rule,
     387             :                                               tolerance, antialias,
     388             :                                               clip);
     389           0 :         if (matched_source == &temp.base) {
     390           0 :             _cairo_pattern_fini (&temp.base);
     391             :         }
     392           0 :         if (unlikely (status))
     393           0 :             return status;
     394             :     }
     395             : 
     396           0 :     return CAIRO_STATUS_SUCCESS;
     397             : }
     398             : 
     399             : static cairo_bool_t
     400           0 : _cairo_tee_surface_has_show_text_glyphs (void *abstract_surface)
     401             : {
     402           0 :     return TRUE;
     403             : }
     404             : 
     405             : static cairo_int_status_t
     406           0 : _cairo_tee_surface_show_text_glyphs (void                   *abstract_surface,
     407             :                                      cairo_operator_t        op,
     408             :                                      const cairo_pattern_t  *source,
     409             :                                      const char             *utf8,
     410             :                                      int                     utf8_len,
     411             :                                      cairo_glyph_t          *glyphs,
     412             :                                      int                     num_glyphs,
     413             :                                      const cairo_text_cluster_t *clusters,
     414             :                                      int                     num_clusters,
     415             :                                      cairo_text_cluster_flags_t cluster_flags,
     416             :                                      cairo_scaled_font_t    *scaled_font,
     417             :                                      cairo_clip_t           *clip)
     418             : {
     419           0 :     cairo_tee_surface_t *surface = abstract_surface;
     420             :     cairo_surface_wrapper_t *slaves;
     421             :     int n, num_slaves;
     422             :     cairo_status_t status;
     423             :     cairo_glyph_t *glyphs_copy;
     424             :     const cairo_pattern_t *matched_source;
     425             :     cairo_surface_pattern_t temp;
     426             : 
     427             :     /* XXX: This copying is ugly. */
     428           0 :     glyphs_copy = _cairo_malloc_ab (num_glyphs, sizeof (cairo_glyph_t));
     429           0 :     if (unlikely (glyphs_copy == NULL))
     430           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     431             : 
     432           0 :     memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
     433           0 :     matched_source = _cairo_tee_surface_match_source (surface, source, 0, &surface->master, &temp);
     434           0 :     status = _cairo_surface_wrapper_show_text_glyphs (&surface->master, op,
     435             :                               matched_source,
     436             :                                                       utf8, utf8_len,
     437             :                                                       glyphs_copy, num_glyphs,
     438             :                                                       clusters, num_clusters,
     439             :                                                       cluster_flags,
     440             :                                                       scaled_font,
     441             :                                                       clip);
     442           0 :     if (matched_source == &temp.base) {
     443           0 :         _cairo_pattern_fini (&temp.base);
     444             :     }
     445           0 :     if (unlikely (status))
     446           0 :         goto CLEANUP;
     447             : 
     448           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     449           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     450           0 :     for (n = 0; n < num_slaves; n++) {
     451           0 :         memcpy (glyphs_copy, glyphs, sizeof (cairo_glyph_t) * num_glyphs);
     452           0 :       matched_source = _cairo_tee_surface_match_source (surface, source, n + 1, &slaves[n], &temp);
     453           0 :         status = _cairo_surface_wrapper_show_text_glyphs (&slaves[n], op,
     454             :                                   matched_source,
     455             :                                                           utf8, utf8_len,
     456             :                                                           glyphs_copy, num_glyphs,
     457             :                                                           clusters, num_clusters,
     458             :                                                           cluster_flags,
     459             :                                                           scaled_font,
     460             :                                                           clip);
     461           0 :         if (matched_source == &temp.base) {
     462           0 :             _cairo_pattern_fini (&temp.base);
     463             :         }
     464           0 :         if (unlikely (status))
     465           0 :             goto CLEANUP;
     466             :     }
     467             : 
     468             :   CLEANUP:
     469           0 :     free (glyphs_copy);
     470           0 :     return status;
     471             : }
     472             : 
     473             : static cairo_status_t
     474           0 : _cairo_tee_surface_flush (void *abstract_surface)
     475             : {
     476           0 :     cairo_tee_surface_t *surface = abstract_surface;
     477             :     cairo_surface_wrapper_t *slaves;
     478             :     int n, num_slaves;
     479             :     cairo_status_t status;
     480             : 
     481           0 :     status = _cairo_surface_wrapper_flush(&surface->master);
     482           0 :     if (unlikely (status))
     483           0 :         return status;
     484             : 
     485           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     486           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     487           0 :     for (n = 0; n < num_slaves; n++) {
     488           0 :         status = _cairo_surface_wrapper_flush(&slaves[n]);
     489           0 :         if (unlikely (status))
     490           0 :             return status;
     491             :     }
     492             : 
     493           0 :     return CAIRO_STATUS_SUCCESS;
     494             : }
     495             : 
     496             : static const cairo_surface_backend_t cairo_tee_surface_backend = {
     497             :     CAIRO_SURFACE_TYPE_TEE,
     498             :     _cairo_tee_surface_create_similar,
     499             :     _cairo_tee_surface_finish,
     500             :     _cairo_tee_surface_acquire_source_image,
     501             :     _cairo_tee_surface_release_source_image,
     502             :     NULL, NULL, /* dest_image */
     503             :     NULL, /* clone_similar */
     504             :     NULL, /* composite */
     505             :     NULL, /* fill_rectangles */
     506             :     NULL, /* composite_trapezoids */
     507             :     NULL, /* create_span_renderer */
     508             :     NULL, /* check_span_renderer */
     509             :     NULL, /* copy_page */
     510             :     NULL, /* show_page */
     511             :     _cairo_tee_surface_get_extents,
     512             :     NULL, /* old_show_glyphs */
     513             :     _cairo_tee_surface_get_font_options,
     514             :     _cairo_tee_surface_flush,
     515             :     NULL, /* mark_dirty_rectangle */
     516             :     NULL, /* scaled_font_fini */
     517             :     NULL, /* scaled_glyph_fini */
     518             : 
     519             :     _cairo_tee_surface_paint,
     520             :     _cairo_tee_surface_mask,
     521             :     _cairo_tee_surface_stroke,
     522             :     _cairo_tee_surface_fill,
     523             :     NULL, /* replaced by show_text_glyphs */
     524             : 
     525             :     _cairo_tee_surface_snapshot,
     526             :     NULL, /* is_similar */
     527             :     NULL, /* fill_stroke */
     528             :     NULL, /* create_solid_pattern_surface */
     529             :     NULL, /* can_repaint_solid_pattern_surface */
     530             : 
     531             :     _cairo_tee_surface_has_show_text_glyphs,
     532             :     _cairo_tee_surface_show_text_glyphs
     533             : };
     534             : 
     535             : cairo_surface_t *
     536           0 : cairo_tee_surface_create (cairo_surface_t *master)
     537             : {
     538             :     cairo_tee_surface_t *surface;
     539             : 
     540           0 :     if (unlikely (master->status))
     541           0 :         return _cairo_surface_create_in_error (master->status);
     542             : 
     543           0 :     surface = malloc (sizeof (cairo_tee_surface_t));
     544           0 :     if (unlikely (surface == NULL))
     545           0 :         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     546             : 
     547           0 :     _cairo_surface_init (&surface->base,
     548             :                          &cairo_tee_surface_backend,
     549             :                          master->device,
     550             :                          master->content);
     551             : 
     552           0 :     _cairo_surface_wrapper_init (&surface->master, master);
     553             :     /* we trust that these are already set and remain constant */
     554           0 :     surface->base.device_transform = master->device_transform;
     555           0 :     surface->base.device_transform_inverse = master->device_transform_inverse;
     556             : 
     557           0 :     _cairo_array_init (&surface->slaves, sizeof (cairo_surface_wrapper_t));
     558             : 
     559           0 :     return &surface->base;
     560             : }
     561             : slim_hidden_def (cairo_tee_surface_create);
     562             : 
     563             : void
     564           0 : cairo_tee_surface_add (cairo_surface_t *abstract_surface,
     565             :                        cairo_surface_t *target)
     566             : {
     567             :     cairo_tee_surface_t *surface;
     568             :     cairo_surface_wrapper_t slave;
     569             :     cairo_status_t status;
     570             : 
     571           0 :     if (unlikely (abstract_surface->status))
     572           0 :         return;
     573           0 :     if (unlikely (abstract_surface->finished)) {
     574           0 :         status = _cairo_surface_set_error (abstract_surface,
     575             :                                            _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
     576           0 :         return;
     577             :     }
     578             : 
     579           0 :     if (abstract_surface->backend != &cairo_tee_surface_backend) {
     580           0 :         status = _cairo_surface_set_error (abstract_surface,
     581             :                                            _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
     582           0 :         return;
     583             :     }
     584             : 
     585           0 :     if (unlikely (target->status)) {
     586           0 :         status = _cairo_surface_set_error (abstract_surface, target->status);
     587           0 :         return;
     588             :     }
     589             : 
     590           0 :     surface = (cairo_tee_surface_t *) abstract_surface;
     591             : 
     592           0 :     _cairo_surface_wrapper_init (&slave, target);
     593           0 :     status = _cairo_array_append (&surface->slaves, &slave);
     594           0 :     if (unlikely (status)) {
     595           0 :         _cairo_surface_wrapper_fini (&slave);
     596           0 :         status = _cairo_surface_set_error (&surface->base, status);
     597             :     }
     598             : }
     599             : slim_hidden_def (cairo_tee_surface_add);
     600             : 
     601             : void
     602           0 : cairo_tee_surface_remove (cairo_surface_t *abstract_surface,
     603             :                           cairo_surface_t *target)
     604             : {
     605             :     cairo_tee_surface_t *surface;
     606             :     cairo_surface_wrapper_t *slaves;
     607             :     int n, num_slaves;
     608             :     cairo_status_t status;
     609             : 
     610           0 :     if (unlikely (abstract_surface->status))
     611           0 :         return;
     612           0 :     if (unlikely (abstract_surface->finished)) {
     613           0 :         status = _cairo_surface_set_error (abstract_surface,
     614             :                                            _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
     615           0 :         return;
     616             :     }
     617             : 
     618           0 :     if (abstract_surface->backend != &cairo_tee_surface_backend) {
     619           0 :         status = _cairo_surface_set_error (abstract_surface,
     620             :                                            _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
     621           0 :         return;
     622             :     }
     623             : 
     624           0 :     surface = (cairo_tee_surface_t *) abstract_surface;
     625           0 :     if (target == surface->master.target) {
     626           0 :         status = _cairo_surface_set_error (abstract_surface,
     627             :                                            _cairo_error (CAIRO_STATUS_INVALID_INDEX));
     628           0 :         return;
     629             :     }
     630             : 
     631           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     632           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     633           0 :     for (n = 0; n < num_slaves; n++) {
     634           0 :         if (slaves[n].target == target)
     635           0 :             break;
     636             :     }
     637             : 
     638           0 :     if (n == num_slaves) {
     639           0 :         status = _cairo_surface_set_error (abstract_surface,
     640             :                                            _cairo_error (CAIRO_STATUS_INVALID_INDEX));
     641           0 :         return;
     642             :     }
     643             : 
     644           0 :     _cairo_surface_wrapper_fini (&slaves[n]);
     645           0 :     for (n++; n < num_slaves; n++)
     646           0 :         slaves[n-1] = slaves[n];
     647           0 :     surface->slaves.num_elements--; /* XXX: cairo_array_remove()? */
     648             : }
     649             : 
     650             : cairo_surface_t *
     651           0 : cairo_tee_surface_index (cairo_surface_t *abstract_surface,
     652             :                          int index)
     653             : {
     654             :     cairo_tee_surface_t *surface;
     655             : 
     656           0 :     if (unlikely (abstract_surface->status))
     657           0 :         return _cairo_surface_create_in_error (abstract_surface->status);
     658           0 :     if (unlikely (abstract_surface->finished))
     659           0 :         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
     660             : 
     661           0 :     if (abstract_surface->backend != &cairo_tee_surface_backend)
     662           0 :         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
     663             : 
     664           0 :     surface = (cairo_tee_surface_t *) abstract_surface;
     665           0 :     if (index == 0) {
     666           0 :         return surface->master.target;
     667             :     } else {
     668             :         cairo_surface_wrapper_t *slave;
     669             : 
     670           0 :         index--;
     671             : 
     672           0 :         if (index >= _cairo_array_num_elements (&surface->slaves))
     673           0 :             return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_INDEX));
     674             : 
     675           0 :         slave = _cairo_array_index (&surface->slaves, index);
     676           0 :         return slave->target;
     677             :     }
     678             : }
     679             : 
     680             : cairo_surface_t *
     681           0 : _cairo_tee_surface_find_match (void *abstract_surface,
     682             :                                const cairo_surface_backend_t *backend,
     683             :                                cairo_content_t content)
     684             : {
     685           0 :     cairo_tee_surface_t *surface = abstract_surface;
     686             :     cairo_surface_wrapper_t *slaves;
     687             :     int num_slaves, n;
     688             : 
     689             :     /* exact match first */
     690           0 :     if (surface->master.target->backend == backend &&
     691           0 :         surface->master.target->content == content)
     692             :     {
     693           0 :         return surface->master.target;
     694             :     }
     695             : 
     696           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     697           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     698           0 :     for (n = 0; n < num_slaves; n++) {
     699           0 :         if (slaves[n].target->backend == backend &&
     700           0 :             slaves[n].target->content == content)
     701             :         {
     702           0 :             return slaves[n].target;
     703             :         }
     704             :     }
     705             : 
     706             :     /* matching backend? */
     707           0 :     if (surface->master.target->backend == backend)
     708           0 :         return surface->master.target;
     709             : 
     710           0 :     num_slaves = _cairo_array_num_elements (&surface->slaves);
     711           0 :     slaves = _cairo_array_index (&surface->slaves, 0);
     712           0 :     for (n = 0; n < num_slaves; n++) {
     713           0 :         if (slaves[n].target->backend == backend)
     714           0 :             return slaves[n].target;
     715             :     }
     716             : 
     717           0 :     return NULL;
     718             : }

Generated by: LCOV version 1.13