Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

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