Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

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