LCOV - code coverage report
Current view: directory - gfx/cairo/cairo/src - cairo-tee-surface.c (source / functions) Found Hit Coverage
Test: app.info Lines: 271 0 0.0 %
Date: 2012-06-02 Functions: 22 0 0.0 %

       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.7