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

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