LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-surface.c (source / functions) Hit Total Coverage
Test: output.info Lines: 64 959 6.7 %
Date: 2017-07-14 16:53:18 Functions: 10 88 11.4 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
       2             : /* cairo - a vector graphics library with display and print output
       3             :  *
       4             :  * Copyright © 2002 University of Southern California
       5             :  * Copyright © 2005 Red Hat, Inc.
       6             :  *
       7             :  * This library is free software; you can redistribute it and/or
       8             :  * modify it either under the terms of the GNU Lesser General Public
       9             :  * License version 2.1 as published by the Free Software Foundation
      10             :  * (the "LGPL") or, at your option, under the terms of the Mozilla
      11             :  * Public License Version 1.1 (the "MPL"). If you do not alter this
      12             :  * notice, a recipient may use your version of this file under either
      13             :  * the MPL or the LGPL.
      14             :  *
      15             :  * You should have received a copy of the LGPL along with this library
      16             :  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
      17             :  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
      18             :  * You should have received a copy of the MPL along with this library
      19             :  * in the file COPYING-MPL-1.1
      20             :  *
      21             :  * The contents of this file are subject to the Mozilla Public License
      22             :  * Version 1.1 (the "License"); you may not use this file except in
      23             :  * compliance with the License. You may obtain a copy of the License at
      24             :  * http://www.mozilla.org/MPL/
      25             :  *
      26             :  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
      27             :  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
      28             :  * the specific language governing rights and limitations.
      29             :  *
      30             :  * The Original Code is the cairo graphics library.
      31             :  *
      32             :  * The Initial Developer of the Original Code is University of Southern
      33             :  * California.
      34             :  *
      35             :  * Contributor(s):
      36             :  *      Carl D. Worth <cworth@cworth.org>
      37             :  */
      38             : 
      39             : #include "cairoint.h"
      40             : 
      41             : #include "cairo-surface-fallback-private.h"
      42             : #include "cairo-clip-private.h"
      43             : #include "cairo-device-private.h"
      44             : #include "cairo-error-private.h"
      45             : #include "cairo-recording-surface-private.h"
      46             : #include "cairo-region-private.h"
      47             : #include "cairo-tee-surface-private.h"
      48             : 
      49             : /**
      50             :  * SECTION:cairo-surface
      51             :  * @Title: cairo_surface_t
      52             :  * @Short_Description: Base class for surfaces
      53             :  * @See_Also: #cairo_t, #cairo_pattern_t
      54             :  *
      55             :  * #cairo_surface_t is the abstract type representing all different drawing
      56             :  * targets that cairo can render to.  The actual drawings are
      57             :  * performed using a cairo <firstterm>context</firstterm>.
      58             :  *
      59             :  * A cairo surface is created by using <firstterm>backend</firstterm>-specific
      60             :  * constructors, typically of the form
      61             :  * cairo_<emphasis>backend</emphasis>_surface_create().
      62             :  *
      63             :  * Most surface types allow accessing the surface without using Cairo
      64             :  * functions. If you do this, keep in mind that it is mandatory that you call
      65             :  * cairo_surface_flush() before reading from or writing to the surface and that
      66             :  * you must use cairo_surface_mark_dirty() after modifying it.
      67             :  * <example>
      68             :  * <title>Directly modifying an image surface</title>
      69             :  * <programlisting>
      70             :  * void
      71             :  * modify_image_surface (cairo_surface_t *surface)
      72             :  * {
      73             :  *   unsigned char *data;
      74             :  *   int width, height, stride;
      75             :  *
      76             :  *   // flush to ensure all writing to the image was done
      77             :  *   cairo_surface_flush (surface);
      78             :  *
      79             :  *   // modify the image
      80             :  *   data = cairo_image_surface_get_data (surface);
      81             :  *   width = cairo_image_surface_get_width (surface);
      82             :  *   height = cairo_image_surface_get_height (surface);
      83             :  *   stride = cairo_image_surface_get_stride (surface);
      84             :  *   modify_image_data (data, width, height, stride);
      85             :  *
      86             :  *   // mark the image dirty so Cairo clears its caches.
      87             :  *   cairo_surface_mark_dirty (surface);
      88             :  * }
      89             :  * </programlisting>
      90             :  * </example>
      91             :  * Note that for other surface types it might be necessary to acquire the
      92             :  * surface's device first. See cairo_device_acquire() for a discussion of
      93             :  * devices.
      94             :  */
      95             : 
      96             : #define DEFINE_NIL_SURFACE(status, name)                        \
      97             : const cairo_surface_t name = {                                  \
      98             :     NULL,                               /* backend */           \
      99             :     NULL,                               /* device */            \
     100             :     CAIRO_SURFACE_TYPE_IMAGE,           /* type */              \
     101             :     CAIRO_CONTENT_COLOR,                /* content */           \
     102             :     CAIRO_REFERENCE_COUNT_INVALID,      /* ref_count */         \
     103             :     status,                             /* status */            \
     104             :     0,                                  /* unique id */         \
     105             :     FALSE,                              /* finished */          \
     106             :     TRUE,                               /* is_clear */          \
     107             :     FALSE,                              /* has_font_options */  \
     108             :     FALSE,                              /* owns_device */       \
     109             :     FALSE,                              /* permit_subpixel_antialiasing */ \
     110             :     { 0, 0, 0, NULL, },                 /* user_data */         \
     111             :     { 0, 0, 0, NULL, },                 /* mime_data */         \
     112             :     { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },   /* device_transform */  \
     113             :     { 1.0, 0.0, 0.0, 1.0, 0.0, 0.0 },   /* device_transform_inverse */  \
     114             :     { NULL, NULL },                     /* device_transform_observers */ \
     115             :     0.0,                                /* x_resolution */      \
     116             :     0.0,                                /* y_resolution */      \
     117             :     0.0,                                /* x_fallback_resolution */     \
     118             :     0.0,                                /* y_fallback_resolution */     \
     119             :     NULL,                               /* snapshot_of */       \
     120             :     NULL,                               /* snapshot_detach */   \
     121             :     { NULL, NULL },                     /* snapshots */         \
     122             :     { NULL, NULL },                     /* snapshot */          \
     123             :     { CAIRO_ANTIALIAS_DEFAULT,          /* antialias */         \
     124             :       CAIRO_SUBPIXEL_ORDER_DEFAULT,     /* subpixel_order */    \
     125             :       CAIRO_LCD_FILTER_DEFAULT,         /* lcd_filter */        \
     126             :       CAIRO_HINT_STYLE_DEFAULT,         /* hint_style */        \
     127             :       CAIRO_HINT_METRICS_DEFAULT,       /* hint_metrics */      \
     128             :       CAIRO_ROUND_GLYPH_POS_DEFAULT     /* round_glyph_positions */     \
     129             :     }                                   /* font_options */      \
     130             : }
     131             : 
     132             : /* XXX error object! */
     133             : 
     134             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_NO_MEMORY, _cairo_surface_nil);
     135             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_SURFACE_TYPE_MISMATCH, _cairo_surface_nil_surface_type_mismatch);
     136             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STATUS, _cairo_surface_nil_invalid_status);
     137             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_CONTENT, _cairo_surface_nil_invalid_content);
     138             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_FORMAT, _cairo_surface_nil_invalid_format);
     139             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_VISUAL, _cairo_surface_nil_invalid_visual);
     140             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_FILE_NOT_FOUND, _cairo_surface_nil_file_not_found);
     141             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_TEMP_FILE_ERROR, _cairo_surface_nil_temp_file_error);
     142             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_READ_ERROR, _cairo_surface_nil_read_error);
     143             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_WRITE_ERROR, _cairo_surface_nil_write_error);
     144             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_STRIDE, _cairo_surface_nil_invalid_stride);
     145             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_INVALID_SIZE, _cairo_surface_nil_invalid_size);
     146             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_DEVICE_TYPE_MISMATCH, _cairo_surface_nil_device_type_mismatch);
     147             : static DEFINE_NIL_SURFACE(CAIRO_STATUS_DEVICE_ERROR, _cairo_surface_nil_device_error);
     148             : 
     149             : /**
     150             :  * _cairo_surface_set_error:
     151             :  * @surface: a surface
     152             :  * @status: a status value indicating an error
     153             :  *
     154             :  * Atomically sets surface->status to @status and calls _cairo_error;
     155             :  * Does nothing if status is %CAIRO_STATUS_SUCCESS or any of the internal
     156             :  * status values.
     157             :  *
     158             :  * All assignments of an error status to surface->status should happen
     159             :  * through _cairo_surface_set_error(). Note that due to the nature of
     160             :  * the atomic operation, it is not safe to call this function on the
     161             :  * nil objects.
     162             :  *
     163             :  * The purpose of this function is to allow the user to set a
     164             :  * breakpoint in _cairo_error() to generate a stack trace for when the
     165             :  * user causes cairo to detect an error.
     166             :  *
     167             :  * Return value: the error status.
     168             :  **/
     169             : cairo_status_t
     170           0 : _cairo_surface_set_error (cairo_surface_t *surface,
     171             :                           cairo_status_t status)
     172             : {
     173           0 :     if (status == CAIRO_INT_STATUS_NOTHING_TO_DO)
     174           0 :         status = CAIRO_STATUS_SUCCESS;
     175             : 
     176           0 :     if (status == CAIRO_STATUS_SUCCESS || status >= CAIRO_INT_STATUS_UNSUPPORTED)
     177           0 :         return status;
     178             : 
     179             :     /* Don't overwrite an existing error. This preserves the first
     180             :      * error, which is the most significant. */
     181           0 :     _cairo_status_set_error (&surface->status, status);
     182             : 
     183           0 :     return _cairo_error (status);
     184             : }
     185             : 
     186             : /**
     187             :  * cairo_surface_get_type:
     188             :  * @surface: a #cairo_surface_t
     189             :  *
     190             :  * This function returns the type of the backend used to create
     191             :  * a surface. See #cairo_surface_type_t for available types.
     192             :  *
     193             :  * Return value: The type of @surface.
     194             :  *
     195             :  * Since: 1.2
     196             :  **/
     197             : cairo_surface_type_t
     198          12 : cairo_surface_get_type (cairo_surface_t *surface)
     199             : {
     200             :     /* We don't use surface->backend->type here so that some of the
     201             :      * special "wrapper" surfaces such as cairo_paginated_surface_t
     202             :      * can override surface->type with the type of the "child"
     203             :      * surface. */
     204          12 :     return surface->type;
     205             : }
     206             : slim_hidden_def (cairo_surface_get_type);
     207             : 
     208             : /**
     209             :  * cairo_surface_get_content:
     210             :  * @surface: a #cairo_surface_t
     211             :  *
     212             :  * This function returns the content type of @surface which indicates
     213             :  * whether the surface contains color and/or alpha information. See
     214             :  * #cairo_content_t.
     215             :  *
     216             :  * Return value: The content type of @surface.
     217             :  *
     218             :  * Since: 1.2
     219             :  **/
     220             : cairo_content_t
     221           3 : cairo_surface_get_content (cairo_surface_t *surface)
     222             : {
     223           3 :     return surface->content;
     224             : }
     225             : slim_hidden_def(cairo_surface_get_content);
     226             : 
     227             : /**
     228             :  * cairo_surface_status:
     229             :  * @surface: a #cairo_surface_t
     230             :  *
     231             :  * Checks whether an error has previously occurred for this
     232             :  * surface.
     233             :  *
     234             :  * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NULL_POINTER,
     235             :  * %CAIRO_STATUS_NO_MEMORY, %CAIRO_STATUS_READ_ERROR,
     236             :  * %CAIRO_STATUS_INVALID_CONTENT, %CAIRO_STATUS_INVALID_FORMAT, or
     237             :  * %CAIRO_STATUS_INVALID_VISUAL.
     238             :  **/
     239             : cairo_status_t
     240           6 : cairo_surface_status (cairo_surface_t *surface)
     241             : {
     242           6 :     return surface->status;
     243             : }
     244             : slim_hidden_def (cairo_surface_status);
     245             : 
     246             : static unsigned int
     247           3 : _cairo_surface_allocate_unique_id (void)
     248             : {
     249             :     static cairo_atomic_int_t unique_id;
     250             : 
     251             : #if CAIRO_NO_MUTEX
     252             :     if (++unique_id == 0)
     253             :         unique_id = 1;
     254             :     return unique_id;
     255             : #else
     256             :     cairo_atomic_int_t old, id;
     257             : 
     258             :     do {
     259           3 :         old = _cairo_atomic_uint_get (&unique_id);
     260           3 :         id = old + 1;
     261           3 :         if (id == 0)
     262           0 :             id = 1;
     263           3 :     } while (! _cairo_atomic_uint_cmpxchg (&unique_id, old, id));
     264             : 
     265           3 :     return id;
     266             : #endif
     267             : }
     268             : 
     269             : /**
     270             :  * cairo_surface_get_device:
     271             :  * @surface: a #cairo_surface_t
     272             :  *
     273             :  * This function returns the device for a @surface.
     274             :  * See #cairo_device_t.
     275             :  *
     276             :  * Return value: The device for @surface or %NULL if the surface does
     277             :  *               not have an associated device.
     278             :  *
     279             :  * Since: 1.10
     280             :  **/
     281             : cairo_device_t *
     282           0 : cairo_surface_get_device (cairo_surface_t *surface)
     283             : {
     284           0 :     if (unlikely (surface->status))
     285           0 :         return _cairo_device_create_in_error (surface->status);
     286             : 
     287           0 :     return surface->device;
     288             : }
     289             : 
     290             : static cairo_bool_t
     291           0 : _cairo_surface_has_snapshots (cairo_surface_t *surface)
     292             : {
     293           0 :     return ! cairo_list_is_empty (&surface->snapshots);
     294             : }
     295             : 
     296             : static cairo_bool_t
     297           0 : _cairo_surface_has_mime_data (cairo_surface_t *surface)
     298             : {
     299           0 :     return surface->mime_data.num_elements != 0;
     300             : }
     301             : 
     302             : static void
     303           0 : _cairo_surface_detach_mime_data (cairo_surface_t *surface)
     304             : {
     305           0 :     if (! _cairo_surface_has_mime_data (surface))
     306           0 :         return;
     307             : 
     308           0 :     _cairo_user_data_array_fini (&surface->mime_data);
     309           0 :     _cairo_user_data_array_init (&surface->mime_data);
     310             : }
     311             : 
     312             : static void
     313           0 : cairo_surface_detach_snapshots (cairo_surface_t *surface)
     314             : {
     315           0 :     while (_cairo_surface_has_snapshots (surface)) {
     316           0 :         cairo_surface_detach_snapshot (cairo_list_first_entry (&surface->snapshots,
     317             :                                                                 cairo_surface_t,
     318             :                                                                 snapshot));
     319             :     }
     320           0 : }
     321             : 
     322             : void
     323           0 : cairo_surface_detach_snapshot (cairo_surface_t *snapshot)
     324             : {
     325           0 :     assert (snapshot->snapshot_of != NULL);
     326             : 
     327           0 :     snapshot->snapshot_of = NULL;
     328           0 :     cairo_list_del (&snapshot->snapshot);
     329             : 
     330           0 :     if (snapshot->snapshot_detach != NULL)
     331           0 :         snapshot->snapshot_detach (snapshot);
     332             : 
     333           0 :     cairo_surface_destroy (snapshot);
     334           0 : }
     335             : 
     336             : void
     337           0 : cairo_surface_attach_snapshot (cairo_surface_t *surface,
     338             :                                  cairo_surface_t *snapshot,
     339             :                                  cairo_surface_func_t detach_func)
     340             : {
     341           0 :     assert (surface != snapshot);
     342           0 :     assert (snapshot->snapshot_of != surface);
     343             : 
     344           0 :     cairo_surface_reference (snapshot);
     345             : 
     346           0 :     if (snapshot->snapshot_of != NULL)
     347           0 :         cairo_surface_detach_snapshot (snapshot);
     348             : 
     349           0 :     snapshot->snapshot_of = surface;
     350           0 :     snapshot->snapshot_detach = detach_func;
     351             : 
     352           0 :     cairo_list_add (&snapshot->snapshot, &surface->snapshots);
     353             : 
     354           0 :     assert (_cairo_surface_has_snapshot (surface, snapshot->backend) == snapshot);
     355           0 : }
     356             : 
     357             : cairo_surface_t *
     358           0 : _cairo_surface_has_snapshot (cairo_surface_t *surface,
     359             :                              const cairo_surface_backend_t *backend)
     360             : {
     361             :     cairo_surface_t *snapshot;
     362             : 
     363           0 :     cairo_list_foreach_entry (snapshot, cairo_surface_t,
     364             :                               &surface->snapshots, snapshot)
     365             :     {
     366             :         /* XXX is_similar? */
     367           0 :         if (snapshot->backend == backend)
     368           0 :             return snapshot;
     369             :     }
     370             : 
     371           0 :     return NULL;
     372             : }
     373             : 
     374             : static cairo_bool_t
     375           0 : _cairo_surface_is_writable (cairo_surface_t *surface)
     376             : {
     377           0 :     return ! surface->finished &&
     378           0 :            surface->snapshot_of == NULL &&
     379           0 :            ! _cairo_surface_has_snapshots (surface) &&
     380           0 :            ! _cairo_surface_has_mime_data (surface);
     381             : }
     382             : 
     383             : static void
     384           0 : _cairo_surface_begin_modification (cairo_surface_t *surface)
     385             : {
     386           0 :     assert (surface->status == CAIRO_STATUS_SUCCESS);
     387           0 :     assert (! surface->finished);
     388           0 :     assert (surface->snapshot_of == NULL);
     389             : 
     390           0 :     cairo_surface_detach_snapshots (surface);
     391           0 :     _cairo_surface_detach_mime_data (surface);
     392           0 : }
     393             : 
     394             : void
     395           3 : _cairo_surface_init (cairo_surface_t                    *surface,
     396             :                      const cairo_surface_backend_t      *backend,
     397             :                      cairo_device_t                     *device,
     398             :                      cairo_content_t                     content)
     399             : {
     400             :     CAIRO_MUTEX_INITIALIZE ();
     401             : 
     402           3 :     surface->backend = backend;
     403           3 :     surface->device = cairo_device_reference (device);
     404           3 :     surface->content = content;
     405           3 :     surface->type = backend->type;
     406             : 
     407           3 :     CAIRO_REFERENCE_COUNT_INIT (&surface->ref_count, 1);
     408           3 :     surface->status = CAIRO_STATUS_SUCCESS;
     409           3 :     surface->unique_id = _cairo_surface_allocate_unique_id ();
     410           3 :     surface->finished = FALSE;
     411           3 :     surface->is_clear = FALSE;
     412           3 :     surface->owns_device = (device != NULL);
     413           3 :     surface->has_font_options = FALSE;
     414           3 :     surface->permit_subpixel_antialiasing = TRUE;
     415             : 
     416           3 :     _cairo_user_data_array_init (&surface->user_data);
     417           3 :     _cairo_user_data_array_init (&surface->mime_data);
     418             : 
     419           3 :     cairo_matrix_init_identity (&surface->device_transform);
     420           3 :     cairo_matrix_init_identity (&surface->device_transform_inverse);
     421           3 :     cairo_list_init (&surface->device_transform_observers);
     422             : 
     423           3 :     surface->x_resolution = CAIRO_SURFACE_RESOLUTION_DEFAULT;
     424           3 :     surface->y_resolution = CAIRO_SURFACE_RESOLUTION_DEFAULT;
     425             : 
     426           3 :     surface->x_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
     427           3 :     surface->y_fallback_resolution = CAIRO_SURFACE_FALLBACK_RESOLUTION_DEFAULT;
     428             : 
     429           3 :     cairo_list_init (&surface->snapshots);
     430           3 :     surface->snapshot_of = NULL;
     431           3 : }
     432             : 
     433             : static void
     434           0 : _cairo_surface_copy_similar_properties (cairo_surface_t *surface,
     435             :                                         cairo_surface_t *other)
     436             : {
     437           0 :     if (other->has_font_options || other->backend != surface->backend) {
     438             :         cairo_font_options_t options;
     439             : 
     440           0 :         cairo_surface_get_font_options (other, &options);
     441           0 :         _cairo_surface_set_font_options (surface, &options);
     442             :     }
     443             : 
     444           0 :     surface->permit_subpixel_antialiasing = other->permit_subpixel_antialiasing;
     445             : 
     446           0 :     cairo_surface_set_fallback_resolution (surface,
     447             :                                            other->x_fallback_resolution,
     448             :                                            other->y_fallback_resolution);
     449           0 : }
     450             : 
     451             : cairo_surface_t *
     452           0 : _cairo_surface_create_similar_scratch (cairo_surface_t *other,
     453             :                                        cairo_content_t  content,
     454             :                                        int              width,
     455             :                                        int              height)
     456             : {
     457             :     cairo_surface_t *surface;
     458             : 
     459           0 :     if (unlikely (other->status))
     460           0 :         return _cairo_surface_create_in_error (other->status);
     461             : 
     462           0 :     if (other->backend->create_similar == NULL)
     463           0 :         return NULL;
     464             : 
     465           0 :     surface = other->backend->create_similar (other,
     466             :                                               content, width, height);
     467           0 :     if (surface == NULL || surface->status)
     468           0 :         return surface;
     469             : 
     470           0 :     _cairo_surface_copy_similar_properties (surface, other);
     471             : 
     472           0 :     return surface;
     473             : }
     474             : 
     475             : /**
     476             :  * cairo_surface_create_similar:
     477             :  * @other: an existing surface used to select the backend of the new surface
     478             :  * @content: the content for the new surface
     479             :  * @width: width of the new surface, (in device-space units)
     480             :  * @height: height of the new surface (in device-space units)
     481             :  *
     482             :  * Create a new surface that is as compatible as possible with an
     483             :  * existing surface. For example the new surface will have the same
     484             :  * fallback resolution and font options as @other. Generally, the new
     485             :  * surface will also use the same backend as @other, unless that is
     486             :  * not possible for some reason. The type of the returned surface may
     487             :  * be examined with cairo_surface_get_type().
     488             :  *
     489             :  * Initially the surface contents are all 0 (transparent if contents
     490             :  * have transparency, black otherwise.)
     491             :  *
     492             :  * Return value: a pointer to the newly allocated surface. The caller
     493             :  * owns the surface and should call cairo_surface_destroy() when done
     494             :  * with it.
     495             :  *
     496             :  * This function always returns a valid pointer, but it will return a
     497             :  * pointer to a "nil" surface if @other is already in an error state
     498             :  * or any other error occurs.
     499             :  **/
     500             : cairo_surface_t *
     501           0 : cairo_surface_create_similar (cairo_surface_t  *other,
     502             :                               cairo_content_t   content,
     503             :                               int               width,
     504             :                               int               height)
     505             : {
     506           0 :     if (unlikely (other->status))
     507           0 :         return _cairo_surface_create_in_error (other->status);
     508           0 :     if (unlikely (other->finished))
     509           0 :         return _cairo_surface_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
     510             : 
     511           0 :     if (unlikely (! CAIRO_CONTENT_VALID (content)))
     512           0 :         return _cairo_surface_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_CONTENT));
     513             : 
     514           0 :     return _cairo_surface_create_similar_solid (other,
     515             :                                                 content, width, height,
     516             :                                                 CAIRO_COLOR_TRANSPARENT,
     517             :                                                 TRUE);
     518             : }
     519             : 
     520             : cairo_surface_t *
     521           0 : _cairo_surface_create_similar_solid (cairo_surface_t     *other,
     522             :                                      cairo_content_t      content,
     523             :                                      int                  width,
     524             :                                      int                  height,
     525             :                                      const cairo_color_t *color,
     526             :                                      cairo_bool_t allow_fallback)
     527             : {
     528             :     cairo_status_t status;
     529             :     cairo_surface_t *surface;
     530             :     cairo_solid_pattern_t pattern;
     531             : 
     532           0 :     surface = _cairo_surface_create_similar_scratch (other, content,
     533             :                                                      width, height);
     534           0 :     if (surface == NULL && allow_fallback)
     535           0 :         surface = _cairo_image_surface_create_with_content (content,
     536             :                                                             width, height);
     537           0 :     if (surface == NULL || surface->status)
     538           0 :         return surface;
     539             : 
     540           0 :     _cairo_pattern_init_solid (&pattern, color);
     541           0 :     status = _cairo_surface_paint (surface,
     542           0 :                                    color == CAIRO_COLOR_TRANSPARENT ?
     543             :                                    CAIRO_OPERATOR_CLEAR : CAIRO_OPERATOR_SOURCE,
     544             :                                    &pattern.base, NULL);
     545           0 :     if (unlikely (status)) {
     546           0 :         cairo_surface_destroy (surface);
     547           0 :         surface = _cairo_surface_create_in_error (status);
     548             :     }
     549             : 
     550           0 :     return surface;
     551             : }
     552             : 
     553             : cairo_surface_t *
     554           0 : _cairo_surface_create_solid_pattern_surface (cairo_surface_t       *other,
     555             :                                              const cairo_solid_pattern_t *solid_pattern)
     556             : {
     557           0 :     if (other->backend->create_solid_pattern_surface != NULL) {
     558             :         cairo_surface_t *surface;
     559             : 
     560           0 :         surface = other->backend->create_solid_pattern_surface (other,
     561             :                                                                 solid_pattern);
     562           0 :         if (surface)
     563           0 :             return surface;
     564             :     }
     565             : 
     566           0 :     return _cairo_surface_create_similar_solid (other,
     567             :                                                 _cairo_color_get_content (&solid_pattern->color),
     568             :                                                 1, 1,
     569             :                                                 &solid_pattern->color,
     570             :                                                 FALSE);
     571             : }
     572             : 
     573             : cairo_int_status_t
     574           0 : _cairo_surface_repaint_solid_pattern_surface (cairo_surface_t       *other,
     575             :                                               cairo_surface_t       *solid_surface,
     576             :                                               const cairo_solid_pattern_t *solid_pattern)
     577             : {
     578             :     /* Solid pattern surface for these backends are special and not trivial
     579             :      * to repaint.  Skip repainting.
     580             :      *
     581             :      * This does not work optimally with things like analysis surface that
     582             :      * are proxies.  But returning UNSUPPORTED is *safe* as it only
     583             :      * disables some caching.
     584             :      */
     585           0 :     if (other->backend->create_solid_pattern_surface != NULL &&
     586           0 :         ! other->backend->can_repaint_solid_pattern_surface (solid_surface,
     587             :                                                              solid_pattern))
     588             :     {
     589           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
     590             :     }
     591             : 
     592           0 :     return _cairo_surface_paint (solid_surface,
     593             :                                  CAIRO_OPERATOR_SOURCE,
     594             :                                  &solid_pattern->base,
     595             :                                  NULL);
     596             : }
     597             : 
     598             : /**
     599             :  * cairo_surface_reference:
     600             :  * @surface: a #cairo_surface_t
     601             :  *
     602             :  * Increases the reference count on @surface by one. This prevents
     603             :  * @surface from being destroyed until a matching call to
     604             :  * cairo_surface_destroy() is made.
     605             :  *
     606             :  * The number of references to a #cairo_surface_t can be get using
     607             :  * cairo_surface_get_reference_count().
     608             :  *
     609             :  * Return value: the referenced #cairo_surface_t.
     610             :  **/
     611             : cairo_surface_t *
     612           4 : cairo_surface_reference (cairo_surface_t *surface)
     613             : {
     614           8 :     if (surface == NULL ||
     615           8 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
     616           0 :         return surface;
     617             : 
     618           8 :     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
     619             : 
     620           4 :     _cairo_reference_count_inc (&surface->ref_count);
     621             : 
     622           4 :     return surface;
     623             : }
     624             : slim_hidden_def (cairo_surface_reference);
     625             : 
     626             : /**
     627             :  * cairo_surface_destroy:
     628             :  * @surface: a #cairo_surface_t
     629             :  *
     630             :  * Decreases the reference count on @surface by one. If the result is
     631             :  * zero, then @surface and all associated resources are freed.  See
     632             :  * cairo_surface_reference().
     633             :  **/
     634             : void
     635           0 : cairo_surface_destroy (cairo_surface_t *surface)
     636             : {
     637           0 :     if (surface == NULL ||
     638           0 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
     639           0 :         return;
     640             : 
     641           0 :     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
     642             : 
     643           0 :     if (! _cairo_reference_count_dec_and_test (&surface->ref_count))
     644           0 :         return;
     645             : 
     646           0 :     assert (surface->snapshot_of == NULL);
     647             : 
     648           0 :     if (! surface->finished)
     649           0 :         cairo_surface_finish (surface);
     650             : 
     651             :     /* paranoid check that nobody took a reference whilst finishing */
     652           0 :     assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&surface->ref_count));
     653             : 
     654           0 :     _cairo_user_data_array_fini (&surface->user_data);
     655           0 :     _cairo_user_data_array_fini (&surface->mime_data);
     656             : 
     657           0 :     if (surface->owns_device)
     658           0 :         cairo_device_destroy (surface->device);
     659             : 
     660           0 :     free (surface);
     661             : }
     662             : slim_hidden_def(cairo_surface_destroy);
     663             : 
     664             : /**
     665             :  * cairo_surface_get_reference_count:
     666             :  * @surface: a #cairo_surface_t
     667             :  *
     668             :  * Returns the current reference count of @surface.
     669             :  *
     670             :  * Return value: the current reference count of @surface.  If the
     671             :  * object is a nil object, 0 will be returned.
     672             :  *
     673             :  * Since: 1.4
     674             :  **/
     675             : unsigned int
     676           3 : cairo_surface_get_reference_count (cairo_surface_t *surface)
     677             : {
     678           6 :     if (surface == NULL ||
     679           6 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
     680           0 :         return 0;
     681             : 
     682           6 :     return CAIRO_REFERENCE_COUNT_GET_VALUE (&surface->ref_count);
     683             : }
     684             : 
     685             : /**
     686             :  * cairo_surface_finish:
     687             :  * @surface: the #cairo_surface_t to finish
     688             :  *
     689             :  * This function finishes the surface and drops all references to
     690             :  * external resources.  For example, for the Xlib backend it means
     691             :  * that cairo will no longer access the drawable, which can be freed.
     692             :  * After calling cairo_surface_finish() the only valid operations on a
     693             :  * surface are getting and setting user, referencing and
     694             :  * destroying, and flushing and finishing it.
     695             :  * Further drawing to the surface will not affect the
     696             :  * surface but will instead trigger a %CAIRO_STATUS_SURFACE_FINISHED
     697             :  * error.
     698             :  *
     699             :  * When the last call to cairo_surface_destroy() decreases the
     700             :  * reference count to zero, cairo will call cairo_surface_finish() if
     701             :  * it hasn't been called already, before freeing the resources
     702             :  * associated with the surface.
     703             :  **/
     704             : void
     705           0 : cairo_surface_finish (cairo_surface_t *surface)
     706             : {
     707             :     cairo_status_t status;
     708             : 
     709           0 :     if (surface == NULL)
     710           0 :         return;
     711             : 
     712           0 :     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
     713           0 :         return;
     714             : 
     715           0 :     if (surface->finished)
     716           0 :         return;
     717             : 
     718             :     /* update the snapshots *before* we declare the surface as finished */
     719           0 :     cairo_surface_detach_snapshots (surface);
     720           0 :     if (surface->snapshot_of != NULL)
     721           0 :         cairo_surface_detach_snapshot (surface);
     722             : 
     723           0 :     cairo_surface_flush (surface);
     724           0 :     surface->finished = TRUE;
     725             : 
     726             :     /* call finish even if in error mode */
     727           0 :     if (surface->backend->finish) {
     728           0 :         status = surface->backend->finish (surface);
     729           0 :         if (unlikely (status))
     730           0 :             status = _cairo_surface_set_error (surface, status);
     731             :     }
     732             : }
     733             : slim_hidden_def (cairo_surface_finish);
     734             : 
     735             : /**
     736             :  * _cairo_surface_release_device_reference:
     737             :  * @surface: a #cairo_surface_t
     738             :  *
     739             :  * This function makes @surface release the reference to its device. The
     740             :  * function is intended to be used for avoiding cycling references for
     741             :  * surfaces that are owned by their device, for example cache surfaces.
     742             :  * Note that the @surface will still assume that the device is available.
     743             :  * So it is the caller's responsibility to ensure the device stays around
     744             :  * until the @surface is destroyed. Just calling cairo_surface_finish() is
     745             :  * not enough.
     746             :  **/
     747             : void
     748           0 : _cairo_surface_release_device_reference (cairo_surface_t *surface)
     749             : {
     750           0 :     assert (surface->owns_device);
     751             : 
     752           0 :     cairo_device_destroy (surface->device);
     753           0 :     surface->owns_device = FALSE;
     754           0 : }
     755             : 
     756             : /**
     757             :  * cairo_surface_get_user_data:
     758             :  * @surface: a #cairo_surface_t
     759             :  * @key: the address of the #cairo_user_data_key_t the user data was
     760             :  * attached to
     761             :  *
     762             :  * Return user data previously attached to @surface using the specified
     763             :  * key.  If no user data has been attached with the given key this
     764             :  * function returns %NULL.
     765             :  *
     766             :  * Return value: the user data previously attached or %NULL.
     767             :  **/
     768             : void *
     769           0 : cairo_surface_get_user_data (cairo_surface_t             *surface,
     770             :                              const cairo_user_data_key_t *key)
     771             : {
     772           0 :     return _cairo_user_data_array_get_data (&surface->user_data,
     773             :                                             key);
     774             : }
     775             : 
     776             : /**
     777             :  * cairo_surface_set_user_data:
     778             :  * @surface: a #cairo_surface_t
     779             :  * @key: the address of a #cairo_user_data_key_t to attach the user data to
     780             :  * @user_data: the user data to attach to the surface
     781             :  * @destroy: a #cairo_destroy_func_t which will be called when the
     782             :  * surface is destroyed or when new user data is attached using the
     783             :  * same key.
     784             :  *
     785             :  * Attach user data to @surface.  To remove user data from a surface,
     786             :  * call this function with the key that was used to set it and %NULL
     787             :  * for @data.
     788             :  *
     789             :  * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
     790             :  * slot could not be allocated for the user data.
     791             :  **/
     792             : cairo_status_t
     793           3 : cairo_surface_set_user_data (cairo_surface_t             *surface,
     794             :                              const cairo_user_data_key_t *key,
     795             :                              void                        *user_data,
     796             :                              cairo_destroy_func_t        destroy)
     797             : {
     798           6 :     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&surface->ref_count))
     799           0 :         return surface->status;
     800             : 
     801           3 :     return _cairo_user_data_array_set_data (&surface->user_data,
     802             :                                             key, user_data, destroy);
     803             : }
     804             : 
     805             : /**
     806             :  * cairo_surface_get_mime_data:
     807             :  * @surface: a #cairo_surface_t
     808             :  * @mime_type: the mime type of the image data
     809             :  * @data: the image data to attached to the surface
     810             :  * @length: the length of the image data
     811             :  *
     812             :  * Return mime data previously attached to @surface using the
     813             :  * specified mime type.  If no data has been attached with the given
     814             :  * mime type, @data is set %NULL.
     815             :  *
     816             :  * Since: 1.10
     817             :  **/
     818             : void
     819           0 : cairo_surface_get_mime_data (cairo_surface_t            *surface,
     820             :                              const char                 *mime_type,
     821             :                              const unsigned char       **data,
     822             :                              unsigned long              *length)
     823             : {
     824             :     cairo_user_data_slot_t *slots;
     825             :     int i, num_slots;
     826             : 
     827           0 :     *data = NULL;
     828           0 :     *length = 0;
     829           0 :     if (unlikely (surface->status))
     830           0 :         return;
     831             : 
     832             :     /* The number of mime-types attached to a surface is usually small,
     833             :      * typically zero. Therefore it is quicker to do a strcmp() against
     834             :      * each key than it is to intern the string (i.e. compute a hash,
     835             :      * search the hash table, and do a final strcmp).
     836             :      */
     837           0 :     num_slots = surface->mime_data.num_elements;
     838           0 :     slots = _cairo_array_index (&surface->mime_data, 0);
     839           0 :     for (i = 0; i < num_slots; i++) {
     840           0 :         if (strcmp ((char *) slots[i].key, mime_type) == 0) {
     841           0 :             cairo_mime_data_t *mime_data = slots[i].user_data;
     842             : 
     843           0 :             *data = mime_data->data;
     844           0 :             *length = mime_data->length;
     845           0 :             return;
     846             :         }
     847             :     }
     848             : }
     849             : slim_hidden_def (cairo_surface_get_mime_data);
     850             : 
     851             : static void
     852           0 : _cairo_mime_data_destroy (void *ptr)
     853             : {
     854           0 :     cairo_mime_data_t *mime_data = ptr;
     855             : 
     856           0 :     if (! _cairo_reference_count_dec_and_test (&mime_data->ref_count))
     857           0 :         return;
     858             : 
     859           0 :     if (mime_data->destroy && mime_data->closure)
     860           0 :         mime_data->destroy (mime_data->closure);
     861             : 
     862           0 :     free (mime_data);
     863             : }
     864             : 
     865             : /**
     866             :  * CAIRO_MIME_TYPE_JP2:
     867             :  *
     868             :  * The Joint Photographic Experts Group (JPEG) 2000 image coding standard (ISO/IEC 15444-1).
     869             :  *
     870             :  * @Since: 1.10
     871             :  */
     872             : 
     873             : /**
     874             :  * CAIRO_MIME_TYPE_JPEG:
     875             :  *
     876             :  * The Joint Photographic Experts Group (JPEG) image coding standard (ISO/IEC 10918-1).
     877             :  *
     878             :  * @Since: 1.10
     879             :  */
     880             : 
     881             : /**
     882             :  * CAIRO_MIME_TYPE_PNG:
     883             :  *
     884             :  * The Portable Network Graphics image file format (ISO/IEC 15948).
     885             :  *
     886             :  * @Since: 1.10
     887             :  */
     888             : 
     889             : /**
     890             :  * CAIRO_MIME_TYPE_URI:
     891             :  *
     892             :  * URI for an image file (unofficial MIME type).
     893             :  *
     894             :  * @Since: 1.10
     895             :  */
     896             : 
     897             : /**
     898             :  * cairo_surface_set_mime_data:
     899             :  * @surface: a #cairo_surface_t
     900             :  * @mime_type: the MIME type of the image data
     901             :  * @data: the image data to attach to the surface
     902             :  * @length: the length of the image data
     903             :  * @destroy: a #cairo_destroy_func_t which will be called when the
     904             :  * surface is destroyed or when new image data is attached using the
     905             :  * same mime type.
     906             :  * @closure: the data to be passed to the @destroy notifier
     907             :  *
     908             :  * Attach an image in the format @mime_type to @surface. To remove
     909             :  * the data from a surface, call this function with same mime type
     910             :  * and %NULL for @data.
     911             :  *
     912             :  * The attached image (or filename) data can later be used by backends
     913             :  * which support it (currently: PDF, PS, SVG and Win32 Printing
     914             :  * surfaces) to emit this data instead of making a snapshot of the
     915             :  * @surface.  This approach tends to be faster and requires less
     916             :  * memory and disk space.
     917             :  *
     918             :  * The recognized MIME types are the following: %CAIRO_MIME_TYPE_JPEG,
     919             :  * %CAIRO_MIME_TYPE_PNG, %CAIRO_MIME_TYPE_JP2, %CAIRO_MIME_TYPE_URI.
     920             :  *
     921             :  * See corresponding backend surface docs for details about which MIME
     922             :  * types it can handle. Caution: the associated MIME data will be
     923             :  * discarded if you draw on the surface afterwards. Use this function
     924             :  * with care.
     925             :  *
     926             :  * Since: 1.10
     927             :  *
     928             :  * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
     929             :  * slot could not be allocated for the user data.
     930             :  **/
     931             : cairo_status_t
     932           0 : cairo_surface_set_mime_data (cairo_surface_t            *surface,
     933             :                              const char                 *mime_type,
     934             :                              const unsigned char        *data,
     935             :                              unsigned long               length,
     936             :                              cairo_destroy_func_t        destroy,
     937             :                              void                       *closure)
     938             : {
     939             :     cairo_status_t status;
     940             :     cairo_mime_data_t *mime_data;
     941             : 
     942           0 :     if (unlikely (surface->status))
     943           0 :         return surface->status;
     944           0 :     if (surface->finished)
     945           0 :         return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
     946             : 
     947           0 :     status = _cairo_intern_string (&mime_type, -1);
     948           0 :     if (unlikely (status))
     949           0 :         return _cairo_surface_set_error (surface, status);
     950             : 
     951           0 :     if (data != NULL) {
     952           0 :         mime_data = malloc (sizeof (cairo_mime_data_t));
     953           0 :         if (unlikely (mime_data == NULL))
     954           0 :             return _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_NO_MEMORY));
     955             : 
     956           0 :         CAIRO_REFERENCE_COUNT_INIT (&mime_data->ref_count, 1);
     957             : 
     958           0 :         mime_data->data = (unsigned char *) data;
     959           0 :         mime_data->length = length;
     960           0 :         mime_data->destroy = destroy;
     961           0 :         mime_data->closure = closure;
     962             :     } else
     963           0 :         mime_data = NULL;
     964             : 
     965           0 :     status = _cairo_user_data_array_set_data (&surface->mime_data,
     966             :                                               (cairo_user_data_key_t *) mime_type,
     967             :                                               mime_data,
     968             :                                               _cairo_mime_data_destroy);
     969           0 :     if (unlikely (status)) {
     970           0 :         if (mime_data != NULL)
     971           0 :             free (mime_data);
     972             : 
     973           0 :         return _cairo_surface_set_error (surface, status);
     974             :     }
     975             : 
     976           0 :     return CAIRO_STATUS_SUCCESS;
     977             : }
     978             : slim_hidden_def (cairo_surface_set_mime_data);
     979             : 
     980             : static void
     981           0 : _cairo_mime_data_reference (const void *key, void *elt, void *closure)
     982             : {
     983           0 :     cairo_mime_data_t *mime_data = elt;
     984             : 
     985           0 :     _cairo_reference_count_inc (&mime_data->ref_count);
     986           0 : }
     987             : 
     988             : cairo_status_t
     989           0 : _cairo_surface_copy_mime_data (cairo_surface_t *dst,
     990             :                                cairo_surface_t *src)
     991             : {
     992             :     cairo_status_t status;
     993             : 
     994           0 :     if (dst->status)
     995           0 :         return dst->status;
     996             : 
     997           0 :     if (src->status)
     998           0 :         return _cairo_surface_set_error (dst, src->status);
     999             : 
    1000             :     /* first copy the mime-data, discarding any already set on dst */
    1001           0 :     status = _cairo_user_data_array_copy (&dst->mime_data, &src->mime_data);
    1002           0 :     if (unlikely (status))
    1003           0 :         return _cairo_surface_set_error (dst, status);
    1004             : 
    1005             :     /* now increment the reference counters for the copies */
    1006           0 :     _cairo_user_data_array_foreach (&dst->mime_data,
    1007             :                                     _cairo_mime_data_reference,
    1008             :                                     NULL);
    1009             : 
    1010           0 :     return CAIRO_STATUS_SUCCESS;
    1011             : }
    1012             : 
    1013             : /**
    1014             :  * _cairo_surface_set_font_options:
    1015             :  * @surface: a #cairo_surface_t
    1016             :  * @options: a #cairo_font_options_t object that contains the
    1017             :  *   options to use for this surface instead of backend's default
    1018             :  *   font options.
    1019             :  *
    1020             :  * Sets the default font rendering options for the surface.
    1021             :  * This is useful to correctly propagate default font options when
    1022             :  * falling back to an image surface in a backend implementation.
    1023             :  * This affects the options returned in cairo_surface_get_font_options().
    1024             :  *
    1025             :  * If @options is %NULL the surface options are reset to those of
    1026             :  * the backend default.
    1027             :  **/
    1028             : void
    1029           0 : _cairo_surface_set_font_options (cairo_surface_t       *surface,
    1030             :                                  cairo_font_options_t  *options)
    1031             : {
    1032             :     cairo_status_t status;
    1033             : 
    1034           0 :     if (surface->status)
    1035           0 :         return;
    1036             : 
    1037           0 :     assert (surface->snapshot_of == NULL);
    1038             : 
    1039           0 :     if (surface->finished) {
    1040           0 :         status = _cairo_surface_set_error (surface,
    1041             :                                            _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
    1042           0 :         return;
    1043             :     }
    1044             : 
    1045           0 :     if (options) {
    1046           0 :         surface->has_font_options = TRUE;
    1047           0 :         _cairo_font_options_init_copy (&surface->font_options, options);
    1048             :     } else {
    1049           0 :         surface->has_font_options = FALSE;
    1050             :     }
    1051             : }
    1052             : 
    1053             : /**
    1054             :  * cairo_surface_get_font_options:
    1055             :  * @surface: a #cairo_surface_t
    1056             :  * @options: a #cairo_font_options_t object into which to store
    1057             :  *   the retrieved options. All existing values are overwritten
    1058             :  *
    1059             :  * Retrieves the default font rendering options for the surface.
    1060             :  * This allows display surfaces to report the correct subpixel order
    1061             :  * for rendering on them, print surfaces to disable hinting of
    1062             :  * metrics and so forth. The result can then be used with
    1063             :  * cairo_scaled_font_create().
    1064             :  **/
    1065             : void
    1066           2 : cairo_surface_get_font_options (cairo_surface_t       *surface,
    1067             :                                 cairo_font_options_t  *options)
    1068             : {
    1069           2 :     if (cairo_font_options_status (options))
    1070           0 :         return;
    1071             : 
    1072           2 :     if (surface->status) {
    1073           0 :         _cairo_font_options_init_default (options);
    1074           0 :         return;
    1075             :     }
    1076             : 
    1077           2 :     if (! surface->has_font_options) {
    1078           2 :         surface->has_font_options = TRUE;
    1079             : 
    1080           2 :         _cairo_font_options_init_default (&surface->font_options);
    1081             : 
    1082           2 :         if (!surface->finished && surface->backend->get_font_options) {
    1083           2 :             surface->backend->get_font_options (surface, &surface->font_options);
    1084             :         }
    1085             :     }
    1086             : 
    1087           2 :     _cairo_font_options_init_copy (options, &surface->font_options);
    1088             : }
    1089             : slim_hidden_def (cairo_surface_get_font_options);
    1090             : 
    1091             : /**
    1092             :  * cairo_surface_flush:
    1093             :  * @surface: a #cairo_surface_t
    1094             :  *
    1095             :  * Do any pending drawing for the surface and also restore any
    1096             :  * temporary modifications cairo has made to the surface's
    1097             :  * state. This function must be called before switching from
    1098             :  * drawing on the surface with cairo to drawing on it directly
    1099             :  * with native APIs. If the surface doesn't support direct access,
    1100             :  * then this function does nothing.
    1101             :  **/
    1102             : void
    1103           0 : cairo_surface_flush (cairo_surface_t *surface)
    1104             : {
    1105             :     cairo_status_t status;
    1106             : 
    1107           0 :     if (surface->status)
    1108           0 :         return;
    1109             : 
    1110           0 :     if (surface->finished)
    1111           0 :         return;
    1112             : 
    1113             :     /* update the current snapshots *before* the user updates the surface */
    1114           0 :     cairo_surface_detach_snapshots (surface);
    1115             : 
    1116           0 :     if (surface->backend->flush) {
    1117           0 :         status = surface->backend->flush (surface);
    1118           0 :         if (unlikely (status))
    1119           0 :             status = _cairo_surface_set_error (surface, status);
    1120             :     }
    1121             : }
    1122             : slim_hidden_def (cairo_surface_flush);
    1123             : 
    1124             : /**
    1125             :  * cairo_surface_mark_dirty:
    1126             :  * @surface: a #cairo_surface_t
    1127             :  *
    1128             :  * Tells cairo that drawing has been done to surface using means other
    1129             :  * than cairo, and that cairo should reread any cached areas. Note
    1130             :  * that you must call cairo_surface_flush() before doing such drawing.
    1131             :  */
    1132             : void
    1133           0 : cairo_surface_mark_dirty (cairo_surface_t *surface)
    1134             : {
    1135           0 :     cairo_surface_mark_dirty_rectangle (surface, 0, 0, -1, -1);
    1136           0 : }
    1137             : slim_hidden_def (cairo_surface_mark_dirty);
    1138             : 
    1139             : /**
    1140             :  * cairo_surface_mark_dirty_rectangle:
    1141             :  * @surface: a #cairo_surface_t
    1142             :  * @x: X coordinate of dirty rectangle
    1143             :  * @y: Y coordinate of dirty rectangle
    1144             :  * @width: width of dirty rectangle
    1145             :  * @height: height of dirty rectangle
    1146             :  *
    1147             :  * Like cairo_surface_mark_dirty(), but drawing has been done only to
    1148             :  * the specified rectangle, so that cairo can retain cached contents
    1149             :  * for other parts of the surface.
    1150             :  *
    1151             :  * Any cached clip set on the surface will be reset by this function,
    1152             :  * to make sure that future cairo calls have the clip set that they
    1153             :  * expect.
    1154             :  */
    1155             : void
    1156           0 : cairo_surface_mark_dirty_rectangle (cairo_surface_t *surface,
    1157             :                                     int              x,
    1158             :                                     int              y,
    1159             :                                     int              width,
    1160             :                                     int              height)
    1161             : {
    1162             :     cairo_status_t status;
    1163             : 
    1164           0 :     if (surface->status)
    1165           0 :         return;
    1166             : 
    1167           0 :     assert (surface->snapshot_of == NULL);
    1168             : 
    1169           0 :     if (surface->finished) {
    1170           0 :         status = _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
    1171           0 :         return;
    1172             :     }
    1173             : 
    1174             :     /* The application *should* have called cairo_surface_flush() before
    1175             :      * modifying the surface independently of cairo (and thus having to
    1176             :      * call mark_dirty()). */
    1177           0 :     assert (! _cairo_surface_has_snapshots (surface));
    1178           0 :     assert (! _cairo_surface_has_mime_data (surface));
    1179             : 
    1180           0 :     surface->is_clear = FALSE;
    1181             : 
    1182           0 :     if (surface->backend->mark_dirty_rectangle != NULL) {
    1183             :         /* XXX: FRAGILE: We're ignoring the scaling component of
    1184             :          * device_transform here. I don't know what the right thing to
    1185             :          * do would actually be if there were some scaling here, but
    1186             :          * we avoid this since device_transfom scaling is not exported
    1187             :          * publicly and mark_dirty is not used internally. */
    1188           0 :         status = surface->backend->mark_dirty_rectangle (surface,
    1189           0 :                                                          x + surface->device_transform.x0,
    1190           0 :                                                          y + surface->device_transform.y0,
    1191             :                                                          width, height);
    1192             : 
    1193           0 :         if (unlikely (status))
    1194           0 :             status = _cairo_surface_set_error (surface, status);
    1195             :     }
    1196             : }
    1197             : slim_hidden_def (cairo_surface_mark_dirty_rectangle);
    1198             : 
    1199             : /**
    1200             :  * _cairo_surface_set_device_scale:
    1201             :  * @surface: a #cairo_surface_t
    1202             :  * @sx: a scale factor in the X direction
    1203             :  * @sy: a scale factor in the Y direction
    1204             :  *
    1205             :  * Private function for setting an extra scale factor to affect all
    1206             :  * drawing to a surface. This is used, for example, when replaying a
    1207             :  * recording surface to an image fallback intended for an eventual
    1208             :  * vector-oriented backend. Since the recording surface will record
    1209             :  * coordinates in one backend space, but the image fallback uses a
    1210             :  * different backend space, (differing by the fallback resolution
    1211             :  * scale factors), we need a scale factor correction.
    1212             :  *
    1213             :  * Caution: Not all places we use device transform correctly handle
    1214             :  * both a translate and a scale.  An audit would be nice.
    1215             :  **/
    1216             : void
    1217           0 : _cairo_surface_set_device_scale (cairo_surface_t *surface,
    1218             :                                  double           sx,
    1219             :                                  double           sy)
    1220             : {
    1221             :     cairo_status_t status;
    1222             : 
    1223           0 :     if (surface->status)
    1224           0 :         return;
    1225             : 
    1226           0 :     assert (surface->snapshot_of == NULL);
    1227             : 
    1228           0 :     if (surface->finished) {
    1229           0 :         status = _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
    1230           0 :         return;
    1231             :     }
    1232             : 
    1233           0 :     _cairo_surface_begin_modification (surface);
    1234             : 
    1235           0 :     surface->device_transform.xx = sx;
    1236           0 :     surface->device_transform.yy = sy;
    1237           0 :     surface->device_transform.xy = 0.0;
    1238           0 :     surface->device_transform.yx = 0.0;
    1239             : 
    1240           0 :     surface->device_transform_inverse = surface->device_transform;
    1241           0 :     status = cairo_matrix_invert (&surface->device_transform_inverse);
    1242             :     /* should always be invertible unless given pathological input */
    1243           0 :     assert (status == CAIRO_STATUS_SUCCESS);
    1244             : 
    1245           0 :     _cairo_observers_notify (&surface->device_transform_observers, surface);
    1246             : }
    1247             : 
    1248             : /**
    1249             :  * cairo_surface_set_device_offset:
    1250             :  * @surface: a #cairo_surface_t
    1251             :  * @x_offset: the offset in the X direction, in device units
    1252             :  * @y_offset: the offset in the Y direction, in device units
    1253             :  *
    1254             :  * Sets an offset that is added to the device coordinates determined
    1255             :  * by the CTM when drawing to @surface. One use case for this function
    1256             :  * is when we want to create a #cairo_surface_t that redirects drawing
    1257             :  * for a portion of an onscreen surface to an offscreen surface in a
    1258             :  * way that is completely invisible to the user of the cairo
    1259             :  * API. Setting a transformation via cairo_translate() isn't
    1260             :  * sufficient to do this, since functions like
    1261             :  * cairo_device_to_user() will expose the hidden offset.
    1262             :  *
    1263             :  * Note that the offset affects drawing to the surface as well as
    1264             :  * using the surface in a source pattern.
    1265             :  **/
    1266             : void
    1267           0 : cairo_surface_set_device_offset (cairo_surface_t *surface,
    1268             :                                  double           x_offset,
    1269             :                                  double           y_offset)
    1270             : {
    1271             :     cairo_status_t status;
    1272             : 
    1273           0 :     if (surface->status)
    1274           0 :         return;
    1275             : 
    1276           0 :     assert (surface->snapshot_of == NULL);
    1277             : 
    1278           0 :     if (surface->finished) {
    1279           0 :         status = _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
    1280           0 :         return;
    1281             :     }
    1282             : 
    1283           0 :     _cairo_surface_begin_modification (surface);
    1284             : 
    1285           0 :     surface->device_transform.x0 = x_offset;
    1286           0 :     surface->device_transform.y0 = y_offset;
    1287             : 
    1288           0 :     surface->device_transform_inverse = surface->device_transform;
    1289           0 :     status = cairo_matrix_invert (&surface->device_transform_inverse);
    1290             :     /* should always be invertible unless given pathological input */
    1291           0 :     assert (status == CAIRO_STATUS_SUCCESS);
    1292             : 
    1293           0 :     _cairo_observers_notify (&surface->device_transform_observers, surface);
    1294             : }
    1295             : slim_hidden_def (cairo_surface_set_device_offset);
    1296             : 
    1297             : /**
    1298             :  * cairo_surface_get_device_offset:
    1299             :  * @surface: a #cairo_surface_t
    1300             :  * @x_offset: the offset in the X direction, in device units
    1301             :  * @y_offset: the offset in the Y direction, in device units
    1302             :  *
    1303             :  * This function returns the previous device offset set by
    1304             :  * cairo_surface_set_device_offset().
    1305             :  *
    1306             :  * Since: 1.2
    1307             :  **/
    1308             : void
    1309           0 : cairo_surface_get_device_offset (cairo_surface_t *surface,
    1310             :                                  double          *x_offset,
    1311             :                                  double          *y_offset)
    1312             : {
    1313           0 :     if (x_offset)
    1314           0 :         *x_offset = surface->device_transform.x0;
    1315           0 :     if (y_offset)
    1316           0 :         *y_offset = surface->device_transform.y0;
    1317           0 : }
    1318             : slim_hidden_def (cairo_surface_get_device_offset);
    1319             : 
    1320             : /**
    1321             :  * cairo_surface_set_fallback_resolution:
    1322             :  * @surface: a #cairo_surface_t
    1323             :  * @x_pixels_per_inch: horizontal setting for pixels per inch
    1324             :  * @y_pixels_per_inch: vertical setting for pixels per inch
    1325             :  *
    1326             :  * Set the horizontal and vertical resolution for image fallbacks.
    1327             :  *
    1328             :  * When certain operations aren't supported natively by a backend,
    1329             :  * cairo will fallback by rendering operations to an image and then
    1330             :  * overlaying that image onto the output. For backends that are
    1331             :  * natively vector-oriented, this function can be used to set the
    1332             :  * resolution used for these image fallbacks, (larger values will
    1333             :  * result in more detailed images, but also larger file sizes).
    1334             :  *
    1335             :  * Some examples of natively vector-oriented backends are the ps, pdf,
    1336             :  * and svg backends.
    1337             :  *
    1338             :  * For backends that are natively raster-oriented, image fallbacks are
    1339             :  * still possible, but they are always performed at the native
    1340             :  * device resolution. So this function has no effect on those
    1341             :  * backends.
    1342             :  *
    1343             :  * Note: The fallback resolution only takes effect at the time of
    1344             :  * completing a page (with cairo_show_page() or cairo_copy_page()) so
    1345             :  * there is currently no way to have more than one fallback resolution
    1346             :  * in effect on a single page.
    1347             :  *
    1348             :  * The default fallback resoultion is 300 pixels per inch in both
    1349             :  * dimensions.
    1350             :  *
    1351             :  * Since: 1.2
    1352             :  **/
    1353             : void
    1354           0 : cairo_surface_set_fallback_resolution (cairo_surface_t  *surface,
    1355             :                                        double            x_pixels_per_inch,
    1356             :                                        double            y_pixels_per_inch)
    1357             : {
    1358             :     cairo_status_t status;
    1359             : 
    1360           0 :     if (surface->status)
    1361           0 :         return;
    1362             : 
    1363           0 :     assert (surface->snapshot_of == NULL);
    1364             : 
    1365           0 :     if (surface->finished) {
    1366           0 :         status = _cairo_surface_set_error (surface, _cairo_error (CAIRO_STATUS_SURFACE_FINISHED));
    1367           0 :         return;
    1368             :     }
    1369             : 
    1370           0 :     if (x_pixels_per_inch <= 0 || y_pixels_per_inch <= 0) {
    1371             :         /* XXX Could delay raising the error until we fallback, but throwing
    1372             :          * the error here means that we can catch the real culprit.
    1373             :          */
    1374           0 :         status = _cairo_surface_set_error (surface, CAIRO_STATUS_INVALID_MATRIX);
    1375           0 :         return;
    1376             :     }
    1377             : 
    1378           0 :     _cairo_surface_begin_modification (surface);
    1379             : 
    1380           0 :     surface->x_fallback_resolution = x_pixels_per_inch;
    1381           0 :     surface->y_fallback_resolution = y_pixels_per_inch;
    1382             : }
    1383             : slim_hidden_def (cairo_surface_set_fallback_resolution);
    1384             : 
    1385             : /**
    1386             :  * cairo_surface_get_fallback_resolution:
    1387             :  * @surface: a #cairo_surface_t
    1388             :  * @x_pixels_per_inch: horizontal pixels per inch
    1389             :  * @y_pixels_per_inch: vertical pixels per inch
    1390             :  *
    1391             :  * This function returns the previous fallback resolution set by
    1392             :  * cairo_surface_set_fallback_resolution(), or default fallback
    1393             :  * resolution if never set.
    1394             :  *
    1395             :  * Since: 1.8
    1396             :  **/
    1397             : void
    1398           0 : cairo_surface_get_fallback_resolution (cairo_surface_t  *surface,
    1399             :                                        double           *x_pixels_per_inch,
    1400             :                                        double           *y_pixels_per_inch)
    1401             : {
    1402           0 :     if (x_pixels_per_inch)
    1403           0 :         *x_pixels_per_inch = surface->x_fallback_resolution;
    1404           0 :     if (y_pixels_per_inch)
    1405           0 :         *y_pixels_per_inch = surface->y_fallback_resolution;
    1406           0 : }
    1407             : 
    1408             : int
    1409           0 : _cairo_surface_get_text_path_fill_threshold (const cairo_surface_t *surface)
    1410             : {
    1411           0 :     return surface->backend->fill == NULL ? 10240 : 256;
    1412             : }
    1413             : 
    1414             : cairo_bool_t
    1415           0 : _cairo_surface_has_device_transform (cairo_surface_t *surface)
    1416             : {
    1417           0 :     return ! _cairo_matrix_is_identity (&surface->device_transform);
    1418             : }
    1419             : 
    1420             : /**
    1421             :  * _cairo_surface_acquire_source_image:
    1422             :  * @surface: a #cairo_surface_t
    1423             :  * @image_out: location to store a pointer to an image surface that
    1424             :  *    has identical contents to @surface. This surface could be @surface
    1425             :  *    itself, a surface held internal to @surface, or it could be a new
    1426             :  *    surface with a copy of the relevant portion of @surface.
    1427             :  * @image_extra: location to store image specific backend data
    1428             :  *
    1429             :  * Gets an image surface to use when drawing as a fallback when drawing with
    1430             :  * @surface as a source. _cairo_surface_release_source_image() must be called
    1431             :  * when finished.
    1432             :  *
    1433             :  * Return value: %CAIRO_STATUS_SUCCESS if an image was stored in @image_out.
    1434             :  * %CAIRO_INT_STATUS_UNSUPPORTED if an image cannot be retrieved for the specified
    1435             :  * surface. Or %CAIRO_STATUS_NO_MEMORY.
    1436             :  **/
    1437             : cairo_status_t
    1438           0 : _cairo_surface_acquire_source_image (cairo_surface_t         *surface,
    1439             :                                      cairo_image_surface_t  **image_out,
    1440             :                                      void                   **image_extra)
    1441             : {
    1442             :     cairo_status_t status;
    1443             : 
    1444           0 :     if (surface->status)
    1445           0 :         return surface->status;
    1446             : 
    1447           0 :     assert (!surface->finished);
    1448             : 
    1449           0 :     if (surface->backend->acquire_source_image == NULL)
    1450           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1451             : 
    1452           0 :     status = surface->backend->acquire_source_image (surface,
    1453             :                                                      image_out, image_extra);
    1454           0 :     if (unlikely (status))
    1455           0 :         return _cairo_surface_set_error (surface, status);
    1456             : 
    1457           0 :     if (PIXMAN_FORMAT_BPP((*image_out)->pixman_format) == 0) {
    1458             :         volatile char* acquire_source_image_ptr[10];
    1459             :         volatile char* crasher;
    1460             :         int i;
    1461           0 :         for (i = 0; i < 10; i++) {
    1462           0 :             acquire_source_image_ptr[i] = (char*)surface->backend->acquire_source_image;
    1463             :         }
    1464           0 :         crasher = NULL;
    1465           0 :         *crasher = acquire_source_image_ptr[5];
    1466             :     }
    1467             :     _cairo_debug_check_image_surface_is_defined (&(*image_out)->base);
    1468             : 
    1469           0 :     return CAIRO_STATUS_SUCCESS;
    1470             : }
    1471             : 
    1472             : /**
    1473             :  * _cairo_surface_release_source_image:
    1474             :  * @surface: a #cairo_surface_t
    1475             :  * @image_extra: same as return from the matching _cairo_surface_acquire_source_image()
    1476             :  *
    1477             :  * Releases any resources obtained with _cairo_surface_acquire_source_image()
    1478             :  **/
    1479             : void
    1480           0 : _cairo_surface_release_source_image (cairo_surface_t        *surface,
    1481             :                                      cairo_image_surface_t  *image,
    1482             :                                      void                   *image_extra)
    1483             : {
    1484           0 :     assert (!surface->finished);
    1485             : 
    1486           0 :     if (surface->backend->release_source_image)
    1487           0 :         surface->backend->release_source_image (surface, image, image_extra);
    1488           0 : }
    1489             : 
    1490             : /**
    1491             :  * _cairo_surface_acquire_dest_image:
    1492             :  * @surface: a #cairo_surface_t
    1493             :  * @interest_rect: area of @surface for which fallback drawing is being done.
    1494             :  *    A value of %NULL indicates that the entire surface is desired.
    1495             :  *    XXXX I'd like to get rid of being able to pass %NULL here (nothing seems to)
    1496             :  * @image_out: location to store a pointer to an image surface that includes at least
    1497             :  *    the intersection of @interest_rect with the visible area of @surface.
    1498             :  *    This surface could be @surface itself, a surface held internal to @surface,
    1499             :  *    or it could be a new surface with a copy of the relevant portion of @surface.
    1500             :  *    If a new surface is created, it should have the same channels and depth
    1501             :  *    as @surface so that copying to and from it is exact.
    1502             :  * @image_rect: location to store area of the original surface occupied
    1503             :  *    by the surface stored in @image.
    1504             :  * @image_extra: location to store image specific backend data
    1505             :  *
    1506             :  * Retrieves a local image for a surface for implementing a fallback drawing
    1507             :  * operation. After calling this function, the implementation of the fallback
    1508             :  * drawing operation draws the primitive to the surface stored in @image_out
    1509             :  * then calls _cairo_surface_release_dest_image(),
    1510             :  * which, if a temporary surface was created, copies the bits back to the
    1511             :  * main surface and frees the temporary surface.
    1512             :  *
    1513             :  * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY.
    1514             :  *  %CAIRO_INT_STATUS_UNSUPPORTED can be returned but this will mean that
    1515             :  *  the backend can't draw with fallbacks. It's possible for the routine
    1516             :  *  to store %NULL in @local_out and return %CAIRO_STATUS_SUCCESS;
    1517             :  *  that indicates that no part of @interest_rect is visible, so no drawing
    1518             :  *  is necessary. _cairo_surface_release_dest_image() should not be called in that
    1519             :  *  case.
    1520             :  **/
    1521             : cairo_status_t
    1522           0 : _cairo_surface_acquire_dest_image (cairo_surface_t         *surface,
    1523             :                                    cairo_rectangle_int_t   *interest_rect,
    1524             :                                    cairo_image_surface_t  **image_out,
    1525             :                                    cairo_rectangle_int_t   *image_rect,
    1526             :                                    void                   **image_extra)
    1527             : {
    1528             :     cairo_status_t status;
    1529             : 
    1530           0 :     if (surface->status)
    1531           0 :         return surface->status;
    1532             : 
    1533           0 :     assert (_cairo_surface_is_writable (surface));
    1534             : 
    1535           0 :     if (surface->backend->acquire_dest_image == NULL)
    1536           0 :         return CAIRO_INT_STATUS_UNSUPPORTED;
    1537             : 
    1538           0 :     status = surface->backend->acquire_dest_image (surface,
    1539             :                                                    interest_rect,
    1540             :                                                    image_out,
    1541             :                                                    image_rect,
    1542             :                                                    image_extra);
    1543           0 :     if (unlikely (status))
    1544           0 :         return _cairo_surface_set_error (surface, status);
    1545             : 
    1546             :     _cairo_debug_check_image_surface_is_defined (&(*image_out)->base);
    1547             : 
    1548           0 :     return CAIRO_STATUS_SUCCESS;
    1549             : }
    1550             : 
    1551             : /**
    1552             :  * _cairo_surface_release_dest_image:
    1553             :  * @surface: a #cairo_surface_t
    1554             :  * @interest_rect: same as passed to the matching _cairo_surface_acquire_dest_image()
    1555             :  * @image: same as returned from the matching _cairo_surface_acquire_dest_image()
    1556             :  * @image_rect: same as returned from the matching _cairo_surface_acquire_dest_image()
    1557             :  * @image_extra: same as return from the matching _cairo_surface_acquire_dest_image()
    1558             :  *
    1559             :  * Finishes the operation started with _cairo_surface_acquire_dest_image(), by, if
    1560             :  * necessary, copying the image from @image back to @surface and freeing any
    1561             :  * resources that were allocated.
    1562             :  **/
    1563             : void
    1564           0 : _cairo_surface_release_dest_image (cairo_surface_t         *surface,
    1565             :                                    cairo_rectangle_int_t   *interest_rect,
    1566             :                                    cairo_image_surface_t   *image,
    1567             :                                    cairo_rectangle_int_t   *image_rect,
    1568             :                                    void                    *image_extra)
    1569             : {
    1570           0 :     assert (_cairo_surface_is_writable (surface));
    1571             : 
    1572           0 :     if (surface->backend->release_dest_image)
    1573           0 :         surface->backend->release_dest_image (surface, interest_rect,
    1574             :                                               image, image_rect, image_extra);
    1575           0 : }
    1576             : 
    1577             : static cairo_status_t
    1578           0 : _cairo_recording_surface_clone_similar (cairo_surface_t  *surface,
    1579             :                                         cairo_surface_t  *src,
    1580             :                                         int               src_x,
    1581             :                                         int               src_y,
    1582             :                                         int               width,
    1583             :                                         int               height,
    1584             :                                         int              *clone_offset_x,
    1585             :                                         int              *clone_offset_y,
    1586             :                                         cairo_surface_t **clone_out)
    1587             : {
    1588           0 :     cairo_recording_surface_t *recorder = (cairo_recording_surface_t *) src;
    1589             :     cairo_surface_t *similar;
    1590             :     cairo_status_t status;
    1591             : 
    1592           0 :     similar = _cairo_surface_has_snapshot (src, surface->backend);
    1593           0 :     if (similar != NULL) {
    1594           0 :         *clone_out = cairo_surface_reference (similar);
    1595           0 :         *clone_offset_x = 0;
    1596           0 :         *clone_offset_y = 0;
    1597           0 :         return CAIRO_STATUS_SUCCESS;
    1598             :     }
    1599             : 
    1600           0 :     if (recorder->unbounded ||
    1601           0 :         width*height*8 < recorder->extents.width*recorder->extents.height)
    1602             :     {
    1603           0 :         similar = _cairo_surface_create_similar_solid (surface,
    1604             :                                                        src->content,
    1605             :                                                        width, height,
    1606             :                                                        CAIRO_COLOR_TRANSPARENT,
    1607             :                                                        FALSE);
    1608           0 :         if (similar == NULL)
    1609           0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
    1610           0 :         if (unlikely (similar->status))
    1611           0 :             return similar->status;
    1612             : 
    1613           0 :         cairo_surface_set_device_offset (similar, -src_x, -src_y);
    1614             : 
    1615           0 :         status = _cairo_recording_surface_replay (src, similar);
    1616           0 :         if (unlikely (status)) {
    1617           0 :             cairo_surface_destroy (similar);
    1618           0 :             return status;
    1619             :         }
    1620             :     } else {
    1621           0 :         similar = _cairo_surface_create_similar_scratch (surface,
    1622             :                                                          src->content,
    1623             :                                                          recorder->extents.width,
    1624             :                                                          recorder->extents.height);
    1625           0 :         if (similar == NULL)
    1626           0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
    1627           0 :         if (unlikely (similar->status))
    1628           0 :             return similar->status;
    1629             : 
    1630           0 :         status = _cairo_recording_surface_replay (src, similar);
    1631           0 :         if (unlikely (status)) {
    1632           0 :             cairo_surface_destroy (similar);
    1633           0 :             return status;
    1634             :         }
    1635             : 
    1636           0 :         cairo_surface_attach_snapshot (src, similar, NULL);
    1637             : 
    1638           0 :         src_x = src_y = 0;
    1639             :     }
    1640             : 
    1641           0 :     *clone_out = similar;
    1642           0 :     *clone_offset_x = src_x;
    1643           0 :     *clone_offset_y = src_y;
    1644           0 :     return CAIRO_STATUS_SUCCESS;
    1645             : }
    1646             : 
    1647             : struct acquire_source_image_data
    1648             : {
    1649             :     cairo_surface_t *src;
    1650             :     cairo_image_surface_t *image;
    1651             :     void *image_extra;
    1652             : };
    1653             : 
    1654             : static void
    1655           0 : _wrap_release_source_image (void *data)
    1656             : {
    1657           0 :     struct acquire_source_image_data *acquire_data = data;
    1658           0 :     _cairo_surface_release_source_image (acquire_data->src,
    1659             :                                          acquire_data->image,
    1660             :                                          acquire_data->image_extra);
    1661           0 :     free(data);
    1662           0 : }
    1663             : 
    1664             : static cairo_status_t
    1665           0 : _wrap_image (cairo_surface_t *src,
    1666             :              cairo_image_surface_t *image,
    1667             :              void *image_extra,
    1668             :              cairo_image_surface_t **out)
    1669             : {
    1670             :     static cairo_user_data_key_t wrap_image_key;
    1671             :     cairo_image_surface_t *surface;
    1672             :     cairo_status_t status;
    1673             : 
    1674           0 :     struct acquire_source_image_data *data = malloc (sizeof (*data));
    1675           0 :     if (unlikely (data == NULL))
    1676           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1677           0 :     data->src = src;
    1678           0 :     data->image = image;
    1679           0 :     data->image_extra = image_extra;
    1680             : 
    1681           0 :     surface = (cairo_image_surface_t*)
    1682           0 :         _cairo_image_surface_create_with_pixman_format (image->data,
    1683             :                                                         image->pixman_format,
    1684             :                                                         image->width,
    1685             :                                                         image->height,
    1686             :                                                         image->stride);
    1687           0 :     status = surface->base.status;
    1688           0 :     if (status) {
    1689           0 :         free (data);
    1690           0 :         return status;
    1691             :     }
    1692             : 
    1693           0 :     status = _cairo_user_data_array_set_data (&surface->base.user_data,
    1694             :                                               &wrap_image_key,
    1695             :                                               data,
    1696             :                                               _wrap_release_source_image);
    1697           0 :     if (status) {
    1698           0 :         cairo_surface_destroy (&surface->base);
    1699           0 :         free (data);
    1700           0 :         return status;
    1701             :     }
    1702             : 
    1703           0 :     pixman_image_set_component_alpha (
    1704             :         surface->pixman_image,
    1705             :         pixman_image_get_component_alpha (image->pixman_image));
    1706             : 
    1707           0 :     *out = surface;
    1708           0 :     return CAIRO_STATUS_SUCCESS;
    1709             : }
    1710             : 
    1711             : /**
    1712             :  * _cairo_surface_clone_similar:
    1713             :  * @surface: a #cairo_surface_t
    1714             :  * @src: the source image
    1715             :  * @src_x: extent for the rectangle in src we actually care about
    1716             :  * @src_y: extent for the rectangle in src we actually care about
    1717             :  * @width: extent for the rectangle in src we actually care about
    1718             :  * @height: extent for the rectangle in src we actually care about
    1719             :  * @clone_out: location to store a surface compatible with @surface
    1720             :  *   and with contents identical to @src. The caller must call
    1721             :  *   cairo_surface_destroy() on the result.
    1722             :  *
    1723             :  * Creates a surface with contents identical to @src but that
    1724             :  *   can be used efficiently with @surface. If @surface and @src are
    1725             :  *   already compatible then it may return a new reference to @src.
    1726             :  *
    1727             :  * Return value: %CAIRO_STATUS_SUCCESS if a surface was created and stored
    1728             :  *   in @clone_out. Otherwise %CAIRO_INT_STATUS_UNSUPPORTED or another
    1729             :  *   error like %CAIRO_STATUS_NO_MEMORY.
    1730             :  **/
    1731             : cairo_status_t
    1732           0 : _cairo_surface_clone_similar (cairo_surface_t  *surface,
    1733             :                               cairo_surface_t  *src,
    1734             :                               int               src_x,
    1735             :                               int               src_y,
    1736             :                               int               width,
    1737             :                               int               height,
    1738             :                               int              *clone_offset_x,
    1739             :                               int              *clone_offset_y,
    1740             :                               cairo_surface_t **clone_out)
    1741             : {
    1742           0 :     cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
    1743             :     cairo_image_surface_t *image;
    1744             :     void *image_extra;
    1745             : 
    1746           0 :     if (unlikely (surface->status))
    1747           0 :         return surface->status;
    1748             : 
    1749           0 :     if (unlikely (surface->finished))
    1750           0 :         return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
    1751             : 
    1752             : #if CAIRO_HAS_TEE_SURFACE
    1753             : 
    1754           0 :     if (src->type == CAIRO_SURFACE_TYPE_TEE) {
    1755             :         cairo_surface_t *match;
    1756             : 
    1757           0 :         match = _cairo_tee_surface_find_match (src,
    1758             :                                                surface->backend,
    1759             :                                                src->content);
    1760           0 :         if (match != NULL)
    1761           0 :             src = match;
    1762             :     }
    1763             : 
    1764             : #endif
    1765             : 
    1766           0 :     if (surface->backend->clone_similar != NULL) {
    1767           0 :         status = surface->backend->clone_similar (surface, src,
    1768             :                                                   src_x, src_y,
    1769             :                                                   width, height,
    1770             :                                                   clone_offset_x,
    1771             :                                                   clone_offset_y,
    1772             :                                                   clone_out);
    1773           0 :         if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
    1774           0 :             if (_cairo_surface_is_image (src))
    1775           0 :                 return CAIRO_INT_STATUS_UNSUPPORTED;
    1776             : 
    1777             :             /* First check to see if we can replay to a similar surface */
    1778           0 :             if (_cairo_surface_is_recording (src)) {
    1779           0 :                 return _cairo_recording_surface_clone_similar (surface, src,
    1780             :                                                                src_x, src_y,
    1781             :                                                                width, height,
    1782             :                                                                clone_offset_x,
    1783             :                                                                clone_offset_y,
    1784             :                                                                clone_out);
    1785             :             }
    1786             : 
    1787             :             /* If we failed, try again with an image surface */
    1788           0 :             status = _cairo_surface_acquire_source_image (src, &image, &image_extra);
    1789           0 :             if (status == CAIRO_STATUS_SUCCESS) {
    1790           0 :                 status = _wrap_image(src, image, image_extra, &image);
    1791           0 :                 if (status != CAIRO_STATUS_SUCCESS) {
    1792           0 :                     _cairo_surface_release_source_image (src, image, image_extra);
    1793             :                 } else {
    1794           0 :                     status =
    1795           0 :                         surface->backend->clone_similar (surface, &image->base,
    1796             :                                                          src_x, src_y,
    1797             :                                                          width, height,
    1798             :                                                          clone_offset_x,
    1799             :                                                          clone_offset_y,
    1800             :                                                          clone_out);
    1801           0 :                     cairo_surface_destroy(&image->base);
    1802             :                 }
    1803             :             }
    1804             :         }
    1805             :     }
    1806             : 
    1807             :     /* If we're still unsupported, hit our fallback path to get a clone */
    1808           0 :     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
    1809           0 :         status =
    1810             :             _cairo_surface_fallback_clone_similar (surface, src,
    1811             :                                                    src_x, src_y,
    1812             :                                                    width, height,
    1813             :                                                    clone_offset_x,
    1814             :                                                    clone_offset_y,
    1815             :                                                    clone_out);
    1816             :     }
    1817             : 
    1818           0 :     if (unlikely (status))
    1819           0 :         return status;
    1820             : 
    1821             :     /* Update the clone's device_transform (which the underlying surface
    1822             :      * backend knows nothing about) */
    1823           0 :     if (*clone_out != src) {
    1824           0 :         (*clone_out)->device_transform = src->device_transform;
    1825           0 :         (*clone_out)->device_transform_inverse = src->device_transform_inverse;
    1826             :     }
    1827             : 
    1828           0 :     return status;
    1829             : }
    1830             : 
    1831             : /**
    1832             :  * _cairo_surface_is_similar
    1833             :  * @surface_a: a #cairo_surface_t
    1834             :  * @surface_b: a #cairo_surface_t
    1835             :  * @content: a #cairo_content_t
    1836             :  *
    1837             :  * Find out whether the given surfaces share the same backend,
    1838             :  * and if so, whether they can be considered similar.
    1839             :  *
    1840             :  * The definition of "similar" depends on the backend. In
    1841             :  * general, it means that the surface is equivalent to one
    1842             :  * that would have been generated by a call to cairo_surface_create_similar().
    1843             :  *
    1844             :  * Return value: %TRUE if the surfaces are similar.
    1845             :  **/
    1846             : cairo_bool_t
    1847           0 : _cairo_surface_is_similar (cairo_surface_t *surface_a,
    1848             :                            cairo_surface_t *surface_b)
    1849             : {
    1850           0 :     if (surface_a->backend != surface_b->backend)
    1851           0 :         return FALSE;
    1852             : 
    1853           0 :     if (surface_a->backend->is_similar != NULL)
    1854           0 :         return surface_a->backend->is_similar (surface_a, surface_b);
    1855             : 
    1856           0 :     return TRUE;
    1857             : }
    1858             : 
    1859             : cairo_status_t
    1860           0 : _cairo_surface_composite (cairo_operator_t      op,
    1861             :                           const cairo_pattern_t *src,
    1862             :                           const cairo_pattern_t *mask,
    1863             :                           cairo_surface_t       *dst,
    1864             :                           int                   src_x,
    1865             :                           int                   src_y,
    1866             :                           int                   mask_x,
    1867             :                           int                   mask_y,
    1868             :                           int                   dst_x,
    1869             :                           int                   dst_y,
    1870             :                           unsigned int          width,
    1871             :                           unsigned int          height,
    1872             :                           cairo_region_t        *clip_region)
    1873             : {
    1874             :     cairo_int_status_t status;
    1875             : 
    1876           0 :     if (unlikely (dst->status))
    1877           0 :         return dst->status;
    1878             : 
    1879           0 :     assert (_cairo_surface_is_writable (dst));
    1880             : 
    1881           0 :     if (mask) {
    1882             :         /* These operators aren't interpreted the same way by the backends;
    1883             :          * they are implemented in terms of other operators in cairo-gstate.c
    1884             :          */
    1885           0 :         assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
    1886             :     }
    1887             : 
    1888           0 :     if (dst->backend->composite) {
    1889           0 :         status = dst->backend->composite (op,
    1890             :                                           src, mask, dst,
    1891             :                                           src_x, src_y,
    1892             :                                           mask_x, mask_y,
    1893             :                                           dst_x, dst_y,
    1894             :                                           width, height,
    1895             :                                           clip_region);
    1896           0 :         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
    1897           0 :             return _cairo_surface_set_error (dst, status);
    1898             :     }
    1899             : 
    1900           0 :     return _cairo_surface_set_error (dst,
    1901             :             _cairo_surface_fallback_composite (op,
    1902             :                                               src, mask, dst,
    1903             :                                               src_x, src_y,
    1904             :                                               mask_x, mask_y,
    1905             :                                               dst_x, dst_y,
    1906             :                                               width, height,
    1907             :                                               clip_region));
    1908             : }
    1909             : 
    1910             : /**
    1911             :  * _cairo_surface_fill_rectangle:
    1912             :  * @surface: a #cairo_surface_t
    1913             :  * @op: the operator to apply to the rectangle
    1914             :  * @color: the source color
    1915             :  * @x: X coordinate of rectangle, in backend coordinates
    1916             :  * @y: Y coordinate of rectangle, in backend coordinates
    1917             :  * @width: width of rectangle, in backend coordinates
    1918             :  * @height: height of rectangle, in backend coordinates
    1919             :  *
    1920             :  * Applies an operator to a rectangle using a solid color as the source.
    1921             :  * See _cairo_surface_fill_rectangles() for full details.
    1922             :  *
    1923             :  * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
    1924             :  **/
    1925             : cairo_status_t
    1926           0 : _cairo_surface_fill_rectangle (cairo_surface_t     *surface,
    1927             :                                cairo_operator_t     op,
    1928             :                                const cairo_color_t *color,
    1929             :                                int                  x,
    1930             :                                int                  y,
    1931             :                                int                  width,
    1932             :                                int                  height)
    1933             : {
    1934             :     cairo_rectangle_int_t rect;
    1935             : 
    1936           0 :     if (surface->status)
    1937           0 :         return surface->status;
    1938             : 
    1939           0 :     assert (_cairo_surface_is_writable (surface));
    1940             : 
    1941           0 :     rect.x = x;
    1942           0 :     rect.y = y;
    1943           0 :     rect.width = width;
    1944           0 :     rect.height = height;
    1945             : 
    1946           0 :     return _cairo_surface_fill_rectangles (surface, op, color, &rect, 1);
    1947             : }
    1948             : 
    1949             : /**
    1950             :  * _cairo_surface_fill_region:
    1951             :  * @surface: a #cairo_surface_t
    1952             :  * @op: the operator to apply to the region
    1953             :  * @color: the source color
    1954             :  * @region: the region to modify, in backend coordinates
    1955             :  *
    1956             :  * Applies an operator to a set of rectangles specified as a
    1957             :  * #cairo_region_t using a solid color as the source.
    1958             :  * See _cairo_surface_fill_rectangles() for full details.
    1959             :  *
    1960             :  * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
    1961             :  **/
    1962             : cairo_status_t
    1963           0 : _cairo_surface_fill_region (cairo_surface_t        *surface,
    1964             :                             cairo_operator_t        op,
    1965             :                             const cairo_color_t    *color,
    1966             :                             cairo_region_t         *region)
    1967             : {
    1968             :     int num_rects;
    1969             :     cairo_rectangle_int_t stack_rects[CAIRO_STACK_ARRAY_LENGTH (cairo_rectangle_int_t)];
    1970           0 :     cairo_rectangle_int_t *rects = stack_rects;
    1971             :     cairo_status_t status;
    1972             :     int i;
    1973             : 
    1974           0 :     if (surface->status)
    1975           0 :         return surface->status;
    1976             : 
    1977           0 :     assert (_cairo_surface_is_writable (surface));
    1978             : 
    1979           0 :     num_rects = cairo_region_num_rectangles (region);
    1980           0 :     if (num_rects == 0)
    1981           0 :         return CAIRO_STATUS_SUCCESS;
    1982             : 
    1983             :     /* catch a common reduction of _cairo_clip_combine_with_surface() */
    1984           0 :     if (op == CAIRO_OPERATOR_IN &&
    1985           0 :         _cairo_color_equal (color, CAIRO_COLOR_WHITE))
    1986             :     {
    1987           0 :         return CAIRO_STATUS_SUCCESS;
    1988             :     }
    1989             : 
    1990           0 :     if (num_rects > ARRAY_LENGTH (stack_rects)) {
    1991           0 :         rects = _cairo_malloc_ab (num_rects,
    1992             :                                   sizeof (cairo_rectangle_int_t));
    1993           0 :         if (rects == NULL) {
    1994           0 :             return _cairo_surface_set_error (surface,
    1995             :                                              _cairo_error (CAIRO_STATUS_NO_MEMORY));
    1996             :         }
    1997             :     }
    1998             : 
    1999           0 :     for (i = 0; i < num_rects; i++)
    2000           0 :         cairo_region_get_rectangle (region, i, &rects[i]);
    2001             : 
    2002           0 :     status =  _cairo_surface_fill_rectangles (surface,
    2003             :                                               op, color, rects, num_rects);
    2004             : 
    2005           0 :     if (rects != stack_rects)
    2006           0 :         free (rects);
    2007             : 
    2008           0 :     return _cairo_surface_set_error (surface, status);
    2009             : }
    2010             : 
    2011             : /**
    2012             :  * _cairo_surface_fill_rectangles:
    2013             :  * @surface: a #cairo_surface_t
    2014             :  * @op: the operator to apply to the region
    2015             :  * @color: the source color
    2016             :  * @rects: the rectangles to modify, in backend coordinates
    2017             :  * @num_rects: the number of rectangles in @rects
    2018             :  *
    2019             :  * Applies an operator to a set of rectangles using a solid color
    2020             :  * as the source. Note that even if the operator is an unbounded operator
    2021             :  * such as %CAIRO_OPERATOR_IN, only the given set of rectangles
    2022             :  * is affected. This differs from _cairo_surface_composite_trapezoids()
    2023             :  * where the entire destination rectangle is cleared.
    2024             :  *
    2025             :  * Return value: %CAIRO_STATUS_SUCCESS or the error that occurred
    2026             :  **/
    2027             : cairo_status_t
    2028           0 : _cairo_surface_fill_rectangles (cairo_surface_t         *surface,
    2029             :                                 cairo_operator_t         op,
    2030             :                                 const cairo_color_t     *color,
    2031             :                                 cairo_rectangle_int_t   *rects,
    2032             :                                 int                      num_rects)
    2033             : {
    2034             :     cairo_int_status_t status;
    2035             : 
    2036           0 :     if (surface->status)
    2037           0 :         return surface->status;
    2038             : 
    2039           0 :     assert (_cairo_surface_is_writable (surface));
    2040             : 
    2041           0 :     if (num_rects == 0)
    2042           0 :         return CAIRO_STATUS_SUCCESS;
    2043             : 
    2044           0 :     if (surface->backend->fill_rectangles) {
    2045           0 :         status = surface->backend->fill_rectangles (surface,
    2046             :                                                     op, color,
    2047             :                                                     rects, num_rects);
    2048           0 :         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
    2049           0 :             return _cairo_surface_set_error (surface, status);
    2050             :     }
    2051             : 
    2052           0 :     return _cairo_surface_set_error (surface,
    2053             :             _cairo_surface_fallback_fill_rectangles (surface,
    2054             :                                                      op, color,
    2055             :                                                      rects, num_rects));
    2056             : }
    2057             : 
    2058             : static cairo_status_t
    2059           0 : _pattern_has_error (const cairo_pattern_t *pattern)
    2060             : {
    2061             :     const cairo_surface_pattern_t *spattern;
    2062             : 
    2063           0 :     if (unlikely (pattern->status))
    2064           0 :         return pattern->status;
    2065             : 
    2066           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
    2067           0 :         return CAIRO_STATUS_SUCCESS;
    2068             : 
    2069           0 :     spattern = (const cairo_surface_pattern_t *) pattern;
    2070           0 :     if (unlikely (spattern->surface->status))
    2071           0 :         return spattern->surface->status;
    2072             : 
    2073           0 :     if (unlikely (spattern->surface->finished))
    2074           0 :         return _cairo_error (CAIRO_STATUS_SURFACE_FINISHED);
    2075             : 
    2076           0 :     return CAIRO_STATUS_SUCCESS;
    2077             : }
    2078             : 
    2079             : cairo_status_t
    2080           0 : _cairo_surface_paint (cairo_surface_t   *surface,
    2081             :                       cairo_operator_t   op,
    2082             :                       const cairo_pattern_t *source,
    2083             :                       cairo_clip_t          *clip)
    2084             : {
    2085             :     cairo_status_t status;
    2086             :     cairo_rectangle_int_t extents;
    2087             : 
    2088           0 :     if (unlikely (surface->status))
    2089           0 :         return surface->status;
    2090             : 
    2091           0 :     if (clip && clip->all_clipped)
    2092           0 :         return CAIRO_STATUS_SUCCESS;
    2093             : 
    2094           0 :     if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
    2095           0 :         return CAIRO_STATUS_SUCCESS;
    2096             : 
    2097           0 :     if (op == CAIRO_OPERATOR_OVER &&
    2098           0 :         _cairo_pattern_is_clear (source))
    2099             :     {
    2100           0 :         return CAIRO_STATUS_SUCCESS;
    2101             :     }
    2102             : 
    2103           0 :     status = _pattern_has_error (source);
    2104           0 :     if (unlikely (status))
    2105           0 :         return status;
    2106             : 
    2107           0 :     _cairo_surface_begin_modification (surface);
    2108             : 
    2109           0 :     if (surface->backend->paint != NULL) {
    2110           0 :         status = surface->backend->paint (surface, op, source, clip);
    2111           0 :         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
    2112           0 :             goto FINISH;
    2113             :     }
    2114             : 
    2115           0 :     status = _cairo_surface_fallback_paint (surface, op, source, clip);
    2116             : 
    2117             :  FINISH:
    2118           0 :     surface->is_clear = op == CAIRO_OPERATOR_CLEAR &&
    2119           0 :                         (clip == NULL ||
    2120           0 :                          (_cairo_surface_get_extents (surface, &extents) &&
    2121           0 :                           _cairo_clip_contains_rectangle (clip, &extents)));
    2122             : 
    2123           0 :     return _cairo_surface_set_error (surface, status);
    2124             : }
    2125             : 
    2126             : cairo_status_t
    2127           0 : _cairo_surface_mask (cairo_surface_t            *surface,
    2128             :                      cairo_operator_t            op,
    2129             :                      const cairo_pattern_t      *source,
    2130             :                      const cairo_pattern_t      *mask,
    2131             :                      cairo_clip_t               *clip)
    2132             : {
    2133             :     cairo_status_t status;
    2134             : 
    2135           0 :     if (unlikely (surface->status))
    2136           0 :         return surface->status;
    2137             : 
    2138           0 :     if (clip && clip->all_clipped)
    2139           0 :         return CAIRO_STATUS_SUCCESS;
    2140             : 
    2141           0 :     if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
    2142           0 :         return CAIRO_STATUS_SUCCESS;
    2143             : 
    2144             :     /* If the mask is blank, this is just an expensive no-op */
    2145           0 :     if (_cairo_pattern_is_clear (mask) &&
    2146           0 :         _cairo_operator_bounded_by_mask (op))
    2147             :     {
    2148           0 :         return CAIRO_STATUS_SUCCESS;
    2149             :     }
    2150             : 
    2151           0 :     if (op == CAIRO_OPERATOR_OVER &&
    2152           0 :         _cairo_pattern_is_clear (source))
    2153             :     {
    2154           0 :         return CAIRO_STATUS_SUCCESS;
    2155             :     }
    2156             : 
    2157           0 :     status = _pattern_has_error (source);
    2158           0 :     if (unlikely (status))
    2159           0 :         return status;
    2160             : 
    2161           0 :     status = _pattern_has_error (mask);
    2162           0 :     if (unlikely (status))
    2163           0 :         return status;
    2164             : 
    2165           0 :     _cairo_surface_begin_modification (surface);
    2166             : 
    2167           0 :     if (surface->backend->mask != NULL) {
    2168           0 :         status = surface->backend->mask (surface, op, source, mask, clip);
    2169           0 :         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
    2170           0 :             goto FINISH;
    2171             :     }
    2172             : 
    2173           0 :     status = _cairo_surface_fallback_mask (surface, op, source, mask, clip);
    2174             : 
    2175             :  FINISH:
    2176           0 :     surface->is_clear = FALSE;
    2177             : 
    2178           0 :     return _cairo_surface_set_error (surface, status);
    2179             : }
    2180             : 
    2181             : cairo_status_t
    2182           0 : _cairo_surface_fill_stroke (cairo_surface_t         *surface,
    2183             :                             cairo_operator_t         fill_op,
    2184             :                             const cairo_pattern_t   *fill_source,
    2185             :                             cairo_fill_rule_t        fill_rule,
    2186             :                             double                   fill_tolerance,
    2187             :                             cairo_antialias_t        fill_antialias,
    2188             :                             cairo_path_fixed_t      *path,
    2189             :                             cairo_operator_t         stroke_op,
    2190             :                             const cairo_pattern_t   *stroke_source,
    2191             :                             const cairo_stroke_style_t    *stroke_style,
    2192             :                             const cairo_matrix_t            *stroke_ctm,
    2193             :                             const cairo_matrix_t            *stroke_ctm_inverse,
    2194             :                             double                   stroke_tolerance,
    2195             :                             cairo_antialias_t        stroke_antialias,
    2196             :                             cairo_clip_t            *clip)
    2197             : {
    2198             :     cairo_status_t status;
    2199             : 
    2200           0 :     if (unlikely (surface->status))
    2201           0 :         return surface->status;
    2202             : 
    2203           0 :     if (clip && clip->all_clipped)
    2204           0 :         return CAIRO_STATUS_SUCCESS;
    2205             : 
    2206           0 :     if (surface->is_clear &&
    2207           0 :         fill_op == CAIRO_OPERATOR_CLEAR &&
    2208             :         stroke_op == CAIRO_OPERATOR_CLEAR)
    2209             :     {
    2210           0 :         return CAIRO_STATUS_SUCCESS;
    2211             :     }
    2212             : 
    2213           0 :     status = _pattern_has_error (fill_source);
    2214           0 :     if (unlikely (status))
    2215           0 :         return status;
    2216             : 
    2217           0 :     status = _pattern_has_error (stroke_source);
    2218           0 :     if (unlikely (status))
    2219           0 :         return status;
    2220             : 
    2221           0 :     _cairo_surface_begin_modification (surface);
    2222             : 
    2223           0 :     if (surface->backend->fill_stroke) {
    2224           0 :         cairo_matrix_t dev_ctm = *stroke_ctm;
    2225           0 :         cairo_matrix_t dev_ctm_inverse = *stroke_ctm_inverse;
    2226             : 
    2227           0 :         status = surface->backend->fill_stroke (surface,
    2228             :                                                 fill_op, fill_source, fill_rule,
    2229             :                                                 fill_tolerance, fill_antialias,
    2230             :                                                 path,
    2231             :                                                 stroke_op, stroke_source,
    2232             :                                                 stroke_style,
    2233             :                                                 &dev_ctm, &dev_ctm_inverse,
    2234             :                                                 stroke_tolerance, stroke_antialias,
    2235             :                                                 clip);
    2236             : 
    2237           0 :         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
    2238           0 :             goto FINISH;
    2239             :     }
    2240             : 
    2241           0 :     status = _cairo_surface_fill (surface, fill_op, fill_source, path,
    2242             :                                   fill_rule, fill_tolerance, fill_antialias,
    2243             :                                   clip);
    2244           0 :     if (unlikely (status))
    2245           0 :         goto FINISH;
    2246             : 
    2247           0 :     status = _cairo_surface_stroke (surface, stroke_op, stroke_source, path,
    2248             :                                     stroke_style, stroke_ctm, stroke_ctm_inverse,
    2249             :                                     stroke_tolerance, stroke_antialias,
    2250             :                                     clip);
    2251           0 :     if (unlikely (status))
    2252           0 :         goto FINISH;
    2253             : 
    2254             :   FINISH:
    2255           0 :     surface->is_clear = FALSE;
    2256             : 
    2257           0 :     return _cairo_surface_set_error (surface, status);
    2258             : }
    2259             : 
    2260             : cairo_status_t
    2261           0 : _cairo_surface_stroke (cairo_surface_t          *surface,
    2262             :                        cairo_operator_t          op,
    2263             :                        const cairo_pattern_t    *source,
    2264             :                        cairo_path_fixed_t       *path,
    2265             :                        const cairo_stroke_style_t       *stroke_style,
    2266             :                        const cairo_matrix_t             *ctm,
    2267             :                        const cairo_matrix_t             *ctm_inverse,
    2268             :                        double                    tolerance,
    2269             :                        cairo_antialias_t         antialias,
    2270             :                        cairo_clip_t             *clip)
    2271             : {
    2272             :     cairo_status_t status;
    2273             : 
    2274           0 :     if (unlikely (surface->status))
    2275           0 :         return surface->status;
    2276             : 
    2277           0 :     if (clip && clip->all_clipped)
    2278           0 :         return CAIRO_STATUS_SUCCESS;
    2279             : 
    2280           0 :     if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
    2281           0 :         return CAIRO_STATUS_SUCCESS;
    2282             : 
    2283           0 :     if (op == CAIRO_OPERATOR_OVER &&
    2284           0 :         _cairo_pattern_is_clear (source))
    2285             :     {
    2286           0 :         return CAIRO_STATUS_SUCCESS;
    2287             :     }
    2288             : 
    2289           0 :     status = _pattern_has_error (source);
    2290           0 :     if (unlikely (status))
    2291           0 :         return status;
    2292             : 
    2293           0 :     _cairo_surface_begin_modification (surface);
    2294             : 
    2295           0 :     if (surface->backend->stroke != NULL) {
    2296           0 :         status = surface->backend->stroke (surface, op, source,
    2297             :                                            path, stroke_style,
    2298             :                                            ctm, ctm_inverse,
    2299             :                                            tolerance, antialias,
    2300             :                                            clip);
    2301             : 
    2302           0 :         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
    2303           0 :             goto FINISH;
    2304             :     }
    2305             : 
    2306           0 :     status = _cairo_surface_fallback_stroke (surface, op, source,
    2307             :                                              path, stroke_style,
    2308             :                                              ctm, ctm_inverse,
    2309             :                                              tolerance, antialias,
    2310             :                                              clip);
    2311             : 
    2312             :  FINISH:
    2313           0 :     surface->is_clear = FALSE;
    2314             : 
    2315           0 :     return _cairo_surface_set_error (surface, status);
    2316             : }
    2317             : 
    2318             : cairo_status_t
    2319           0 : _cairo_surface_fill (cairo_surface_t    *surface,
    2320             :                      cairo_operator_t    op,
    2321             :                      const cairo_pattern_t *source,
    2322             :                      cairo_path_fixed_t *path,
    2323             :                      cairo_fill_rule_t   fill_rule,
    2324             :                      double              tolerance,
    2325             :                      cairo_antialias_t   antialias,
    2326             :                      cairo_clip_t       *clip)
    2327             : {
    2328             :     cairo_status_t status;
    2329             : 
    2330           0 :     if (unlikely (surface->status))
    2331           0 :         return surface->status;
    2332             : 
    2333           0 :     if (clip && clip->all_clipped)
    2334           0 :         return CAIRO_STATUS_SUCCESS;
    2335             : 
    2336           0 :     if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
    2337           0 :         return CAIRO_STATUS_SUCCESS;
    2338             : 
    2339           0 :     if (op == CAIRO_OPERATOR_OVER &&
    2340           0 :         _cairo_pattern_is_clear (source))
    2341             :     {
    2342           0 :         return CAIRO_STATUS_SUCCESS;
    2343             :     }
    2344             : 
    2345           0 :     status = _pattern_has_error (source);
    2346           0 :     if (unlikely (status))
    2347           0 :         return status;
    2348             : 
    2349           0 :     _cairo_surface_begin_modification (surface);
    2350             : 
    2351           0 :     if (surface->backend->fill != NULL) {
    2352           0 :         status = surface->backend->fill (surface, op, source,
    2353             :                                          path, fill_rule,
    2354             :                                          tolerance, antialias,
    2355             :                                          clip);
    2356             : 
    2357           0 :         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
    2358           0 :             goto FINISH;
    2359             :     }
    2360             : 
    2361           0 :     status = _cairo_surface_fallback_fill (surface, op, source,
    2362             :                                            path, fill_rule,
    2363             :                                            tolerance, antialias,
    2364             :                                            clip);
    2365             : 
    2366             :  FINISH:
    2367           0 :     surface->is_clear = FALSE;
    2368             : 
    2369           0 :     return _cairo_surface_set_error (surface, status);
    2370             : }
    2371             : 
    2372             : cairo_status_t
    2373           0 : _cairo_surface_composite_trapezoids (cairo_operator_t           op,
    2374             :                                      const cairo_pattern_t      *pattern,
    2375             :                                      cairo_surface_t            *dst,
    2376             :                                      cairo_antialias_t          antialias,
    2377             :                                      int                        src_x,
    2378             :                                      int                        src_y,
    2379             :                                      int                        dst_x,
    2380             :                                      int                        dst_y,
    2381             :                                      unsigned int               width,
    2382             :                                      unsigned int               height,
    2383             :                                      cairo_trapezoid_t          *traps,
    2384             :                                      int                        num_traps,
    2385             :                                      cairo_region_t             *clip_region)
    2386             : {
    2387             :     cairo_int_status_t status;
    2388             : 
    2389           0 :     if (dst->status)
    2390           0 :         return dst->status;
    2391             : 
    2392           0 :     assert (_cairo_surface_is_writable (dst));
    2393             : 
    2394             :     /* These operators aren't interpreted the same way by the backends;
    2395             :      * they are implemented in terms of other operators in cairo-gstate.c
    2396             :      */
    2397           0 :     assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
    2398             : 
    2399           0 :     if (dst->backend->composite_trapezoids) {
    2400           0 :         status = dst->backend->composite_trapezoids (op,
    2401             :                                                      pattern, dst,
    2402             :                                                      antialias,
    2403             :                                                      src_x, src_y,
    2404             :                                                      dst_x, dst_y,
    2405             :                                                      width, height,
    2406             :                                                      traps, num_traps,
    2407             :                                                      clip_region);
    2408           0 :         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
    2409           0 :             return _cairo_surface_set_error (dst, status);
    2410             :     }
    2411             : 
    2412           0 :     return  _cairo_surface_set_error (dst,
    2413             :             _cairo_surface_fallback_composite_trapezoids (op, pattern, dst,
    2414             :                                                           antialias,
    2415             :                                                           src_x, src_y,
    2416             :                                                           dst_x, dst_y,
    2417             :                                                           width, height,
    2418             :                                                           traps, num_traps,
    2419             :                                                           clip_region));
    2420             : }
    2421             : 
    2422             : cairo_span_renderer_t *
    2423           0 : _cairo_surface_create_span_renderer (cairo_operator_t            op,
    2424             :                                      const cairo_pattern_t      *pattern,
    2425             :                                      cairo_surface_t            *dst,
    2426             :                                      cairo_antialias_t           antialias,
    2427             :                                      const cairo_composite_rectangles_t *rects,
    2428             :                                      cairo_region_t             *clip_region)
    2429             : {
    2430           0 :     assert (dst->snapshot_of == NULL);
    2431             : 
    2432           0 :     if (unlikely (dst->status))
    2433           0 :         return _cairo_span_renderer_create_in_error (dst->status);
    2434             : 
    2435           0 :     if (unlikely (dst->finished))
    2436           0 :         return _cairo_span_renderer_create_in_error (CAIRO_STATUS_SURFACE_FINISHED);
    2437             : 
    2438           0 :     if (dst->backend->create_span_renderer) {
    2439           0 :         return dst->backend->create_span_renderer (op,
    2440             :                                                    pattern, dst,
    2441             :                                                    antialias,
    2442             :                                                    rects,
    2443             :                                                    clip_region);
    2444             :     }
    2445           0 :     ASSERT_NOT_REACHED;
    2446           0 :     return _cairo_span_renderer_create_in_error (CAIRO_INT_STATUS_UNSUPPORTED);
    2447             : }
    2448             : 
    2449             : cairo_bool_t
    2450           0 : _cairo_surface_check_span_renderer (cairo_operator_t             op,
    2451             :                                     const cairo_pattern_t       *pattern,
    2452             :                                     cairo_surface_t             *dst,
    2453             :                                     cairo_antialias_t            antialias)
    2454             : {
    2455           0 :     assert (dst->snapshot_of == NULL);
    2456           0 :     assert (dst->status == CAIRO_STATUS_SUCCESS);
    2457           0 :     assert (! dst->finished);
    2458             : 
    2459             :     /* XXX: Currently we have no mono span renderer */
    2460           0 :     if (antialias == CAIRO_ANTIALIAS_NONE)
    2461           0 :         return FALSE;
    2462             : 
    2463           0 :     if (dst->backend->check_span_renderer != NULL)
    2464           0 :         return dst->backend->check_span_renderer (op, pattern, dst, antialias);
    2465             : 
    2466           0 :     return FALSE;
    2467             : }
    2468             : 
    2469             : /**
    2470             :  * cairo_surface_copy_page:
    2471             :  * @surface: a #cairo_surface_t
    2472             :  *
    2473             :  * Emits the current page for backends that support multiple pages,
    2474             :  * but doesn't clear it, so that the contents of the current page will
    2475             :  * be retained for the next page.  Use cairo_surface_show_page() if you
    2476             :  * want to get an empty page after the emission.
    2477             :  *
    2478             :  * There is a convenience function for this that takes a #cairo_t,
    2479             :  * namely cairo_copy_page().
    2480             :  *
    2481             :  * Since: 1.6
    2482             :  */
    2483             : void
    2484           0 : cairo_surface_copy_page (cairo_surface_t *surface)
    2485             : {
    2486             :     cairo_status_t status_ignored;
    2487             : 
    2488           0 :     if (surface->status)
    2489           0 :         return;
    2490             : 
    2491           0 :     assert (surface->snapshot_of == NULL);
    2492             : 
    2493           0 :     if (surface->finished) {
    2494           0 :         status_ignored = _cairo_surface_set_error (surface,
    2495             :                                                  CAIRO_STATUS_SURFACE_FINISHED);
    2496           0 :         return;
    2497             :     }
    2498             : 
    2499             :     /* It's fine if some backends don't implement copy_page */
    2500           0 :     if (surface->backend->copy_page == NULL)
    2501           0 :         return;
    2502             : 
    2503           0 :     status_ignored = _cairo_surface_set_error (surface,
    2504           0 :                                          surface->backend->copy_page (surface));
    2505             : }
    2506             : slim_hidden_def (cairo_surface_copy_page);
    2507             : 
    2508             : /**
    2509             :  * cairo_surface_show_page:
    2510             :  * @surface: a #cairo_Surface_t
    2511             :  *
    2512             :  * Emits and clears the current page for backends that support multiple
    2513             :  * pages.  Use cairo_surface_copy_page() if you don't want to clear the page.
    2514             :  *
    2515             :  * There is a convenience function for this that takes a #cairo_t,
    2516             :  * namely cairo_show_page().
    2517             :  *
    2518             :  * Since: 1.6
    2519             :  **/
    2520             : void
    2521           0 : cairo_surface_show_page (cairo_surface_t *surface)
    2522             : {
    2523             :     cairo_status_t status_ignored;
    2524             : 
    2525           0 :     if (surface->status)
    2526           0 :         return;
    2527             : 
    2528           0 :     if (surface->finished) {
    2529           0 :         status_ignored = _cairo_surface_set_error (surface,
    2530             :                                                  CAIRO_STATUS_SURFACE_FINISHED);
    2531           0 :         return;
    2532             :     }
    2533             : 
    2534           0 :     _cairo_surface_begin_modification (surface);
    2535             : 
    2536             :     /* It's fine if some backends don't implement show_page */
    2537           0 :     if (surface->backend->show_page == NULL)
    2538           0 :         return;
    2539             : 
    2540           0 :     status_ignored = _cairo_surface_set_error (surface,
    2541           0 :                                          surface->backend->show_page (surface));
    2542             : }
    2543             : slim_hidden_def (cairo_surface_show_page);
    2544             : 
    2545             : /**
    2546             :  * _cairo_surface_get_extents:
    2547             :  * @surface: the #cairo_surface_t to fetch extents for
    2548             :  *
    2549             :  * This function returns a bounding box for the surface.  The surface
    2550             :  * bounds are defined as a region beyond which no rendering will
    2551             :  * possibly be recorded, in other words, it is the maximum extent of
    2552             :  * potentially usable coordinates.
    2553             :  *
    2554             :  * For vector surfaces, (PDF, PS, SVG and recording-surfaces), the surface
    2555             :  * might be conceived as unbounded, but we force the user to provide a
    2556             :  * maximum size at the time of surface_create. So get_extents uses
    2557             :  * that size.
    2558             :  *
    2559             :  * Note: The coordinates returned are in "backend" space rather than
    2560             :  * "surface" space. That is, they are relative to the true (0,0)
    2561             :  * origin rather than the device_transform origin. This might seem a
    2562             :  * bit inconsistent with other #cairo_surface_t interfaces, but all
    2563             :  * current callers are within the surface layer where backend space is
    2564             :  * desired.
    2565             :  *
    2566             :  * This behavior would have to be changed is we ever exported a public
    2567             :  * variant of this function.
    2568             :  */
    2569             : cairo_bool_t
    2570           0 : _cairo_surface_get_extents (cairo_surface_t         *surface,
    2571             :                             cairo_rectangle_int_t   *extents)
    2572             : {
    2573             :     cairo_bool_t bounded;
    2574             : 
    2575           0 :     bounded = FALSE;
    2576           0 :     if (! surface->status && surface->backend->get_extents != NULL)
    2577           0 :         bounded = surface->backend->get_extents (surface, extents);
    2578             : 
    2579           0 :     if (! bounded)
    2580           0 :         _cairo_unbounded_rectangle_init (extents);
    2581             : 
    2582           0 :     return bounded;
    2583             : }
    2584             : 
    2585             : /**
    2586             :  * cairo_surface_has_show_text_glyphs:
    2587             :  * @surface: a #cairo_surface_t
    2588             :  *
    2589             :  * Returns whether the surface supports
    2590             :  * sophisticated cairo_show_text_glyphs() operations.  That is,
    2591             :  * whether it actually uses the provided text and cluster data
    2592             :  * to a cairo_show_text_glyphs() call.
    2593             :  *
    2594             :  * Note: Even if this function returns %FALSE, a
    2595             :  * cairo_show_text_glyphs() operation targeted at @surface will
    2596             :  * still succeed.  It just will
    2597             :  * act like a cairo_show_glyphs() operation.  Users can use this
    2598             :  * function to avoid computing UTF-8 text and cluster mapping if the
    2599             :  * target surface does not use it.
    2600             :  *
    2601             :  * Return value: %TRUE if @surface supports
    2602             :  *               cairo_show_text_glyphs(), %FALSE otherwise
    2603             :  *
    2604             :  * Since: 1.8
    2605             :  **/
    2606             : cairo_bool_t
    2607           0 : cairo_surface_has_show_text_glyphs (cairo_surface_t         *surface)
    2608             : {
    2609             :     cairo_status_t status_ignored;
    2610             : 
    2611           0 :     if (surface->status)
    2612           0 :         return FALSE;
    2613             : 
    2614           0 :     if (surface->finished) {
    2615           0 :         status_ignored = _cairo_surface_set_error (surface,
    2616             :                                                    CAIRO_STATUS_SURFACE_FINISHED);
    2617           0 :         return FALSE;
    2618             :     }
    2619             : 
    2620           0 :     if (surface->backend->has_show_text_glyphs)
    2621           0 :         return surface->backend->has_show_text_glyphs (surface);
    2622             :     else
    2623           0 :         return surface->backend->show_text_glyphs != NULL;
    2624             : }
    2625             : slim_hidden_def (cairo_surface_has_show_text_glyphs);
    2626             : 
    2627             : /**
    2628             :  * cairo_surface_set_subpixel_antialiasing:
    2629             :  * @surface: a #cairo_surface_t
    2630             :  *
    2631             :  * Sets whether the surface permits subpixel antialiasing. By default,
    2632             :  * surfaces permit subpixel antialiasing.
    2633             :  *
    2634             :  * Enabling subpixel antialiasing for CONTENT_COLOR_ALPHA surfaces generally
    2635             :  * requires that the pixels in the areas under a subpixel antialiasing
    2636             :  * operation already be opaque.
    2637             :  *
    2638             :  * Since: 1.12
    2639             :  **/
    2640             : void
    2641           3 : cairo_surface_set_subpixel_antialiasing (cairo_surface_t *surface,
    2642             :                                          cairo_subpixel_antialiasing_t enabled)
    2643             : {
    2644           3 :     if (surface->status)
    2645           0 :         return;
    2646             : 
    2647           3 :     if (surface->finished) {
    2648           0 :         _cairo_surface_set_error (surface, CAIRO_STATUS_SURFACE_FINISHED);
    2649           0 :         return;
    2650             :     }
    2651             : 
    2652           3 :     surface->permit_subpixel_antialiasing =
    2653           3 :         enabled == CAIRO_SUBPIXEL_ANTIALIASING_ENABLED;
    2654             : }
    2655             : slim_hidden_def (cairo_surface_set_subpixel_antialiasing);
    2656             : 
    2657             : /**
    2658             :  * cairo_surface_get_subpixel_antialiasing:
    2659             :  * @surface: a #cairo_surface_t
    2660             :  *
    2661             :  * Gets whether the surface supports subpixel antialiasing. By default,
    2662             :  * CAIRO_CONTENT_COLOR surfaces support subpixel antialiasing but other
    2663             :  * surfaces do not.
    2664             :  *
    2665             :  * Since: 1.12
    2666             :  **/
    2667             : cairo_subpixel_antialiasing_t
    2668           0 : cairo_surface_get_subpixel_antialiasing (cairo_surface_t *surface)
    2669             : {
    2670           0 :     if (surface->status)
    2671           0 :         return CAIRO_SUBPIXEL_ANTIALIASING_DISABLED;
    2672             : 
    2673           0 :     return surface->permit_subpixel_antialiasing ?
    2674           0 :         CAIRO_SUBPIXEL_ANTIALIASING_ENABLED : CAIRO_SUBPIXEL_ANTIALIASING_DISABLED;
    2675             : }
    2676             : slim_hidden_def (cairo_surface_get_subpixel_antialiasing);
    2677             : 
    2678             : /* Note: the backends may modify the contents of the glyph array as long as
    2679             :  * they do not return %CAIRO_INT_STATUS_UNSUPPORTED. This makes it possible to
    2680             :  * avoid copying the array again and again, and edit it in-place.
    2681             :  * Backends are in fact free to use the array as a generic buffer as they
    2682             :  * see fit.
    2683             :  *
    2684             :  * For show_glyphs backend method, and NOT for show_text_glyphs method,
    2685             :  * when they do return UNSUPPORTED, they may adjust remaining_glyphs to notify
    2686             :  * that they have successfully rendered some of the glyphs (from the beginning
    2687             :  * of the array), but not all.  If they don't touch remaining_glyphs, it
    2688             :  * defaults to all glyphs.
    2689             :  *
    2690             :  * See commits 5a9642c5746fd677aed35ce620ce90b1029b1a0c and
    2691             :  * 1781e6018c17909311295a9cc74b70500c6b4d0a for the rationale.
    2692             :  */
    2693             : cairo_status_t
    2694           0 : _cairo_surface_show_text_glyphs (cairo_surface_t            *surface,
    2695             :                                  cairo_operator_t            op,
    2696             :                                  const cairo_pattern_t      *source,
    2697             :                                  const char                 *utf8,
    2698             :                                  int                         utf8_len,
    2699             :                                  cairo_glyph_t              *glyphs,
    2700             :                                  int                         num_glyphs,
    2701             :                                  const cairo_text_cluster_t *clusters,
    2702             :                                  int                         num_clusters,
    2703             :                                  cairo_text_cluster_flags_t  cluster_flags,
    2704             :                                  cairo_scaled_font_t        *scaled_font,
    2705             :                                  cairo_clip_t               *clip)
    2706             : {
    2707             :     cairo_status_t status;
    2708           0 :     cairo_scaled_font_t *dev_scaled_font = scaled_font;
    2709             : 
    2710           0 :     if (unlikely (surface->status))
    2711           0 :         return surface->status;
    2712             : 
    2713           0 :     if (num_glyphs == 0 && utf8_len == 0)
    2714           0 :         return CAIRO_STATUS_SUCCESS;
    2715             : 
    2716           0 :     if (clip && clip->all_clipped)
    2717           0 :         return CAIRO_STATUS_SUCCESS;
    2718             : 
    2719           0 :     if (op == CAIRO_OPERATOR_CLEAR && surface->is_clear)
    2720           0 :         return CAIRO_STATUS_SUCCESS;
    2721             : 
    2722           0 :     status = _pattern_has_error (source);
    2723           0 :     if (unlikely (status))
    2724           0 :         return status;
    2725             : 
    2726           0 :     _cairo_surface_begin_modification (surface);
    2727             : 
    2728           0 :     if (_cairo_surface_has_device_transform (surface) &&
    2729           0 :         ! _cairo_matrix_is_integer_translation (&surface->device_transform, NULL, NULL))
    2730             :     {
    2731             :         cairo_font_options_t font_options;
    2732             :         cairo_matrix_t dev_ctm, font_matrix;
    2733             : 
    2734           0 :         cairo_scaled_font_get_font_matrix (scaled_font, &font_matrix);
    2735           0 :         cairo_scaled_font_get_ctm (scaled_font, &dev_ctm);
    2736           0 :         cairo_matrix_multiply (&dev_ctm, &dev_ctm, &surface->device_transform);
    2737           0 :         cairo_scaled_font_get_font_options (scaled_font, &font_options);
    2738           0 :         dev_scaled_font = cairo_scaled_font_create (cairo_scaled_font_get_font_face (scaled_font),
    2739             :                                                     &font_matrix,
    2740             :                                                     &dev_ctm,
    2741             :                                                     &font_options);
    2742             :     }
    2743           0 :     status = cairo_scaled_font_status (dev_scaled_font);
    2744           0 :     if (unlikely (status))
    2745           0 :         return _cairo_surface_set_error (surface, status);
    2746             : 
    2747           0 :     status = CAIRO_INT_STATUS_UNSUPPORTED;
    2748             : 
    2749             :     /* The logic here is duplicated in _cairo_analysis_surface show_glyphs and
    2750             :      * show_text_glyphs.  Keep in synch. */
    2751           0 :     if (clusters) {
    2752             :         /* A real show_text_glyphs call.  Try show_text_glyphs backend
    2753             :          * method first */
    2754           0 :         if (surface->backend->show_text_glyphs != NULL) {
    2755           0 :             status = surface->backend->show_text_glyphs (surface, op,
    2756             :                                                          source,
    2757             :                                                          utf8, utf8_len,
    2758             :                                                          glyphs, num_glyphs,
    2759             :                                                          clusters, num_clusters, cluster_flags,
    2760             :                                                          dev_scaled_font,
    2761             :                                                          clip);
    2762             :         }
    2763           0 :         if (status == CAIRO_INT_STATUS_UNSUPPORTED &&
    2764           0 :             surface->backend->show_glyphs)
    2765             :         {
    2766           0 :             int remaining_glyphs = num_glyphs;
    2767           0 :             status = surface->backend->show_glyphs (surface, op,
    2768             :                                                     source,
    2769             :                                                     glyphs, num_glyphs,
    2770             :                                                     dev_scaled_font,
    2771             :                                                     clip,
    2772             :                                                     &remaining_glyphs);
    2773           0 :             glyphs += num_glyphs - remaining_glyphs;
    2774           0 :             num_glyphs = remaining_glyphs;
    2775           0 :             if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
    2776           0 :                 status = CAIRO_STATUS_SUCCESS;
    2777             :         }
    2778             :     } else {
    2779             :         /* A mere show_glyphs call.  Try show_glyphs backend method first */
    2780           0 :         if (surface->backend->show_glyphs != NULL) {
    2781           0 :             int remaining_glyphs = num_glyphs;
    2782           0 :             status = surface->backend->show_glyphs (surface, op,
    2783             :                                                     source,
    2784             :                                                     glyphs, num_glyphs,
    2785             :                                                     dev_scaled_font,
    2786             :                                                     clip,
    2787             :                                                     &remaining_glyphs);
    2788           0 :             glyphs += num_glyphs - remaining_glyphs;
    2789           0 :             num_glyphs = remaining_glyphs;
    2790           0 :             if (status == CAIRO_INT_STATUS_UNSUPPORTED && remaining_glyphs == 0)
    2791           0 :                 status = CAIRO_STATUS_SUCCESS;
    2792           0 :         } else if (surface->backend->show_text_glyphs != NULL) {
    2793             :             /* Intentionally only try show_text_glyphs method for show_glyphs
    2794             :              * calls if backend does not have show_glyphs.  If backend has
    2795             :              * both methods implemented, we don't fallback from show_glyphs to
    2796             :              * show_text_glyphs, and hence the backend can assume in its
    2797             :              * show_text_glyphs call that clusters is not NULL (which also
    2798             :              * implies that UTF-8 is not NULL, unless the text is
    2799             :              * zero-length).
    2800             :              */
    2801           0 :             status = surface->backend->show_text_glyphs (surface, op,
    2802             :                                                          source,
    2803             :                                                          utf8, utf8_len,
    2804             :                                                          glyphs, num_glyphs,
    2805             :                                                          clusters, num_clusters, cluster_flags,
    2806             :                                                          dev_scaled_font,
    2807             :                                                          clip);
    2808             :         }
    2809             :     }
    2810             : 
    2811           0 :     if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
    2812           0 :         status = _cairo_surface_fallback_show_glyphs (surface, op,
    2813             :                                                       source,
    2814             :                                                       glyphs, num_glyphs,
    2815             :                                                       dev_scaled_font,
    2816             :                                                       clip);
    2817             :     }
    2818             : 
    2819           0 :     if (dev_scaled_font != scaled_font)
    2820           0 :         cairo_scaled_font_destroy (dev_scaled_font);
    2821             : 
    2822           0 :     surface->is_clear = FALSE;
    2823             : 
    2824           0 :     return _cairo_surface_set_error (surface, status);
    2825             : }
    2826             : 
    2827             : /* XXX: Previously, we had a function named _cairo_surface_show_glyphs
    2828             :  * with not-so-useful semantics. We've now got a
    2829             :  * _cairo_surface_show_text_glyphs with the proper semantics, and its
    2830             :  * fallback still uses this old function (which still needs to be
    2831             :  * cleaned up in terms of both semantics and naming). */
    2832             : cairo_status_t
    2833           0 : _cairo_surface_old_show_glyphs (cairo_scaled_font_t     *scaled_font,
    2834             :                                 cairo_operator_t         op,
    2835             :                                 const cairo_pattern_t   *pattern,
    2836             :                                 cairo_surface_t         *dst,
    2837             :                                 int                      source_x,
    2838             :                                 int                      source_y,
    2839             :                                 int                      dest_x,
    2840             :                                 int                      dest_y,
    2841             :                                 unsigned int             width,
    2842             :                                 unsigned int             height,
    2843             :                                 cairo_glyph_t           *glyphs,
    2844             :                                 int                      num_glyphs,
    2845             :                                 cairo_region_t          *clip_region)
    2846             : {
    2847             :     cairo_status_t status;
    2848             : 
    2849           0 :     if (dst->status)
    2850           0 :         return dst->status;
    2851             : 
    2852           0 :     assert (_cairo_surface_is_writable (dst));
    2853             : 
    2854           0 :     if (dst->backend->old_show_glyphs) {
    2855           0 :         status = dst->backend->old_show_glyphs (scaled_font,
    2856             :                                                 op, pattern, dst,
    2857             :                                                 source_x, source_y,
    2858             :                                                 dest_x, dest_y,
    2859             :                                                 width, height,
    2860             :                                                 glyphs, num_glyphs,
    2861             :                                                 clip_region);
    2862             :     } else
    2863           0 :         status = CAIRO_INT_STATUS_UNSUPPORTED;
    2864             : 
    2865           0 :     return _cairo_surface_set_error (dst, status);
    2866             : }
    2867             : 
    2868             : static cairo_status_t
    2869           0 : _cairo_surface_composite_fixup_unbounded_internal (cairo_surface_t         *dst,
    2870             :                                                    cairo_rectangle_int_t   *src_rectangle,
    2871             :                                                    cairo_rectangle_int_t   *mask_rectangle,
    2872             :                                                    int                      dst_x,
    2873             :                                                    int                      dst_y,
    2874             :                                                    unsigned int             width,
    2875             :                                                    unsigned int             height,
    2876             :                                                    cairo_region_t           *clip_region)
    2877             : {
    2878             :     cairo_rectangle_int_t dst_rectangle;
    2879             :     cairo_region_t clear_region;
    2880             :     cairo_status_t status;
    2881             : 
    2882             :     /* The area that was drawn is the area in the destination rectangle but
    2883             :      * not within the source or the mask.
    2884             :      */
    2885           0 :     dst_rectangle.x = dst_x;
    2886           0 :     dst_rectangle.y = dst_y;
    2887           0 :     dst_rectangle.width = width;
    2888           0 :     dst_rectangle.height = height;
    2889             : 
    2890           0 :     _cairo_region_init_rectangle (&clear_region, &dst_rectangle);
    2891             : 
    2892           0 :     if (clip_region != NULL) {
    2893           0 :         status = cairo_region_intersect (&clear_region, clip_region);
    2894           0 :         if (unlikely (status))
    2895           0 :             goto CLEANUP_REGIONS;
    2896             :     }
    2897             : 
    2898           0 :     if (src_rectangle != NULL) {
    2899           0 :         if (! _cairo_rectangle_intersect (&dst_rectangle, src_rectangle))
    2900           0 :             goto EMPTY;
    2901             :     }
    2902             : 
    2903           0 :     if (mask_rectangle != NULL) {
    2904           0 :         if (! _cairo_rectangle_intersect (&dst_rectangle, mask_rectangle))
    2905           0 :             goto EMPTY;
    2906             :     }
    2907             : 
    2908             :     /* Now compute the area that is in dst but not drawn */
    2909           0 :     status = cairo_region_subtract_rectangle (&clear_region, &dst_rectangle);
    2910           0 :     if (unlikely (status) || cairo_region_is_empty (&clear_region))
    2911             :         goto CLEANUP_REGIONS;
    2912             : 
    2913             :   EMPTY:
    2914           0 :     status = _cairo_surface_fill_region (dst, CAIRO_OPERATOR_CLEAR,
    2915             :                                          CAIRO_COLOR_TRANSPARENT,
    2916             :                                          &clear_region);
    2917             : 
    2918             :   CLEANUP_REGIONS:
    2919           0 :     _cairo_region_fini (&clear_region);
    2920             : 
    2921           0 :     return _cairo_surface_set_error (dst, status);
    2922             : }
    2923             : 
    2924             : /**
    2925             :  * _cairo_surface_composite_fixup_unbounded:
    2926             :  * @dst: the destination surface
    2927             :  * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface())
    2928             :  * @src_width: width of source surface
    2929             :  * @src_height: height of source surface
    2930             :  * @mask_attr: mask surface attributes or %NULL if no mask
    2931             :  * @mask_width: width of mask surface
    2932             :  * @mask_height: height of mask surface
    2933             :  * @src_x: @src_x from _cairo_surface_composite()
    2934             :  * @src_y: @src_y from _cairo_surface_composite()
    2935             :  * @mask_x: @mask_x from _cairo_surface_composite()
    2936             :  * @mask_y: @mask_y from _cairo_surface_composite()
    2937             :  * @dst_x: @dst_x from _cairo_surface_composite()
    2938             :  * @dst_y: @dst_y from _cairo_surface_composite()
    2939             :  * @width: @width from _cairo_surface_composite()
    2940             :  * @height: @height_x from _cairo_surface_composite()
    2941             :  *
    2942             :  * Eeek! Too many parameters! This is a helper function to take care of fixing
    2943             :  * up for bugs in libpixman and RENDER where, when asked to composite an
    2944             :  * untransformed surface with an unbounded operator (like CLEAR or SOURCE)
    2945             :  * only the region inside both the source and the mask is affected.
    2946             :  * This function clears the region that should have been drawn but was wasn't.
    2947             :  **/
    2948             : cairo_status_t
    2949           0 : _cairo_surface_composite_fixup_unbounded (cairo_surface_t            *dst,
    2950             :                                           cairo_surface_attributes_t *src_attr,
    2951             :                                           int                         src_width,
    2952             :                                           int                         src_height,
    2953             :                                           cairo_surface_attributes_t *mask_attr,
    2954             :                                           int                         mask_width,
    2955             :                                           int                         mask_height,
    2956             :                                           int                         src_x,
    2957             :                                           int                         src_y,
    2958             :                                           int                         mask_x,
    2959             :                                           int                         mask_y,
    2960             :                                           int                         dst_x,
    2961             :                                           int                         dst_y,
    2962             :                                           unsigned int                width,
    2963             :                                           unsigned int                height,
    2964             :                                           cairo_region_t             *clip_region)
    2965             : {
    2966             :     cairo_rectangle_int_t src_tmp, mask_tmp;
    2967           0 :     cairo_rectangle_int_t *src_rectangle = NULL;
    2968           0 :     cairo_rectangle_int_t *mask_rectangle = NULL;
    2969             : 
    2970           0 :     if (unlikely (dst->status))
    2971           0 :         return dst->status;
    2972             : 
    2973           0 :     assert (_cairo_surface_is_writable (dst));
    2974             : 
    2975             :     /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
    2976             :      * non-repeating sources and masks. Other sources and masks can be ignored.
    2977             :      */
    2978           0 :     if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
    2979           0 :         src_attr->extend == CAIRO_EXTEND_NONE)
    2980             :     {
    2981           0 :         src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
    2982           0 :         src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
    2983           0 :         src_tmp.width = src_width;
    2984           0 :         src_tmp.height = src_height;
    2985             : 
    2986           0 :         src_rectangle = &src_tmp;
    2987             :     }
    2988             : 
    2989           0 :     if (mask_attr &&
    2990           0 :         _cairo_matrix_is_integer_translation (&mask_attr->matrix, NULL, NULL) &&
    2991           0 :         mask_attr->extend == CAIRO_EXTEND_NONE)
    2992             :     {
    2993           0 :         mask_tmp.x = (dst_x - (mask_x + mask_attr->x_offset));
    2994           0 :         mask_tmp.y = (dst_y - (mask_y + mask_attr->y_offset));
    2995           0 :         mask_tmp.width = mask_width;
    2996           0 :         mask_tmp.height = mask_height;
    2997             : 
    2998           0 :         mask_rectangle = &mask_tmp;
    2999             :     }
    3000             : 
    3001           0 :     return _cairo_surface_composite_fixup_unbounded_internal (dst, src_rectangle, mask_rectangle,
    3002             :                                                               dst_x, dst_y, width, height,
    3003             :                                                               clip_region);
    3004             : }
    3005             : 
    3006             : /**
    3007             :  * _cairo_surface_composite_shape_fixup_unbounded:
    3008             :  * @dst: the destination surface
    3009             :  * @src_attr: source surface attributes (from _cairo_pattern_acquire_surface())
    3010             :  * @src_width: width of source surface
    3011             :  * @src_height: height of source surface
    3012             :  * @mask_width: width of mask surface
    3013             :  * @mask_height: height of mask surface
    3014             :  * @src_x: @src_x from _cairo_surface_composite()
    3015             :  * @src_y: @src_y from _cairo_surface_composite()
    3016             :  * @mask_x: @mask_x from _cairo_surface_composite()
    3017             :  * @mask_y: @mask_y from _cairo_surface_composite()
    3018             :  * @dst_x: @dst_x from _cairo_surface_composite()
    3019             :  * @dst_y: @dst_y from _cairo_surface_composite()
    3020             :  * @width: @width from _cairo_surface_composite()
    3021             :  * @height: @height_x from _cairo_surface_composite()
    3022             :  *
    3023             :  * Like _cairo_surface_composite_fixup_unbounded(), but instead of
    3024             :  * handling the case where we have a source pattern and a mask
    3025             :  * pattern, handle the case where we are compositing a source pattern
    3026             :  * using a mask we create ourselves, as in
    3027             :  * _cairo_surface_composite_glyphs() or _cairo_surface_composite_trapezoids()
    3028             :  **/
    3029             : cairo_status_t
    3030           0 : _cairo_surface_composite_shape_fixup_unbounded (cairo_surface_t            *dst,
    3031             :                                                 cairo_surface_attributes_t *src_attr,
    3032             :                                                 int                         src_width,
    3033             :                                                 int                         src_height,
    3034             :                                                 int                         mask_width,
    3035             :                                                 int                         mask_height,
    3036             :                                                 int                         src_x,
    3037             :                                                 int                         src_y,
    3038             :                                                 int                         mask_x,
    3039             :                                                 int                         mask_y,
    3040             :                                                 int                         dst_x,
    3041             :                                                 int                         dst_y,
    3042             :                                                 unsigned int                width,
    3043             :                                                 unsigned int                height,
    3044             :                                                 cairo_region_t      *clip_region)
    3045             : {
    3046           0 :     cairo_rectangle_int_t src_tmp, *src= NULL;
    3047             :     cairo_rectangle_int_t mask;
    3048             : 
    3049           0 :     if (dst->status)
    3050           0 :         return dst->status;
    3051             : 
    3052           0 :     assert (_cairo_surface_is_writable (dst));
    3053             : 
    3054             :     /* The RENDER/libpixman operators are clipped to the bounds of the untransformed,
    3055             :      * non-repeating sources and masks. Other sources and masks can be ignored.
    3056             :      */
    3057           0 :     if (_cairo_matrix_is_integer_translation (&src_attr->matrix, NULL, NULL) &&
    3058           0 :         src_attr->extend == CAIRO_EXTEND_NONE)
    3059             :     {
    3060           0 :         src_tmp.x = (dst_x - (src_x + src_attr->x_offset));
    3061           0 :         src_tmp.y = (dst_y - (src_y + src_attr->y_offset));
    3062           0 :         src_tmp.width  = src_width;
    3063           0 :         src_tmp.height = src_height;
    3064             : 
    3065           0 :         src = &src_tmp;
    3066             :     }
    3067             : 
    3068           0 :     mask.x = dst_x - mask_x;
    3069           0 :     mask.y = dst_y - mask_y;
    3070           0 :     mask.width  = mask_width;
    3071           0 :     mask.height = mask_height;
    3072             : 
    3073           0 :     return _cairo_surface_composite_fixup_unbounded_internal (dst, src, &mask,
    3074             :                                                               dst_x, dst_y, width, height,
    3075             :                                                               clip_region);
    3076             : }
    3077             : 
    3078             : /**
    3079             :  * _cairo_surface_set_resolution
    3080             :  * @surface: the surface
    3081             :  * @x_res: x resolution, in dpi
    3082             :  * @y_res: y resolution, in dpi
    3083             :  *
    3084             :  * Set the actual surface resolution of @surface to the given x and y DPI.
    3085             :  * Mainly used for correctly computing the scale factor when fallback
    3086             :  * rendering needs to take place in the paginated surface.
    3087             :  */
    3088             : void
    3089           0 : _cairo_surface_set_resolution (cairo_surface_t *surface,
    3090             :                                double x_res,
    3091             :                                double y_res)
    3092             : {
    3093           0 :     if (surface->status)
    3094           0 :         return;
    3095             : 
    3096           0 :     surface->x_resolution = x_res;
    3097           0 :     surface->y_resolution = y_res;
    3098             : }
    3099             : 
    3100             : /* Generic methods for determining operation extents. */
    3101             : 
    3102             : static void
    3103           0 : _rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
    3104             : {
    3105             :     const cairo_rectangle_int_t *clip_extents;
    3106             :     cairo_bool_t is_empty;
    3107             : 
    3108           0 :     clip_extents = NULL;
    3109           0 :     if (clip != NULL)
    3110           0 :         clip_extents = _cairo_clip_get_extents (clip);
    3111             : 
    3112           0 :     if (clip_extents != NULL)
    3113           0 :         is_empty = _cairo_rectangle_intersect (extents, clip_extents);
    3114           0 : }
    3115             : 
    3116             : static void
    3117           0 : _cairo_surface_operation_extents (cairo_surface_t *surface,
    3118             :                                   cairo_operator_t op,
    3119             :                                   const cairo_pattern_t *source,
    3120             :                                   cairo_clip_t *clip,
    3121             :                                   cairo_rectangle_int_t *extents)
    3122             : {
    3123             :     cairo_bool_t is_empty;
    3124             : 
    3125           0 :     is_empty = _cairo_surface_get_extents (surface, extents);
    3126             : 
    3127           0 :     if (_cairo_operator_bounded_by_source (op)) {
    3128             :         cairo_rectangle_int_t source_extents;
    3129             : 
    3130           0 :         _cairo_pattern_get_extents (source, &source_extents);
    3131           0 :         is_empty = _cairo_rectangle_intersect (extents, &source_extents);
    3132             :     }
    3133             : 
    3134           0 :     _rectangle_intersect_clip (extents, clip);
    3135           0 : }
    3136             : 
    3137             : cairo_status_t
    3138           0 : _cairo_surface_paint_extents (cairo_surface_t *surface,
    3139             :                               cairo_operator_t          op,
    3140             :                               const cairo_pattern_t     *source,
    3141             :                               cairo_clip_t              *clip,
    3142             :                               cairo_rectangle_int_t     *extents)
    3143             : {
    3144           0 :     _cairo_surface_operation_extents (surface, op, source, clip, extents);
    3145           0 :     return CAIRO_STATUS_SUCCESS;
    3146             : }
    3147             : 
    3148             : cairo_status_t
    3149           0 : _cairo_surface_mask_extents (cairo_surface_t *surface,
    3150             :                              cairo_operator_t            op,
    3151             :                              const cairo_pattern_t      *source,
    3152             :                              const cairo_pattern_t      *mask,
    3153             :                              cairo_clip_t               *clip,
    3154             :                              cairo_rectangle_int_t      *extents)
    3155             : {
    3156             :     cairo_bool_t is_empty;
    3157             : 
    3158           0 :     _cairo_surface_operation_extents (surface, op, source, clip, extents);
    3159             : 
    3160           0 :     if (_cairo_operator_bounded_by_mask (op)) {
    3161             :         cairo_rectangle_int_t mask_extents;
    3162             : 
    3163           0 :         _cairo_pattern_get_extents (mask, &mask_extents);
    3164           0 :         is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
    3165             :     }
    3166             : 
    3167           0 :     return CAIRO_STATUS_SUCCESS;
    3168             : }
    3169             : 
    3170             : cairo_status_t
    3171           0 : _cairo_surface_stroke_extents (cairo_surface_t *surface,
    3172             :                                cairo_operator_t op,
    3173             :                                const cairo_pattern_t *source,
    3174             :                                cairo_path_fixed_t       *path,
    3175             :                                const cairo_stroke_style_t *style,
    3176             :                                const cairo_matrix_t *ctm,
    3177             :                                const cairo_matrix_t *ctm_inverse,
    3178             :                                double tolerance,
    3179             :                                cairo_antialias_t         antialias,
    3180             :                                cairo_clip_t *clip,
    3181             :                                cairo_rectangle_int_t *extents)
    3182             : {
    3183             :     cairo_status_t status;
    3184             :     cairo_bool_t is_empty;
    3185             : 
    3186           0 :     _cairo_surface_operation_extents (surface, op, source, clip, extents);
    3187             : 
    3188           0 :     if (_cairo_operator_bounded_by_mask (op)) {
    3189             :         cairo_rectangle_int_t mask_extents;
    3190             : 
    3191           0 :         status = _cairo_path_fixed_stroke_extents (path, style,
    3192             :                                                    ctm, ctm_inverse,
    3193             :                                                    tolerance,
    3194             :                                                    &mask_extents);
    3195           0 :         if (unlikely (status))
    3196           0 :             return status;
    3197             : 
    3198           0 :         is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
    3199             :     }
    3200             : 
    3201           0 :     return CAIRO_STATUS_SUCCESS;
    3202             : }
    3203             : 
    3204             : cairo_status_t
    3205           0 : _cairo_surface_fill_extents (cairo_surface_t            *surface,
    3206             :                              cairo_operator_t            op,
    3207             :                              const cairo_pattern_t      *source,
    3208             :                              cairo_path_fixed_t         *path,
    3209             :                              cairo_fill_rule_t           fill_rule,
    3210             :                              double                      tolerance,
    3211             :                              cairo_antialias_t           antialias,
    3212             :                              cairo_clip_t               *clip,
    3213             :                              cairo_rectangle_int_t      *extents)
    3214             : {
    3215             :     cairo_bool_t is_empty;
    3216             : 
    3217           0 :     _cairo_surface_operation_extents (surface, op, source, clip, extents);
    3218             : 
    3219           0 :     if (_cairo_operator_bounded_by_mask (op)) {
    3220             :         cairo_rectangle_int_t mask_extents;
    3221             : 
    3222           0 :         _cairo_path_fixed_fill_extents (path, fill_rule, tolerance,
    3223             :                                         &mask_extents);
    3224           0 :         is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
    3225             :     }
    3226             : 
    3227           0 :     return CAIRO_STATUS_SUCCESS;
    3228             : }
    3229             : 
    3230             : cairo_status_t
    3231           0 : _cairo_surface_glyphs_extents (cairo_surface_t *surface,
    3232             :                                cairo_operator_t    op,
    3233             :                                const cairo_pattern_t *source,
    3234             :                                cairo_glyph_t      *glyphs,
    3235             :                                int                 num_glyphs,
    3236             :                                cairo_scaled_font_t  *scaled_font,
    3237             :                                cairo_clip_t         *clip,
    3238             :                                cairo_rectangle_int_t *extents)
    3239             : {
    3240             :     cairo_status_t           status;
    3241             :     cairo_bool_t             is_empty;
    3242             : 
    3243           0 :     _cairo_surface_operation_extents (surface, op, source, clip, extents);
    3244             : 
    3245           0 :     if (_cairo_operator_bounded_by_mask (op)) {
    3246             :         cairo_rectangle_int_t glyph_extents;
    3247             : 
    3248           0 :         status = _cairo_scaled_font_glyph_device_extents (scaled_font,
    3249             :                                                           glyphs,
    3250             :                                                           num_glyphs,
    3251             :                                                           &glyph_extents,
    3252             :                                                           NULL);
    3253           0 :         if (unlikely (status))
    3254           0 :             return status;
    3255             : 
    3256           0 :         is_empty = _cairo_rectangle_intersect (extents, &glyph_extents);
    3257             :     }
    3258             : 
    3259           0 :     return CAIRO_STATUS_SUCCESS;
    3260             : }
    3261             : 
    3262             : cairo_surface_t *
    3263           0 : _cairo_surface_create_in_error (cairo_status_t status)
    3264             : {
    3265           0 :     switch (status) {
    3266             :     case CAIRO_STATUS_NO_MEMORY:
    3267           0 :         return (cairo_surface_t *) &_cairo_surface_nil;
    3268             :     case CAIRO_STATUS_SURFACE_TYPE_MISMATCH:
    3269           0 :         return (cairo_surface_t *) &_cairo_surface_nil_surface_type_mismatch;
    3270             :     case CAIRO_STATUS_INVALID_STATUS:
    3271           0 :         return (cairo_surface_t *) &_cairo_surface_nil_invalid_status;
    3272             :     case CAIRO_STATUS_INVALID_CONTENT:
    3273           0 :         return (cairo_surface_t *) &_cairo_surface_nil_invalid_content;
    3274             :     case CAIRO_STATUS_INVALID_FORMAT:
    3275           0 :         return (cairo_surface_t *) &_cairo_surface_nil_invalid_format;
    3276             :     case CAIRO_STATUS_INVALID_VISUAL:
    3277           0 :         return (cairo_surface_t *) &_cairo_surface_nil_invalid_visual;
    3278             :     case CAIRO_STATUS_READ_ERROR:
    3279           0 :         return (cairo_surface_t *) &_cairo_surface_nil_read_error;
    3280             :     case CAIRO_STATUS_WRITE_ERROR:
    3281           0 :         return (cairo_surface_t *) &_cairo_surface_nil_write_error;
    3282             :     case CAIRO_STATUS_FILE_NOT_FOUND:
    3283           0 :         return (cairo_surface_t *) &_cairo_surface_nil_file_not_found;
    3284             :     case CAIRO_STATUS_TEMP_FILE_ERROR:
    3285           0 :         return (cairo_surface_t *) &_cairo_surface_nil_temp_file_error;
    3286             :     case CAIRO_STATUS_INVALID_STRIDE:
    3287           0 :         return (cairo_surface_t *) &_cairo_surface_nil_invalid_stride;
    3288             :     case CAIRO_STATUS_INVALID_SIZE:
    3289           0 :         return (cairo_surface_t *) &_cairo_surface_nil_invalid_size;
    3290             :     case CAIRO_STATUS_DEVICE_TYPE_MISMATCH:
    3291           0 :         return (cairo_surface_t *) &_cairo_surface_nil_device_type_mismatch;
    3292             :     case CAIRO_STATUS_DEVICE_ERROR:
    3293           0 :         return (cairo_surface_t *) &_cairo_surface_nil_device_error;
    3294             :     case CAIRO_STATUS_SUCCESS:
    3295             :     case CAIRO_STATUS_LAST_STATUS:
    3296           0 :         ASSERT_NOT_REACHED;
    3297             :         /* fall-through */
    3298             :     case CAIRO_STATUS_INVALID_RESTORE:
    3299             :     case CAIRO_STATUS_INVALID_POP_GROUP:
    3300             :     case CAIRO_STATUS_NO_CURRENT_POINT:
    3301             :     case CAIRO_STATUS_INVALID_MATRIX:
    3302             :     case CAIRO_STATUS_NULL_POINTER:
    3303             :     case CAIRO_STATUS_INVALID_STRING:
    3304             :     case CAIRO_STATUS_INVALID_PATH_DATA:
    3305             :     case CAIRO_STATUS_SURFACE_FINISHED:
    3306             :     case CAIRO_STATUS_PATTERN_TYPE_MISMATCH:
    3307             :     case CAIRO_STATUS_INVALID_DASH:
    3308             :     case CAIRO_STATUS_INVALID_DSC_COMMENT:
    3309             :     case CAIRO_STATUS_INVALID_INDEX:
    3310             :     case CAIRO_STATUS_CLIP_NOT_REPRESENTABLE:
    3311             :     case CAIRO_STATUS_FONT_TYPE_MISMATCH:
    3312             :     case CAIRO_STATUS_USER_FONT_IMMUTABLE:
    3313             :     case CAIRO_STATUS_USER_FONT_ERROR:
    3314             :     case CAIRO_STATUS_NEGATIVE_COUNT:
    3315             :     case CAIRO_STATUS_INVALID_CLUSTERS:
    3316             :     case CAIRO_STATUS_INVALID_SLANT:
    3317             :     case CAIRO_STATUS_INVALID_WEIGHT:
    3318             :     case CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED:
    3319             :     default:
    3320           0 :         _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
    3321           0 :         return (cairo_surface_t *) &_cairo_surface_nil;
    3322             :     }
    3323             : }
    3324             : 
    3325             : /*  LocalWords:  rasterized
    3326             :  */

Generated by: LCOV version 1.13