LCOV - code coverage report
Current view: top level - gfx/cairo/cairo/src - cairo-pattern.c (source / functions) Hit Total Coverage
Test: output.info Lines: 0 1182 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 83 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
       2             : /* cairo - a vector graphics library with display and print output
       3             :  *
       4             :  * Copyright © 2004 David Reveman
       5             :  * Copyright © 2005 Red Hat, Inc.
       6             :  *
       7             :  * Permission to use, copy, modify, distribute, and sell this software
       8             :  * and its documentation for any purpose is hereby granted without
       9             :  * fee, provided that the above copyright notice appear in all copies
      10             :  * and that both that copyright notice and this permission notice
      11             :  * appear in supporting documentation, and that the name of David
      12             :  * Reveman not be used in advertising or publicity pertaining to
      13             :  * distribution of the software without specific, written prior
      14             :  * permission. David Reveman makes no representations about the
      15             :  * suitability of this software for any purpose.  It is provided "as
      16             :  * is" without express or implied warranty.
      17             :  *
      18             :  * DAVID REVEMAN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
      19             :  * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
      20             :  * FITNESS, IN NO EVENT SHALL DAVID REVEMAN BE LIABLE FOR ANY SPECIAL,
      21             :  * INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
      22             :  * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
      23             :  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR
      24             :  * IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      25             :  *
      26             :  * Authors: David Reveman <davidr@novell.com>
      27             :  *          Keith Packard <keithp@keithp.com>
      28             :  *          Carl Worth <cworth@cworth.org>
      29             :  */
      30             : 
      31             : #include "cairoint.h"
      32             : #include "cairo-error-private.h"
      33             : #include "cairo-freed-pool-private.h"
      34             : 
      35             : /**
      36             :  * SECTION:cairo-pattern
      37             :  * @Title: cairo_pattern_t
      38             :  * @Short_Description: Sources for drawing
      39             :  * @See_Also: #cairo_t, #cairo_surface_t
      40             :  *
      41             :  * #cairo_pattern_t is the paint with which cairo draws.
      42             :  * The primary use of patterns is as the source for all cairo drawing 
      43             :  * operations, although they can also be used as masks, that is, as the 
      44             :  * brush too.
      45             :  *
      46             :  * A cairo pattern is created by using one of the many constructors,
      47             :  * of the form cairo_pattern_create_<emphasis>type</emphasis>()
      48             :  * or implicitly through
      49             :  * cairo_set_source_<emphasis>type</emphasis>() functions.
      50             :  */
      51             : 
      52             : #if HAS_FREED_POOL
      53             : static freed_pool_t freed_pattern_pool[4];
      54             : #endif
      55             : 
      56             : static const cairo_solid_pattern_t _cairo_pattern_nil = {
      57             :     { CAIRO_PATTERN_TYPE_SOLID,         /* type */
      58             :       CAIRO_REFERENCE_COUNT_INVALID,    /* ref_count */
      59             :       CAIRO_STATUS_NO_MEMORY,           /* status */
      60             :       { 0, 0, 0, NULL },                /* user_data */
      61             :       { 1., 0., 0., 1., 0., 0., },      /* matrix */
      62             :       CAIRO_FILTER_DEFAULT,             /* filter */
      63             :       CAIRO_EXTEND_GRADIENT_DEFAULT },  /* extend */
      64             : };
      65             : 
      66             : static const cairo_solid_pattern_t _cairo_pattern_nil_null_pointer = {
      67             :     { CAIRO_PATTERN_TYPE_SOLID,         /* type */
      68             :       CAIRO_REFERENCE_COUNT_INVALID,    /* ref_count */
      69             :       CAIRO_STATUS_NULL_POINTER,        /* status */
      70             :       { 0, 0, 0, NULL },                /* user_data */
      71             :       { 1., 0., 0., 1., 0., 0., },      /* matrix */
      72             :       CAIRO_FILTER_DEFAULT,             /* filter */
      73             :       CAIRO_EXTEND_GRADIENT_DEFAULT },  /* extend */
      74             : };
      75             : 
      76             : const cairo_solid_pattern_t _cairo_pattern_black = {
      77             :     { CAIRO_PATTERN_TYPE_SOLID,         /* type */
      78             :       CAIRO_REFERENCE_COUNT_INVALID,    /* ref_count */
      79             :       CAIRO_STATUS_SUCCESS,             /* status */
      80             :       { 0, 0, 0, NULL },                /* user_data */
      81             :       { 1., 0., 0., 1., 0., 0., },      /* matrix */
      82             :       CAIRO_FILTER_DEFAULT,             /* filter */
      83             :       CAIRO_EXTEND_GRADIENT_DEFAULT},   /* extend */
      84             :     { 0., 0., 0., 1., 0, 0, 0, 0xffff },/* color (double rgba, short rgba) */
      85             : };
      86             : 
      87             : const cairo_solid_pattern_t _cairo_pattern_clear = {
      88             :     { CAIRO_PATTERN_TYPE_SOLID,         /* type */
      89             :       CAIRO_REFERENCE_COUNT_INVALID,    /* ref_count */
      90             :       CAIRO_STATUS_SUCCESS,             /* status */
      91             :       { 0, 0, 0, NULL },                /* user_data */
      92             :       { 1., 0., 0., 1., 0., 0., },      /* matrix */
      93             :       CAIRO_FILTER_DEFAULT,             /* filter */
      94             :       CAIRO_EXTEND_GRADIENT_DEFAULT},   /* extend */
      95             :     { 0., 0., 0., 0., 0, 0, 0, 0 },/* color (double rgba, short rgba) */
      96             : };
      97             : 
      98             : const cairo_solid_pattern_t _cairo_pattern_white = {
      99             :     { CAIRO_PATTERN_TYPE_SOLID,         /* type */
     100             :       CAIRO_REFERENCE_COUNT_INVALID,    /* ref_count */
     101             :       CAIRO_STATUS_SUCCESS,             /* status */
     102             :       { 0, 0, 0, NULL },                /* user_data */
     103             :       { 1., 0., 0., 1., 0., 0., },      /* matrix */
     104             :       CAIRO_FILTER_DEFAULT,             /* filter */
     105             :       CAIRO_EXTEND_GRADIENT_DEFAULT},   /* extend */
     106             :     { 1., 1., 1., 1., 0xffff, 0xffff, 0xffff, 0xffff },/* color (double rgba, short rgba) */
     107             : };
     108             : 
     109             : /**
     110             :  * _cairo_pattern_set_error:
     111             :  * @pattern: a pattern
     112             :  * @status: a status value indicating an error
     113             :  *
     114             :  * Atomically sets pattern->status to @status and calls _cairo_error;
     115             :  * Does nothing if status is %CAIRO_STATUS_SUCCESS.
     116             :  *
     117             :  * All assignments of an error status to pattern->status should happen
     118             :  * through _cairo_pattern_set_error(). Note that due to the nature of
     119             :  * the atomic operation, it is not safe to call this function on the nil
     120             :  * objects.
     121             :  *
     122             :  * The purpose of this function is to allow the user to set a
     123             :  * breakpoint in _cairo_error() to generate a stack trace for when the
     124             :  * user causes cairo to detect an error.
     125             :  **/
     126             : static cairo_status_t
     127           0 : _cairo_pattern_set_error (cairo_pattern_t *pattern,
     128             :                           cairo_status_t status)
     129             : {
     130           0 :     if (status == CAIRO_STATUS_SUCCESS)
     131           0 :         return status;
     132             : 
     133             :     /* Don't overwrite an existing error. This preserves the first
     134             :      * error, which is the most significant. */
     135           0 :     _cairo_status_set_error (&pattern->status, status);
     136             : 
     137           0 :     return _cairo_error (status);
     138             : }
     139             : 
     140             : static void
     141           0 : _cairo_pattern_init (cairo_pattern_t *pattern, cairo_pattern_type_t type)
     142             : {
     143             : #if HAVE_VALGRIND
     144             :     switch (type) {
     145             :     case CAIRO_PATTERN_TYPE_SOLID:
     146             :         VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t));
     147             :         break;
     148             :     case CAIRO_PATTERN_TYPE_SURFACE:
     149             :         VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t));
     150             :         break;
     151             :     case CAIRO_PATTERN_TYPE_LINEAR:
     152             :         VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t));
     153             :         break;
     154             :     case CAIRO_PATTERN_TYPE_RADIAL:
     155             :         VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t));
     156             :         break;
     157             :     }
     158             : #endif
     159             : 
     160           0 :     pattern->type      = type;
     161           0 :     pattern->status    = CAIRO_STATUS_SUCCESS;
     162             : 
     163             :     /* Set the reference count to zero for on-stack patterns.
     164             :      * Callers needs to explicitly increment the count for heap allocations. */
     165           0 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
     166             : 
     167           0 :     _cairo_user_data_array_init (&pattern->user_data);
     168             : 
     169           0 :     if (type == CAIRO_PATTERN_TYPE_SURFACE)
     170           0 :         pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
     171             :     else
     172           0 :         pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
     173             : 
     174           0 :     pattern->filter    = CAIRO_FILTER_DEFAULT;
     175             : 
     176           0 :     pattern->has_component_alpha = FALSE;
     177             : 
     178           0 :     cairo_matrix_init_identity (&pattern->matrix);
     179           0 : }
     180             : 
     181             : static cairo_status_t
     182           0 : _cairo_gradient_pattern_init_copy (cairo_gradient_pattern_t       *pattern,
     183             :                                    const cairo_gradient_pattern_t *other)
     184             : {
     185             :     if (CAIRO_INJECT_FAULT ())
     186             :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     187             : 
     188           0 :     if (other->base.type == CAIRO_PATTERN_TYPE_LINEAR)
     189             :     {
     190           0 :         cairo_linear_pattern_t *dst = (cairo_linear_pattern_t *) pattern;
     191           0 :         cairo_linear_pattern_t *src = (cairo_linear_pattern_t *) other;
     192             : 
     193           0 :         *dst = *src;
     194             :     }
     195             :     else
     196             :     {
     197           0 :         cairo_radial_pattern_t *dst = (cairo_radial_pattern_t *) pattern;
     198           0 :         cairo_radial_pattern_t *src = (cairo_radial_pattern_t *) other;
     199             : 
     200           0 :         *dst = *src;
     201             :     }
     202             : 
     203           0 :     if (other->stops == other->stops_embedded)
     204           0 :         pattern->stops = pattern->stops_embedded;
     205           0 :     else if (other->stops)
     206             :     {
     207           0 :         pattern->stops = _cairo_malloc_ab (other->stops_size,
     208             :                                            sizeof (cairo_gradient_stop_t));
     209           0 :         if (unlikely (pattern->stops == NULL)) {
     210           0 :             pattern->stops_size = 0;
     211           0 :             pattern->n_stops = 0;
     212           0 :             return _cairo_pattern_set_error (&pattern->base, CAIRO_STATUS_NO_MEMORY);
     213             :         }
     214             : 
     215           0 :         memcpy (pattern->stops, other->stops,
     216           0 :                 other->n_stops * sizeof (cairo_gradient_stop_t));
     217             :     }
     218             : 
     219           0 :     return CAIRO_STATUS_SUCCESS;
     220             : }
     221             : 
     222             : cairo_status_t
     223           0 : _cairo_pattern_init_copy (cairo_pattern_t       *pattern,
     224             :                           const cairo_pattern_t *other)
     225             : {
     226           0 :     if (other->status)
     227           0 :         return _cairo_pattern_set_error (pattern, other->status);
     228             : 
     229           0 :     switch (other->type) {
     230             :     case CAIRO_PATTERN_TYPE_SOLID: {
     231           0 :         cairo_solid_pattern_t *dst = (cairo_solid_pattern_t *) pattern;
     232           0 :         cairo_solid_pattern_t *src = (cairo_solid_pattern_t *) other;
     233             : 
     234             :         VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_solid_pattern_t)));
     235             : 
     236           0 :         *dst = *src;
     237           0 :     } break;
     238             :     case CAIRO_PATTERN_TYPE_SURFACE: {
     239           0 :         cairo_surface_pattern_t *dst = (cairo_surface_pattern_t *) pattern;
     240           0 :         cairo_surface_pattern_t *src = (cairo_surface_pattern_t *) other;
     241             : 
     242             :         VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_surface_pattern_t)));
     243             : 
     244           0 :         *dst = *src;
     245           0 :         cairo_surface_reference (dst->surface);
     246           0 :     } break;
     247             :     case CAIRO_PATTERN_TYPE_LINEAR:
     248             :     case CAIRO_PATTERN_TYPE_RADIAL: {
     249           0 :         cairo_gradient_pattern_t *dst = (cairo_gradient_pattern_t *) pattern;
     250           0 :         cairo_gradient_pattern_t *src = (cairo_gradient_pattern_t *) other;
     251             :         cairo_status_t status;
     252             : 
     253           0 :         if (other->type == CAIRO_PATTERN_TYPE_LINEAR) {
     254             :             VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_linear_pattern_t)));
     255             :         } else {
     256             :             VG (VALGRIND_MAKE_MEM_UNDEFINED (pattern, sizeof (cairo_radial_pattern_t)));
     257             :         }
     258             : 
     259           0 :         status = _cairo_gradient_pattern_init_copy (dst, src);
     260           0 :         if (unlikely (status))
     261           0 :             return status;
     262             : 
     263           0 :     } break;
     264             :     }
     265             : 
     266             :     /* The reference count and user_data array are unique to the copy. */
     267           0 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
     268           0 :     _cairo_user_data_array_init (&pattern->user_data);
     269             : 
     270           0 :     return CAIRO_STATUS_SUCCESS;
     271             : }
     272             : 
     273             : void
     274           0 : _cairo_pattern_init_static_copy (cairo_pattern_t        *pattern,
     275             :                                  const cairo_pattern_t *other)
     276             : {
     277             :     int size;
     278             : 
     279           0 :     assert (other->status == CAIRO_STATUS_SUCCESS);
     280             : 
     281           0 :     switch (other->type) {
     282             :     default:
     283           0 :         ASSERT_NOT_REACHED;
     284             :     case CAIRO_PATTERN_TYPE_SOLID:
     285           0 :         size = sizeof (cairo_solid_pattern_t);
     286           0 :         break;
     287             :     case CAIRO_PATTERN_TYPE_SURFACE:
     288           0 :         size = sizeof (cairo_surface_pattern_t);
     289           0 :         break;
     290             :     case CAIRO_PATTERN_TYPE_LINEAR:
     291           0 :         size = sizeof (cairo_linear_pattern_t);
     292           0 :         break;
     293             :     case CAIRO_PATTERN_TYPE_RADIAL:
     294           0 :         size = sizeof (cairo_radial_pattern_t);
     295           0 :         break;
     296             :     }
     297             : 
     298           0 :     memcpy (pattern, other, size);
     299             : 
     300           0 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
     301           0 :     _cairo_user_data_array_init (&pattern->user_data);
     302           0 : }
     303             : 
     304             : cairo_status_t
     305           0 : _cairo_pattern_init_snapshot (cairo_pattern_t       *pattern,
     306             :                               const cairo_pattern_t *other)
     307             : {
     308             :     cairo_status_t status;
     309             : 
     310             :     /* We don't bother doing any fancy copy-on-write implementation
     311             :      * for the pattern's data. It's generally quite tiny. */
     312           0 :     status = _cairo_pattern_init_copy (pattern, other);
     313           0 :     if (unlikely (status))
     314           0 :         return status;
     315             : 
     316             :     /* But we do let the surface snapshot stuff be as fancy as it
     317             :      * would like to be. */
     318           0 :     if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE) {
     319           0 :         cairo_surface_pattern_t *surface_pattern =
     320             :             (cairo_surface_pattern_t *) pattern;
     321           0 :         cairo_surface_t *surface = surface_pattern->surface;
     322             : 
     323           0 :         surface_pattern->surface = _cairo_surface_snapshot (surface);
     324             : 
     325           0 :         cairo_surface_destroy (surface);
     326             : 
     327           0 :         if (surface_pattern->surface->status)
     328           0 :             return surface_pattern->surface->status;
     329             :     }
     330             : 
     331           0 :     return CAIRO_STATUS_SUCCESS;
     332             : }
     333             : 
     334             : void
     335           0 : _cairo_pattern_fini (cairo_pattern_t *pattern)
     336             : {
     337           0 :     _cairo_user_data_array_fini (&pattern->user_data);
     338             : 
     339           0 :     switch (pattern->type) {
     340             :     case CAIRO_PATTERN_TYPE_SOLID:
     341           0 :         break;
     342             :     case CAIRO_PATTERN_TYPE_SURFACE: {
     343           0 :         cairo_surface_pattern_t *surface_pattern =
     344             :             (cairo_surface_pattern_t *) pattern;
     345             : 
     346           0 :         cairo_surface_destroy (surface_pattern->surface);
     347           0 :     } break;
     348             :     case CAIRO_PATTERN_TYPE_LINEAR:
     349             :     case CAIRO_PATTERN_TYPE_RADIAL: {
     350           0 :         cairo_gradient_pattern_t *gradient =
     351             :             (cairo_gradient_pattern_t *) pattern;
     352             : 
     353           0 :         if (gradient->stops && gradient->stops != gradient->stops_embedded)
     354           0 :             free (gradient->stops);
     355           0 :     } break;
     356             :     }
     357             : 
     358             : #if HAVE_VALGRIND
     359             :     switch (pattern->type) {
     360             :     case CAIRO_PATTERN_TYPE_SOLID:
     361             :         VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_solid_pattern_t));
     362             :         break;
     363             :     case CAIRO_PATTERN_TYPE_SURFACE:
     364             :         VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_surface_pattern_t));
     365             :         break;
     366             :     case CAIRO_PATTERN_TYPE_LINEAR:
     367             :         VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_linear_pattern_t));
     368             :         break;
     369             :     case CAIRO_PATTERN_TYPE_RADIAL:
     370             :         VALGRIND_MAKE_MEM_NOACCESS (pattern, sizeof (cairo_radial_pattern_t));
     371             :         break;
     372             :     }
     373             : #endif
     374           0 : }
     375             : 
     376             : cairo_status_t
     377           0 : _cairo_pattern_create_copy (cairo_pattern_t       **pattern_out,
     378             :                             const cairo_pattern_t  *other)
     379             : {
     380             :     cairo_pattern_t *pattern;
     381             :     cairo_status_t status;
     382             : 
     383           0 :     if (other->status)
     384           0 :         return other->status;
     385             : 
     386           0 :     switch (other->type) {
     387             :     case CAIRO_PATTERN_TYPE_SOLID:
     388           0 :         pattern = malloc (sizeof (cairo_solid_pattern_t));
     389           0 :         break;
     390             :     case CAIRO_PATTERN_TYPE_SURFACE:
     391           0 :         pattern = malloc (sizeof (cairo_surface_pattern_t));
     392           0 :         break;
     393             :     case CAIRO_PATTERN_TYPE_LINEAR:
     394           0 :         pattern = malloc (sizeof (cairo_linear_pattern_t));
     395           0 :         break;
     396             :     case CAIRO_PATTERN_TYPE_RADIAL:
     397           0 :         pattern = malloc (sizeof (cairo_radial_pattern_t));
     398           0 :         break;
     399             :     default:
     400           0 :         ASSERT_NOT_REACHED;
     401           0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
     402             :     }
     403           0 :     if (unlikely (pattern == NULL))
     404           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     405             : 
     406           0 :     status = _cairo_pattern_init_copy (pattern, other);
     407           0 :     if (unlikely (status)) {
     408           0 :         free (pattern);
     409           0 :         return status;
     410             :     }
     411             : 
     412           0 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 1);
     413           0 :     *pattern_out = pattern;
     414           0 :     return CAIRO_STATUS_SUCCESS;
     415             : }
     416             : 
     417             : 
     418             : void
     419           0 : _cairo_pattern_init_solid (cairo_solid_pattern_t *pattern,
     420             :                            const cairo_color_t   *color)
     421             : {
     422           0 :     _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
     423           0 :     pattern->color = *color;
     424           0 : }
     425             : 
     426             : void
     427           0 : _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
     428             :                                  cairo_surface_t         *surface)
     429             : {
     430           0 :     if (surface->status) {
     431             :         /* Force to solid to simplify the pattern_fini process. */
     432           0 :         _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SOLID);
     433           0 :         _cairo_pattern_set_error (&pattern->base, surface->status);
     434           0 :         return;
     435             :     }
     436             : 
     437           0 :     _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
     438             : 
     439           0 :     pattern->surface = cairo_surface_reference (surface);
     440             : }
     441             : 
     442             : static void
     443           0 : _cairo_pattern_init_gradient (cairo_gradient_pattern_t *pattern,
     444             :                               cairo_pattern_type_t     type)
     445             : {
     446           0 :     _cairo_pattern_init (&pattern->base, type);
     447             : 
     448           0 :     pattern->n_stops    = 0;
     449           0 :     pattern->stops_size = 0;
     450           0 :     pattern->stops      = NULL;
     451           0 : }
     452             : 
     453             : void
     454           0 : _cairo_pattern_init_linear (cairo_linear_pattern_t *pattern,
     455             :                             double x0, double y0, double x1, double y1)
     456             : {
     457           0 :     _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_LINEAR);
     458             : 
     459           0 :     pattern->p1.x = _cairo_fixed_from_double (x0);
     460           0 :     pattern->p1.y = _cairo_fixed_from_double (y0);
     461           0 :     pattern->p2.x = _cairo_fixed_from_double (x1);
     462           0 :     pattern->p2.y = _cairo_fixed_from_double (y1);
     463           0 : }
     464             : 
     465             : void
     466           0 : _cairo_pattern_init_radial (cairo_radial_pattern_t *pattern,
     467             :                             double cx0, double cy0, double radius0,
     468             :                             double cx1, double cy1, double radius1)
     469             : {
     470           0 :     _cairo_pattern_init_gradient (&pattern->base, CAIRO_PATTERN_TYPE_RADIAL);
     471             : 
     472           0 :     pattern->c1.x = _cairo_fixed_from_double (cx0);
     473           0 :     pattern->c1.y = _cairo_fixed_from_double (cy0);
     474           0 :     pattern->r1   = _cairo_fixed_from_double (fabs (radius0));
     475           0 :     pattern->c2.x = _cairo_fixed_from_double (cx1);
     476           0 :     pattern->c2.y = _cairo_fixed_from_double (cy1);
     477           0 :     pattern->r2   = _cairo_fixed_from_double (fabs (radius1));
     478           0 : }
     479             : 
     480             : cairo_pattern_t *
     481           0 : _cairo_pattern_create_solid (const cairo_color_t *color)
     482             : {
     483             :     cairo_solid_pattern_t *pattern;
     484             : 
     485           0 :     pattern =
     486             :         _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
     487           0 :     if (unlikely (pattern == NULL)) {
     488             :         /* None cached, need to create a new pattern. */
     489           0 :         pattern = malloc (sizeof (cairo_solid_pattern_t));
     490           0 :         if (unlikely (pattern == NULL)) {
     491           0 :             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
     492           0 :             return (cairo_pattern_t *) &_cairo_pattern_nil;
     493             :         }
     494             :     }
     495             : 
     496           0 :     _cairo_pattern_init_solid (pattern, color);
     497           0 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
     498             : 
     499           0 :     return &pattern->base;
     500             : }
     501             : 
     502             : cairo_pattern_t *
     503           0 : _cairo_pattern_create_in_error (cairo_status_t status)
     504             : {
     505             :     cairo_pattern_t *pattern;
     506             : 
     507           0 :     if (status == CAIRO_STATUS_NO_MEMORY)
     508           0 :         return (cairo_pattern_t *)&_cairo_pattern_nil.base;
     509             : 
     510             :     CAIRO_MUTEX_INITIALIZE ();
     511             : 
     512           0 :     pattern = _cairo_pattern_create_solid (CAIRO_COLOR_BLACK);
     513           0 :     if (pattern->status == CAIRO_STATUS_SUCCESS)
     514           0 :         status = _cairo_pattern_set_error (pattern, status);
     515             : 
     516           0 :     return pattern;
     517             : }
     518             : 
     519             : /**
     520             :  * cairo_pattern_create_rgb:
     521             :  * @red: red component of the color
     522             :  * @green: green component of the color
     523             :  * @blue: blue component of the color
     524             :  *
     525             :  * Creates a new #cairo_pattern_t corresponding to an opaque color.  The
     526             :  * color components are floating point numbers in the range 0 to 1.
     527             :  * If the values passed in are outside that range, they will be
     528             :  * clamped.
     529             :  *
     530             :  * Return value: the newly created #cairo_pattern_t if successful, or
     531             :  * an error pattern in case of no memory.  The caller owns the
     532             :  * returned object and should call cairo_pattern_destroy() when
     533             :  * finished with it.
     534             :  *
     535             :  * This function will always return a valid pointer, but if an error
     536             :  * occurred the pattern status will be set to an error.  To inspect
     537             :  * the status of a pattern use cairo_pattern_status().
     538             :  **/
     539             : cairo_pattern_t *
     540           0 : cairo_pattern_create_rgb (double red, double green, double blue)
     541             : {
     542             :     cairo_color_t color;
     543             : 
     544           0 :     red   = _cairo_restrict_value (red,   0.0, 1.0);
     545           0 :     green = _cairo_restrict_value (green, 0.0, 1.0);
     546           0 :     blue  = _cairo_restrict_value (blue,  0.0, 1.0);
     547             : 
     548           0 :     _cairo_color_init_rgb (&color, red, green, blue);
     549             : 
     550             :     CAIRO_MUTEX_INITIALIZE ();
     551             : 
     552           0 :     return _cairo_pattern_create_solid (&color);
     553             : }
     554             : slim_hidden_def (cairo_pattern_create_rgb);
     555             : 
     556             : /**
     557             :  * cairo_pattern_create_rgba:
     558             :  * @red: red component of the color
     559             :  * @green: green component of the color
     560             :  * @blue: blue component of the color
     561             :  * @alpha: alpha component of the color
     562             :  *
     563             :  * Creates a new #cairo_pattern_t corresponding to a translucent color.
     564             :  * The color components are floating point numbers in the range 0 to
     565             :  * 1.  If the values passed in are outside that range, they will be
     566             :  * clamped.
     567             :  *
     568             :  * Return value: the newly created #cairo_pattern_t if successful, or
     569             :  * an error pattern in case of no memory.  The caller owns the
     570             :  * returned object and should call cairo_pattern_destroy() when
     571             :  * finished with it.
     572             :  *
     573             :  * This function will always return a valid pointer, but if an error
     574             :  * occurred the pattern status will be set to an error.  To inspect
     575             :  * the status of a pattern use cairo_pattern_status().
     576             :  **/
     577             : cairo_pattern_t *
     578           0 : cairo_pattern_create_rgba (double red, double green, double blue,
     579             :                            double alpha)
     580             : {
     581             :     cairo_color_t color;
     582             : 
     583           0 :     red   = _cairo_restrict_value (red,   0.0, 1.0);
     584           0 :     green = _cairo_restrict_value (green, 0.0, 1.0);
     585           0 :     blue  = _cairo_restrict_value (blue,  0.0, 1.0);
     586           0 :     alpha = _cairo_restrict_value (alpha, 0.0, 1.0);
     587             : 
     588           0 :     _cairo_color_init_rgba (&color, red, green, blue, alpha);
     589             : 
     590             :     CAIRO_MUTEX_INITIALIZE ();
     591             : 
     592           0 :     return _cairo_pattern_create_solid (&color);
     593             : }
     594             : slim_hidden_def (cairo_pattern_create_rgba);
     595             : 
     596             : /**
     597             :  * cairo_pattern_create_for_surface:
     598             :  * @surface: the surface
     599             :  *
     600             :  * Create a new #cairo_pattern_t for the given surface.
     601             :  *
     602             :  * Return value: the newly created #cairo_pattern_t if successful, or
     603             :  * an error pattern in case of no memory.  The caller owns the
     604             :  * returned object and should call cairo_pattern_destroy() when
     605             :  * finished with it.
     606             :  *
     607             :  * This function will always return a valid pointer, but if an error
     608             :  * occurred the pattern status will be set to an error.  To inspect
     609             :  * the status of a pattern use cairo_pattern_status().
     610             :  **/
     611             : cairo_pattern_t *
     612           0 : cairo_pattern_create_for_surface (cairo_surface_t *surface)
     613             : {
     614             :     cairo_surface_pattern_t *pattern;
     615             : 
     616           0 :     if (surface == NULL) {
     617           0 :         _cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
     618           0 :         return (cairo_pattern_t*) &_cairo_pattern_nil_null_pointer;
     619             :     }
     620             : 
     621           0 :     if (surface->status)
     622           0 :         return _cairo_pattern_create_in_error (surface->status);
     623             : 
     624           0 :     pattern =
     625             :         _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
     626           0 :     if (unlikely (pattern == NULL)) {
     627           0 :         pattern = malloc (sizeof (cairo_surface_pattern_t));
     628           0 :         if (unlikely (pattern == NULL)) {
     629           0 :             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
     630           0 :             return (cairo_pattern_t *)&_cairo_pattern_nil.base;
     631             :         }
     632             :     }
     633             : 
     634             :     CAIRO_MUTEX_INITIALIZE ();
     635             : 
     636           0 :     _cairo_pattern_init_for_surface (pattern, surface);
     637           0 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
     638             : 
     639           0 :     return &pattern->base;
     640             : }
     641             : slim_hidden_def (cairo_pattern_create_for_surface);
     642             : 
     643             : /**
     644             :  * cairo_pattern_create_linear:
     645             :  * @x0: x coordinate of the start point
     646             :  * @y0: y coordinate of the start point
     647             :  * @x1: x coordinate of the end point
     648             :  * @y1: y coordinate of the end point
     649             :  *
     650             :  * Create a new linear gradient #cairo_pattern_t along the line defined
     651             :  * by (x0, y0) and (x1, y1).  Before using the gradient pattern, a
     652             :  * number of color stops should be defined using
     653             :  * cairo_pattern_add_color_stop_rgb() or
     654             :  * cairo_pattern_add_color_stop_rgba().
     655             :  *
     656             :  * Note: The coordinates here are in pattern space. For a new pattern,
     657             :  * pattern space is identical to user space, but the relationship
     658             :  * between the spaces can be changed with cairo_pattern_set_matrix().
     659             :  *
     660             :  * Return value: the newly created #cairo_pattern_t if successful, or
     661             :  * an error pattern in case of no memory.  The caller owns the
     662             :  * returned object and should call cairo_pattern_destroy() when
     663             :  * finished with it.
     664             :  *
     665             :  * This function will always return a valid pointer, but if an error
     666             :  * occurred the pattern status will be set to an error.  To inspect
     667             :  * the status of a pattern use cairo_pattern_status().
     668             :  **/
     669             : cairo_pattern_t *
     670           0 : cairo_pattern_create_linear (double x0, double y0, double x1, double y1)
     671             : {
     672             :     cairo_linear_pattern_t *pattern;
     673             : 
     674           0 :     pattern =
     675             :         _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_LINEAR]);
     676           0 :     if (unlikely (pattern == NULL)) {
     677           0 :         pattern = malloc (sizeof (cairo_linear_pattern_t));
     678           0 :         if (unlikely (pattern == NULL)) {
     679           0 :             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
     680           0 :             return (cairo_pattern_t *) &_cairo_pattern_nil.base;
     681             :         }
     682             :     }
     683             : 
     684             :     CAIRO_MUTEX_INITIALIZE ();
     685             : 
     686           0 :     _cairo_pattern_init_linear (pattern, x0, y0, x1, y1);
     687           0 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
     688             : 
     689           0 :     return &pattern->base.base;
     690             : }
     691             : 
     692             : /**
     693             :  * cairo_pattern_create_radial:
     694             :  * @cx0: x coordinate for the center of the start circle
     695             :  * @cy0: y coordinate for the center of the start circle
     696             :  * @radius0: radius of the start circle
     697             :  * @cx1: x coordinate for the center of the end circle
     698             :  * @cy1: y coordinate for the center of the end circle
     699             :  * @radius1: radius of the end circle
     700             :  *
     701             :  * Creates a new radial gradient #cairo_pattern_t between the two
     702             :  * circles defined by (cx0, cy0, radius0) and (cx1, cy1, radius1).  Before using the
     703             :  * gradient pattern, a number of color stops should be defined using
     704             :  * cairo_pattern_add_color_stop_rgb() or
     705             :  * cairo_pattern_add_color_stop_rgba().
     706             :  *
     707             :  * Note: The coordinates here are in pattern space. For a new pattern,
     708             :  * pattern space is identical to user space, but the relationship
     709             :  * between the spaces can be changed with cairo_pattern_set_matrix().
     710             :  *
     711             :  * Return value: the newly created #cairo_pattern_t if successful, or
     712             :  * an error pattern in case of no memory.  The caller owns the
     713             :  * returned object and should call cairo_pattern_destroy() when
     714             :  * finished with it.
     715             :  *
     716             :  * This function will always return a valid pointer, but if an error
     717             :  * occurred the pattern status will be set to an error.  To inspect
     718             :  * the status of a pattern use cairo_pattern_status().
     719             :  **/
     720             : cairo_pattern_t *
     721           0 : cairo_pattern_create_radial (double cx0, double cy0, double radius0,
     722             :                              double cx1, double cy1, double radius1)
     723             : {
     724             :     cairo_radial_pattern_t *pattern;
     725             : 
     726           0 :     pattern =
     727             :         _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_RADIAL]);
     728           0 :     if (unlikely (pattern == NULL)) {
     729           0 :         pattern = malloc (sizeof (cairo_radial_pattern_t));
     730           0 :         if (unlikely (pattern == NULL)) {
     731           0 :             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
     732           0 :             return (cairo_pattern_t *) &_cairo_pattern_nil.base;
     733             :         }
     734             :     }
     735             : 
     736             :     CAIRO_MUTEX_INITIALIZE ();
     737             : 
     738           0 :     _cairo_pattern_init_radial (pattern, cx0, cy0, radius0, cx1, cy1, radius1);
     739           0 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->base.base.ref_count, 1);
     740             : 
     741           0 :     return &pattern->base.base;
     742             : }
     743             : 
     744             : /**
     745             :  * cairo_pattern_reference:
     746             :  * @pattern: a #cairo_pattern_t
     747             :  *
     748             :  * Increases the reference count on @pattern by one. This prevents
     749             :  * @pattern from being destroyed until a matching call to
     750             :  * cairo_pattern_destroy() is made.
     751             :  *
     752             :  * The number of references to a #cairo_pattern_t can be get using
     753             :  * cairo_pattern_get_reference_count().
     754             :  *
     755             :  * Return value: the referenced #cairo_pattern_t.
     756             :  **/
     757             : cairo_pattern_t *
     758           0 : cairo_pattern_reference (cairo_pattern_t *pattern)
     759             : {
     760           0 :     if (pattern == NULL ||
     761           0 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
     762           0 :         return pattern;
     763             : 
     764           0 :     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
     765             : 
     766           0 :     _cairo_reference_count_inc (&pattern->ref_count);
     767             : 
     768           0 :     return pattern;
     769             : }
     770             : slim_hidden_def (cairo_pattern_reference);
     771             : 
     772             : /**
     773             :  * cairo_pattern_get_type:
     774             :  * @pattern: a #cairo_pattern_t
     775             :  *
     776             :  * This function returns the type a pattern.
     777             :  * See #cairo_pattern_type_t for available types.
     778             :  *
     779             :  * Return value: The type of @pattern.
     780             :  *
     781             :  * Since: 1.2
     782             :  **/
     783             : cairo_pattern_type_t
     784           0 : cairo_pattern_get_type (cairo_pattern_t *pattern)
     785             : {
     786           0 :     return pattern->type;
     787             : }
     788             : 
     789             : /**
     790             :  * cairo_pattern_status:
     791             :  * @pattern: a #cairo_pattern_t
     792             :  *
     793             :  * Checks whether an error has previously occurred for this
     794             :  * pattern.
     795             :  *
     796             :  * Return value: %CAIRO_STATUS_SUCCESS, %CAIRO_STATUS_NO_MEMORY, or
     797             :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
     798             :  **/
     799             : cairo_status_t
     800           0 : cairo_pattern_status (cairo_pattern_t *pattern)
     801             : {
     802           0 :     return pattern->status;
     803             : }
     804             : 
     805             : /**
     806             :  * cairo_pattern_destroy:
     807             :  * @pattern: a #cairo_pattern_t
     808             :  *
     809             :  * Decreases the reference count on @pattern by one. If the result is
     810             :  * zero, then @pattern and all associated resources are freed.  See
     811             :  * cairo_pattern_reference().
     812             :  **/
     813             : void
     814           0 : cairo_pattern_destroy (cairo_pattern_t *pattern)
     815             : {
     816             :     cairo_pattern_type_t type;
     817             : 
     818           0 :     if (pattern == NULL ||
     819           0 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
     820           0 :         return;
     821             : 
     822           0 :     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
     823             : 
     824           0 :     if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
     825           0 :         return;
     826             : 
     827           0 :     type = pattern->type;
     828           0 :     _cairo_pattern_fini (pattern);
     829             : 
     830             :     /* maintain a small cache of freed patterns */
     831           0 :     _freed_pool_put (&freed_pattern_pool[type], pattern);
     832             : }
     833             : slim_hidden_def (cairo_pattern_destroy);
     834             : 
     835             : /**
     836             :  * cairo_pattern_get_reference_count:
     837             :  * @pattern: a #cairo_pattern_t
     838             :  *
     839             :  * Returns the current reference count of @pattern.
     840             :  *
     841             :  * Return value: the current reference count of @pattern.  If the
     842             :  * object is a nil object, 0 will be returned.
     843             :  *
     844             :  * Since: 1.4
     845             :  **/
     846             : unsigned int
     847           0 : cairo_pattern_get_reference_count (cairo_pattern_t *pattern)
     848             : {
     849           0 :     if (pattern == NULL ||
     850           0 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
     851           0 :         return 0;
     852             : 
     853           0 :     return CAIRO_REFERENCE_COUNT_GET_VALUE (&pattern->ref_count);
     854             : }
     855             : 
     856             : /**
     857             :  * cairo_pattern_get_user_data:
     858             :  * @pattern: a #cairo_pattern_t
     859             :  * @key: the address of the #cairo_user_data_key_t the user data was
     860             :  * attached to
     861             :  *
     862             :  * Return user data previously attached to @pattern using the
     863             :  * specified key.  If no user data has been attached with the given
     864             :  * key this function returns %NULL.
     865             :  *
     866             :  * Return value: the user data previously attached or %NULL.
     867             :  *
     868             :  * Since: 1.4
     869             :  **/
     870             : void *
     871           0 : cairo_pattern_get_user_data (cairo_pattern_t             *pattern,
     872             :                              const cairo_user_data_key_t *key)
     873             : {
     874           0 :     return _cairo_user_data_array_get_data (&pattern->user_data,
     875             :                                             key);
     876             : }
     877             : 
     878             : /**
     879             :  * cairo_pattern_set_user_data:
     880             :  * @pattern: a #cairo_pattern_t
     881             :  * @key: the address of a #cairo_user_data_key_t to attach the user data to
     882             :  * @user_data: the user data to attach to the #cairo_pattern_t
     883             :  * @destroy: a #cairo_destroy_func_t which will be called when the
     884             :  * #cairo_t is destroyed or when new user data is attached using the
     885             :  * same key.
     886             :  *
     887             :  * Attach user data to @pattern.  To remove user data from a surface,
     888             :  * call this function with the key that was used to set it and %NULL
     889             :  * for @data.
     890             :  *
     891             :  * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
     892             :  * slot could not be allocated for the user data.
     893             :  *
     894             :  * Since: 1.4
     895             :  **/
     896             : cairo_status_t
     897           0 : cairo_pattern_set_user_data (cairo_pattern_t             *pattern,
     898             :                              const cairo_user_data_key_t *key,
     899             :                              void                        *user_data,
     900             :                              cairo_destroy_func_t         destroy)
     901             : {
     902           0 :     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
     903           0 :         return pattern->status;
     904             : 
     905           0 :     return _cairo_user_data_array_set_data (&pattern->user_data,
     906             :                                             key, user_data, destroy);
     907             : }
     908             : 
     909             : /* make room for at least one more color stop */
     910             : static cairo_status_t
     911           0 : _cairo_pattern_gradient_grow (cairo_gradient_pattern_t *pattern)
     912             : {
     913             :     cairo_gradient_stop_t *new_stops;
     914           0 :     int old_size = pattern->stops_size;
     915           0 :     int embedded_size = ARRAY_LENGTH (pattern->stops_embedded);
     916           0 :     int new_size = 2 * MAX (old_size, 4);
     917             : 
     918             :     /* we have a local buffer at pattern->stops_embedded.  try to fulfill the request
     919             :      * from there. */
     920           0 :     if (old_size < embedded_size) {
     921           0 :         pattern->stops = pattern->stops_embedded;
     922           0 :         pattern->stops_size = embedded_size;
     923           0 :         return CAIRO_STATUS_SUCCESS;
     924             :     }
     925             : 
     926             :     if (CAIRO_INJECT_FAULT ())
     927             :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     928             : 
     929           0 :     assert (pattern->n_stops <= pattern->stops_size);
     930             : 
     931           0 :     if (pattern->stops == pattern->stops_embedded) {
     932           0 :         new_stops = _cairo_malloc_ab (new_size, sizeof (cairo_gradient_stop_t));
     933           0 :         if (new_stops)
     934           0 :             memcpy (new_stops, pattern->stops, old_size * sizeof (cairo_gradient_stop_t));
     935             :     } else {
     936           0 :         new_stops = _cairo_realloc_ab (pattern->stops,
     937             :                                        new_size,
     938             :                                        sizeof (cairo_gradient_stop_t));
     939             :     }
     940             : 
     941           0 :     if (unlikely (new_stops == NULL))
     942           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
     943             : 
     944           0 :     pattern->stops = new_stops;
     945           0 :     pattern->stops_size = new_size;
     946             : 
     947           0 :     return CAIRO_STATUS_SUCCESS;
     948             : }
     949             : 
     950             : static void
     951           0 : _cairo_pattern_add_color_stop (cairo_gradient_pattern_t *pattern,
     952             :                                double                    offset,
     953             :                                double                    red,
     954             :                                double                    green,
     955             :                                double                    blue,
     956             :                                double                    alpha)
     957             : {
     958             :     cairo_gradient_stop_t *stops;
     959             :     unsigned int           i;
     960             : 
     961           0 :     if (pattern->n_stops >= pattern->stops_size) {
     962           0 :         cairo_status_t status = _cairo_pattern_gradient_grow (pattern);
     963           0 :         if (unlikely (status)) {
     964           0 :             status = _cairo_pattern_set_error (&pattern->base, status);
     965           0 :             return;
     966             :         }
     967             :     }
     968             : 
     969           0 :     stops = pattern->stops;
     970             : 
     971           0 :     for (i = 0; i < pattern->n_stops; i++)
     972             :     {
     973           0 :         if (offset < stops[i].offset)
     974             :         {
     975           0 :             memmove (&stops[i + 1], &stops[i],
     976           0 :                      sizeof (cairo_gradient_stop_t) * (pattern->n_stops - i));
     977             : 
     978           0 :             break;
     979             :         }
     980             :     }
     981             : 
     982           0 :     stops[i].offset = offset;
     983             : 
     984           0 :     stops[i].color.red   = red;
     985           0 :     stops[i].color.green = green;
     986           0 :     stops[i].color.blue  = blue;
     987           0 :     stops[i].color.alpha = alpha;
     988             : 
     989           0 :     stops[i].color.red_short   = _cairo_color_double_to_short (red);
     990           0 :     stops[i].color.green_short = _cairo_color_double_to_short (green);
     991           0 :     stops[i].color.blue_short  = _cairo_color_double_to_short (blue);
     992           0 :     stops[i].color.alpha_short = _cairo_color_double_to_short (alpha);
     993             : 
     994           0 :     pattern->n_stops++;
     995             : }
     996             : 
     997             : /**
     998             :  * cairo_pattern_add_color_stop_rgb:
     999             :  * @pattern: a #cairo_pattern_t
    1000             :  * @offset: an offset in the range [0.0 .. 1.0]
    1001             :  * @red: red component of color
    1002             :  * @green: green component of color
    1003             :  * @blue: blue component of color
    1004             :  *
    1005             :  * Adds an opaque color stop to a gradient pattern. The offset
    1006             :  * specifies the location along the gradient's control vector. For
    1007             :  * example, a linear gradient's control vector is from (x0,y0) to
    1008             :  * (x1,y1) while a radial gradient's control vector is from any point
    1009             :  * on the start circle to the corresponding point on the end circle.
    1010             :  *
    1011             :  * The color is specified in the same way as in cairo_set_source_rgb().
    1012             :  *
    1013             :  * If two (or more) stops are specified with identical offset values,
    1014             :  * they will be sorted according to the order in which the stops are
    1015             :  * added, (stops added earlier will compare less than stops added
    1016             :  * later). This can be useful for reliably making sharp color
    1017             :  * transitions instead of the typical blend.
    1018             :  *
    1019             :  *
    1020             :  * Note: If the pattern is not a gradient pattern, (eg. a linear or
    1021             :  * radial pattern), then the pattern will be put into an error status
    1022             :  * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
    1023             :  **/
    1024             : void
    1025           0 : cairo_pattern_add_color_stop_rgb (cairo_pattern_t *pattern,
    1026             :                                   double           offset,
    1027             :                                   double           red,
    1028             :                                   double           green,
    1029             :                                   double           blue)
    1030             : {
    1031           0 :     if (pattern->status)
    1032           0 :         return;
    1033             : 
    1034           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
    1035           0 :         pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
    1036             :     {
    1037           0 :         _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
    1038           0 :         return;
    1039             :     }
    1040             : 
    1041           0 :     offset = _cairo_restrict_value (offset, 0.0, 1.0);
    1042           0 :     red    = _cairo_restrict_value (red,    0.0, 1.0);
    1043           0 :     green  = _cairo_restrict_value (green,  0.0, 1.0);
    1044           0 :     blue   = _cairo_restrict_value (blue,   0.0, 1.0);
    1045             : 
    1046           0 :     _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
    1047             :                                    offset, red, green, blue, 1.0);
    1048             : }
    1049             : 
    1050             : /**
    1051             :  * cairo_pattern_add_color_stop_rgba:
    1052             :  * @pattern: a #cairo_pattern_t
    1053             :  * @offset: an offset in the range [0.0 .. 1.0]
    1054             :  * @red: red component of color
    1055             :  * @green: green component of color
    1056             :  * @blue: blue component of color
    1057             :  * @alpha: alpha component of color
    1058             :  *
    1059             :  * Adds a translucent color stop to a gradient pattern. The offset
    1060             :  * specifies the location along the gradient's control vector. For
    1061             :  * example, a linear gradient's control vector is from (x0,y0) to
    1062             :  * (x1,y1) while a radial gradient's control vector is from any point
    1063             :  * on the start circle to the corresponding point on the end circle.
    1064             :  *
    1065             :  * The color is specified in the same way as in cairo_set_source_rgba().
    1066             :  *
    1067             :  * If two (or more) stops are specified with identical offset values,
    1068             :  * they will be sorted according to the order in which the stops are
    1069             :  * added, (stops added earlier will compare less than stops added
    1070             :  * later). This can be useful for reliably making sharp color
    1071             :  * transitions instead of the typical blend.
    1072             :  *
    1073             :  * Note: If the pattern is not a gradient pattern, (eg. a linear or
    1074             :  * radial pattern), then the pattern will be put into an error status
    1075             :  * with a status of %CAIRO_STATUS_PATTERN_TYPE_MISMATCH.
    1076             :  */
    1077             : void
    1078           0 : cairo_pattern_add_color_stop_rgba (cairo_pattern_t *pattern,
    1079             :                                    double          offset,
    1080             :                                    double          red,
    1081             :                                    double          green,
    1082             :                                    double          blue,
    1083             :                                    double          alpha)
    1084             : {
    1085           0 :     if (pattern->status)
    1086           0 :         return;
    1087             : 
    1088           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
    1089           0 :         pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
    1090             :     {
    1091           0 :         _cairo_pattern_set_error (pattern, CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
    1092           0 :         return;
    1093             :     }
    1094             : 
    1095           0 :     offset = _cairo_restrict_value (offset, 0.0, 1.0);
    1096           0 :     red    = _cairo_restrict_value (red,    0.0, 1.0);
    1097           0 :     green  = _cairo_restrict_value (green,  0.0, 1.0);
    1098           0 :     blue   = _cairo_restrict_value (blue,   0.0, 1.0);
    1099           0 :     alpha  = _cairo_restrict_value (alpha,  0.0, 1.0);
    1100             : 
    1101           0 :     _cairo_pattern_add_color_stop ((cairo_gradient_pattern_t *) pattern,
    1102             :                                    offset, red, green, blue, alpha);
    1103             : }
    1104             : 
    1105             : /**
    1106             :  * cairo_pattern_set_matrix:
    1107             :  * @pattern: a #cairo_pattern_t
    1108             :  * @matrix: a #cairo_matrix_t
    1109             :  *
    1110             :  * Sets the pattern's transformation matrix to @matrix. This matrix is
    1111             :  * a transformation from user space to pattern space.
    1112             :  *
    1113             :  * When a pattern is first created it always has the identity matrix
    1114             :  * for its transformation matrix, which means that pattern space is
    1115             :  * initially identical to user space.
    1116             :  *
    1117             :  * Important: Please note that the direction of this transformation
    1118             :  * matrix is from user space to pattern space. This means that if you
    1119             :  * imagine the flow from a pattern to user space (and on to device
    1120             :  * space), then coordinates in that flow will be transformed by the
    1121             :  * inverse of the pattern matrix.
    1122             :  *
    1123             :  * For example, if you want to make a pattern appear twice as large as
    1124             :  * it does by default the correct code to use is:
    1125             :  *
    1126             :  * <informalexample><programlisting>
    1127             :  * cairo_matrix_init_scale (&amp;matrix, 0.5, 0.5);
    1128             :  * cairo_pattern_set_matrix (pattern, &amp;matrix);
    1129             :  * </programlisting></informalexample>
    1130             :  *
    1131             :  * Meanwhile, using values of 2.0 rather than 0.5 in the code above
    1132             :  * would cause the pattern to appear at half of its default size.
    1133             :  *
    1134             :  * Also, please note the discussion of the user-space locking
    1135             :  * semantics of cairo_set_source().
    1136             :  **/
    1137             : void
    1138           0 : cairo_pattern_set_matrix (cairo_pattern_t      *pattern,
    1139             :                           const cairo_matrix_t *matrix)
    1140             : {
    1141             :     cairo_matrix_t inverse;
    1142             :     cairo_status_t status;
    1143             : 
    1144           0 :     if (pattern->status)
    1145           0 :         return;
    1146             : 
    1147           0 :     if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
    1148           0 :         return;
    1149             : 
    1150           0 :     pattern->matrix = *matrix;
    1151             : 
    1152           0 :     inverse = *matrix;
    1153           0 :     status = cairo_matrix_invert (&inverse);
    1154           0 :     if (unlikely (status))
    1155           0 :         status = _cairo_pattern_set_error (pattern, status);
    1156             : }
    1157             : slim_hidden_def (cairo_pattern_set_matrix);
    1158             : 
    1159             : /**
    1160             :  * cairo_pattern_get_matrix:
    1161             :  * @pattern: a #cairo_pattern_t
    1162             :  * @matrix: return value for the matrix
    1163             :  *
    1164             :  * Stores the pattern's transformation matrix into @matrix.
    1165             :  **/
    1166             : void
    1167           0 : cairo_pattern_get_matrix (cairo_pattern_t *pattern, cairo_matrix_t *matrix)
    1168             : {
    1169           0 :     *matrix = pattern->matrix;
    1170           0 : }
    1171             : 
    1172             : /**
    1173             :  * cairo_pattern_set_filter:
    1174             :  * @pattern: a #cairo_pattern_t
    1175             :  * @filter: a #cairo_filter_t describing the filter to use for resizing
    1176             :  * the pattern
    1177             :  *
    1178             :  * Sets the filter to be used for resizing when using this pattern.
    1179             :  * See #cairo_filter_t for details on each filter.
    1180             :  *
    1181             :  * * Note that you might want to control filtering even when you do not
    1182             :  * have an explicit #cairo_pattern_t object, (for example when using
    1183             :  * cairo_set_source_surface()). In these cases, it is convenient to
    1184             :  * use cairo_get_source() to get access to the pattern that cairo
    1185             :  * creates implicitly. For example:
    1186             :  *
    1187             :  * <informalexample><programlisting>
    1188             :  * cairo_set_source_surface (cr, image, x, y);
    1189             :  * cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
    1190             :  * </programlisting></informalexample>
    1191             :  **/
    1192             : void
    1193           0 : cairo_pattern_set_filter (cairo_pattern_t *pattern, cairo_filter_t filter)
    1194             : {
    1195           0 :     if (pattern->status)
    1196           0 :         return;
    1197             : 
    1198           0 :     pattern->filter = filter;
    1199             : }
    1200             : 
    1201             : /**
    1202             :  * cairo_pattern_get_filter:
    1203             :  * @pattern: a #cairo_pattern_t
    1204             :  *
    1205             :  * Gets the current filter for a pattern.  See #cairo_filter_t
    1206             :  * for details on each filter.
    1207             :  *
    1208             :  * Return value: the current filter used for resizing the pattern.
    1209             :  **/
    1210             : cairo_filter_t
    1211           0 : cairo_pattern_get_filter (cairo_pattern_t *pattern)
    1212             : {
    1213           0 :     return pattern->filter;
    1214             : }
    1215             : 
    1216             : /**
    1217             :  * cairo_pattern_set_extend:
    1218             :  * @pattern: a #cairo_pattern_t
    1219             :  * @extend: a #cairo_extend_t describing how the area outside of the
    1220             :  * pattern will be drawn
    1221             :  *
    1222             :  * Sets the mode to be used for drawing outside the area of a pattern.
    1223             :  * See #cairo_extend_t for details on the semantics of each extend
    1224             :  * strategy.
    1225             :  *
    1226             :  * The default extend mode is %CAIRO_EXTEND_NONE for surface patterns
    1227             :  * and %CAIRO_EXTEND_PAD for gradient patterns.
    1228             :  **/
    1229             : void
    1230           0 : cairo_pattern_set_extend (cairo_pattern_t *pattern, cairo_extend_t extend)
    1231             : {
    1232           0 :     if (pattern->status)
    1233           0 :         return;
    1234             : 
    1235           0 :     pattern->extend = extend;
    1236             : }
    1237             : 
    1238             : /**
    1239             :  * cairo_pattern_get_extend:
    1240             :  * @pattern: a #cairo_pattern_t
    1241             :  *
    1242             :  * Gets the current extend mode for a pattern.  See #cairo_extend_t
    1243             :  * for details on the semantics of each extend strategy.
    1244             :  *
    1245             :  * Return value: the current extend strategy used for drawing the
    1246             :  * pattern.
    1247             :  **/
    1248             : cairo_extend_t
    1249           0 : cairo_pattern_get_extend (cairo_pattern_t *pattern)
    1250             : {
    1251           0 :     return pattern->extend;
    1252             : }
    1253             : slim_hidden_def (cairo_pattern_get_extend);
    1254             : 
    1255             : void
    1256           0 : _cairo_pattern_transform (cairo_pattern_t       *pattern,
    1257             :                           const cairo_matrix_t  *ctm_inverse)
    1258             : {
    1259           0 :     if (pattern->status)
    1260           0 :         return;
    1261             : 
    1262           0 :     cairo_matrix_multiply (&pattern->matrix, ctm_inverse, &pattern->matrix);
    1263             : }
    1264             : 
    1265             : static void
    1266           0 : _cairo_linear_pattern_classify (cairo_linear_pattern_t *pattern,
    1267             :                                 double                 offset_x,
    1268             :                                 double                 offset_y,
    1269             :                                 int                    width,
    1270             :                                 int                    height,
    1271             :                                 cairo_bool_t           *is_horizontal,
    1272             :                                 cairo_bool_t           *is_vertical)
    1273             : {
    1274             :     cairo_point_double_t point0, point1;
    1275             :     double a, b, c, d, tx, ty;
    1276             :     double scale, start, dx, dy;
    1277             :     cairo_fixed_t factors[3];
    1278             :     int i;
    1279             : 
    1280             :     /* To classify a pattern as horizontal or vertical, we first
    1281             :      * compute the (fixed point) factors at the corners of the
    1282             :      * pattern. We actually only need 3/4 corners, so we skip the
    1283             :      * fourth.
    1284             :      */
    1285           0 :     point0.x = _cairo_fixed_to_double (pattern->p1.x);
    1286           0 :     point0.y = _cairo_fixed_to_double (pattern->p1.y);
    1287           0 :     point1.x = _cairo_fixed_to_double (pattern->p2.x);
    1288           0 :     point1.y = _cairo_fixed_to_double (pattern->p2.y);
    1289             : 
    1290           0 :     _cairo_matrix_get_affine (&pattern->base.base.matrix,
    1291             :                               &a, &b, &c, &d, &tx, &ty);
    1292             : 
    1293           0 :     dx = point1.x - point0.x;
    1294           0 :     dy = point1.y - point0.y;
    1295           0 :     scale = dx * dx + dy * dy;
    1296           0 :     scale = (scale) ? 1.0 / scale : 1.0;
    1297             : 
    1298           0 :     start = dx * point0.x + dy * point0.y;
    1299             : 
    1300           0 :     for (i = 0; i < 3; i++) {
    1301           0 :         double qx_device = (i % 2) * (width - 1) + offset_x;
    1302           0 :         double qy_device = (i / 2) * (height - 1) + offset_y;
    1303             : 
    1304             :         /* transform fragment into pattern space */
    1305           0 :         double qx = a * qx_device + c * qy_device + tx;
    1306           0 :         double qy = b * qx_device + d * qy_device + ty;
    1307             : 
    1308           0 :         factors[i] = _cairo_fixed_from_double (((dx * qx + dy * qy) - start) * scale);
    1309             :     }
    1310             : 
    1311             :     /* We consider a pattern to be vertical if the fixed point factor
    1312             :      * at the two upper corners is the same. We could accept a small
    1313             :      * change, but determining what change is acceptable would require
    1314             :      * sorting the stops in the pattern and looking at the differences.
    1315             :      *
    1316             :      * Horizontal works the same way with the two left corners.
    1317             :      */
    1318             : 
    1319           0 :     *is_vertical = factors[1] == factors[0];
    1320           0 :     *is_horizontal = factors[2] == factors[0];
    1321           0 : }
    1322             : 
    1323             : static cairo_int_status_t
    1324           0 : _cairo_pattern_acquire_surface_for_gradient (const cairo_gradient_pattern_t *pattern,
    1325             :                                              cairo_surface_t            *dst,
    1326             :                                              int                        x,
    1327             :                                              int                        y,
    1328             :                                              unsigned int               width,
    1329             :                                              unsigned int               height,
    1330             :                                              cairo_surface_t            **out,
    1331             :                                              cairo_surface_attributes_t *attr)
    1332             : {
    1333             :     cairo_image_surface_t *image;
    1334             :     pixman_image_t        *pixman_image;
    1335             :     pixman_transform_t    pixman_transform;
    1336             :     cairo_status_t        status;
    1337           0 :     cairo_bool_t          repeat = FALSE;
    1338           0 :     cairo_bool_t          opaque = TRUE;
    1339             : 
    1340             :     pixman_gradient_stop_t pixman_stops_static[2];
    1341           0 :     pixman_gradient_stop_t *pixman_stops = pixman_stops_static;
    1342             :     unsigned int i;
    1343             :     int clone_offset_x, clone_offset_y;
    1344           0 :     cairo_matrix_t matrix = pattern->base.matrix;
    1345             : 
    1346             :     if (CAIRO_INJECT_FAULT ())
    1347             :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1348             : 
    1349           0 :     if (pattern->n_stops > ARRAY_LENGTH(pixman_stops_static)) {
    1350           0 :         pixman_stops = _cairo_malloc_ab (pattern->n_stops,
    1351             :                                          sizeof(pixman_gradient_stop_t));
    1352           0 :         if (unlikely (pixman_stops == NULL))
    1353           0 :             return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1354             :     }
    1355             : 
    1356           0 :     for (i = 0; i < pattern->n_stops; i++) {
    1357           0 :         pixman_stops[i].x = _cairo_fixed_16_16_from_double (pattern->stops[i].offset);
    1358           0 :         pixman_stops[i].color.red = pattern->stops[i].color.red_short;
    1359           0 :         pixman_stops[i].color.green = pattern->stops[i].color.green_short;
    1360           0 :         pixman_stops[i].color.blue = pattern->stops[i].color.blue_short;
    1361           0 :         pixman_stops[i].color.alpha = pattern->stops[i].color.alpha_short;
    1362           0 :         if (! CAIRO_ALPHA_SHORT_IS_OPAQUE (pixman_stops[i].color.alpha))
    1363           0 :             opaque = FALSE;
    1364             :     }
    1365             : 
    1366           0 :     if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR)
    1367             :     {
    1368           0 :         cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) pattern;
    1369             :         pixman_point_fixed_t p1, p2;
    1370             :         double x0, y0, x1, y1, maxabs;
    1371             : 
    1372             :         /*
    1373             :          * Transform the matrix to avoid overflow when converting between
    1374             :          * cairo_fixed_t and pixman_fixed_t (without incurring performance
    1375             :          * loss when the transformation is unnecessary).
    1376             :          *
    1377             :          * Having a function to compute the required transformation to
    1378             :          * "normalize" a given bounding box would be generally useful -
    1379             :          * cf linear patterns, gradient patterns, surface patterns...
    1380             :          */
    1381           0 :         x0 = _cairo_fixed_to_double (linear->p1.x);
    1382           0 :         y0 = _cairo_fixed_to_double (linear->p1.y);
    1383           0 :         x1 = _cairo_fixed_to_double (linear->p2.x);
    1384           0 :         y1 = _cairo_fixed_to_double (linear->p2.y);
    1385           0 :         cairo_matrix_transform_point (&matrix, &x0, &y0);
    1386           0 :         cairo_matrix_transform_point (&matrix, &x1, &y1);
    1387           0 :         maxabs = MAX (MAX (fabs (x0), fabs (x1)), MAX (fabs (y0), fabs (y1)));
    1388             : 
    1389             : #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
    1390           0 :         if (maxabs > PIXMAN_MAX_INT)
    1391             :         {
    1392             :             double sf;
    1393             :             cairo_matrix_t scale;
    1394             : 
    1395           0 :             sf = PIXMAN_MAX_INT / maxabs;
    1396             : 
    1397           0 :             p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
    1398           0 :             p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
    1399           0 :             p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
    1400           0 :             p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
    1401             : 
    1402             :             /* cairo_matrix_scale does a pre-scale, we want a post-scale */
    1403           0 :             cairo_matrix_init_scale (&scale, sf, sf);
    1404           0 :             cairo_matrix_multiply (&matrix, &matrix, &scale);
    1405             :         }
    1406             :         else
    1407             :         {
    1408           0 :             p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
    1409           0 :             p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
    1410           0 :             p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
    1411           0 :             p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
    1412             :         }
    1413             : 
    1414           0 :         pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
    1415             :                                                             pixman_stops,
    1416           0 :                                                             pattern->n_stops);
    1417             :     }
    1418             :     else
    1419             :     {
    1420           0 :         cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
    1421             :         pixman_point_fixed_t c1, c2;
    1422             :         pixman_fixed_t r1, r2;
    1423             : 
    1424           0 :         c1.x = _cairo_fixed_to_16_16 (radial->c1.x);
    1425           0 :         c1.y = _cairo_fixed_to_16_16 (radial->c1.y);
    1426           0 :         r1   = _cairo_fixed_to_16_16 (radial->r1);
    1427             : 
    1428           0 :         c2.x = _cairo_fixed_to_16_16 (radial->c2.x);
    1429           0 :         c2.y = _cairo_fixed_to_16_16 (radial->c2.y);
    1430           0 :         r2   = _cairo_fixed_to_16_16 (radial->r2);
    1431             : 
    1432           0 :         pixman_image = pixman_image_create_radial_gradient (&c1, &c2,
    1433             :                                                             r1, r2,
    1434             :                                                             pixman_stops,
    1435           0 :                                                             pattern->n_stops);
    1436             :     }
    1437             : 
    1438           0 :     if (pixman_stops != pixman_stops_static)
    1439           0 :         free (pixman_stops);
    1440             : 
    1441           0 :     if (unlikely (pixman_image == NULL))
    1442           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1443             : 
    1444           0 :     if (_cairo_surface_is_image (dst))
    1445             :     {
    1446           0 :         image = (cairo_image_surface_t *)
    1447             :             _cairo_image_surface_create_for_pixman_image (pixman_image,
    1448             :                                                           PIXMAN_a8r8g8b8);
    1449           0 :         if (image->base.status)
    1450             :         {
    1451           0 :             pixman_image_unref (pixman_image);
    1452           0 :             return image->base.status;
    1453             :         }
    1454             : 
    1455           0 :         attr->x_offset = attr->y_offset = 0;
    1456           0 :         attr->matrix = matrix;
    1457           0 :         attr->extend = pattern->base.extend;
    1458           0 :         attr->filter = CAIRO_FILTER_NEAREST;
    1459           0 :         attr->has_component_alpha = pattern->base.has_component_alpha;
    1460             : 
    1461           0 :         *out = &image->base;
    1462             : 
    1463           0 :         return CAIRO_STATUS_SUCCESS;
    1464             :     }
    1465             : 
    1466           0 :     if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
    1467             :         cairo_bool_t is_horizontal;
    1468             :         cairo_bool_t is_vertical;
    1469             : 
    1470           0 :         _cairo_linear_pattern_classify ((cairo_linear_pattern_t *)pattern,
    1471             :                                         x, y, width, height,
    1472             :                                         &is_horizontal, &is_vertical);
    1473           0 :         if (is_horizontal) {
    1474           0 :             height = 1;
    1475           0 :             repeat = TRUE;
    1476             :         }
    1477             :         /* width-1 repeating patterns are quite slow with scan-line based
    1478             :          * compositing code, so we use a wider strip and spend some extra
    1479             :          * expense in computing the gradient. It's possible that for narrow
    1480             :          * gradients we'd be better off using a 2 or 4 pixel strip; the
    1481             :          * wider the gradient, the more it's worth spending extra time
    1482             :          * computing a sample.
    1483             :          */
    1484           0 :         if (is_vertical && width > 8) {
    1485           0 :             width = 8;
    1486           0 :             repeat = TRUE;
    1487             :         }
    1488             :     }
    1489             : 
    1490           0 :     if (! pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR,
    1491             :                                    NULL, 0))
    1492             :     {
    1493           0 :         pixman_image_unref (pixman_image);
    1494           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1495             :     }
    1496             : 
    1497           0 :     image = (cairo_image_surface_t *)
    1498           0 :         cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
    1499           0 :     if (image->base.status) {
    1500           0 :         pixman_image_unref (pixman_image);
    1501           0 :         return image->base.status;
    1502             :     }
    1503             : 
    1504           0 :     _cairo_matrix_to_pixman_matrix (&matrix, &pixman_transform,
    1505             :                                     width/2., height/2.);
    1506           0 :     if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
    1507           0 :         cairo_surface_destroy (&image->base);
    1508           0 :         pixman_image_unref (pixman_image);
    1509           0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
    1510             :     }
    1511             : 
    1512           0 :     switch (pattern->base.extend) {
    1513             :     case CAIRO_EXTEND_NONE:
    1514           0 :         pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NONE);
    1515           0 :         break;
    1516             :     case CAIRO_EXTEND_REPEAT:
    1517           0 :         pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL);
    1518           0 :         break;
    1519             :     case CAIRO_EXTEND_REFLECT:
    1520           0 :         pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT);
    1521           0 :         break;
    1522             :     case CAIRO_EXTEND_PAD:
    1523           0 :         pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD);
    1524           0 :         break;
    1525             :     }
    1526             : 
    1527           0 :     pixman_image_composite32 (PIXMAN_OP_SRC,
    1528             :                               pixman_image,
    1529             :                               NULL,
    1530             :                               image->pixman_image,
    1531             :                               x, y,
    1532             :                               0, 0,
    1533             :                               0, 0,
    1534             :                               width, height);
    1535             : 
    1536           0 :     pixman_image_unref (pixman_image);
    1537             : 
    1538             :     _cairo_debug_check_image_surface_is_defined (&image->base);
    1539             : 
    1540           0 :     status = _cairo_surface_clone_similar (dst, &image->base,
    1541             :                                            0, 0, width, height,
    1542             :                                            &clone_offset_x,
    1543             :                                            &clone_offset_y,
    1544             :                                            out);
    1545             : 
    1546           0 :     cairo_surface_destroy (&image->base);
    1547             : 
    1548           0 :     attr->x_offset = -x;
    1549           0 :     attr->y_offset = -y;
    1550           0 :     cairo_matrix_init_identity (&attr->matrix);
    1551           0 :     attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
    1552           0 :     attr->filter = CAIRO_FILTER_NEAREST;
    1553           0 :     attr->has_component_alpha = pattern->base.has_component_alpha;
    1554             : 
    1555           0 :     return status;
    1556             : }
    1557             : 
    1558             : /* We maintain a small cache here, because we don't want to constantly
    1559             :  * recreate surfaces for simple solid colors. */
    1560             : #define MAX_SURFACE_CACHE_SIZE 16
    1561             : static struct {
    1562             :     struct _cairo_pattern_solid_surface_cache{
    1563             :         cairo_color_t    color;
    1564             :         cairo_surface_t *surface;
    1565             :     } cache[MAX_SURFACE_CACHE_SIZE];
    1566             :     int size;
    1567             : } solid_surface_cache;
    1568             : 
    1569             : static cairo_bool_t
    1570           0 : _cairo_pattern_solid_surface_matches (
    1571             :         const struct _cairo_pattern_solid_surface_cache     *cache,
    1572             :         const cairo_solid_pattern_t                         *pattern,
    1573             :         cairo_surface_t                                     *dst)
    1574             : {
    1575           0 :     if (cairo_surface_get_content (cache->surface) != _cairo_color_get_content (&pattern->color))
    1576           0 :         return FALSE;
    1577             : 
    1578           0 :     if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
    1579           0 :         return FALSE;
    1580             : 
    1581           0 :     if (! _cairo_surface_is_similar (cache->surface, dst))
    1582           0 :         return FALSE;
    1583             : 
    1584           0 :     return TRUE;
    1585             : }
    1586             : 
    1587             : static cairo_bool_t
    1588           0 : _cairo_pattern_solid_surface_matches_color (
    1589             :         const struct _cairo_pattern_solid_surface_cache     *cache,
    1590             :         const cairo_solid_pattern_t                         *pattern,
    1591             :         cairo_surface_t                                     *dst)
    1592             : {
    1593           0 :     if (! _cairo_color_equal (&cache->color, &pattern->color))
    1594           0 :         return FALSE;
    1595             : 
    1596           0 :     return _cairo_pattern_solid_surface_matches (cache, pattern, dst);
    1597             : }
    1598             : 
    1599             : static cairo_int_status_t
    1600           0 : _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t        *pattern,
    1601             :                                           cairo_surface_t            *dst,
    1602             :                                           int                        x,
    1603             :                                           int                        y,
    1604             :                                           unsigned int               width,
    1605             :                                           unsigned int               height,
    1606             :                                           cairo_surface_t            **out,
    1607             :                                           cairo_surface_attributes_t *attribs)
    1608             : {
    1609             :     static int i;
    1610             : 
    1611           0 :     cairo_surface_t *surface, *to_destroy = NULL;
    1612             :     cairo_status_t   status;
    1613             : 
    1614           0 :     CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
    1615             : 
    1616             :     /* Check cache first */
    1617           0 :     if (i < solid_surface_cache.size &&
    1618           0 :         _cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
    1619             :                                                     pattern,
    1620             :                                                     dst))
    1621             :     {
    1622           0 :         goto DONE;
    1623             :     }
    1624             : 
    1625           0 :     for (i = 0 ; i < solid_surface_cache.size; i++) {
    1626           0 :         if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
    1627             :                                                         pattern,
    1628             :                                                         dst))
    1629             :         {
    1630           0 :             goto DONE;
    1631             :         }
    1632             :     }
    1633             : 
    1634             :     /* Choose a surface to repaint/evict */
    1635           0 :     surface = NULL;
    1636           0 :     if (solid_surface_cache.size == MAX_SURFACE_CACHE_SIZE) {
    1637           0 :         i = rand () % MAX_SURFACE_CACHE_SIZE;
    1638           0 :         surface = solid_surface_cache.cache[i].surface;
    1639             : 
    1640           0 :         if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
    1641             :                                                   pattern,
    1642             :                                                   dst))
    1643             :         {
    1644             :             /* Reuse the surface instead of evicting */
    1645           0 :             status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
    1646           0 :             if (unlikely (status))
    1647           0 :                 goto EVICT;
    1648             : 
    1649           0 :             cairo_surface_reference (surface);
    1650             :         }
    1651             :         else
    1652             :         {
    1653             :           EVICT:
    1654           0 :             surface = NULL;
    1655             :         }
    1656             :     }
    1657             : 
    1658           0 :     if (surface == NULL) {
    1659             :         /* Not cached, need to create new */
    1660           0 :         surface = _cairo_surface_create_solid_pattern_surface (dst, pattern);
    1661           0 :         if (surface == NULL) {
    1662           0 :             status = CAIRO_INT_STATUS_UNSUPPORTED;
    1663           0 :             goto UNLOCK;
    1664             :         }
    1665           0 :         if (unlikely (surface->status)) {
    1666           0 :             status = surface->status;
    1667           0 :             goto UNLOCK;
    1668             :         }
    1669             : 
    1670           0 :         if (unlikely (! _cairo_surface_is_similar (surface, dst)))
    1671             :         {
    1672             :             /* In the rare event of a substitute surface being returned,
    1673             :              * don't cache the fallback.
    1674             :              */
    1675           0 :             *out = surface;
    1676           0 :             goto NOCACHE;
    1677             :         }
    1678             :     }
    1679             : 
    1680           0 :     if (i == solid_surface_cache.size)
    1681           0 :         solid_surface_cache.size++;
    1682             : 
    1683           0 :     to_destroy = solid_surface_cache.cache[i].surface;
    1684           0 :     solid_surface_cache.cache[i].surface = surface;
    1685           0 :     solid_surface_cache.cache[i].color   = pattern->color;
    1686             : 
    1687             : DONE:
    1688           0 :     *out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
    1689             : 
    1690             : NOCACHE:
    1691           0 :     attribs->x_offset = attribs->y_offset = 0;
    1692           0 :     cairo_matrix_init_identity (&attribs->matrix);
    1693           0 :     attribs->extend = CAIRO_EXTEND_REPEAT;
    1694           0 :     attribs->filter = CAIRO_FILTER_NEAREST;
    1695           0 :     attribs->has_component_alpha = pattern->base.has_component_alpha;
    1696             : 
    1697           0 :     status = CAIRO_STATUS_SUCCESS;
    1698             : 
    1699             : UNLOCK:
    1700           0 :     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
    1701             : 
    1702           0 :     if (to_destroy)
    1703           0 :       cairo_surface_destroy (to_destroy);
    1704             : 
    1705           0 :     return status;
    1706             : }
    1707             : 
    1708             : static void
    1709           0 : _cairo_pattern_reset_solid_surface_cache (void)
    1710             : {
    1711           0 :     CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
    1712             : 
    1713             :     /* remove surfaces starting from the end so that solid_surface_cache.cache
    1714             :      * is always in a consistent state when we release the mutex. */
    1715           0 :     while (solid_surface_cache.size) {
    1716             :         cairo_surface_t *surface;
    1717             : 
    1718           0 :         solid_surface_cache.size--;
    1719           0 :         surface = solid_surface_cache.cache[solid_surface_cache.size].surface;
    1720           0 :         solid_surface_cache.cache[solid_surface_cache.size].surface = NULL;
    1721             : 
    1722             :         /* release the lock to avoid the possibility of a recursive
    1723             :          * deadlock when the surface destroy closure gets called */
    1724           0 :         CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
    1725           0 :         cairo_surface_destroy (surface);
    1726           0 :         CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
    1727             :     }
    1728             : 
    1729           0 :     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
    1730           0 : }
    1731             : 
    1732             : static void
    1733           0 : _extents_to_linear_parameter (const cairo_linear_pattern_t *linear,
    1734             :                               const cairo_rectangle_int_t *extents,
    1735             :                               double t[2])
    1736             : {
    1737             :     double t0, tdx, tdy;
    1738             :     double p1x, p1y, pdx, pdy, invsqnorm;
    1739             : 
    1740           0 :     p1x = _cairo_fixed_to_double (linear->p1.x);
    1741           0 :     p1y = _cairo_fixed_to_double (linear->p1.y);
    1742           0 :     pdx = _cairo_fixed_to_double (linear->p2.x) - p1x;
    1743           0 :     pdy = _cairo_fixed_to_double (linear->p2.y) - p1y;
    1744           0 :     invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
    1745           0 :     pdx *= invsqnorm;
    1746           0 :     pdy *= invsqnorm;
    1747             : 
    1748           0 :     t0 = (extents->x - p1x) * pdx + (extents->y - p1y) * pdy;
    1749           0 :     tdx = extents->width * pdx;
    1750           0 :     tdy = extents->height * pdy;
    1751             : 
    1752           0 :     t[0] = t[1] = t0;
    1753           0 :     if (tdx < 0)
    1754           0 :         t[0] += tdx;
    1755             :     else
    1756           0 :         t[1] += tdx;
    1757             : 
    1758           0 :     if (tdy < 0)
    1759           0 :         t[0] += tdy;
    1760             :     else
    1761           0 :         t[1] += tdy;
    1762           0 : }
    1763             : 
    1764             : static cairo_bool_t
    1765           0 : _linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
    1766             : {
    1767           0 :     return linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y;
    1768             : }
    1769             : 
    1770             : static cairo_bool_t
    1771           0 : _radial_pattern_is_degenerate (const cairo_radial_pattern_t *radial)
    1772             : {
    1773           0 :     return radial->r1 == radial->r2 &&
    1774           0 :         (radial->r1 == 0 /* && radial->r2 == 0 */ ||
    1775           0 :          (radial->c1.x == radial->c2.x && radial->c1.y == radial->c2.y));
    1776             : }
    1777             : 
    1778             : static cairo_bool_t
    1779           0 : _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
    1780             :                     const cairo_rectangle_int_t *extents)
    1781             : {
    1782             :     unsigned int i;
    1783             : 
    1784           0 :     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
    1785             :             gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
    1786             : 
    1787           0 :     if (gradient->n_stops == 0 ||
    1788           0 :         (gradient->base.extend == CAIRO_EXTEND_NONE &&
    1789           0 :          gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
    1790           0 :         return TRUE;
    1791             : 
    1792             :     /* Check if the extents intersect the drawn part of the pattern. */
    1793           0 :     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
    1794           0 :         if (gradient->base.extend == CAIRO_EXTEND_NONE) {
    1795           0 :             cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
    1796             :             /* EXTEND_NONE degenerate linear gradients are clear */
    1797           0 :             if (_linear_pattern_is_degenerate (linear))
    1798           0 :                 return TRUE;
    1799             : 
    1800           0 :             if (extents != NULL) {
    1801             :                 double t[2];
    1802           0 :                 _extents_to_linear_parameter (linear, extents, t);
    1803           0 :                 if ((t[0] <= 0.0 && t[1] <= 0.0) || (t[0] >= 1.0 && t[1] >= 1.0))
    1804           0 :                     return TRUE;
    1805             :             }
    1806             :         }
    1807             :     } else {
    1808           0 :         cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
    1809             :         /* degenerate radial gradients are clear */
    1810           0 :         if (_radial_pattern_is_degenerate (radial) && FALSE)
    1811             :             return TRUE;
    1812             :         /* TODO: check actual intersection */
    1813             :     }
    1814             : 
    1815           0 :     for (i = 0; i < gradient->n_stops; i++)
    1816           0 :         if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
    1817           0 :             return FALSE;
    1818             : 
    1819           0 :     return TRUE;
    1820             : }
    1821             : 
    1822             : /**
    1823             :  * _cairo_gradient_pattern_is_solid
    1824             :  *
    1825             :  * Convenience function to determine whether a gradient pattern is
    1826             :  * a solid color within the given extents. In this case the color
    1827             :  * argument is initialized to the color the pattern represents.
    1828             :  * This functions doesn't handle completely transparent gradients,
    1829             :  * thus it should be called only after _cairo_pattern_is_clear has
    1830             :  * returned FALSE.
    1831             :  *
    1832             :  * Return value: %TRUE if the pattern is a solid color.
    1833             :  **/
    1834             : cairo_bool_t
    1835           0 : _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
    1836             :                                   const cairo_rectangle_int_t *extents,
    1837             :                                   cairo_color_t *color)
    1838             : {
    1839             :     unsigned int i;
    1840             : 
    1841           0 :     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
    1842             :             gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
    1843             : 
    1844             :     /* TODO: radial, degenerate linear */
    1845           0 :     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
    1846           0 :         if (gradient->base.extend == CAIRO_EXTEND_NONE) {
    1847           0 :             cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
    1848             :             double t[2];
    1849             : 
    1850             :             /* We already know that the pattern is not clear, thus if some
    1851             :              * part of it is clear, the whole is not solid.
    1852             :              */
    1853             : 
    1854           0 :             if (extents == NULL)
    1855           0 :                 return FALSE;
    1856             : 
    1857           0 :             _extents_to_linear_parameter (linear, extents, t);
    1858           0 :             if (t[0] < 0.0 || t[1] > 1.0)
    1859           0 :                 return FALSE;
    1860             :         }
    1861             :     }
    1862             : 
    1863           0 :     for (i = 1; i < gradient->n_stops; i++)
    1864           0 :         if (! _cairo_color_stop_equal (&gradient->stops[0].color,
    1865           0 :                                        &gradient->stops[i].color))
    1866           0 :             return FALSE;
    1867             : 
    1868           0 :     _cairo_color_init_rgba (color,
    1869           0 :                             gradient->stops[0].color.red,
    1870           0 :                             gradient->stops[0].color.green,
    1871           0 :                             gradient->stops[0].color.blue,
    1872           0 :                             gradient->stops[0].color.alpha);
    1873             : 
    1874           0 :     return TRUE;
    1875             : }
    1876             : 
    1877             : /**
    1878             :  * _cairo_pattern_is_opaque_solid
    1879             :  *
    1880             :  * Convenience function to determine whether a pattern is an opaque
    1881             :  * (alpha==1.0) solid color pattern. This is done by testing whether
    1882             :  * the pattern's alpha value when converted to a byte is 255, so if a
    1883             :  * backend actually supported deep alpha channels this function might
    1884             :  * not do the right thing.
    1885             :  *
    1886             :  * Return value: %TRUE if the pattern is an opaque, solid color.
    1887             :  **/
    1888             : cairo_bool_t
    1889           0 : _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
    1890             : {
    1891             :     cairo_solid_pattern_t *solid;
    1892             : 
    1893           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
    1894           0 :         return FALSE;
    1895             : 
    1896           0 :     solid = (cairo_solid_pattern_t *) pattern;
    1897             : 
    1898           0 :     return CAIRO_COLOR_IS_OPAQUE (&solid->color);
    1899             : }
    1900             : 
    1901             : static cairo_bool_t
    1902           0 : _surface_is_opaque (const cairo_surface_pattern_t *pattern,
    1903             :                     const cairo_rectangle_int_t *r)
    1904             : {
    1905           0 :     if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
    1906           0 :         return FALSE;
    1907             : 
    1908           0 :     if (pattern->base.extend != CAIRO_EXTEND_NONE)
    1909           0 :         return TRUE;
    1910             : 
    1911           0 :     if (r != NULL) {
    1912             :         cairo_rectangle_int_t extents;
    1913             : 
    1914           0 :         if (! _cairo_surface_get_extents (pattern->surface, &extents))
    1915           0 :             return TRUE;
    1916             : 
    1917           0 :         if (r->x >= extents.x &&
    1918           0 :             r->y >= extents.y &&
    1919           0 :             r->x + r->width <= extents.x + extents.width &&
    1920           0 :             r->y + r->height <= extents.y + extents.height)
    1921             :         {
    1922           0 :             return TRUE;
    1923             :         }
    1924             :     }
    1925             : 
    1926           0 :     return FALSE;
    1927             : }
    1928             : 
    1929             : static cairo_bool_t
    1930           0 : _surface_is_clear (const cairo_surface_pattern_t *pattern)
    1931             : {
    1932             :     cairo_rectangle_int_t extents;
    1933             : 
    1934           0 :     if (_cairo_surface_get_extents (pattern->surface, &extents) &&
    1935           0 :         (extents.width == 0 || extents.height == 0))
    1936           0 :         return TRUE;
    1937             : 
    1938           0 :     return pattern->surface->is_clear &&
    1939           0 :         pattern->surface->content & CAIRO_CONTENT_ALPHA;
    1940             : }
    1941             : 
    1942             : static cairo_bool_t
    1943           0 : _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
    1944             :                      const cairo_rectangle_int_t *extents)
    1945             : {
    1946             :     unsigned int i;
    1947             : 
    1948           0 :     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
    1949             :             gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
    1950             : 
    1951           0 :     if (gradient->n_stops == 0 ||
    1952           0 :         (gradient->base.extend == CAIRO_EXTEND_NONE &&
    1953           0 :          gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
    1954           0 :         return FALSE;
    1955             : 
    1956           0 :     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
    1957           0 :         if (gradient->base.extend == CAIRO_EXTEND_NONE) {
    1958             :             double t[2];
    1959           0 :             cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
    1960             : 
    1961             :             /* EXTEND_NONE degenerate radial gradients are clear */
    1962           0 :             if (_linear_pattern_is_degenerate (linear))
    1963           0 :                 return FALSE;
    1964             : 
    1965           0 :             if (extents == NULL)
    1966           0 :                 return FALSE;
    1967             : 
    1968           0 :             _extents_to_linear_parameter (linear, extents, t);
    1969           0 :             if (t[0] < 0.0 || t[1] > 1.0)
    1970           0 :                 return FALSE;
    1971             :         }
    1972             :     }
    1973             : 
    1974           0 :     for (i = 0; i < gradient->n_stops; i++)
    1975           0 :         if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
    1976           0 :             return FALSE;
    1977             : 
    1978           0 :     return TRUE;
    1979             : }
    1980             : 
    1981             : /**
    1982             :  * _cairo_pattern_is_opaque
    1983             :  *
    1984             :  * Convenience function to determine whether a pattern is an opaque
    1985             :  * pattern (of any type). The same caveats that apply to
    1986             :  * _cairo_pattern_is_opaque_solid apply here as well.
    1987             :  *
    1988             :  * Return value: %TRUE if the pattern is a opaque.
    1989             :  **/
    1990             : cairo_bool_t
    1991           0 : _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
    1992             :                           const cairo_rectangle_int_t *extents)
    1993             : {
    1994             :     const cairo_pattern_union_t *pattern;
    1995             : 
    1996           0 :     if (abstract_pattern->has_component_alpha)
    1997           0 :         return FALSE;
    1998             : 
    1999           0 :     pattern = (cairo_pattern_union_t *) abstract_pattern;
    2000           0 :     switch (pattern->base.type) {
    2001             :     case CAIRO_PATTERN_TYPE_SOLID:
    2002           0 :         return _cairo_pattern_is_opaque_solid (abstract_pattern);
    2003             :     case CAIRO_PATTERN_TYPE_SURFACE:
    2004           0 :         return _surface_is_opaque (&pattern->surface, extents);
    2005             :     case CAIRO_PATTERN_TYPE_LINEAR:
    2006             :     case CAIRO_PATTERN_TYPE_RADIAL:
    2007           0 :         return _gradient_is_opaque (&pattern->gradient.base, extents);
    2008             :     }
    2009             : 
    2010           0 :     ASSERT_NOT_REACHED;
    2011           0 :     return FALSE;
    2012             : }
    2013             : 
    2014             : cairo_bool_t
    2015           0 : _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
    2016             : {
    2017             :     const cairo_pattern_union_t *pattern;
    2018             : 
    2019           0 :     if (abstract_pattern->has_component_alpha)
    2020           0 :         return FALSE;
    2021             : 
    2022           0 :     pattern = (cairo_pattern_union_t *) abstract_pattern;
    2023           0 :     switch (pattern->type) {
    2024             :     case CAIRO_PATTERN_TYPE_SOLID:
    2025           0 :         return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
    2026             :     case CAIRO_PATTERN_TYPE_SURFACE:
    2027           0 :         return _surface_is_clear (&pattern->surface);
    2028             :     case CAIRO_PATTERN_TYPE_LINEAR:
    2029             :     case CAIRO_PATTERN_TYPE_RADIAL:
    2030           0 :         return _gradient_is_clear (&pattern->gradient.base, NULL);
    2031             :     }
    2032             : 
    2033           0 :     ASSERT_NOT_REACHED;
    2034           0 :     return FALSE;
    2035             : }
    2036             : 
    2037             : /**
    2038             :  * _cairo_pattern_analyze_filter:
    2039             :  * @pattern: surface pattern
    2040             :  * @pad_out: location to store necessary padding in the source image, or %NULL
    2041             :  * Returns: the optimized #cairo_filter_t to use with @pattern.
    2042             :  *
    2043             :  * Analyze the filter to determine how much extra needs to be sampled
    2044             :  * from the source image to account for the filter radius and whether
    2045             :  * we can optimize the filter to a simpler value.
    2046             :  *
    2047             :  * XXX: We don't actually have any way of querying the backend for
    2048             :  *      the filter radius, so we just guess base on what we know that
    2049             :  *      backends do currently (see bug #10508)
    2050             :  */
    2051             : cairo_filter_t
    2052           0 : _cairo_pattern_analyze_filter (const cairo_pattern_t    *pattern,
    2053             :                                double                   *pad_out)
    2054             : {
    2055             :     double pad;
    2056             :     cairo_filter_t optimized_filter;
    2057             : 
    2058           0 :     switch (pattern->filter) {
    2059             :     case CAIRO_FILTER_GOOD:
    2060             :     case CAIRO_FILTER_BEST:
    2061             :     case CAIRO_FILTER_BILINEAR:
    2062             :         /* If source pixels map 1:1 onto destination pixels, we do
    2063             :          * not need to filter (and do not want to filter, since it
    2064             :          * will cause blurriness)
    2065             :          */
    2066           0 :         if (_cairo_matrix_is_pixel_exact (&pattern->matrix)) {
    2067           0 :             pad = 0.;
    2068           0 :             optimized_filter = CAIRO_FILTER_NEAREST;
    2069             :         } else {
    2070             :             /* 0.5 is enough for a bilinear filter. It's possible we
    2071             :              * should defensively use more for CAIRO_FILTER_BEST, but
    2072             :              * without a single example, it's hard to know how much
    2073             :              * more would be defensive...
    2074             :              */
    2075           0 :             pad = 0.5;
    2076           0 :             optimized_filter = pattern->filter;
    2077             :         }
    2078           0 :         break;
    2079             : 
    2080             :     case CAIRO_FILTER_FAST:
    2081             :     case CAIRO_FILTER_NEAREST:
    2082             :     case CAIRO_FILTER_GAUSSIAN:
    2083             :     default:
    2084           0 :         pad = 0.;
    2085           0 :         optimized_filter = pattern->filter;
    2086           0 :         break;
    2087             :     }
    2088             : 
    2089           0 :     if (pad_out)
    2090           0 :         *pad_out = pad;
    2091             : 
    2092           0 :     return optimized_filter;
    2093             : }
    2094             : 
    2095             : 
    2096             : static double
    2097           0 : _pixman_nearest_sample (double d)
    2098             : {
    2099           0 :     return ceil (d - .5);
    2100             : }
    2101             : 
    2102             : static cairo_int_status_t
    2103           0 : _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pattern,
    2104             :                                             cairo_surface_t            *dst,
    2105             :                                             int                        x,
    2106             :                                             int                        y,
    2107             :                                             unsigned int               width,
    2108             :                                             unsigned int               height,
    2109             :                                             unsigned int               flags,
    2110             :                                             cairo_surface_t            **out,
    2111             :                                             cairo_surface_attributes_t *attr)
    2112             : {
    2113             :     cairo_surface_t *surface;
    2114             :     cairo_rectangle_int_t extents;
    2115             :     cairo_rectangle_int_t sampled_area;
    2116             :     double x1, y1, x2, y2;
    2117             :     int tx, ty;
    2118             :     double pad;
    2119             :     cairo_bool_t is_identity;
    2120             :     cairo_bool_t is_empty;
    2121             :     cairo_bool_t is_bounded;
    2122             :     cairo_int_status_t status;
    2123             : 
    2124           0 :     surface = cairo_surface_reference (pattern->surface);
    2125             : 
    2126           0 :     is_identity = FALSE;
    2127           0 :     attr->matrix = pattern->base.matrix;
    2128           0 :     attr->extend = pattern->base.extend;
    2129           0 :     attr->filter = _cairo_pattern_analyze_filter (&pattern->base, &pad);
    2130           0 :     attr->has_component_alpha = pattern->base.has_component_alpha;
    2131             : 
    2132           0 :     attr->x_offset = attr->y_offset = tx = ty = 0;
    2133           0 :     if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
    2134           0 :         cairo_matrix_init_identity (&attr->matrix);
    2135           0 :         attr->x_offset = tx;
    2136           0 :         attr->y_offset = ty;
    2137           0 :         is_identity = TRUE;
    2138           0 :     } else if (attr->filter == CAIRO_FILTER_NEAREST) {
    2139             :         /*
    2140             :          * For NEAREST, we can remove the fractional translation component
    2141             :          * from the transformation - this ensures that the pattern will always
    2142             :          * hit fast-paths in the backends for simple transformations that
    2143             :          * become (almost) identity, without loss of quality.
    2144             :          */
    2145           0 :         attr->matrix.x0 = 0;
    2146           0 :         attr->matrix.y0 = 0;
    2147           0 :         if (_cairo_matrix_is_pixel_exact (&attr->matrix)) {
    2148             :             /* The rounding here is rather peculiar as it needs to match the
    2149             :              * rounding performed on the sample coordinate used by pixman.
    2150             :              */
    2151           0 :             attr->matrix.x0 = _pixman_nearest_sample (pattern->base.matrix.x0);
    2152           0 :             attr->matrix.y0 = _pixman_nearest_sample (pattern->base.matrix.y0);
    2153             :         } else {
    2154           0 :             attr->matrix.x0 = pattern->base.matrix.x0;
    2155           0 :             attr->matrix.y0 = pattern->base.matrix.y0;
    2156             :         }
    2157             : 
    2158           0 :         if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
    2159           0 :             cairo_matrix_init_identity (&attr->matrix);
    2160           0 :             attr->x_offset = tx;
    2161           0 :             attr->y_offset = ty;
    2162           0 :             is_identity = TRUE;
    2163             :         }
    2164             :     }
    2165             : 
    2166             :     /* XXX: Hack:
    2167             :      *
    2168             :      * The way we currently support CAIRO_EXTEND_REFLECT is to create
    2169             :      * an image twice bigger on each side, and create a pattern of four
    2170             :      * images such that the new image, when repeated, has the same effect
    2171             :      * of reflecting the original pattern.
    2172             :      */
    2173           0 :     if (flags & CAIRO_PATTERN_ACQUIRE_NO_REFLECT &&
    2174           0 :         attr->extend == CAIRO_EXTEND_REFLECT)
    2175             :     {
    2176             :         cairo_t *cr;
    2177             :         cairo_surface_t *src;
    2178             :         int w, h;
    2179             : 
    2180           0 :         is_bounded = _cairo_surface_get_extents (surface, &extents);
    2181           0 :         assert (is_bounded);
    2182             : 
    2183           0 :         status = _cairo_surface_clone_similar (dst, surface,
    2184             :                                                extents.x, extents.y,
    2185             :                                                extents.width, extents.height,
    2186             :                                                &extents.x, &extents.y, &src);
    2187           0 :         if (unlikely (status))
    2188           0 :             goto BAIL;
    2189             : 
    2190           0 :         w = 2 * extents.width;
    2191           0 :         h = 2 * extents.height;
    2192             : 
    2193           0 :         if (is_identity) {
    2194           0 :             attr->x_offset = -x;
    2195           0 :             x += tx;
    2196           0 :             while (x <= -w)
    2197           0 :                 x += w;
    2198           0 :             while (x >= w)
    2199           0 :                 x -= w;
    2200           0 :             extents.x += x;
    2201           0 :             tx = x = 0;
    2202             : 
    2203           0 :             attr->y_offset = -y;
    2204           0 :             y += ty;
    2205           0 :             while (y <= -h)
    2206           0 :                 y += h;
    2207           0 :             while (y >= h)
    2208           0 :                 y -= h;
    2209           0 :             extents.y += y;
    2210           0 :             ty = y = 0;
    2211             :         }
    2212             : 
    2213           0 :         cairo_surface_destroy (surface);
    2214           0 :         surface = _cairo_surface_create_similar_solid (dst,
    2215             :                                                        dst->content, w, h,
    2216             :                                                        CAIRO_COLOR_TRANSPARENT,
    2217             :                                                        FALSE);
    2218           0 :         if (surface == NULL)
    2219           0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
    2220           0 :         if (unlikely (surface->status)) {
    2221           0 :             cairo_surface_destroy (src);
    2222           0 :             return surface->status;
    2223             :         }
    2224             : 
    2225           0 :         surface->device_transform = pattern->surface->device_transform;
    2226           0 :         surface->device_transform_inverse = pattern->surface->device_transform_inverse;
    2227             : 
    2228           0 :         cr = cairo_create (surface);
    2229             : 
    2230           0 :         cairo_set_source_surface (cr, src, -extents.x, -extents.y);
    2231           0 :         cairo_paint (cr);
    2232             : 
    2233           0 :         cairo_scale (cr, -1, +1);
    2234           0 :         cairo_set_source_surface (cr, src, extents.x-w, -extents.y);
    2235           0 :         cairo_paint (cr);
    2236           0 :         cairo_set_source_surface (cr, src, extents.x, -extents.y);
    2237           0 :         cairo_paint (cr);
    2238             : 
    2239           0 :         cairo_scale (cr, +1, -1);
    2240           0 :         cairo_set_source_surface (cr, src, extents.x-w, extents.y-h);
    2241           0 :         cairo_paint (cr);
    2242           0 :         cairo_set_source_surface (cr, src, extents.x, extents.y-h);
    2243           0 :         cairo_paint (cr);
    2244           0 :         cairo_set_source_surface (cr, src, extents.x-w, extents.y);
    2245           0 :         cairo_paint (cr);
    2246           0 :         cairo_set_source_surface (cr, src, extents.x, extents.y);
    2247           0 :         cairo_paint (cr);
    2248             : 
    2249           0 :         cairo_scale (cr, -1, +1);
    2250           0 :         cairo_set_source_surface (cr, src, -extents.x, extents.y-h);
    2251           0 :         cairo_paint (cr);
    2252           0 :         cairo_set_source_surface (cr, src, -extents.x, extents.y);
    2253           0 :         cairo_paint (cr);
    2254             : 
    2255           0 :         status = cairo_status (cr);
    2256           0 :         cairo_destroy (cr);
    2257             : 
    2258           0 :         cairo_surface_destroy (src);
    2259             : 
    2260           0 :         if (unlikely (status))
    2261           0 :             goto BAIL;
    2262             : 
    2263           0 :         attr->extend = CAIRO_EXTEND_REPEAT;
    2264             :     }
    2265             : 
    2266             :     /* We first transform the rectangle to the coordinate space of the
    2267             :      * source surface so that we only need to clone that portion of the
    2268             :      * surface that will be read.
    2269             :      */
    2270           0 :     x1 = x;
    2271           0 :     y1 = y;
    2272           0 :     x2 = x + (int) width;
    2273           0 :     y2 = y + (int) height;
    2274           0 :     if (! is_identity) {
    2275           0 :         _cairo_matrix_transform_bounding_box (&attr->matrix,
    2276             :                                               &x1, &y1, &x2, &y2,
    2277             :                                               NULL);
    2278             :     }
    2279             : 
    2280           0 :     sampled_area.x = floor (x1 - pad);
    2281           0 :     sampled_area.y = floor (y1 - pad);
    2282           0 :     sampled_area.width  = ceil (x2 + pad) - sampled_area.x;
    2283           0 :     sampled_area.height = ceil (y2 + pad) - sampled_area.y;
    2284             : 
    2285           0 :     sampled_area.x += tx;
    2286           0 :     sampled_area.y += ty;
    2287             : 
    2288           0 :     if ( _cairo_surface_get_extents (surface, &extents)) {
    2289           0 :         if (attr->extend == CAIRO_EXTEND_NONE) {
    2290             :             /* Never acquire a larger area than the source itself */
    2291           0 :             is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
    2292             :         } else {
    2293           0 :             int trim = 0;
    2294             : 
    2295           0 :             if (sampled_area.x >= extents.x &&
    2296           0 :                 sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width)
    2297             :             {
    2298             :                 /* source is horizontally contained within extents, trim */
    2299           0 :                 extents.x = sampled_area.x;
    2300           0 :                 extents.width = sampled_area.width;
    2301           0 :                 trim |= 0x1;
    2302             :             }
    2303             : 
    2304           0 :             if (sampled_area.y >= extents.y &&
    2305           0 :                 sampled_area.y + (int) sampled_area.height <= extents.y + (int) extents.height)
    2306             :             {
    2307             :                 /* source is vertically contained within extents, trim */
    2308           0 :                 extents.y = sampled_area.y;
    2309           0 :                 extents.height = sampled_area.height;
    2310           0 :                 trim |= 0x2;
    2311             :             }
    2312             : 
    2313           0 :             if (trim == 0x3) {
    2314             :                 /* source is wholly contained within extents, drop the REPEAT */
    2315           0 :                 attr->extend = CAIRO_EXTEND_NONE;
    2316             :             }
    2317             : 
    2318           0 :             is_empty = extents.width == 0 || extents.height == 0;
    2319             :         }
    2320             :     }
    2321             : 
    2322             :     /* XXX can we use is_empty? */
    2323             : 
    2324           0 :     status = _cairo_surface_clone_similar (dst, surface,
    2325             :                                            extents.x, extents.y,
    2326             :                                            extents.width, extents.height,
    2327             :                                            &x, &y, out);
    2328           0 :     if (unlikely (status))
    2329           0 :         goto BAIL;
    2330             : 
    2331           0 :     if (x != 0 || y != 0) {
    2332           0 :         if (is_identity) {
    2333           0 :             attr->x_offset -= x;
    2334           0 :             attr->y_offset -= y;
    2335             :         } else {
    2336             :             cairo_matrix_t m;
    2337             : 
    2338           0 :             x -= attr->x_offset;
    2339           0 :             y -= attr->y_offset;
    2340           0 :             attr->x_offset = 0;
    2341           0 :             attr->y_offset = 0;
    2342             : 
    2343           0 :             cairo_matrix_init_translate (&m, -x, -y);
    2344           0 :             cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
    2345             :         }
    2346             :     }
    2347             : 
    2348             :     /* reduce likelihood of range overflow with large downscaling */
    2349           0 :     if (! is_identity) {
    2350             :         cairo_matrix_t m;
    2351             :         cairo_status_t invert_status;
    2352             : 
    2353           0 :         m = attr->matrix;
    2354           0 :         invert_status = cairo_matrix_invert (&m);
    2355           0 :         assert (invert_status == CAIRO_STATUS_SUCCESS);
    2356             : 
    2357           0 :         if (m.x0 != 0. || m.y0 != 0.) {
    2358             :             /* pixman also limits the [xy]_offset to 16 bits so evenly
    2359             :              * spread the bits between the two.
    2360             :              */
    2361           0 :             x = floor (m.x0 / 2);
    2362           0 :             y = floor (m.y0 / 2);
    2363           0 :             attr->x_offset -= x;
    2364           0 :             attr->y_offset -= y;
    2365           0 :             cairo_matrix_init_translate (&m, x, y);
    2366           0 :             cairo_matrix_multiply (&attr->matrix, &m, &attr->matrix);
    2367             :         }
    2368             :     }
    2369             : 
    2370             :   BAIL:
    2371           0 :     cairo_surface_destroy (surface);
    2372           0 :     return status;
    2373             : }
    2374             : 
    2375             : /**
    2376             :  * _cairo_pattern_acquire_surface:
    2377             :  * @pattern: a #cairo_pattern_t
    2378             :  * @dst: destination surface
    2379             :  * @x: X coordinate in source corresponding to left side of destination area
    2380             :  * @y: Y coordinate in source corresponding to top side of destination area
    2381             :  * @width: width of destination area
    2382             :  * @height: height of destination area
    2383             :  * @surface_out: location to store a pointer to a surface
    2384             :  * @attributes: surface attributes that destination backend should apply to
    2385             :  * the returned surface
    2386             :  *
    2387             :  * A convenience function to obtain a surface to use as the source for
    2388             :  * drawing on @dst.
    2389             :  *
    2390             :  * Note that this function is only suitable for use when the destination
    2391             :  * surface is pixel based and 1 device unit maps to one pixel.
    2392             :  *
    2393             :  * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
    2394             :  **/
    2395             : cairo_int_status_t
    2396           0 : _cairo_pattern_acquire_surface (const cairo_pattern_t      *pattern,
    2397             :                                 cairo_surface_t            *dst,
    2398             :                                 int                        x,
    2399             :                                 int                        y,
    2400             :                                 unsigned int               width,
    2401             :                                 unsigned int               height,
    2402             :                                 unsigned int               flags,
    2403             :                                 cairo_surface_t            **surface_out,
    2404             :                                 cairo_surface_attributes_t *attributes)
    2405             : {
    2406           0 :     if (unlikely (pattern->status)) {
    2407           0 :         *surface_out = NULL;
    2408           0 :         return pattern->status;
    2409             :     }
    2410             : 
    2411           0 :     switch (pattern->type) {
    2412             :     case CAIRO_PATTERN_TYPE_SOLID:
    2413           0 :         return _cairo_pattern_acquire_surface_for_solid ((cairo_solid_pattern_t *) pattern,
    2414             :                                                          dst, x, y, width, height,
    2415             :                                                          surface_out,
    2416             :                                                          attributes);
    2417             : 
    2418             :     case CAIRO_PATTERN_TYPE_LINEAR:
    2419             :     case CAIRO_PATTERN_TYPE_RADIAL:
    2420           0 :         return _cairo_pattern_acquire_surface_for_gradient ((cairo_gradient_pattern_t *) pattern,
    2421             :                                                             dst, x, y, width, height,
    2422             :                                                             surface_out,
    2423             :                                                             attributes);
    2424             : 
    2425             :     case CAIRO_PATTERN_TYPE_SURFACE:
    2426           0 :         return _cairo_pattern_acquire_surface_for_surface ((cairo_surface_pattern_t *) pattern,
    2427             :                                                            dst, x, y, width, height,
    2428             :                                                            flags,
    2429             :                                                            surface_out,
    2430             :                                                            attributes);
    2431             : 
    2432             :     default:
    2433           0 :         ASSERT_NOT_REACHED;
    2434           0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
    2435             :     }
    2436             : }
    2437             : 
    2438             : /**
    2439             :  * _cairo_pattern_release_surface:
    2440             :  * @pattern: a #cairo_pattern_t
    2441             :  * @surface: a surface obtained by _cairo_pattern_acquire_surface
    2442             :  * @attributes: attributes obtained by _cairo_pattern_acquire_surface
    2443             :  *
    2444             :  * Releases resources obtained by _cairo_pattern_acquire_surface.
    2445             :  **/
    2446             : void
    2447           0 : _cairo_pattern_release_surface (const cairo_pattern_t *pattern,
    2448             :                                 cairo_surface_t            *surface,
    2449             :                                 cairo_surface_attributes_t *attributes)
    2450             : {
    2451           0 :     cairo_surface_destroy (surface);
    2452           0 : }
    2453             : 
    2454             : cairo_int_status_t
    2455           0 : _cairo_pattern_acquire_surfaces (const cairo_pattern_t      *src,
    2456             :                                  const cairo_pattern_t      *mask,
    2457             :                                  cairo_surface_t            *dst,
    2458             :                                  int                        src_x,
    2459             :                                  int                        src_y,
    2460             :                                  int                        mask_x,
    2461             :                                  int                        mask_y,
    2462             :                                  unsigned int               width,
    2463             :                                  unsigned int               height,
    2464             :                                  unsigned int               flags,
    2465             :                                  cairo_surface_t            **src_out,
    2466             :                                  cairo_surface_t            **mask_out,
    2467             :                                  cairo_surface_attributes_t *src_attributes,
    2468             :                                  cairo_surface_attributes_t *mask_attributes)
    2469             : {
    2470             :     cairo_int_status_t    status;
    2471             :     cairo_pattern_union_t src_tmp;
    2472             : 
    2473           0 :     if (unlikely (src->status))
    2474           0 :         return src->status;
    2475           0 :     if (unlikely (mask != NULL && mask->status))
    2476           0 :         return mask->status;
    2477             : 
    2478             :     /* If src and mask are both solid, then the mask alpha can be
    2479             :      * combined into src and mask can be ignored. */
    2480             : 
    2481           0 :     if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
    2482           0 :         mask &&
    2483           0 :         ! mask->has_component_alpha &&
    2484           0 :         mask->type == CAIRO_PATTERN_TYPE_SOLID)
    2485             :     {
    2486             :         cairo_color_t combined;
    2487           0 :         cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
    2488           0 :         cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
    2489             : 
    2490           0 :         combined = src_solid->color;
    2491           0 :         _cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
    2492             : 
    2493           0 :         _cairo_pattern_init_solid (&src_tmp.solid, &combined);
    2494             : 
    2495           0 :         src = &src_tmp.base;
    2496           0 :         mask = NULL;
    2497             :     }
    2498             : 
    2499           0 :     status = _cairo_pattern_acquire_surface (src, dst,
    2500             :                                              src_x, src_y,
    2501             :                                              width, height,
    2502             :                                              flags,
    2503             :                                              src_out, src_attributes);
    2504           0 :     if (unlikely (status))
    2505           0 :         goto BAIL;
    2506             : 
    2507           0 :     if (mask == NULL) {
    2508           0 :         *mask_out = NULL;
    2509           0 :         goto BAIL;
    2510             :     }
    2511             : 
    2512           0 :     status = _cairo_pattern_acquire_surface (mask, dst,
    2513             :                                              mask_x, mask_y,
    2514             :                                              width, height,
    2515             :                                              flags,
    2516             :                                              mask_out, mask_attributes);
    2517           0 :     if (unlikely (status))
    2518           0 :         _cairo_pattern_release_surface (src, *src_out, src_attributes);
    2519             : 
    2520             :   BAIL:
    2521           0 :     if (src == &src_tmp.base)
    2522           0 :         _cairo_pattern_fini (&src_tmp.base);
    2523             : 
    2524           0 :     return status;
    2525             : }
    2526             : 
    2527             : /**
    2528             :  * _cairo_pattern_get_extents:
    2529             :  *
    2530             :  * Return the "target-space" extents of @pattern in @extents.
    2531             :  *
    2532             :  * For unbounded patterns, the @extents will be initialized with
    2533             :  * "infinite" extents, (minimum and maximum fixed-point values).
    2534             :  *
    2535             :  * XXX: Currently, bounded gradient patterns will also return
    2536             :  * "infinite" extents, though it would be possible to optimize these
    2537             :  * with a little more work.
    2538             :  **/
    2539             : void
    2540           0 : _cairo_pattern_get_extents (const cairo_pattern_t         *pattern,
    2541             :                             cairo_rectangle_int_t         *extents)
    2542             : {
    2543             :     double x1, y1, x2, y2;
    2544             :     cairo_status_t status;
    2545             : 
    2546           0 :     switch (pattern->type) {
    2547             :     case CAIRO_PATTERN_TYPE_SOLID:
    2548           0 :         goto UNBOUNDED;
    2549             : 
    2550             :     case CAIRO_PATTERN_TYPE_SURFACE:
    2551             :         {
    2552             :             cairo_rectangle_int_t surface_extents;
    2553           0 :             const cairo_surface_pattern_t *surface_pattern =
    2554             :                 (const cairo_surface_pattern_t *) pattern;
    2555           0 :             cairo_surface_t *surface = surface_pattern->surface;
    2556             :             double pad;
    2557             : 
    2558           0 :             if (! _cairo_surface_get_extents (surface, &surface_extents))
    2559           0 :                 goto UNBOUNDED;
    2560             : 
    2561           0 :             if (surface_extents.width == 0 || surface_extents.height == 0)
    2562             :                 goto EMPTY;
    2563             : 
    2564           0 :             if (pattern->extend != CAIRO_EXTEND_NONE)
    2565           0 :                 goto UNBOUNDED;
    2566             : 
    2567             :             /* The filter can effectively enlarge the extents of the
    2568             :              * pattern, so extend as necessary.
    2569             :              */
    2570           0 :             _cairo_pattern_analyze_filter (&surface_pattern->base, &pad);
    2571           0 :             x1 = surface_extents.x - pad;
    2572           0 :             y1 = surface_extents.y - pad;
    2573           0 :             x2 = surface_extents.x + (int) surface_extents.width  + pad;
    2574           0 :             y2 = surface_extents.y + (int) surface_extents.height + pad;
    2575             :         }
    2576           0 :         break;
    2577             : 
    2578             :     case CAIRO_PATTERN_TYPE_RADIAL:
    2579             :         {
    2580           0 :             const cairo_radial_pattern_t *radial =
    2581             :                 (const cairo_radial_pattern_t *) pattern;
    2582             :             double cx1, cy1;
    2583             :             double cx2, cy2;
    2584             :             double r, D;
    2585             : 
    2586           0 :             if (radial->r1 == 0 && radial->r2 == 0)
    2587           0 :                 goto EMPTY;
    2588             : 
    2589           0 :             cx1 = _cairo_fixed_to_double (radial->c1.x);
    2590           0 :             cy1 = _cairo_fixed_to_double (radial->c1.y);
    2591           0 :             r = _cairo_fixed_to_double (radial->r1);
    2592           0 :             x1 = cx1 - r; x2 = cx1 + r;
    2593           0 :             y1 = cy1 - r; y2 = cy1 + r;
    2594             : 
    2595           0 :             cx2 = _cairo_fixed_to_double (radial->c2.x);
    2596           0 :             cy2 = _cairo_fixed_to_double (radial->c2.y);
    2597           0 :             r = fabs (_cairo_fixed_to_double (radial->r2));
    2598             : 
    2599           0 :             if (pattern->extend != CAIRO_EXTEND_NONE)
    2600           0 :                 goto UNBOUNDED;
    2601             : 
    2602             :             /* We need to be careful, as if the circles are not
    2603             :              * self-contained, then the solution is actually unbounded.
    2604             :              */
    2605           0 :             D = (cx1-cx2)*(cx1-cx2) + (cy1-cy2)*(cy1-cy2);
    2606           0 :             if (D > r*r - 1e-5)
    2607           0 :                 goto UNBOUNDED;
    2608             : 
    2609           0 :             if (cx2 - r < x1)
    2610           0 :                 x1 = cx2 - r;
    2611           0 :             if (cx2 + r > x2)
    2612           0 :                 x2 = cx2 + r;
    2613             : 
    2614           0 :             if (cy2 - r < y1)
    2615           0 :                 y1 = cy2 - r;
    2616           0 :             if (cy2 + r > y2)
    2617           0 :                 y2 = cy2 + r;
    2618             :         }
    2619           0 :         break;
    2620             : 
    2621             :     case CAIRO_PATTERN_TYPE_LINEAR:
    2622             :         {
    2623           0 :             const cairo_linear_pattern_t *linear =
    2624             :                 (const cairo_linear_pattern_t *) pattern;
    2625             : 
    2626           0 :             if (pattern->extend != CAIRO_EXTEND_NONE)
    2627           0 :                 goto UNBOUNDED;
    2628             : 
    2629           0 :             if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
    2630           0 :                 goto EMPTY;
    2631             : 
    2632           0 :             if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
    2633             :                 goto UNBOUNDED;
    2634             : 
    2635           0 :             if (linear->p1.x == linear->p2.x) {
    2636           0 :                 x1 = -HUGE_VAL;
    2637           0 :                 x2 = HUGE_VAL;
    2638           0 :                 y1 = _cairo_fixed_to_double (MIN (linear->p1.y, linear->p2.y));
    2639           0 :                 y2 = _cairo_fixed_to_double (MAX (linear->p1.y, linear->p2.y));
    2640           0 :             } else if (linear->p1.y == linear->p2.y) {
    2641           0 :                 x1 = _cairo_fixed_to_double (MIN (linear->p1.x, linear->p2.x));
    2642           0 :                 x2 = _cairo_fixed_to_double (MAX (linear->p1.x, linear->p2.x));
    2643           0 :                 y1 = -HUGE_VAL;
    2644           0 :                 y2 = HUGE_VAL;
    2645             :             } else {
    2646           0 :                 goto  UNBOUNDED;
    2647             :             }
    2648             :         }
    2649           0 :         break;
    2650             : 
    2651             :     default:
    2652           0 :         ASSERT_NOT_REACHED;
    2653             :     }
    2654             : 
    2655           0 :     if (_cairo_matrix_is_translation (&pattern->matrix)) {
    2656           0 :         x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
    2657           0 :         y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
    2658             :     } else {
    2659             :         cairo_matrix_t imatrix;
    2660             : 
    2661           0 :         imatrix = pattern->matrix;
    2662           0 :         status = cairo_matrix_invert (&imatrix);
    2663             :         /* cairo_pattern_set_matrix ensures the matrix is invertible */
    2664           0 :         assert (status == CAIRO_STATUS_SUCCESS);
    2665             : 
    2666           0 :         _cairo_matrix_transform_bounding_box (&imatrix,
    2667             :                                               &x1, &y1, &x2, &y2,
    2668             :                                               NULL);
    2669             :     }
    2670             : 
    2671           0 :     x1 = floor (x1);
    2672           0 :     if (x1 < CAIRO_RECT_INT_MIN)
    2673           0 :         x1 = CAIRO_RECT_INT_MIN;
    2674           0 :     y1 = floor (y1);
    2675           0 :     if (y1 < CAIRO_RECT_INT_MIN)
    2676           0 :         y1 = CAIRO_RECT_INT_MIN;
    2677             : 
    2678           0 :     x2 = ceil (x2);
    2679           0 :     if (x2 > CAIRO_RECT_INT_MAX)
    2680           0 :         x2 = CAIRO_RECT_INT_MAX;
    2681           0 :     y2 = ceil (y2);
    2682           0 :     if (y2 > CAIRO_RECT_INT_MAX)
    2683           0 :         y2 = CAIRO_RECT_INT_MAX;
    2684             : 
    2685           0 :     extents->x = x1; extents->width  = x2 - x1;
    2686           0 :     extents->y = y1; extents->height = y2 - y1;
    2687           0 :     return;
    2688             : 
    2689             :   UNBOUNDED:
    2690             :     /* unbounded patterns -> 'infinite' extents */
    2691           0 :     _cairo_unbounded_rectangle_init (extents);
    2692           0 :     return;
    2693             : 
    2694             :   EMPTY:
    2695           0 :     extents->x = extents->y = 0;
    2696           0 :     extents->width = extents->height = 0;
    2697           0 :     return;
    2698             : }
    2699             : 
    2700             : 
    2701             : static unsigned long
    2702           0 : _cairo_solid_pattern_hash (unsigned long hash,
    2703             :                            const cairo_pattern_t *pattern)
    2704             : {
    2705           0 :     const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
    2706             : 
    2707           0 :     hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
    2708             : 
    2709           0 :     return hash;
    2710             : }
    2711             : 
    2712             : static unsigned long
    2713           0 : _cairo_gradient_color_stops_hash (unsigned long hash,
    2714             :                                   const cairo_gradient_pattern_t *gradient)
    2715             : {
    2716             :     unsigned int n;
    2717             : 
    2718           0 :     hash = _cairo_hash_bytes (hash,
    2719           0 :                               &gradient->n_stops,
    2720             :                               sizeof (gradient->n_stops));
    2721             : 
    2722           0 :     for (n = 0; n < gradient->n_stops; n++) {
    2723           0 :         hash = _cairo_hash_bytes (hash,
    2724           0 :                                   &gradient->stops[n].offset,
    2725             :                                   sizeof (double));
    2726           0 :         hash = _cairo_hash_bytes (hash,
    2727           0 :                                   &gradient->stops[n].color,
    2728             :                                   sizeof (cairo_color_t));
    2729             :     }
    2730             : 
    2731           0 :     return hash;
    2732             : }
    2733             : 
    2734             : unsigned long
    2735           0 : _cairo_linear_pattern_hash (unsigned long hash,
    2736             :                             const cairo_linear_pattern_t *linear)
    2737             : {
    2738           0 :     hash = _cairo_hash_bytes (hash, &linear->p1, sizeof (linear->p1));
    2739           0 :     hash = _cairo_hash_bytes (hash, &linear->p2, sizeof (linear->p2));
    2740             : 
    2741           0 :     return _cairo_gradient_color_stops_hash (hash, &linear->base);
    2742             : }
    2743             : 
    2744             : unsigned long
    2745           0 : _cairo_radial_pattern_hash (unsigned long hash,
    2746             :                             const cairo_radial_pattern_t *radial)
    2747             : {
    2748           0 :     hash = _cairo_hash_bytes (hash, &radial->c1, sizeof (radial->c1));
    2749           0 :     hash = _cairo_hash_bytes (hash, &radial->r1, sizeof (radial->r1));
    2750           0 :     hash = _cairo_hash_bytes (hash, &radial->c2, sizeof (radial->c2));
    2751           0 :     hash = _cairo_hash_bytes (hash, &radial->r2, sizeof (radial->r2));
    2752             : 
    2753           0 :     return _cairo_gradient_color_stops_hash (hash, &radial->base);
    2754             : }
    2755             : 
    2756             : static unsigned long
    2757           0 : _cairo_surface_pattern_hash (unsigned long hash,
    2758             :                              const cairo_pattern_t *pattern)
    2759             : {
    2760           0 :     const cairo_surface_pattern_t *surface = (cairo_surface_pattern_t *) pattern;
    2761             : 
    2762           0 :     hash ^= surface->surface->unique_id;
    2763             : 
    2764           0 :     return hash;
    2765             : }
    2766             : 
    2767             : unsigned long
    2768           0 : _cairo_pattern_hash (const cairo_pattern_t *pattern)
    2769             : {
    2770           0 :     unsigned long hash = _CAIRO_HASH_INIT_VALUE;
    2771             : 
    2772           0 :     if (pattern->status)
    2773           0 :         return 0;
    2774             : 
    2775           0 :     hash = _cairo_hash_bytes (hash, &pattern->type, sizeof (pattern->type));
    2776           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
    2777           0 :         hash = _cairo_hash_bytes (hash,
    2778           0 :                                   &pattern->matrix, sizeof (pattern->matrix));
    2779           0 :         hash = _cairo_hash_bytes (hash,
    2780           0 :                                   &pattern->filter, sizeof (pattern->filter));
    2781           0 :         hash = _cairo_hash_bytes (hash,
    2782           0 :                                   &pattern->extend, sizeof (pattern->extend));
    2783           0 :         hash = _cairo_hash_bytes (hash,
    2784           0 :                                   &pattern->has_component_alpha,
    2785             :                                   sizeof (pattern->has_component_alpha));
    2786             :     }
    2787             : 
    2788           0 :     switch (pattern->type) {
    2789             :     case CAIRO_PATTERN_TYPE_SOLID:
    2790           0 :         return _cairo_solid_pattern_hash (hash, pattern);
    2791             :     case CAIRO_PATTERN_TYPE_LINEAR:
    2792           0 :         return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
    2793             :     case CAIRO_PATTERN_TYPE_RADIAL:
    2794           0 :         return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
    2795             :     case CAIRO_PATTERN_TYPE_SURFACE:
    2796           0 :         return _cairo_surface_pattern_hash (hash, pattern);
    2797             :     default:
    2798           0 :         ASSERT_NOT_REACHED;
    2799           0 :         return FALSE;
    2800             :     }
    2801             : }
    2802             : 
    2803             : static unsigned long
    2804           0 : _cairo_gradient_pattern_color_stops_size (const cairo_pattern_t *pattern)
    2805             : {
    2806           0 :     cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
    2807             : 
    2808           0 :     return gradient->n_stops * (sizeof (double) + sizeof (cairo_color_t));
    2809             : }
    2810             : 
    2811             : unsigned long
    2812           0 : _cairo_pattern_size (const cairo_pattern_t *pattern)
    2813             : {
    2814           0 :     if (pattern->status)
    2815           0 :         return 0;
    2816             : 
    2817             :     /* XXX */
    2818           0 :     switch (pattern->type) {
    2819             :     case CAIRO_PATTERN_TYPE_SOLID:
    2820           0 :         return sizeof (cairo_solid_pattern_t);
    2821             :         break;
    2822             :     case CAIRO_PATTERN_TYPE_SURFACE:
    2823           0 :         return sizeof (cairo_surface_pattern_t);
    2824             :         break;
    2825             :     case CAIRO_PATTERN_TYPE_LINEAR:
    2826           0 :         return sizeof (cairo_linear_pattern_t) +
    2827           0 :             _cairo_gradient_pattern_color_stops_size (pattern);
    2828             :         break;
    2829             :     case CAIRO_PATTERN_TYPE_RADIAL:
    2830           0 :         return sizeof (cairo_radial_pattern_t) +
    2831           0 :             _cairo_gradient_pattern_color_stops_size (pattern);
    2832             :     default:
    2833           0 :         ASSERT_NOT_REACHED;
    2834           0 :         return 0;
    2835             :     }
    2836             : }
    2837             : 
    2838             : 
    2839             : static cairo_bool_t
    2840           0 : _cairo_solid_pattern_equal (const cairo_pattern_t *A,
    2841             :                             const cairo_pattern_t *B)
    2842             : {
    2843           0 :     const cairo_solid_pattern_t *a = (cairo_solid_pattern_t *) A;
    2844           0 :     const cairo_solid_pattern_t *b = (cairo_solid_pattern_t *) B;
    2845             : 
    2846           0 :     return _cairo_color_equal (&a->color, &b->color);
    2847             : }
    2848             : 
    2849             : static cairo_bool_t
    2850           0 : _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
    2851             :                                    const cairo_gradient_pattern_t *b)
    2852             : {
    2853             :     unsigned int n;
    2854             : 
    2855           0 :     if (a->n_stops != b->n_stops)
    2856           0 :         return FALSE;
    2857             : 
    2858           0 :     for (n = 0; n < a->n_stops; n++) {
    2859           0 :         if (a->stops[n].offset != b->stops[n].offset)
    2860           0 :             return FALSE;
    2861           0 :         if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
    2862           0 :             return FALSE;
    2863             :     }
    2864             : 
    2865           0 :     return TRUE;
    2866             : }
    2867             : 
    2868             : cairo_bool_t
    2869           0 : _cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
    2870             :                              const cairo_linear_pattern_t *b)
    2871             : {
    2872           0 :     if (a->p1.x != b->p1.x)
    2873           0 :         return FALSE;
    2874             : 
    2875           0 :     if (a->p1.y != b->p1.y)
    2876           0 :         return FALSE;
    2877             : 
    2878           0 :     if (a->p2.x != b->p2.x)
    2879           0 :         return FALSE;
    2880             : 
    2881           0 :     if (a->p2.y != b->p2.y)
    2882           0 :         return FALSE;
    2883             : 
    2884           0 :     return _cairo_gradient_color_stops_equal (&a->base, &b->base);
    2885             : }
    2886             : 
    2887             : cairo_bool_t
    2888           0 : _cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
    2889             :                              const cairo_radial_pattern_t *b)
    2890             : {
    2891           0 :     if (a->c1.x != b->c1.x)
    2892           0 :         return FALSE;
    2893             : 
    2894           0 :     if (a->c1.y != b->c1.y)
    2895           0 :         return FALSE;
    2896             : 
    2897           0 :     if (a->r1 != b->r1)
    2898           0 :         return FALSE;
    2899             : 
    2900           0 :     if (a->c2.x != b->c2.x)
    2901           0 :         return FALSE;
    2902             : 
    2903           0 :     if (a->c2.y != b->c2.y)
    2904           0 :         return FALSE;
    2905             : 
    2906           0 :     if (a->r2 != b->r2)
    2907           0 :         return FALSE;
    2908             : 
    2909           0 :     return _cairo_gradient_color_stops_equal (&a->base, &b->base);
    2910             : }
    2911             : 
    2912             : static cairo_bool_t
    2913           0 : _cairo_surface_pattern_equal (const cairo_pattern_t *A,
    2914             :                               const cairo_pattern_t *B)
    2915             : {
    2916           0 :     const cairo_surface_pattern_t *a = (cairo_surface_pattern_t *) A;
    2917           0 :     const cairo_surface_pattern_t *b = (cairo_surface_pattern_t *) B;
    2918             : 
    2919           0 :     return a->surface->unique_id == b->surface->unique_id;
    2920             : }
    2921             : 
    2922             : cairo_bool_t
    2923           0 : _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
    2924             : {
    2925           0 :     if (a->status || b->status)
    2926           0 :         return FALSE;
    2927             : 
    2928           0 :     if (a == b)
    2929           0 :         return TRUE;
    2930             : 
    2931           0 :     if (a->type != b->type)
    2932           0 :         return FALSE;
    2933             : 
    2934           0 :     if (a->has_component_alpha != b->has_component_alpha)
    2935           0 :         return FALSE;
    2936             : 
    2937           0 :     if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
    2938           0 :         if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
    2939           0 :             return FALSE;
    2940             : 
    2941           0 :         if (a->filter != b->filter)
    2942           0 :             return FALSE;
    2943             : 
    2944           0 :         if (a->extend != b->extend)
    2945           0 :             return FALSE;
    2946             :     }
    2947             : 
    2948           0 :     switch (a->type) {
    2949             :     case CAIRO_PATTERN_TYPE_SOLID:
    2950           0 :         return _cairo_solid_pattern_equal (a, b);
    2951             :     case CAIRO_PATTERN_TYPE_LINEAR:
    2952           0 :         return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
    2953             :                                             (cairo_linear_pattern_t *) b);
    2954             :     case CAIRO_PATTERN_TYPE_RADIAL:
    2955           0 :         return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
    2956             :                                             (cairo_radial_pattern_t *) b);
    2957             :     case CAIRO_PATTERN_TYPE_SURFACE:
    2958           0 :         return _cairo_surface_pattern_equal (a, b);
    2959             :     default:
    2960           0 :         ASSERT_NOT_REACHED;
    2961           0 :         return FALSE;
    2962             :     }
    2963             : }
    2964             : 
    2965             : /**
    2966             :  * cairo_pattern_get_rgba
    2967             :  * @pattern: a #cairo_pattern_t
    2968             :  * @red: return value for red component of color, or %NULL
    2969             :  * @green: return value for green component of color, or %NULL
    2970             :  * @blue: return value for blue component of color, or %NULL
    2971             :  * @alpha: return value for alpha component of color, or %NULL
    2972             :  *
    2973             :  * Gets the solid color for a solid color pattern.
    2974             :  *
    2975             :  * Return value: %CAIRO_STATUS_SUCCESS, or
    2976             :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
    2977             :  * color pattern.
    2978             :  *
    2979             :  * Since: 1.4
    2980             :  **/
    2981             : cairo_status_t
    2982           0 : cairo_pattern_get_rgba (cairo_pattern_t *pattern,
    2983             :                         double *red, double *green,
    2984             :                         double *blue, double *alpha)
    2985             : {
    2986           0 :     cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
    2987             :     double r0, g0, b0, a0;
    2988             : 
    2989           0 :     if (pattern->status)
    2990           0 :         return pattern->status;
    2991             : 
    2992           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
    2993           0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
    2994             : 
    2995           0 :     _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
    2996             : 
    2997           0 :     if (red)
    2998           0 :         *red = r0;
    2999           0 :     if (green)
    3000           0 :         *green = g0;
    3001           0 :     if (blue)
    3002           0 :         *blue = b0;
    3003           0 :     if (alpha)
    3004           0 :         *alpha = a0;
    3005             : 
    3006           0 :     return CAIRO_STATUS_SUCCESS;
    3007             : }
    3008             : 
    3009             : /**
    3010             :  * cairo_pattern_get_surface
    3011             :  * @pattern: a #cairo_pattern_t
    3012             :  * @surface: return value for surface of pattern, or %NULL
    3013             :  * 
    3014             :  * Gets the surface of a surface pattern.  The reference returned in
    3015             :  * @surface is owned by the pattern; the caller should call
    3016             :  * cairo_surface_reference() if the surface is to be retained.
    3017             :  *
    3018             :  * Return value: %CAIRO_STATUS_SUCCESS, or
    3019             :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
    3020             :  * pattern.
    3021             :  *
    3022             :  * Since: 1.4
    3023             :  **/
    3024             : cairo_status_t
    3025           0 : cairo_pattern_get_surface (cairo_pattern_t *pattern,
    3026             :                            cairo_surface_t **surface)
    3027             : {
    3028           0 :     cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
    3029             : 
    3030           0 :     if (pattern->status)
    3031           0 :         return pattern->status;
    3032             : 
    3033           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
    3034           0 :         return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
    3035             : 
    3036           0 :     if (surface)
    3037           0 :         *surface = spat->surface;
    3038             : 
    3039           0 :     return CAIRO_STATUS_SUCCESS;
    3040             : }
    3041             : 
    3042             : /**
    3043             :  * cairo_pattern_get_color_stop_rgba
    3044             :  * @pattern: a #cairo_pattern_t
    3045             :  * @index: index of the stop to return data for
    3046             :  * @offset: return value for the offset of the stop, or %NULL
    3047             :  * @red: return value for red component of color, or %NULL
    3048             :  * @green: return value for green component of color, or %NULL
    3049             :  * @blue: return value for blue component of color, or %NULL
    3050             :  * @alpha: return value for alpha component of color, or %NULL
    3051             :  *
    3052             :  * Gets the color and offset information at the given @index for a
    3053             :  * gradient pattern.  Values of @index are 0 to 1 less than the number
    3054             :  * returned by cairo_pattern_get_color_stop_count().
    3055             :  *
    3056             :  * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
    3057             :  * if @index is not valid for the given pattern.  If the pattern is
    3058             :  * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
    3059             :  * returned.
    3060             :  *
    3061             :  * Since: 1.4
    3062             :  **/
    3063             : cairo_status_t
    3064           0 : cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
    3065             :                                    int index, double *offset,
    3066             :                                    double *red, double *green,
    3067             :                                    double *blue, double *alpha)
    3068             : {
    3069           0 :     cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
    3070             : 
    3071           0 :     if (pattern->status)
    3072           0 :         return pattern->status;
    3073             : 
    3074           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
    3075           0 :         pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
    3076           0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
    3077             : 
    3078           0 :     if (index < 0 || (unsigned int) index >= gradient->n_stops)
    3079           0 :         return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
    3080             : 
    3081           0 :     if (offset)
    3082           0 :         *offset = gradient->stops[index].offset;
    3083           0 :     if (red)
    3084           0 :         *red = gradient->stops[index].color.red;
    3085           0 :     if (green)
    3086           0 :         *green = gradient->stops[index].color.green;
    3087           0 :     if (blue)
    3088           0 :         *blue = gradient->stops[index].color.blue;
    3089           0 :     if (alpha)
    3090           0 :         *alpha = gradient->stops[index].color.alpha;
    3091             : 
    3092           0 :     return CAIRO_STATUS_SUCCESS;
    3093             : }
    3094             : 
    3095             : /**
    3096             :  * cairo_pattern_get_color_stop_count
    3097             :  * @pattern: a #cairo_pattern_t
    3098             :  * @count: return value for the number of color stops, or %NULL
    3099             :  *
    3100             :  * Gets the number of color stops specified in the given gradient
    3101             :  * pattern.
    3102             :  *
    3103             :  * Return value: %CAIRO_STATUS_SUCCESS, or
    3104             :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
    3105             :  * pattern.
    3106             :  *
    3107             :  * Since: 1.4
    3108             :  */
    3109             : cairo_status_t
    3110           0 : cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
    3111             :                                     int *count)
    3112             : {
    3113           0 :     cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
    3114             : 
    3115           0 :     if (pattern->status)
    3116           0 :         return pattern->status;
    3117             : 
    3118           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
    3119           0 :         pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
    3120           0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
    3121             : 
    3122           0 :     if (count)
    3123           0 :         *count = gradient->n_stops;
    3124             : 
    3125           0 :     return CAIRO_STATUS_SUCCESS;
    3126             : }
    3127             : 
    3128             : /**
    3129             :  * cairo_pattern_get_linear_points
    3130             :  * @pattern: a #cairo_pattern_t
    3131             :  * @x0: return value for the x coordinate of the first point, or %NULL
    3132             :  * @y0: return value for the y coordinate of the first point, or %NULL
    3133             :  * @x1: return value for the x coordinate of the second point, or %NULL
    3134             :  * @y1: return value for the y coordinate of the second point, or %NULL
    3135             :  *
    3136             :  * Gets the gradient endpoints for a linear gradient.
    3137             :  *
    3138             :  * Return value: %CAIRO_STATUS_SUCCESS, or
    3139             :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
    3140             :  * gradient pattern.
    3141             :  *
    3142             :  * Since: 1.4
    3143             :  **/
    3144             : cairo_status_t
    3145           0 : cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
    3146             :                                  double *x0, double *y0,
    3147             :                                  double *x1, double *y1)
    3148             : {
    3149           0 :     cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
    3150             : 
    3151           0 :     if (pattern->status)
    3152           0 :         return pattern->status;
    3153             : 
    3154           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
    3155           0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
    3156             : 
    3157           0 :     if (x0)
    3158           0 :         *x0 = _cairo_fixed_to_double (linear->p1.x);
    3159           0 :     if (y0)
    3160           0 :         *y0 = _cairo_fixed_to_double (linear->p1.y);
    3161           0 :     if (x1)
    3162           0 :         *x1 = _cairo_fixed_to_double (linear->p2.x);
    3163           0 :     if (y1)
    3164           0 :         *y1 = _cairo_fixed_to_double (linear->p2.y);
    3165             : 
    3166           0 :     return CAIRO_STATUS_SUCCESS;
    3167             : }
    3168             : 
    3169             : /**
    3170             :  * cairo_pattern_get_radial_circles
    3171             :  * @pattern: a #cairo_pattern_t
    3172             :  * @x0: return value for the x coordinate of the center of the first circle, or %NULL
    3173             :  * @y0: return value for the y coordinate of the center of the first circle, or %NULL
    3174             :  * @r0: return value for the radius of the first circle, or %NULL
    3175             :  * @x1: return value for the x coordinate of the center of the second circle, or %NULL
    3176             :  * @y1: return value for the y coordinate of the center of the second circle, or %NULL
    3177             :  * @r1: return value for the radius of the second circle, or %NULL
    3178             :  *
    3179             :  * Gets the gradient endpoint circles for a radial gradient, each
    3180             :  * specified as a center coordinate and a radius.
    3181             :  *
    3182             :  * Return value: %CAIRO_STATUS_SUCCESS, or
    3183             :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
    3184             :  * gradient pattern.
    3185             :  *
    3186             :  * Since: 1.4
    3187             :  **/
    3188             : cairo_status_t
    3189           0 : cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
    3190             :                                   double *x0, double *y0, double *r0,
    3191             :                                   double *x1, double *y1, double *r1)
    3192             : {
    3193           0 :     cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
    3194             : 
    3195           0 :     if (pattern->status)
    3196           0 :         return pattern->status;
    3197             : 
    3198           0 :     if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
    3199           0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
    3200             : 
    3201           0 :     if (x0)
    3202           0 :         *x0 = _cairo_fixed_to_double (radial->c1.x);
    3203           0 :     if (y0)
    3204           0 :         *y0 = _cairo_fixed_to_double (radial->c1.y);
    3205           0 :     if (r0)
    3206           0 :         *r0 = _cairo_fixed_to_double (radial->r1);
    3207           0 :     if (x1)
    3208           0 :         *x1 = _cairo_fixed_to_double (radial->c2.x);
    3209           0 :     if (y1)
    3210           0 :         *y1 = _cairo_fixed_to_double (radial->c2.y);
    3211           0 :     if (r1)
    3212           0 :         *r1 = _cairo_fixed_to_double (radial->r2);
    3213             : 
    3214           0 :     return CAIRO_STATUS_SUCCESS;
    3215             : }
    3216             : 
    3217             : void
    3218           0 : _cairo_pattern_reset_static_data (void)
    3219             : {
    3220             : #if HAS_FREED_POOL
    3221             :     int i;
    3222             : 
    3223           0 :     for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
    3224           0 :         _freed_pool_reset (&freed_pattern_pool[i]);
    3225             : #endif
    3226             : 
    3227           0 :     _cairo_pattern_reset_solid_surface_cache ();
    3228           0 : }

Generated by: LCOV version 1.13