LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-surface-subsurface.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 206 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 16 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 © 2009 Intel Corporation
       4             :  *
       5             :  * This library is free software; you can redistribute it and/or
       6             :  * modify it either under the terms of the GNU Lesser General Public
       7             :  * License version 2.1 as published by the Free Software Foundation
       8             :  * (the "LGPL") or, at your option, under the terms of the Mozilla
       9             :  * Public License Version 1.1 (the "MPL"). If you do not alter this
      10             :  * notice, a recipient may use your version of this file under either
      11             :  * the MPL or the LGPL.
      12             :  *
      13             :  * You should have received a copy of the LGPL along with this library
      14             :  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
      15             :  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
      16             :  * You should have received a copy of the MPL along with this library
      17             :  * in the file COPYING-MPL-1.1
      18             :  *
      19             :  * The contents of this file are subject to the Mozilla Public License
      20             :  * Version 1.1 (the "License"); you may not use this file except in
      21             :  * compliance with the License. You may obtain a copy of the License at
      22             :  * http://www.mozilla.org/MPL/
      23             :  *
      24             :  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
      25             :  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
      26             :  * the specific language governing rights and limitations.
      27             :  *
      28             :  * The Original Code is the cairo graphics library.
      29             :  *
      30             :  * The Initial Developer of the Original Code is Intel Corporation.
      31             :  *
      32             :  * Contributor(s):
      33             :  *      Chris Wilson <chris@chris-wilson.co.uk>
      34             :  */
      35             : 
      36             : #include "cairoint.h"
      37             : 
      38             : #include "cairo-error-private.h"
      39             : #include "cairo-recording-surface-private.h"
      40             : #include "cairo-surface-offset-private.h"
      41             : #include "cairo-surface-subsurface-private.h"
      42             : 
      43             : static const cairo_surface_backend_t _cairo_surface_subsurface_backend;
      44             : 
      45             : static cairo_status_t
      46           0 : _cairo_surface_subsurface_finish (void *abstract_surface)
      47             : {
      48           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
      49             : 
      50           0 :     cairo_surface_destroy (surface->target);
      51             : 
      52           0 :     return CAIRO_STATUS_SUCCESS;
      53             : }
      54             : 
      55             : static cairo_surface_t *
      56           0 : _cairo_surface_subsurface_create_similar (void *other,
      57             :                                           cairo_content_t content,
      58             :                                           int width, int height)
      59             : {
      60           0 :     cairo_surface_subsurface_t *surface = other;
      61           0 :     return surface->target->backend->create_similar (surface->target, content, width, height);
      62             : }
      63             : 
      64             : static cairo_int_status_t
      65           0 : _cairo_surface_subsurface_paint (void *abstract_surface,
      66             :                                  cairo_operator_t op,
      67             :                                  const cairo_pattern_t *source,
      68             :                                  cairo_clip_t *clip)
      69             : {
      70           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
      71           0 :     cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
      72             :     cairo_status_t status;
      73             :     cairo_clip_t target_clip;
      74             : 
      75           0 :     _cairo_clip_init_copy (&target_clip, clip);
      76           0 :     status = _cairo_clip_rectangle (&target_clip, &rect);
      77           0 :     if (unlikely (status))
      78           0 :         goto CLEANUP;
      79             : 
      80           0 :     status = _cairo_surface_offset_paint (surface->target,
      81           0 :                                          -surface->extents.x, -surface->extents.y,
      82             :                                           op, source, &target_clip);
      83             :   CLEANUP:
      84           0 :     _cairo_clip_fini (&target_clip);
      85           0 :     return status;
      86             : }
      87             : 
      88             : static cairo_int_status_t
      89           0 : _cairo_surface_subsurface_mask (void *abstract_surface,
      90             :                                 cairo_operator_t op,
      91             :                                 const cairo_pattern_t *source,
      92             :                                 const cairo_pattern_t *mask,
      93             :                                 cairo_clip_t *clip)
      94             : {
      95           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
      96           0 :     cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
      97             :     cairo_status_t status;
      98             :     cairo_clip_t target_clip;
      99             : 
     100           0 :     _cairo_clip_init_copy (&target_clip, clip);
     101           0 :     status = _cairo_clip_rectangle (&target_clip, &rect);
     102           0 :     if (unlikely (status))
     103           0 :         goto CLEANUP;
     104             : 
     105           0 :     status = _cairo_surface_offset_mask (surface->target,
     106           0 :                                          -surface->extents.x, -surface->extents.y,
     107             :                                          op, source, mask, &target_clip);
     108             :   CLEANUP:
     109           0 :     _cairo_clip_fini (&target_clip);
     110           0 :     return status;
     111             : }
     112             : 
     113             : static cairo_int_status_t
     114           0 : _cairo_surface_subsurface_fill (void                    *abstract_surface,
     115             :                                 cairo_operator_t         op,
     116             :                                 const cairo_pattern_t   *source,
     117             :                                 cairo_path_fixed_t      *path,
     118             :                                 cairo_fill_rule_t        fill_rule,
     119             :                                 double                   tolerance,
     120             :                                 cairo_antialias_t        antialias,
     121             :                                 cairo_clip_t            *clip)
     122             : {
     123           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     124           0 :     cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
     125             :     cairo_status_t status;
     126             :     cairo_clip_t target_clip;
     127             : 
     128           0 :     _cairo_clip_init_copy (&target_clip, clip);
     129           0 :     status = _cairo_clip_rectangle (&target_clip, &rect);
     130           0 :     if (unlikely (status))
     131           0 :         goto CLEANUP;
     132             : 
     133           0 :     status = _cairo_surface_offset_fill (surface->target,
     134           0 :                                          -surface->extents.x, -surface->extents.y,
     135             :                                          op, source, path, fill_rule, tolerance, antialias,
     136             :                                          &target_clip);
     137             :   CLEANUP:
     138           0 :     _cairo_clip_fini (&target_clip);
     139           0 :     return status;
     140             : }
     141             : 
     142             : static cairo_int_status_t
     143           0 : _cairo_surface_subsurface_stroke (void                          *abstract_surface,
     144             :                                   cairo_operator_t               op,
     145             :                                   const cairo_pattern_t         *source,
     146             :                                   cairo_path_fixed_t            *path,
     147             :                                   const cairo_stroke_style_t    *stroke_style,
     148             :                                   const cairo_matrix_t          *ctm,
     149             :                                   const cairo_matrix_t          *ctm_inverse,
     150             :                                   double                         tolerance,
     151             :                                   cairo_antialias_t              antialias,
     152             :                                   cairo_clip_t                  *clip)
     153             : {
     154           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     155           0 :     cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
     156             :     cairo_status_t status;
     157             :     cairo_clip_t target_clip;
     158             : 
     159           0 :     _cairo_clip_init_copy (&target_clip, clip);
     160           0 :     status = _cairo_clip_rectangle (&target_clip, &rect);
     161           0 :     if (unlikely (status))
     162           0 :         goto CLEANUP;
     163             : 
     164           0 :     status = _cairo_surface_offset_stroke (surface->target,
     165           0 :                                            -surface->extents.x, -surface->extents.y,
     166             :                                            op, source, path, stroke_style, ctm, ctm_inverse,
     167             :                                            tolerance, antialias,
     168             :                                            &target_clip);
     169             :   CLEANUP:
     170           0 :     _cairo_clip_fini (&target_clip);
     171           0 :     return status;
     172             : }
     173             : 
     174             : static cairo_int_status_t
     175           0 : _cairo_surface_subsurface_glyphs (void                  *abstract_surface,
     176             :                                   cairo_operator_t       op,
     177             :                                   const cairo_pattern_t *source,
     178             :                                   cairo_glyph_t         *glyphs,
     179             :                                   int                    num_glyphs,
     180             :                                   cairo_scaled_font_t   *scaled_font,
     181             :                                   cairo_clip_t          *clip,
     182             :                                   int *remaining_glyphs)
     183             : {
     184           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     185           0 :     cairo_rectangle_int_t rect = { 0, 0, surface->extents.width, surface->extents.height };
     186             :     cairo_status_t status;
     187             :     cairo_clip_t target_clip;
     188             : 
     189           0 :     _cairo_clip_init_copy (&target_clip, clip);
     190           0 :     status = _cairo_clip_rectangle (&target_clip, &rect);
     191           0 :     if (unlikely (status))
     192           0 :         goto CLEANUP;
     193             : 
     194           0 :     status = _cairo_surface_offset_glyphs (surface->target,
     195           0 :                                            -surface->extents.x, -surface->extents.y,
     196             :                                            op, source,
     197             :                                            scaled_font, glyphs, num_glyphs,
     198             :                                            &target_clip);
     199           0 :     *remaining_glyphs = 0;
     200             :   CLEANUP:
     201           0 :     _cairo_clip_fini (&target_clip);
     202           0 :     return status;
     203             : }
     204             : 
     205             : static cairo_status_t
     206           0 : _cairo_surface_subsurface_flush (void *abstract_surface)
     207             : {
     208           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     209             :     cairo_status_t status;
     210             : 
     211           0 :     status = CAIRO_STATUS_SUCCESS;
     212           0 :     if (surface->target->backend->flush != NULL)
     213           0 :         status = surface->target->backend->flush (surface->target);
     214             : 
     215           0 :     return status;
     216             : }
     217             : 
     218             : static cairo_status_t
     219           0 : _cairo_surface_subsurface_mark_dirty (void *abstract_surface,
     220             :                                       int x, int y,
     221             :                                       int width, int height)
     222             : {
     223           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     224             :     cairo_status_t status;
     225             : 
     226           0 :     status = CAIRO_STATUS_SUCCESS;
     227           0 :     if (surface->target->backend->mark_dirty_rectangle != NULL) {
     228             :         cairo_rectangle_int_t rect, extents;
     229             : 
     230           0 :         rect.x = x;
     231           0 :         rect.y = y;
     232           0 :         rect.width  = width;
     233           0 :         rect.height = height;
     234             : 
     235           0 :         extents.x = extents.y = 0;
     236           0 :         extents.width  = surface->extents.width;
     237           0 :         extents.height = surface->extents.height;
     238             : 
     239           0 :         if (_cairo_rectangle_intersect (&rect, &extents)) {
     240           0 :             status = surface->target->backend->mark_dirty_rectangle (surface->target,
     241           0 :                                                                      rect.x + surface->extents.x,
     242           0 :                                                                      rect.y + surface->extents.y,
     243             :                                                                      rect.width, rect.height);
     244             :         }
     245             :     }
     246             : 
     247           0 :     return status;
     248             : }
     249             : 
     250             : static cairo_bool_t
     251           0 : _cairo_surface_subsurface_get_extents (void *abstract_surface,
     252             :                                        cairo_rectangle_int_t *extents)
     253             : {
     254           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     255             : 
     256           0 :     extents->x = 0;
     257           0 :     extents->y = 0;
     258           0 :     extents->width  = surface->extents.width;
     259           0 :     extents->height = surface->extents.height;
     260             : 
     261           0 :     return TRUE;
     262             : }
     263             : 
     264             : static void
     265           0 : _cairo_surface_subsurface_get_font_options (void *abstract_surface,
     266             :                                             cairo_font_options_t *options)
     267             : {
     268           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     269             : 
     270           0 :     if (surface->target->backend->get_font_options != NULL)
     271           0 :         surface->target->backend->get_font_options (surface->target, options);
     272           0 : }
     273             : 
     274             : struct extra {
     275             :     cairo_image_surface_t *image;
     276             :     void *image_extra;
     277             : };
     278             : 
     279             : static void
     280           0 : cairo_surface_paint_to_target (cairo_surface_t            *target,
     281             :                                cairo_surface_subsurface_t *subsurface)
     282             : {
     283             :     cairo_t *cr;
     284             :     
     285           0 :     cr = cairo_create (target);
     286             : 
     287           0 :     cairo_set_source_surface (cr,
     288             :                               subsurface->target,
     289           0 :                               - subsurface->extents.x,
     290           0 :                               - subsurface->extents.y);
     291           0 :     cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
     292           0 :     cairo_paint (cr);
     293             :     
     294           0 :     cairo_destroy (cr);
     295           0 : }
     296             : 
     297             : static cairo_status_t
     298           0 : _cairo_surface_subsurface_acquire_source_image (void                    *abstract_surface,
     299             :                                                 cairo_image_surface_t  **image_out,
     300             :                                                 void                   **extra_out)
     301             : {
     302             :     cairo_rectangle_int_t target_extents;
     303           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     304             :     cairo_image_surface_t *image;
     305             :     cairo_status_t status;
     306             :     struct extra *extra;
     307             :     uint8_t *data;
     308             :     cairo_bool_t ret;
     309             : 
     310           0 :     if (surface->target->type == CAIRO_SURFACE_TYPE_RECORDING) {
     311           0 :         cairo_recording_surface_t *meta = (cairo_recording_surface_t *) surface->target;
     312             :         cairo_surface_t *snapshot;
     313             : 
     314           0 :         snapshot = _cairo_surface_has_snapshot (&surface->base,
     315             :                                                 &_cairo_image_surface_backend);
     316           0 :         if (snapshot != NULL) {
     317           0 :             *image_out = (cairo_image_surface_t *) cairo_surface_reference (snapshot);
     318           0 :             *extra_out = NULL;
     319           0 :             return CAIRO_STATUS_SUCCESS;
     320             :         }
     321             : 
     322           0 :         if (! _cairo_surface_has_snapshot (&meta->base,
     323             :                                            &_cairo_image_surface_backend))
     324             :         {
     325           0 :             image = (cairo_image_surface_t *)
     326           0 :                 _cairo_image_surface_create_with_content (meta->content,
     327             :                                                           surface->extents.width,
     328             :                                                           surface->extents.height);
     329           0 :             if (unlikely (image->base.status))
     330           0 :                 return image->base.status;
     331             : 
     332           0 :             cairo_surface_paint_to_target (&image->base, surface);
     333             : 
     334           0 :             cairo_surface_attach_snapshot (&surface->base, &image->base, NULL);
     335             : 
     336           0 :             *image_out = image;
     337           0 :             *extra_out = NULL;
     338           0 :             return CAIRO_STATUS_SUCCESS;
     339             :         }
     340             :     }
     341             : 
     342           0 :     extra = malloc (sizeof (struct extra));
     343           0 :     if (unlikely (extra == NULL))
     344           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     345             : 
     346           0 :     status = _cairo_surface_acquire_source_image (surface->target, &extra->image, &extra->image_extra);
     347           0 :     if (unlikely (status))
     348           0 :         goto CLEANUP;
     349             : 
     350           0 :     ret = _cairo_surface_get_extents (&extra->image->base, &target_extents);
     351           0 :     assert (ret);
     352             : 
     353             :     /* only copy if we need to perform sub-byte manipulation */
     354           0 :     if (PIXMAN_FORMAT_BPP (extra->image->pixman_format) >= 8 &&
     355           0 :         target_extents.x <= surface->extents.x &&
     356           0 :         target_extents.y <= surface->extents.y &&
     357           0 :         surface->extents.x + surface->extents.width <= target_extents.x + target_extents.width &&
     358           0 :         surface->extents.y + surface->extents.height <= target_extents.y + target_extents.height) {
     359             : 
     360           0 :         assert ((PIXMAN_FORMAT_BPP (extra->image->pixman_format) % 8) == 0);
     361             : 
     362           0 :         data = extra->image->data + surface->extents.y * extra->image->stride;
     363           0 :         data += PIXMAN_FORMAT_BPP (extra->image->pixman_format) / 8 * surface->extents.x;
     364             : 
     365           0 :         image = (cairo_image_surface_t *)
     366           0 :             _cairo_image_surface_create_with_pixman_format (data,
     367           0 :                                                             extra->image->pixman_format,
     368             :                                                             surface->extents.width,
     369             :                                                             surface->extents.height,
     370           0 :                                                             extra->image->stride);
     371           0 :         if (unlikely ((status = image->base.status)))
     372           0 :             goto CLEANUP_IMAGE;
     373             : 
     374           0 :         image->base.is_clear = FALSE;
     375             :     } else {
     376           0 :         image = (cairo_image_surface_t *)
     377           0 :             _cairo_image_surface_create_with_pixman_format (NULL,
     378           0 :                                                             extra->image->pixman_format,
     379             :                                                             surface->extents.width,
     380             :                                                             surface->extents.height,
     381             :                                                             0);
     382           0 :         if (unlikely ((status = image->base.status)))
     383           0 :             goto CLEANUP_IMAGE;
     384             : 
     385           0 :         cairo_surface_paint_to_target (&image->base, surface);
     386             :     }
     387             : 
     388           0 :     *image_out = image;
     389           0 :     *extra_out = extra;
     390           0 :     return CAIRO_STATUS_SUCCESS;
     391             : 
     392             : CLEANUP_IMAGE:
     393           0 :     _cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra);
     394             : CLEANUP:
     395           0 :     free (extra);
     396           0 :     return status;
     397             : }
     398             : 
     399             : static void
     400           0 : _cairo_surface_subsurface_release_source_image (void                   *abstract_surface,
     401             :                                                 cairo_image_surface_t  *image,
     402             :                                                 void                   *abstract_extra)
     403             : {
     404           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     405             : 
     406           0 :     if (abstract_extra != NULL) {
     407           0 :         struct extra *extra = abstract_extra;
     408             : 
     409           0 :         _cairo_surface_release_source_image (surface->target, extra->image, extra->image_extra);
     410           0 :         free (extra);
     411             :     }
     412             : 
     413           0 :     cairo_surface_destroy (&image->base);
     414           0 : }
     415             : 
     416             : static cairo_surface_t *
     417           0 : _cairo_surface_subsurface_snapshot (void *abstract_surface)
     418             : {
     419           0 :     cairo_surface_subsurface_t *surface = abstract_surface;
     420             :     cairo_surface_subsurface_t *snapshot;
     421             : 
     422           0 :     snapshot = malloc (sizeof (cairo_surface_subsurface_t));
     423           0 :     if (unlikely (snapshot == NULL))
     424           0 :         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     425             : 
     426           0 :     _cairo_surface_init (&snapshot->base,
     427             :                          &_cairo_surface_subsurface_backend,
     428             :                          NULL, /* device */
     429           0 :                          surface->target->content);
     430           0 :     snapshot->target = _cairo_surface_snapshot (surface->target);
     431           0 :     if (unlikely (snapshot->target->status)) {
     432             :         cairo_status_t status;
     433             : 
     434           0 :         status = snapshot->target->status;
     435           0 :         free (snapshot);
     436           0 :         return _cairo_surface_create_in_error (status);
     437             :     }
     438             : 
     439           0 :     snapshot->base.type = snapshot->target->type;
     440           0 :     snapshot->extents = surface->extents;
     441             : 
     442           0 :     return &snapshot->base;
     443             : }
     444             : 
     445             : static const cairo_surface_backend_t _cairo_surface_subsurface_backend = {
     446             :     CAIRO_SURFACE_TYPE_SUBSURFACE,
     447             :     _cairo_surface_subsurface_create_similar,
     448             :     _cairo_surface_subsurface_finish,
     449             : 
     450             :     _cairo_surface_subsurface_acquire_source_image,
     451             :     _cairo_surface_subsurface_release_source_image,
     452             :     NULL, NULL, /* acquire, release dest */
     453             :     NULL, /* clone similar */
     454             :     NULL, /* composite */
     455             :     NULL, /* fill rectangles */
     456             :     NULL, /* composite trapezoids */
     457             :     NULL, /* create span renderer */
     458             :     NULL, /* check span renderer */
     459             :     NULL, /* copy_page */
     460             :     NULL, /* show_page */
     461             :     _cairo_surface_subsurface_get_extents,
     462             :     NULL, /* old_show_glyphs */
     463             :     _cairo_surface_subsurface_get_font_options,
     464             :     _cairo_surface_subsurface_flush,
     465             :     _cairo_surface_subsurface_mark_dirty,
     466             :     NULL, /* font_fini */
     467             :     NULL, /* glyph_fini */
     468             : 
     469             :     _cairo_surface_subsurface_paint,
     470             :     _cairo_surface_subsurface_mask,
     471             :     _cairo_surface_subsurface_stroke,
     472             :     _cairo_surface_subsurface_fill,
     473             :     _cairo_surface_subsurface_glyphs,
     474             : 
     475             :     _cairo_surface_subsurface_snapshot,
     476             : };
     477             : 
     478             : /**
     479             :  * cairo_surface_create_for_rectangle:
     480             :  * @target: an existing surface for which the sub-surface will point to
     481             :  * @x: the x-origin of the sub-surface from the top-left of the target surface (in device-space units)
     482             :  * @y: the y-origin of the sub-surface from the top-left of the target surface (in device-space units)
     483             :  * @width: width of the sub-surface (in device-space units)
     484             :  * @height: height of the sub-surface (in device-space units)
     485             :  *
     486             :  * Create a new surface that is a rectangle within the target surface.
     487             :  * All operations drawn to this surface are then clipped and translated
     488             :  * onto the target surface. Nothing drawn via this sub-surface outside of
     489             :  * its bounds is drawn onto the target surface, making this a useful method
     490             :  * for passing constrained child surfaces to library routines that draw
     491             :  * directly onto the parent surface, i.e. with no further backend allocations,
     492             :  * double buffering or copies.
     493             :  *
     494             :  * <note><para>The semantics of subsurfaces have not been finalized yet
     495             :  * unless the rectangle is in full device units, is contained within
     496             :  * the extents of the target surface, and the target or subsurface's
     497             :  * device transforms are not changed.</para></note>
     498             :  *
     499             :  * Return value: a pointer to the newly allocated surface. The caller
     500             :  * owns the surface and should call cairo_surface_destroy() when done
     501             :  * with it.
     502             :  *
     503             :  * This function always returns a valid pointer, but it will return a
     504             :  * pointer to a "nil" surface if @other is already in an error state
     505             :  * or any other error occurs.
     506             :  *
     507             :  * Since: 1.10
     508             :  **/
     509             : cairo_surface_t *
     510           0 : cairo_surface_create_for_rectangle (cairo_surface_t *target,
     511             :                                     double x, double y,
     512             :                                     double width, double height)
     513             : {
     514             :     cairo_surface_subsurface_t *surface;
     515             : 
     516           0 :     if (unlikely (target->status))
     517           0 :         return _cairo_surface_create_in_error (target->status);
     518           0 :     if (unlikely (target->finished))
     519           0 :         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
     520             : 
     521           0 :     surface = malloc (sizeof (cairo_surface_subsurface_t));
     522           0 :     if (unlikely (surface == NULL))
     523           0 :         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
     524             : 
     525           0 :     assert (_cairo_matrix_is_translation (&target->device_transform));
     526           0 :     x += target->device_transform.x0;
     527           0 :     y += target->device_transform.y0;
     528             : 
     529           0 :     _cairo_surface_init (&surface->base,
     530             :                          &_cairo_surface_subsurface_backend,
     531             :                          NULL, /* device */
     532             :                          target->content);
     533             : 
     534             :     /* XXX forced integer alignment */
     535           0 :     surface->extents.x = ceil (x);
     536           0 :     surface->extents.y = ceil (y);
     537           0 :     surface->extents.width = floor (x + width) - surface->extents.x;
     538           0 :     surface->extents.height = floor (y + height) - surface->extents.y;
     539             : 
     540           0 :     if (target->backend->type == CAIRO_SURFACE_TYPE_SUBSURFACE) {
     541             :         /* Maintain subsurfaces as 1-depth */
     542           0 :         cairo_surface_subsurface_t *sub = (cairo_surface_subsurface_t *) target;
     543           0 :         surface->extents.x += sub->extents.x;
     544           0 :         surface->extents.y += sub->extents.y;
     545           0 :         target = sub->target;
     546             :     }
     547             : 
     548           0 :     surface->target = cairo_surface_reference (target);
     549             : 
     550           0 :     return &surface->base;
     551             : }
     552             : /* XXX observe mark-dirty */

Generated by: LCOV version 1.13