LCOV - app.info - gfx/cairo/cairo/src/cairo-pattern.c

LCOV - code coverage report
| Current view: | directory - gfx/cairo/cairo/src - cairo-pattern.c (source / functions) |  | Found | Hit | Coverage |
| Test: | app.info | Lines: | 1173 | 128 | 10.9 %
| Date: | 2012-06-02 | Functions: | 90 | 15 | 16.7 %

           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              47 : _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              47 :     pattern->type      = type;
         161              47 :     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              47 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
         166                 :
         167              47 :     _cairo_user_data_array_init (&pattern->user_data);
         168                 :
         169              47 :     if (type == CAIRO_PATTERN_TYPE_SURFACE)
         170              47 :         pattern->extend = CAIRO_EXTEND_SURFACE_DEFAULT;
         171                 :     else
         172               0 :         pattern->extend = CAIRO_EXTEND_GRADIENT_DEFAULT;
         173                 :
         174              47 :     pattern->filter    = CAIRO_FILTER_DEFAULT;
         175                 :
         176              47 :     pattern->has_component_alpha = FALSE;
         177                 :
         178              47 :     cairo_matrix_init_identity (&pattern->matrix);
         179              47 : }
         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              47 : _cairo_pattern_init_static_copy (cairo_pattern_t        *pattern,
         275                 :                                  const cairo_pattern_t *other)
         276                 : {
         277                 :     int size;
         278                 :
         279              47 :     assert (other->status == CAIRO_STATUS_SUCCESS);
         280                 :
         281              47 :     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              47 :         size = sizeof (cairo_surface_pattern_t);
         289              47 :         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              47 :     memcpy (pattern, other, size);
         299                 :
         300              47 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->ref_count, 0);
         301              47 :     _cairo_user_data_array_init (&pattern->user_data);
         302              47 : }
         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              47 : _cairo_pattern_fini (cairo_pattern_t *pattern)
         336                 : {
         337              47 :     _cairo_user_data_array_fini (&pattern->user_data);
         338                 :
         339              47 :     switch (pattern->type) {
         340                 :     case CAIRO_PATTERN_TYPE_SOLID:
         341               0 :         break;
         342                 :     case CAIRO_PATTERN_TYPE_SURFACE: {
         343              47 :         cairo_surface_pattern_t *surface_pattern =
         344                 :             (cairo_surface_pattern_t *) pattern;
         345                 :
         346              47 :         cairo_surface_destroy (surface_pattern->surface);
         347              47 :     } 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              47 : }
         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              47 : _cairo_pattern_init_for_surface (cairo_surface_pattern_t *pattern,
         428                 :                                  cairo_surface_t         *surface)
         429                 : {
         430              47 :     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              47 :     _cairo_pattern_init (&pattern->base, CAIRO_PATTERN_TYPE_SURFACE);
         438                 :
         439              47 :     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              47 : cairo_pattern_create_for_surface (cairo_surface_t *surface)
         613                 : {
         614                 :     cairo_surface_pattern_t *pattern;
         615                 :
         616              47 :     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              47 :     if (surface->status)
         622               0 :         return _cairo_pattern_create_in_error (surface->status);
         623                 :
         624              47 :     pattern =
         625                 :         _freed_pool_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SURFACE]);
         626              47 :     if (unlikely (pattern == NULL)) {
         627              47 :         pattern = malloc (sizeof (cairo_surface_pattern_t));
         628              47 :         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              47 :     _cairo_pattern_init_for_surface (pattern, surface);
         637              47 :     CAIRO_REFERENCE_COUNT_INIT (&pattern->base.ref_count, 1);
         638                 :
         639              47 :     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              75 : cairo_pattern_reference (cairo_pattern_t *pattern)
         759                 : {
         760             150 :     if (pattern == NULL ||
         761              75 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
         762              28 :         return pattern;
         763                 :
         764              47 :     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
         765                 :
         766              47 :     _cairo_reference_count_inc (&pattern->ref_count);
         767                 :
         768              47 :     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             186 : cairo_pattern_destroy (cairo_pattern_t *pattern)
         815                 : {
         816                 :     cairo_pattern_type_t type;
         817                 :
         818             372 :     if (pattern == NULL ||
         819             186 :             CAIRO_REFERENCE_COUNT_IS_INVALID (&pattern->ref_count))
         820              92 :         return;
         821                 :
         822              94 :     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&pattern->ref_count));
         823                 :
         824              94 :     if (! _cairo_reference_count_dec_and_test (&pattern->ref_count))
         825              47 :         return;
         826                 :
         827              47 :     type = pattern->type;
         828              47 :     _cairo_pattern_fini (pattern);
         829                 :
         830                 :     /* maintain a small cache of freed patterns */
         831              47 :     _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              28 : 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              28 :     if (pattern->status)
        1145               0 :         return;
        1146                 :
        1147              28 :     if (memcmp (&pattern->matrix, matrix, sizeof (cairo_matrix_t)) == 0)
        1148               0 :         return;
        1149                 :
        1150              28 :     pattern->matrix = *matrix;
        1151                 :
        1152              28 :     inverse = *matrix;
        1153              28 :     status = cairo_matrix_invert (&inverse);
        1154              28 :     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              10 : _cairo_pattern_transform (cairo_pattern_t       *pattern,
        1257                 :                           const cairo_matrix_t  *ctm_inverse)
        1258                 : {
        1259              10 :     if (pattern->status)
        1260               0 :         return;
        1261                 :
        1262              10 :     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                 :         cairo_fixed_t xdim, ydim;
        1371                 :
        1372               0 :         xdim = linear->p2.x - linear->p1.x;
        1373               0 :         ydim = linear->p2.y - linear->p1.y;
        1374                 :
        1375                 :         /*
        1376                 :          * Transform the matrix to avoid overflow when converting between
        1377                 :          * cairo_fixed_t and pixman_fixed_t (without incurring performance
        1378                 :          * loss when the transformation is unnecessary).
        1379                 :          *
        1380                 :          * XXX: Consider converting out-of-range co-ordinates and transforms.
        1381                 :          * Having a function to compute the required transformation to
        1382                 :          * "normalize" a given bounding box would be generally useful -
        1383                 :          * cf linear patterns, gradient patterns, surface patterns...
        1384                 :          */
        1385                 : #define PIXMAN_MAX_INT ((pixman_fixed_1 >> 1) - pixman_fixed_e) /* need to ensure deltas also fit */
        1386               0 :         if (_cairo_fixed_integer_ceil (xdim) > PIXMAN_MAX_INT ||
        1387               0 :             _cairo_fixed_integer_ceil (ydim) > PIXMAN_MAX_INT)
        1388               0 :         {
        1389                 :             double sf;
        1390                 :
        1391               0 :             if (xdim > ydim)
        1392               0 :                 sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (xdim);
        1393                 :             else
        1394               0 :                 sf = PIXMAN_MAX_INT / _cairo_fixed_to_double (ydim);
        1395                 :
        1396               0 :             p1.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.x) * sf);
        1397               0 :             p1.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p1.y) * sf);
        1398               0 :             p2.x = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.x) * sf);
        1399               0 :             p2.y = _cairo_fixed_16_16_from_double (_cairo_fixed_to_double (linear->p2.y) * sf);
        1400                 :
        1401               0 :             cairo_matrix_scale (&matrix, sf, sf);
        1402                 :         }
        1403                 :         else
        1404                 :         {
        1405               0 :             p1.x = _cairo_fixed_to_16_16 (linear->p1.x);
        1406               0 :             p1.y = _cairo_fixed_to_16_16 (linear->p1.y);
        1407               0 :             p2.x = _cairo_fixed_to_16_16 (linear->p2.x);
        1408               0 :             p2.y = _cairo_fixed_to_16_16 (linear->p2.y);
        1409                 :         }
        1410                 :
        1411               0 :         pixman_image = pixman_image_create_linear_gradient (&p1, &p2,
        1412                 :                                                             pixman_stops,
        1413               0 :                                                             pattern->n_stops);
        1414                 :     }
        1415                 :     else
        1416                 :     {
        1417               0 :         cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) pattern;
        1418                 :         pixman_point_fixed_t c1, c2;
        1419                 :         pixman_fixed_t r1, r2;
        1420                 :
        1421               0 :         c1.x = _cairo_fixed_to_16_16 (radial->c1.x);
        1422               0 :         c1.y = _cairo_fixed_to_16_16 (radial->c1.y);
        1423               0 :         r1   = _cairo_fixed_to_16_16 (radial->r1);
        1424                 :
        1425               0 :         c2.x = _cairo_fixed_to_16_16 (radial->c2.x);
        1426               0 :         c2.y = _cairo_fixed_to_16_16 (radial->c2.y);
        1427               0 :         r2   = _cairo_fixed_to_16_16 (radial->r2);
        1428                 :
        1429               0 :         pixman_image = pixman_image_create_radial_gradient (&c1, &c2,
        1430                 :                                                             r1, r2,
        1431                 :                                                             pixman_stops,
        1432               0 :                                                             pattern->n_stops);
        1433                 :     }
        1434                 :
        1435               0 :     if (pixman_stops != pixman_stops_static)
        1436               0 :         free (pixman_stops);
        1437                 :
        1438               0 :     if (unlikely (pixman_image == NULL))
        1439               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
        1440                 :
        1441               0 :     if (_cairo_surface_is_image (dst))
        1442                 :     {
        1443               0 :         image = (cairo_image_surface_t *)
        1444               0 :             _cairo_image_surface_create_for_pixman_image (pixman_image,
        1445                 :                                                           PIXMAN_a8r8g8b8);
        1446               0 :         if (image->base.status)
        1447                 :         {
        1448               0 :             pixman_image_unref (pixman_image);
        1449               0 :             return image->base.status;
        1450                 :         }
        1451                 :
        1452               0 :         attr->x_offset = attr->y_offset = 0;
        1453               0 :         attr->matrix = matrix;
        1454               0 :         attr->extend = pattern->base.extend;
        1455               0 :         attr->filter = CAIRO_FILTER_NEAREST;
        1456               0 :         attr->has_component_alpha = pattern->base.has_component_alpha;
        1457                 :
        1458               0 :         *out = &image->base;
        1459                 :
        1460               0 :         return CAIRO_STATUS_SUCCESS;
        1461                 :     }
        1462                 :
        1463               0 :     if (pattern->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
        1464                 :         cairo_bool_t is_horizontal;
        1465                 :         cairo_bool_t is_vertical;
        1466                 :
        1467               0 :         _cairo_linear_pattern_classify ((cairo_linear_pattern_t *)pattern,
        1468                 :                                         x, y, width, height,
        1469                 :                                         &is_horizontal, &is_vertical);
        1470               0 :         if (is_horizontal) {
        1471               0 :             height = 1;
        1472               0 :             repeat = TRUE;
        1473                 :         }
        1474                 :         /* width-1 repeating patterns are quite slow with scan-line based
        1475                 :          * compositing code, so we use a wider strip and spend some extra
        1476                 :          * expense in computing the gradient. It's possible that for narrow
        1477                 :          * gradients we'd be better off using a 2 or 4 pixel strip; the
        1478                 :          * wider the gradient, the more it's worth spending extra time
        1479                 :          * computing a sample.
        1480                 :          */
        1481               0 :         if (is_vertical && width > 8) {
        1482               0 :             width = 8;
        1483               0 :             repeat = TRUE;
        1484                 :         }
        1485                 :     }
        1486                 :
        1487               0 :     if (! pixman_image_set_filter (pixman_image, PIXMAN_FILTER_BILINEAR,
        1488                 :                                    NULL, 0))
        1489                 :     {
        1490               0 :         pixman_image_unref (pixman_image);
        1491               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
        1492                 :     }
        1493                 :
        1494               0 :     image = (cairo_image_surface_t *)
        1495               0 :         cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
        1496               0 :     if (image->base.status) {
        1497               0 :         pixman_image_unref (pixman_image);
        1498               0 :         return image->base.status;
        1499                 :     }
        1500                 :
        1501               0 :     _cairo_matrix_to_pixman_matrix (&matrix, &pixman_transform,
        1502                 :                                     width/2., height/2.);
        1503               0 :     if (!pixman_image_set_transform (pixman_image, &pixman_transform)) {
        1504               0 :         cairo_surface_destroy (&image->base);
        1505               0 :         pixman_image_unref (pixman_image);
        1506               0 :         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
        1507                 :     }
        1508                 :
        1509               0 :     switch (pattern->base.extend) {
        1510                 :     case CAIRO_EXTEND_NONE:
        1511               0 :         pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NONE);
        1512               0 :         break;
        1513                 :     case CAIRO_EXTEND_REPEAT:
        1514               0 :         pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_NORMAL);
        1515               0 :         break;
        1516                 :     case CAIRO_EXTEND_REFLECT:
        1517               0 :         pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_REFLECT);
        1518               0 :         break;
        1519                 :     case CAIRO_EXTEND_PAD:
        1520               0 :         pixman_image_set_repeat (pixman_image, PIXMAN_REPEAT_PAD);
        1521               0 :         break;
        1522                 :     }
        1523                 :
        1524               0 :     pixman_image_composite32 (PIXMAN_OP_SRC,
        1525                 :                               pixman_image,
        1526                 :                               NULL,
        1527                 :                               image->pixman_image,
        1528                 :                               x, y,
        1529                 :                               0, 0,
        1530                 :                               0, 0,
        1531                 :                               width, height);
        1532                 :
        1533               0 :     pixman_image_unref (pixman_image);
        1534                 :
        1535                 :     _cairo_debug_check_image_surface_is_defined (&image->base);
        1536                 :
        1537               0 :     status = _cairo_surface_clone_similar (dst, &image->base,
        1538                 :                                            0, 0, width, height,
        1539                 :                                            &clone_offset_x,
        1540                 :                                            &clone_offset_y,
        1541                 :                                            out);
        1542                 :
        1543               0 :     cairo_surface_destroy (&image->base);
        1544                 :
        1545               0 :     attr->x_offset = -x;
        1546               0 :     attr->y_offset = -y;
        1547               0 :     cairo_matrix_init_identity (&attr->matrix);
        1548               0 :     attr->extend = repeat ? CAIRO_EXTEND_REPEAT : CAIRO_EXTEND_NONE;
        1549               0 :     attr->filter = CAIRO_FILTER_NEAREST;
        1550               0 :     attr->has_component_alpha = pattern->base.has_component_alpha;
        1551                 :
        1552               0 :     return status;
        1553                 : }
        1554                 :
        1555                 : /* We maintain a small cache here, because we don't want to constantly
        1556                 :  * recreate surfaces for simple solid colors. */
        1557                 : #define MAX_SURFACE_CACHE_SIZE 16
        1558                 : static struct {
        1559                 :     struct _cairo_pattern_solid_surface_cache{
        1560                 :         cairo_color_t    color;
        1561                 :         cairo_surface_t *surface;
        1562                 :     } cache[MAX_SURFACE_CACHE_SIZE];
        1563                 :     int size;
        1564                 : } solid_surface_cache;
        1565                 :
        1566                 : static cairo_bool_t
        1567               0 : _cairo_pattern_solid_surface_matches (
        1568                 :         const struct _cairo_pattern_solid_surface_cache     *cache,
        1569                 :         const cairo_solid_pattern_t                         *pattern,
        1570                 :         cairo_surface_t                                     *dst)
        1571                 : {
        1572               0 :     if (cairo_surface_get_content (cache->surface) != _cairo_color_get_content (&pattern->color))
        1573               0 :         return FALSE;
        1574                 :
        1575               0 :     if (CAIRO_REFERENCE_COUNT_GET_VALUE (&cache->surface->ref_count) != 1)
        1576               0 :         return FALSE;
        1577                 :
        1578               0 :     if (! _cairo_surface_is_similar (cache->surface, dst))
        1579               0 :         return FALSE;
        1580                 :
        1581               0 :     return TRUE;
        1582                 : }
        1583                 :
        1584                 : static cairo_bool_t
        1585               0 : _cairo_pattern_solid_surface_matches_color (
        1586                 :         const struct _cairo_pattern_solid_surface_cache     *cache,
        1587                 :         const cairo_solid_pattern_t                         *pattern,
        1588                 :         cairo_surface_t                                     *dst)
        1589                 : {
        1590               0 :     if (! _cairo_color_equal (&cache->color, &pattern->color))
        1591               0 :         return FALSE;
        1592                 :
        1593               0 :     return _cairo_pattern_solid_surface_matches (cache, pattern, dst);
        1594                 : }
        1595                 :
        1596                 : static cairo_int_status_t
        1597               0 : _cairo_pattern_acquire_surface_for_solid (const cairo_solid_pattern_t        *pattern,
        1598                 :                                           cairo_surface_t            *dst,
        1599                 :                                           int                        x,
        1600                 :                                           int                        y,
        1601                 :                                           unsigned int               width,
        1602                 :                                           unsigned int               height,
        1603                 :                                           cairo_surface_t            **out,
        1604                 :                                           cairo_surface_attributes_t *attribs)
        1605                 : {
        1606                 :     static int i;
        1607                 :
        1608               0 :     cairo_surface_t *surface, *to_destroy = NULL;
        1609                 :     cairo_status_t   status;
        1610                 :
        1611                 :     CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
        1612                 :
        1613                 :     /* Check cache first */
        1614               0 :     if (i < solid_surface_cache.size &&
        1615               0 :         _cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
        1616                 :                                                     pattern,
        1617                 :                                                     dst))
        1618                 :     {
        1619               0 :         goto DONE;
        1620                 :     }
        1621                 :
        1622               0 :     for (i = 0 ; i < solid_surface_cache.size; i++) {
        1623               0 :         if (_cairo_pattern_solid_surface_matches_color (&solid_surface_cache.cache[i],
        1624                 :                                                         pattern,
        1625                 :                                                         dst))
        1626                 :         {
        1627               0 :             goto DONE;
        1628                 :         }
        1629                 :     }
        1630                 :
        1631                 :     /* Choose a surface to repaint/evict */
        1632               0 :     surface = NULL;
        1633               0 :     if (solid_surface_cache.size == MAX_SURFACE_CACHE_SIZE) {
        1634               0 :         i = rand () % MAX_SURFACE_CACHE_SIZE;
        1635               0 :         surface = solid_surface_cache.cache[i].surface;
        1636                 :
        1637               0 :         if (_cairo_pattern_solid_surface_matches (&solid_surface_cache.cache[i],
        1638                 :                                                   pattern,
        1639                 :                                                   dst))
        1640                 :         {
        1641                 :             /* Reuse the surface instead of evicting */
        1642               0 :             status = _cairo_surface_repaint_solid_pattern_surface (dst, surface, pattern);
        1643               0 :             if (unlikely (status))
        1644               0 :                 goto EVICT;
        1645                 :
        1646               0 :             cairo_surface_reference (surface);
        1647                 :         }
        1648                 :         else
        1649                 :         {
        1650                 :           EVICT:
        1651               0 :             surface = NULL;
        1652                 :         }
        1653                 :     }
        1654                 :
        1655               0 :     if (surface == NULL) {
        1656                 :         /* Not cached, need to create new */
        1657               0 :         surface = _cairo_surface_create_solid_pattern_surface (dst, pattern);
        1658               0 :         if (surface == NULL) {
        1659               0 :             status = CAIRO_INT_STATUS_UNSUPPORTED;
        1660               0 :             goto UNLOCK;
        1661                 :         }
        1662               0 :         if (unlikely (surface->status)) {
        1663               0 :             status = surface->status;
        1664               0 :             goto UNLOCK;
        1665                 :         }
        1666                 :
        1667               0 :         if (unlikely (! _cairo_surface_is_similar (surface, dst)))
        1668                 :         {
        1669                 :             /* In the rare event of a substitute surface being returned,
        1670                 :              * don't cache the fallback.
        1671                 :              */
        1672               0 :             *out = surface;
        1673               0 :             goto NOCACHE;
        1674                 :         }
        1675                 :     }
        1676                 :
        1677               0 :     if (i == solid_surface_cache.size)
        1678               0 :         solid_surface_cache.size++;
        1679                 :
        1680               0 :     to_destroy = solid_surface_cache.cache[i].surface;
        1681               0 :     solid_surface_cache.cache[i].surface = surface;
        1682               0 :     solid_surface_cache.cache[i].color   = pattern->color;
        1683                 :
        1684                 : DONE:
        1685               0 :     *out = cairo_surface_reference (solid_surface_cache.cache[i].surface);
        1686                 :
        1687                 : NOCACHE:
        1688               0 :     attribs->x_offset = attribs->y_offset = 0;
        1689               0 :     cairo_matrix_init_identity (&attribs->matrix);
        1690               0 :     attribs->extend = CAIRO_EXTEND_REPEAT;
        1691               0 :     attribs->filter = CAIRO_FILTER_NEAREST;
        1692               0 :     attribs->has_component_alpha = pattern->base.has_component_alpha;
        1693                 :
        1694               0 :     status = CAIRO_STATUS_SUCCESS;
        1695                 :
        1696                 : UNLOCK:
        1697                 :     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
        1698                 :
        1699               0 :     if (to_destroy)
        1700               0 :       cairo_surface_destroy (to_destroy);
        1701                 :
        1702               0 :     return status;
        1703                 : }
        1704                 :
        1705                 : static void
        1706               3 : _cairo_pattern_reset_solid_surface_cache (void)
        1707                 : {
        1708                 :     CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
        1709                 :
        1710                 :     /* remove surfaces starting from the end so that solid_surface_cache.cache
        1711                 :      * is always in a consistent state when we release the mutex. */
        1712               6 :     while (solid_surface_cache.size) {
        1713                 :         cairo_surface_t *surface;
        1714                 :
        1715               0 :         solid_surface_cache.size--;
        1716               0 :         surface = solid_surface_cache.cache[solid_surface_cache.size].surface;
        1717               0 :         solid_surface_cache.cache[solid_surface_cache.size].surface = NULL;
        1718                 :
        1719                 :         /* release the lock to avoid the possibility of a recursive
        1720                 :          * deadlock when the surface destroy closure gets called */
        1721                 :         CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
        1722               0 :         cairo_surface_destroy (surface);
        1723                 :         CAIRO_MUTEX_LOCK (_cairo_pattern_solid_surface_cache_lock);
        1724                 :     }
        1725                 :
        1726                 :     CAIRO_MUTEX_UNLOCK (_cairo_pattern_solid_surface_cache_lock);
        1727               3 : }
        1728                 :
        1729                 : static void
        1730               0 : _extents_to_linear_parameter (const cairo_linear_pattern_t *linear,
        1731                 :                               const cairo_rectangle_int_t *extents,
        1732                 :                               double t[2])
        1733                 : {
        1734                 :     double t0, tdx, tdy;
        1735                 :     double p1x, p1y, pdx, pdy, invsqnorm;
        1736                 :
        1737               0 :     p1x = _cairo_fixed_to_double (linear->p1.x);
        1738               0 :     p1y = _cairo_fixed_to_double (linear->p1.y);
        1739               0 :     pdx = _cairo_fixed_to_double (linear->p2.x) - p1x;
        1740               0 :     pdy = _cairo_fixed_to_double (linear->p2.y) - p1y;
        1741               0 :     invsqnorm = 1.0 / (pdx * pdx + pdy * pdy);
        1742               0 :     pdx *= invsqnorm;
        1743               0 :     pdy *= invsqnorm;
        1744                 :
        1745               0 :     t0 = (extents->x - p1x) * pdx + (extents->y - p1y) * pdy;
        1746               0 :     tdx = extents->width * pdx;
        1747               0 :     tdy = extents->height * pdy;
        1748                 :
        1749               0 :     t[0] = t[1] = t0;
        1750               0 :     if (tdx < 0)
        1751               0 :         t[0] += tdx;
        1752                 :     else
        1753               0 :         t[1] += tdx;
        1754                 :
        1755               0 :     if (tdy < 0)
        1756               0 :         t[0] += tdy;
        1757                 :     else
        1758               0 :         t[1] += tdy;
        1759               0 : }
        1760                 :
        1761                 : static cairo_bool_t
        1762               0 : _linear_pattern_is_degenerate (const cairo_linear_pattern_t *linear)
        1763                 : {
        1764               0 :     return linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y;
        1765                 : }
        1766                 :
        1767                 : static cairo_bool_t
        1768               0 : _radial_pattern_is_degenerate (const cairo_radial_pattern_t *radial)
        1769                 : {
        1770               0 :     return radial->r1 == radial->r2 &&
        1771               0 :         (radial->r1 == 0 /* && radial->r2 == 0 */ ||
        1772               0 :          (radial->c1.x == radial->c2.x && radial->c1.y == radial->c2.y));
        1773                 : }
        1774                 :
        1775                 : static cairo_bool_t
        1776               0 : _gradient_is_clear (const cairo_gradient_pattern_t *gradient,
        1777                 :                     const cairo_rectangle_int_t *extents)
        1778                 : {
        1779                 :     unsigned int i;
        1780                 :
        1781               0 :     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
        1782                 :             gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
        1783                 :
        1784               0 :     if (gradient->n_stops == 0 ||
        1785               0 :         (gradient->base.extend == CAIRO_EXTEND_NONE &&
        1786               0 :          gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
        1787               0 :         return TRUE;
        1788                 :
        1789                 :     /* Check if the extents intersect the drawn part of the pattern. */
        1790               0 :     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
        1791               0 :         if (gradient->base.extend == CAIRO_EXTEND_NONE) {
        1792               0 :             cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
        1793                 :             /* EXTEND_NONE degenerate linear gradients are clear */
        1794               0 :             if (_linear_pattern_is_degenerate (linear))
        1795               0 :                 return TRUE;
        1796                 :
        1797               0 :             if (extents != NULL) {
        1798                 :                 double t[2];
        1799               0 :                 _extents_to_linear_parameter (linear, extents, t);
        1800               0 :                 if ((t[0] <= 0.0 && t[1] <= 0.0) || (t[0] >= 1.0 && t[1] >= 1.0))
        1801               0 :                     return TRUE;
        1802                 :             }
        1803                 :         }
        1804                 :     } else {
        1805               0 :         cairo_radial_pattern_t *radial = (cairo_radial_pattern_t *) gradient;
        1806                 :         /* degenerate radial gradients are clear */
        1807               0 :         if (_radial_pattern_is_degenerate (radial) && FALSE)
        1808                 :             return TRUE;
        1809                 :         /* TODO: check actual intersection */
        1810                 :     }
        1811                 :
        1812               0 :     for (i = 0; i < gradient->n_stops; i++)
        1813               0 :         if (! CAIRO_COLOR_IS_CLEAR (&gradient->stops[i].color))
        1814               0 :             return FALSE;
        1815                 :
        1816               0 :     return TRUE;
        1817                 : }
        1818                 :
        1819                 : /**
        1820                 :  * _cairo_gradient_pattern_is_solid
        1821                 :  *
        1822                 :  * Convenience function to determine whether a gradient pattern is
        1823                 :  * a solid color within the given extents. In this case the color
        1824                 :  * argument is initialized to the color the pattern represents.
        1825                 :  * This functions doesn't handle completely transparent gradients,
        1826                 :  * thus it should be called only after _cairo_pattern_is_clear has
        1827                 :  * returned FALSE.
        1828                 :  *
        1829                 :  * Return value: %TRUE if the pattern is a solid color.
        1830                 :  **/
        1831                 : cairo_bool_t
        1832               0 : _cairo_gradient_pattern_is_solid (const cairo_gradient_pattern_t *gradient,
        1833                 :                                   const cairo_rectangle_int_t *extents,
        1834                 :                                   cairo_color_t *color)
        1835                 : {
        1836                 :     unsigned int i;
        1837                 :
        1838               0 :     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
        1839                 :             gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
        1840                 :
        1841                 :     /* TODO: radial, degenerate linear */
        1842               0 :     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
        1843               0 :         if (gradient->base.extend == CAIRO_EXTEND_NONE) {
        1844               0 :             cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
        1845                 :             double t[2];
        1846                 :
        1847                 :             /* We already know that the pattern is not clear, thus if some
        1848                 :              * part of it is clear, the whole is not solid.
        1849                 :              */
        1850                 :
        1851               0 :             if (extents == NULL)
        1852               0 :                 return FALSE;
        1853                 :
        1854               0 :             _extents_to_linear_parameter (linear, extents, t);
        1855               0 :             if (t[0] < 0.0 || t[1] > 1.0)
        1856               0 :                 return FALSE;
        1857                 :         }
        1858                 :     }
        1859                 :
        1860               0 :     for (i = 1; i < gradient->n_stops; i++)
        1861               0 :         if (! _cairo_color_stop_equal (&gradient->stops[0].color,
        1862               0 :                                        &gradient->stops[i].color))
        1863               0 :             return FALSE;
        1864                 :
        1865               0 :     _cairo_color_init_rgba (color,
        1866               0 :                             gradient->stops[0].color.red,
        1867               0 :                             gradient->stops[0].color.green,
        1868               0 :                             gradient->stops[0].color.blue,
        1869               0 :                             gradient->stops[0].color.alpha);
        1870                 :
        1871               0 :     return TRUE;
        1872                 : }
        1873                 :
        1874                 : /**
        1875                 :  * _cairo_pattern_is_opaque_solid
        1876                 :  *
        1877                 :  * Convenience function to determine whether a pattern is an opaque
        1878                 :  * (alpha==1.0) solid color pattern. This is done by testing whether
        1879                 :  * the pattern's alpha value when converted to a byte is 255, so if a
        1880                 :  * backend actually supported deep alpha channels this function might
        1881                 :  * not do the right thing.
        1882                 :  *
        1883                 :  * Return value: %TRUE if the pattern is an opaque, solid color.
        1884                 :  **/
        1885                 : cairo_bool_t
        1886               0 : _cairo_pattern_is_opaque_solid (const cairo_pattern_t *pattern)
        1887                 : {
        1888                 :     cairo_solid_pattern_t *solid;
        1889                 :
        1890               0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
        1891               0 :         return FALSE;
        1892                 :
        1893               0 :     solid = (cairo_solid_pattern_t *) pattern;
        1894                 :
        1895               0 :     return CAIRO_COLOR_IS_OPAQUE (&solid->color);
        1896                 : }
        1897                 :
        1898                 : static cairo_bool_t
        1899               0 : _surface_is_opaque (const cairo_surface_pattern_t *pattern,
        1900                 :                     const cairo_rectangle_int_t *r)
        1901                 : {
        1902               0 :     if (pattern->surface->content & CAIRO_CONTENT_ALPHA)
        1903               0 :         return FALSE;
        1904                 :
        1905               0 :     if (pattern->base.extend != CAIRO_EXTEND_NONE)
        1906               0 :         return TRUE;
        1907                 :
        1908               0 :     if (r != NULL) {
        1909                 :         cairo_rectangle_int_t extents;
        1910                 :
        1911               0 :         if (! _cairo_surface_get_extents (pattern->surface, &extents))
        1912               0 :             return TRUE;
        1913                 :
        1914               0 :         if (r->x >= extents.x &&
        1915               0 :             r->y >= extents.y &&
        1916               0 :             r->x + r->width <= extents.x + extents.width &&
        1917               0 :             r->y + r->height <= extents.y + extents.height)
        1918                 :         {
        1919               0 :             return TRUE;
        1920                 :         }
        1921                 :     }
        1922                 :
        1923               0 :     return FALSE;
        1924                 : }
        1925                 :
        1926                 : static cairo_bool_t
        1927              47 : _surface_is_clear (const cairo_surface_pattern_t *pattern)
        1928                 : {
        1929                 :     cairo_rectangle_int_t extents;
        1930                 :
        1931              94 :     if (_cairo_surface_get_extents (pattern->surface, &extents) &&
        1932              94 :         (extents.width == 0 || extents.height == 0))
        1933               0 :         return TRUE;
        1934                 :
        1935              47 :     return pattern->surface->is_clear &&
        1936               0 :         pattern->surface->content & CAIRO_CONTENT_ALPHA;
        1937                 : }
        1938                 :
        1939                 : static cairo_bool_t
        1940               0 : _gradient_is_opaque (const cairo_gradient_pattern_t *gradient,
        1941                 :                      const cairo_rectangle_int_t *extents)
        1942                 : {
        1943                 :     unsigned int i;
        1944                 :
        1945               0 :     assert (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR ||
        1946                 :             gradient->base.type == CAIRO_PATTERN_TYPE_RADIAL);
        1947                 :
        1948               0 :     if (gradient->n_stops == 0 ||
        1949               0 :         (gradient->base.extend == CAIRO_EXTEND_NONE &&
        1950               0 :          gradient->stops[0].offset == gradient->stops[gradient->n_stops - 1].offset))
        1951               0 :         return FALSE;
        1952                 :
        1953               0 :     if (gradient->base.type == CAIRO_PATTERN_TYPE_LINEAR) {
        1954               0 :         if (gradient->base.extend == CAIRO_EXTEND_NONE) {
        1955                 :             double t[2];
        1956               0 :             cairo_linear_pattern_t *linear = (cairo_linear_pattern_t *) gradient;
        1957                 :
        1958                 :             /* EXTEND_NONE degenerate radial gradients are clear */
        1959               0 :             if (_linear_pattern_is_degenerate (linear))
        1960               0 :                 return FALSE;
        1961                 :
        1962               0 :             if (extents == NULL)
        1963               0 :                 return FALSE;
        1964                 :
        1965               0 :             _extents_to_linear_parameter (linear, extents, t);
        1966               0 :             if (t[0] < 0.0 || t[1] > 1.0)
        1967               0 :                 return FALSE;
        1968                 :         }
        1969                 :     }
        1970                 :
        1971               0 :     for (i = 0; i < gradient->n_stops; i++)
        1972               0 :         if (! CAIRO_COLOR_IS_OPAQUE (&gradient->stops[i].color))
        1973               0 :             return FALSE;
        1974                 :
        1975               0 :     return TRUE;
        1976                 : }
        1977                 :
        1978                 : /**
        1979                 :  * _cairo_pattern_is_opaque
        1980                 :  *
        1981                 :  * Convenience function to determine whether a pattern is an opaque
        1982                 :  * pattern (of any type). The same caveats that apply to
        1983                 :  * _cairo_pattern_is_opaque_solid apply here as well.
        1984                 :  *
        1985                 :  * Return value: %TRUE if the pattern is a opaque.
        1986                 :  **/
        1987                 : cairo_bool_t
        1988               0 : _cairo_pattern_is_opaque (const cairo_pattern_t *abstract_pattern,
        1989                 :                           const cairo_rectangle_int_t *extents)
        1990                 : {
        1991                 :     const cairo_pattern_union_t *pattern;
        1992                 :
        1993               0 :     if (abstract_pattern->has_component_alpha)
        1994               0 :         return FALSE;
        1995                 :
        1996               0 :     pattern = (cairo_pattern_union_t *) abstract_pattern;
        1997               0 :     switch (pattern->base.type) {
        1998                 :     case CAIRO_PATTERN_TYPE_SOLID:
        1999               0 :         return _cairo_pattern_is_opaque_solid (abstract_pattern);
        2000                 :     case CAIRO_PATTERN_TYPE_SURFACE:
        2001               0 :         return _surface_is_opaque (&pattern->surface, extents);
        2002                 :     case CAIRO_PATTERN_TYPE_LINEAR:
        2003                 :     case CAIRO_PATTERN_TYPE_RADIAL:
        2004               0 :         return _gradient_is_opaque (&pattern->gradient.base, extents);
        2005                 :     }
        2006                 :
        2007               0 :     ASSERT_NOT_REACHED;
        2008               0 :     return FALSE;
        2009                 : }
        2010                 :
        2011                 : cairo_bool_t
        2012              47 : _cairo_pattern_is_clear (const cairo_pattern_t *abstract_pattern)
        2013                 : {
        2014                 :     const cairo_pattern_union_t *pattern;
        2015                 :
        2016              47 :     if (abstract_pattern->has_component_alpha)
        2017               0 :         return FALSE;
        2018                 :
        2019              47 :     pattern = (cairo_pattern_union_t *) abstract_pattern;
        2020              47 :     switch (pattern->type) {
        2021                 :     case CAIRO_PATTERN_TYPE_SOLID:
        2022               0 :         return CAIRO_COLOR_IS_CLEAR (&pattern->solid.color);
        2023                 :     case CAIRO_PATTERN_TYPE_SURFACE:
        2024              47 :         return _surface_is_clear (&pattern->surface);
        2025                 :     case CAIRO_PATTERN_TYPE_LINEAR:
        2026                 :     case CAIRO_PATTERN_TYPE_RADIAL:
        2027               0 :         return _gradient_is_clear (&pattern->gradient.base, NULL);
        2028                 :     }
        2029                 :
        2030               0 :     ASSERT_NOT_REACHED;
        2031               0 :     return FALSE;
        2032                 : }
        2033                 :
        2034                 : /**
        2035                 :  * _cairo_pattern_analyze_filter:
        2036                 :  * @pattern: surface pattern
        2037                 :  * @pad_out: location to store necessary padding in the source image, or %NULL
        2038                 :  * Returns: the optimized #cairo_filter_t to use with @pattern.
        2039                 :  *
        2040                 :  * Analyze the filter to determine how much extra needs to be sampled
        2041                 :  * from the source image to account for the filter radius and whether
        2042                 :  * we can optimize the filter to a simpler value.
        2043                 :  *
        2044                 :  * XXX: We don't actually have any way of querying the backend for
        2045                 :  *      the filter radius, so we just guess base on what we know that
        2046                 :  *      backends do currently (see bug #10508)
        2047                 :  */
        2048                 : cairo_filter_t
        2049              94 : _cairo_pattern_analyze_filter (const cairo_pattern_t    *pattern,
        2050                 :                                double                   *pad_out)
        2051                 : {
        2052                 :     double pad;
        2053                 :     cairo_filter_t optimized_filter;
        2054                 :
        2055              94 :     switch (pattern->filter) {
        2056                 :     case CAIRO_FILTER_GOOD:
        2057                 :     case CAIRO_FILTER_BEST:
        2058                 :     case CAIRO_FILTER_BILINEAR:
        2059                 :         /* If source pixels map 1:1 onto destination pixels, we do
        2060                 :          * not need to filter (and do not want to filter, since it
        2061                 :          * will cause blurriness)
        2062                 :          */
        2063              94 :         if (_cairo_matrix_is_pixel_exact (&pattern->matrix)) {
        2064              74 :             pad = 0.;
        2065              74 :             optimized_filter = CAIRO_FILTER_NEAREST;
        2066                 :         } else {
        2067                 :             /* 0.5 is enough for a bilinear filter. It's possible we
        2068                 :              * should defensively use more for CAIRO_FILTER_BEST, but
        2069                 :              * without a single example, it's hard to know how much
        2070                 :              * more would be defensive...
        2071                 :              */
        2072              20 :             pad = 0.5;
        2073              20 :             optimized_filter = pattern->filter;
        2074                 :         }
        2075              94 :         break;
        2076                 :
        2077                 :     case CAIRO_FILTER_FAST:
        2078                 :     case CAIRO_FILTER_NEAREST:
        2079                 :     case CAIRO_FILTER_GAUSSIAN:
        2080                 :     default:
        2081               0 :         pad = 0.;
        2082               0 :         optimized_filter = pattern->filter;
        2083               0 :         break;
        2084                 :     }
        2085                 :
        2086              94 :     if (pad_out)
        2087              94 :         *pad_out = pad;
        2088                 :
        2089              94 :     return optimized_filter;
        2090                 : }
        2091                 :
        2092                 :
        2093                 : static double
        2094               0 : _pixman_nearest_sample (double d)
        2095                 : {
        2096               0 :     return ceil (d - .5);
        2097                 : }
        2098                 :
        2099                 : static cairo_int_status_t
        2100               0 : _cairo_pattern_acquire_surface_for_surface (const cairo_surface_pattern_t   *pattern,
        2101                 :                                             cairo_surface_t            *dst,
        2102                 :                                             int                        x,
        2103                 :                                             int                        y,
        2104                 :                                             unsigned int               width,
        2105                 :                                             unsigned int               height,
        2106                 :                                             unsigned int               flags,
        2107                 :                                             cairo_surface_t            **out,
        2108                 :                                             cairo_surface_attributes_t *attr)
        2109                 : {
        2110                 :     cairo_surface_t *surface;
        2111                 :     cairo_rectangle_int_t extents;
        2112                 :     cairo_rectangle_int_t sampled_area;
        2113                 :     double x1, y1, x2, y2;
        2114                 :     int tx, ty;
        2115                 :     double pad;
        2116                 :     cairo_bool_t is_identity;
        2117                 :     cairo_bool_t is_empty;
        2118                 :     cairo_bool_t is_bounded;
        2119                 :     cairo_int_status_t status;
        2120                 :
        2121               0 :     surface = cairo_surface_reference (pattern->surface);
        2122                 :
        2123               0 :     is_identity = FALSE;
        2124               0 :     attr->matrix = pattern->base.matrix;
        2125               0 :     attr->extend = pattern->base.extend;
        2126               0 :     attr->filter = _cairo_pattern_analyze_filter (&pattern->base, &pad);
        2127               0 :     attr->has_component_alpha = pattern->base.has_component_alpha;
        2128                 :
        2129               0 :     attr->x_offset = attr->y_offset = tx = ty = 0;
        2130               0 :     if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
        2131               0 :         cairo_matrix_init_identity (&attr->matrix);
        2132               0 :         attr->x_offset = tx;
        2133               0 :         attr->y_offset = ty;
        2134               0 :         is_identity = TRUE;
        2135               0 :     } else if (attr->filter == CAIRO_FILTER_NEAREST) {
        2136                 :         /*
        2137                 :          * For NEAREST, we can remove the fractional translation component
        2138                 :          * from the transformation - this ensures that the pattern will always
        2139                 :          * hit fast-paths in the backends for simple transformations that
        2140                 :          * become (almost) identity, without loss of quality.
        2141                 :          */
        2142               0 :         attr->matrix.x0 = 0;
        2143               0 :         attr->matrix.y0 = 0;
        2144               0 :         if (_cairo_matrix_is_pixel_exact (&attr->matrix)) {
        2145                 :             /* The rounding here is rather peculiar as it needs to match the
        2146                 :              * rounding performed on the sample coordinate used by pixman.
        2147                 :              */
        2148               0 :             attr->matrix.x0 = _pixman_nearest_sample (pattern->base.matrix.x0);
        2149               0 :             attr->matrix.y0 = _pixman_nearest_sample (pattern->base.matrix.y0);
        2150                 :         } else {
        2151               0 :             attr->matrix.x0 = pattern->base.matrix.x0;
        2152               0 :             attr->matrix.y0 = pattern->base.matrix.y0;
        2153                 :         }
        2154                 :
        2155               0 :         if (_cairo_matrix_is_integer_translation (&attr->matrix, &tx, &ty)) {
        2156               0 :             cairo_matrix_init_identity (&attr->matrix);
        2157               0 :             attr->x_offset = tx;
        2158               0 :             attr->y_offset = ty;
        2159               0 :             is_identity = TRUE;
        2160                 :         }
        2161                 :     }
        2162                 :
        2163                 :     /* XXX: Hack:
        2164                 :      *
        2165                 :      * The way we currently support CAIRO_EXTEND_REFLECT is to create
        2166                 :      * an image twice bigger on each side, and create a pattern of four
        2167                 :      * images such that the new image, when repeated, has the same effect
        2168                 :      * of reflecting the original pattern.
        2169                 :      */
        2170               0 :     if (flags & CAIRO_PATTERN_ACQUIRE_NO_REFLECT &&
        2171               0 :         attr->extend == CAIRO_EXTEND_REFLECT)
        2172                 :     {
        2173                 :         cairo_t *cr;
        2174                 :         cairo_surface_t *src;
        2175                 :         int w, h;
        2176                 :
        2177               0 :         is_bounded = _cairo_surface_get_extents (surface, &extents);
        2178               0 :         assert (is_bounded);
        2179                 :
        2180               0 :         status = _cairo_surface_clone_similar (dst, surface,
        2181                 :                                                extents.x, extents.y,
        2182                 :                                                extents.width, extents.height,
        2183                 :                                                &extents.x, &extents.y, &src);
        2184               0 :         if (unlikely (status))
        2185               0 :             goto BAIL;
        2186                 :
        2187               0 :         w = 2 * extents.width;
        2188               0 :         h = 2 * extents.height;
        2189                 :
        2190               0 :         if (is_identity) {
        2191               0 :             attr->x_offset = -x;
        2192               0 :             x += tx;
        2193               0 :             while (x <= -w)
        2194               0 :                 x += w;
        2195               0 :             while (x >= w)
        2196               0 :                 x -= w;
        2197               0 :             extents.x += x;
        2198               0 :             tx = x = 0;
        2199                 :
        2200               0 :             attr->y_offset = -y;
        2201               0 :             y += ty;
        2202               0 :             while (y <= -h)
        2203               0 :                 y += h;
        2204               0 :             while (y >= h)
        2205               0 :                 y -= h;
        2206               0 :             extents.y += y;
        2207               0 :             ty = y = 0;
        2208                 :         }
        2209                 :
        2210               0 :         cairo_surface_destroy (surface);
        2211               0 :         surface = _cairo_surface_create_similar_solid (dst,
        2212                 :                                                        dst->content, w, h,
        2213                 :                                                        CAIRO_COLOR_TRANSPARENT,
        2214                 :                                                        FALSE);
        2215               0 :         if (surface == NULL)
        2216               0 :             return CAIRO_INT_STATUS_UNSUPPORTED;
        2217               0 :         if (unlikely (surface->status)) {
        2218               0 :             cairo_surface_destroy (src);
        2219               0 :             return surface->status;
        2220                 :         }
        2221                 :
        2222               0 :         surface->device_transform = pattern->surface->device_transform;
        2223               0 :         surface->device_transform_inverse = pattern->surface->device_transform_inverse;
        2224                 :
        2225               0 :         cr = cairo_create (surface);
        2226                 :
        2227               0 :         cairo_set_source_surface (cr, src, -extents.x, -extents.y);
        2228               0 :         cairo_paint (cr);
        2229                 :
        2230               0 :         cairo_scale (cr, -1, +1);
        2231               0 :         cairo_set_source_surface (cr, src, extents.x-w, -extents.y);
        2232               0 :         cairo_paint (cr);
        2233               0 :         cairo_set_source_surface (cr, src, extents.x, -extents.y);
        2234               0 :         cairo_paint (cr);
        2235                 :
        2236               0 :         cairo_scale (cr, +1, -1);
        2237               0 :         cairo_set_source_surface (cr, src, extents.x-w, extents.y-h);
        2238               0 :         cairo_paint (cr);
        2239               0 :         cairo_set_source_surface (cr, src, extents.x, extents.y-h);
        2240               0 :         cairo_paint (cr);
        2241               0 :         cairo_set_source_surface (cr, src, extents.x-w, extents.y);
        2242               0 :         cairo_paint (cr);
        2243               0 :         cairo_set_source_surface (cr, src, extents.x, extents.y);
        2244               0 :         cairo_paint (cr);
        2245                 :
        2246               0 :         cairo_scale (cr, -1, +1);
        2247               0 :         cairo_set_source_surface (cr, src, -extents.x, extents.y-h);
        2248               0 :         cairo_paint (cr);
        2249               0 :         cairo_set_source_surface (cr, src, -extents.x, extents.y);
        2250               0 :         cairo_paint (cr);
        2251                 :
        2252               0 :         status = cairo_status (cr);
        2253               0 :         cairo_destroy (cr);
        2254                 :
        2255               0 :         cairo_surface_destroy (src);
        2256                 :
        2257               0 :         if (unlikely (status))
        2258               0 :             goto BAIL;
        2259                 :
        2260               0 :         attr->extend = CAIRO_EXTEND_REPEAT;
        2261                 :     }
        2262                 :
        2263                 :     /* We first transform the rectangle to the coordinate space of the
        2264                 :      * source surface so that we only need to clone that portion of the
        2265                 :      * surface that will be read.
        2266                 :      */
        2267               0 :     x1 = x;
        2268               0 :     y1 = y;
        2269               0 :     x2 = x + (int) width;
        2270               0 :     y2 = y + (int) height;
        2271               0 :     if (! is_identity) {
        2272               0 :         _cairo_matrix_transform_bounding_box (&attr->matrix,
        2273                 :                                               &x1, &y1, &x2, &y2,
        2274                 :                                               NULL);
        2275                 :     }
        2276                 :
        2277               0 :     sampled_area.x = floor (x1 - pad);
        2278               0 :     sampled_area.y = floor (y1 - pad);
        2279               0 :     sampled_area.width  = ceil (x2 + pad) - sampled_area.x;
        2280               0 :     sampled_area.height = ceil (y2 + pad) - sampled_area.y;
        2281                 :
        2282               0 :     sampled_area.x += tx;
        2283               0 :     sampled_area.y += ty;
        2284                 :
        2285               0 :     if ( _cairo_surface_get_extents (surface, &extents)) {
        2286               0 :         if (attr->extend == CAIRO_EXTEND_NONE) {
        2287                 :             /* Never acquire a larger area than the source itself */
        2288               0 :             is_empty = _cairo_rectangle_intersect (&extents, &sampled_area);
        2289                 :         } else {
        2290               0 :             int trim = 0;
        2291                 :
        2292               0 :             if (sampled_area.x >= extents.x &&
        2293               0 :                 sampled_area.x + (int) sampled_area.width <= extents.x + (int) extents.width)
        2294                 :             {
        2295                 :                 /* source is horizontally contained within extents, trim */
        2296               0 :                 extents.x = sampled_area.x;
        2297               0 :                 extents.width = sampled_area.width;
        2298               0 :                 trim |= 0x1;
        2299                 :             }
        2300                 :
        2301               0 :             if (sampled_area.y >= extents.y &&
        2302               0 :                 sampled_area.y + (int) sampled_area.height <= extents.y + (int) extents.height)
        2303                 :             {
        2304                 :                 /* source is vertically contained within extents, trim */
        2305               0 :                 extents.y = sampled_area.y;
        2306               0 :                 extents.height = sampled_area.height;
        2307               0 :                 trim |= 0x2;
        2308                 :             }
        2309                 :
        2310               0 :             if (trim == 0x3) {
        2311                 :                 /* source is wholly contained within extents, drop the REPEAT */
        2312               0 :                 attr->extend = CAIRO_EXTEND_NONE;
        2313                 :             }
        2314                 :
        2315               0 :             is_empty = extents.width == 0 || extents.height == 0;
        2316                 :         }
        2317                 :     }
        2318                 :
        2319                 :     /* XXX can we use is_empty? */
        2320                 :
        2321               0 :     status = _cairo_surface_clone_similar (dst, surface,
        2322                 :                                            extents.x, extents.y,
        2323                 :                                            extents.width, extents.height,
        2324                 :                                            &x, &y, out);
        2325               0 :     if (unlikely (status))
        2326               0 :         goto BAIL;
        2327                 :
        2328               0 :     if (x != 0 || y != 0) {
        2329               0 :         if (is_identity) {
        2330               0 :             attr->x_offset -= x;
        2331               0 :             attr->y_offset -= y;
        2332                 :         } else {
        2333                 :             cairo_matrix_t m;
        2334                 :
        2335               0 :             x -= attr->x_offset;
        2336               0 :             y -= attr->y_offset;
        2337               0 :             attr->x_offset = 0;
        2338               0 :             attr->y_offset = 0;
        2339                 :
        2340               0 :             cairo_matrix_init_translate (&m, -x, -y);
        2341               0 :             cairo_matrix_multiply (&attr->matrix, &attr->matrix, &m);
        2342                 :         }
        2343                 :     }
        2344                 :
        2345                 :     /* reduce likelihood of range overflow with large downscaling */
        2346               0 :     if (! is_identity) {
        2347                 :         cairo_matrix_t m;
        2348                 :         cairo_status_t invert_status;
        2349                 :
        2350               0 :         m = attr->matrix;
        2351               0 :         invert_status = cairo_matrix_invert (&m);
        2352               0 :         assert (invert_status == CAIRO_STATUS_SUCCESS);
        2353                 :
        2354               0 :         if (m.x0 != 0. || m.y0 != 0.) {
        2355                 :             /* pixman also limits the [xy]_offset to 16 bits so evenly
        2356                 :              * spread the bits between the two.
        2357                 :              */
        2358               0 :             x = floor (m.x0 / 2);
        2359               0 :             y = floor (m.y0 / 2);
        2360               0 :             attr->x_offset -= x;
        2361               0 :             attr->y_offset -= y;
        2362               0 :             cairo_matrix_init_translate (&m, x, y);
        2363               0 :             cairo_matrix_multiply (&attr->matrix, &m, &attr->matrix);
        2364                 :         }
        2365                 :     }
        2366                 :
        2367                 :   BAIL:
        2368               0 :     cairo_surface_destroy (surface);
        2369               0 :     return status;
        2370                 : }
        2371                 :
        2372                 : /**
        2373                 :  * _cairo_pattern_acquire_surface:
        2374                 :  * @pattern: a #cairo_pattern_t
        2375                 :  * @dst: destination surface
        2376                 :  * @x: X coordinate in source corresponding to left side of destination area
        2377                 :  * @y: Y coordinate in source corresponding to top side of destination area
        2378                 :  * @width: width of destination area
        2379                 :  * @height: height of destination area
        2380                 :  * @surface_out: location to store a pointer to a surface
        2381                 :  * @attributes: surface attributes that destination backend should apply to
        2382                 :  * the returned surface
        2383                 :  *
        2384                 :  * A convenience function to obtain a surface to use as the source for
        2385                 :  * drawing on @dst.
        2386                 :  *
        2387                 :  * Note that this function is only suitable for use when the destination
        2388                 :  * surface is pixel based and 1 device unit maps to one pixel.
        2389                 :  *
        2390                 :  * Return value: %CAIRO_STATUS_SUCCESS if a surface was stored in @surface_out.
        2391                 :  **/
        2392                 : cairo_int_status_t
        2393               0 : _cairo_pattern_acquire_surface (const cairo_pattern_t      *pattern,
        2394                 :                                 cairo_surface_t            *dst,
        2395                 :                                 int                        x,
        2396                 :                                 int                        y,
        2397                 :                                 unsigned int               width,
        2398                 :                                 unsigned int               height,
        2399                 :                                 unsigned int               flags,
        2400                 :                                 cairo_surface_t            **surface_out,
        2401                 :                                 cairo_surface_attributes_t *attributes)
        2402                 : {
        2403               0 :     if (unlikely (pattern->status)) {
        2404               0 :         *surface_out = NULL;
        2405               0 :         return pattern->status;
        2406                 :     }
        2407                 :
        2408               0 :     switch (pattern->type) {
        2409                 :     case CAIRO_PATTERN_TYPE_SOLID:
        2410               0 :         return _cairo_pattern_acquire_surface_for_solid ((cairo_solid_pattern_t *) pattern,
        2411                 :                                                          dst, x, y, width, height,
        2412                 :                                                          surface_out,
        2413                 :                                                          attributes);
        2414                 :
        2415                 :     case CAIRO_PATTERN_TYPE_LINEAR:
        2416                 :     case CAIRO_PATTERN_TYPE_RADIAL:
        2417               0 :         return _cairo_pattern_acquire_surface_for_gradient ((cairo_gradient_pattern_t *) pattern,
        2418                 :                                                             dst, x, y, width, height,
        2419                 :                                                             surface_out,
        2420                 :                                                             attributes);
        2421                 :
        2422                 :     case CAIRO_PATTERN_TYPE_SURFACE:
        2423               0 :         return _cairo_pattern_acquire_surface_for_surface ((cairo_surface_pattern_t *) pattern,
        2424                 :                                                            dst, x, y, width, height,
        2425                 :                                                            flags,
        2426                 :                                                            surface_out,
        2427                 :                                                            attributes);
        2428                 :
        2429                 :     default:
        2430               0 :         ASSERT_NOT_REACHED;
        2431               0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
        2432                 :     }
        2433                 : }
        2434                 :
        2435                 : /**
        2436                 :  * _cairo_pattern_release_surface:
        2437                 :  * @pattern: a #cairo_pattern_t
        2438                 :  * @surface: a surface obtained by _cairo_pattern_acquire_surface
        2439                 :  * @attributes: attributes obtained by _cairo_pattern_acquire_surface
        2440                 :  *
        2441                 :  * Releases resources obtained by _cairo_pattern_acquire_surface.
        2442                 :  **/
        2443                 : void
        2444               0 : _cairo_pattern_release_surface (const cairo_pattern_t *pattern,
        2445                 :                                 cairo_surface_t            *surface,
        2446                 :                                 cairo_surface_attributes_t *attributes)
        2447                 : {
        2448               0 :     cairo_surface_destroy (surface);
        2449               0 : }
        2450                 :
        2451                 : cairo_int_status_t
        2452               0 : _cairo_pattern_acquire_surfaces (const cairo_pattern_t      *src,
        2453                 :                                  const cairo_pattern_t      *mask,
        2454                 :                                  cairo_surface_t            *dst,
        2455                 :                                  int                        src_x,
        2456                 :                                  int                        src_y,
        2457                 :                                  int                        mask_x,
        2458                 :                                  int                        mask_y,
        2459                 :                                  unsigned int               width,
        2460                 :                                  unsigned int               height,
        2461                 :                                  unsigned int               flags,
        2462                 :                                  cairo_surface_t            **src_out,
        2463                 :                                  cairo_surface_t            **mask_out,
        2464                 :                                  cairo_surface_attributes_t *src_attributes,
        2465                 :                                  cairo_surface_attributes_t *mask_attributes)
        2466                 : {
        2467                 :     cairo_int_status_t    status;
        2468                 :     cairo_pattern_union_t src_tmp;
        2469                 :
        2470               0 :     if (unlikely (src->status))
        2471               0 :         return src->status;
        2472               0 :     if (unlikely (mask != NULL && mask->status))
        2473               0 :         return mask->status;
        2474                 :
        2475                 :     /* If src and mask are both solid, then the mask alpha can be
        2476                 :      * combined into src and mask can be ignored. */
        2477                 :
        2478               0 :     if (src->type == CAIRO_PATTERN_TYPE_SOLID &&
        2479               0 :         mask &&
        2480               0 :         ! mask->has_component_alpha &&
        2481               0 :         mask->type == CAIRO_PATTERN_TYPE_SOLID)
        2482                 :     {
        2483                 :         cairo_color_t combined;
        2484               0 :         cairo_solid_pattern_t *src_solid = (cairo_solid_pattern_t *) src;
        2485               0 :         cairo_solid_pattern_t *mask_solid = (cairo_solid_pattern_t *) mask;
        2486                 :
        2487               0 :         combined = src_solid->color;
        2488               0 :         _cairo_color_multiply_alpha (&combined, mask_solid->color.alpha);
        2489                 :
        2490               0 :         _cairo_pattern_init_solid (&src_tmp.solid, &combined);
        2491                 :
        2492               0 :         src = &src_tmp.base;
        2493               0 :         mask = NULL;
        2494                 :     }
        2495                 :
        2496               0 :     status = _cairo_pattern_acquire_surface (src, dst,
        2497                 :                                              src_x, src_y,
        2498                 :                                              width, height,
        2499                 :                                              flags,
        2500                 :                                              src_out, src_attributes);
        2501               0 :     if (unlikely (status))
        2502               0 :         goto BAIL;
        2503                 :
        2504               0 :     if (mask == NULL) {
        2505               0 :         *mask_out = NULL;
        2506               0 :         goto BAIL;
        2507                 :     }
        2508                 :
        2509               0 :     status = _cairo_pattern_acquire_surface (mask, dst,
        2510                 :                                              mask_x, mask_y,
        2511                 :                                              width, height,
        2512                 :                                              flags,
        2513                 :                                              mask_out, mask_attributes);
        2514               0 :     if (unlikely (status))
        2515               0 :         _cairo_pattern_release_surface (src, *src_out, src_attributes);
        2516                 :
        2517                 :   BAIL:
        2518               0 :     if (src == &src_tmp.base)
        2519               0 :         _cairo_pattern_fini (&src_tmp.base);
        2520                 :
        2521               0 :     return status;
        2522                 : }
        2523                 :
        2524                 : /**
        2525                 :  * _cairo_pattern_get_extents:
        2526                 :  *
        2527                 :  * Return the "target-space" extents of @pattern in @extents.
        2528                 :  *
        2529                 :  * For unbounded patterns, the @extents will be initialized with
        2530                 :  * "infinite" extents, (minimum and maximum fixed-point values).
        2531                 :  *
        2532                 :  * XXX: Currently, bounded gradient patterns will also return
        2533                 :  * "infinite" extents, though it would be possible to optimize these
        2534                 :  * with a little more work.
        2535                 :  **/
        2536                 : void
        2537              64 : _cairo_pattern_get_extents (const cairo_pattern_t         *pattern,
        2538                 :                             cairo_rectangle_int_t         *extents)
        2539                 : {
        2540                 :     double x1, y1, x2, y2;
        2541                 :     cairo_status_t status;
        2542                 :
        2543              64 :     switch (pattern->type) {
        2544                 :     case CAIRO_PATTERN_TYPE_SOLID:
        2545              17 :         goto UNBOUNDED;
        2546                 :
        2547                 :     case CAIRO_PATTERN_TYPE_SURFACE:
        2548                 :         {
        2549                 :             cairo_rectangle_int_t surface_extents;
        2550              47 :             const cairo_surface_pattern_t *surface_pattern =
        2551                 :                 (const cairo_surface_pattern_t *) pattern;
        2552              47 :             cairo_surface_t *surface = surface_pattern->surface;
        2553                 :             double pad;
        2554                 :
        2555              47 :             if (! _cairo_surface_get_extents (surface, &surface_extents))
        2556               0 :                 goto UNBOUNDED;
        2557                 :
        2558              47 :             if (surface_extents.width == 0 || surface_extents.height == 0)
        2559                 :                 goto EMPTY;
        2560                 :
        2561              47 :             if (pattern->extend != CAIRO_EXTEND_NONE)
        2562               0 :                 goto UNBOUNDED;
        2563                 :
        2564                 :             /* The filter can effectively enlarge the extents of the
        2565                 :              * pattern, so extend as necessary.
        2566                 :              */
        2567              47 :             _cairo_pattern_analyze_filter (&surface_pattern->base, &pad);
        2568              47 :             x1 = surface_extents.x - pad;
        2569              47 :             y1 = surface_extents.y - pad;
        2570              47 :             x2 = surface_extents.x + (int) surface_extents.width  + pad;
        2571              47 :             y2 = surface_extents.y + (int) surface_extents.height + pad;
        2572                 :         }
        2573              47 :         break;
        2574                 :
        2575                 :     case CAIRO_PATTERN_TYPE_RADIAL:
        2576                 :         {
        2577               0 :             const cairo_radial_pattern_t *radial =
        2578                 :                 (const cairo_radial_pattern_t *) pattern;
        2579                 :             double cx1, cy1;
        2580                 :             double cx2, cy2;
        2581                 :             double r, D;
        2582                 :
        2583               0 :             if (radial->r1 == 0 && radial->r2 == 0)
        2584               0 :                 goto EMPTY;
        2585                 :
        2586               0 :             cx1 = _cairo_fixed_to_double (radial->c1.x);
        2587               0 :             cy1 = _cairo_fixed_to_double (radial->c1.y);
        2588               0 :             r = _cairo_fixed_to_double (radial->r1);
        2589               0 :             x1 = cx1 - r; x2 = cx1 + r;
        2590               0 :             y1 = cy1 - r; y2 = cy1 + r;
        2591                 :
        2592               0 :             cx2 = _cairo_fixed_to_double (radial->c2.x);
        2593               0 :             cy2 = _cairo_fixed_to_double (radial->c2.y);
        2594               0 :             r = fabs (_cairo_fixed_to_double (radial->r2));
        2595                 :
        2596               0 :             if (pattern->extend != CAIRO_EXTEND_NONE)
        2597               0 :                 goto UNBOUNDED;
        2598                 :
        2599                 :             /* We need to be careful, as if the circles are not
        2600                 :              * self-contained, then the solution is actually unbounded.
        2601                 :              */
        2602               0 :             D = (cx1-cx2)*(cx1-cx2) + (cy1-cy2)*(cy1-cy2);
        2603               0 :             if (D > r*r - 1e-5)
        2604               0 :                 goto UNBOUNDED;
        2605                 :
        2606               0 :             if (cx2 - r < x1)
        2607               0 :                 x1 = cx2 - r;
        2608               0 :             if (cx2 + r > x2)
        2609               0 :                 x2 = cx2 + r;
        2610                 :
        2611               0 :             if (cy2 - r < y1)
        2612               0 :                 y1 = cy2 - r;
        2613               0 :             if (cy2 + r > y2)
        2614               0 :                 y2 = cy2 + r;
        2615                 :         }
        2616               0 :         break;
        2617                 :
        2618                 :     case CAIRO_PATTERN_TYPE_LINEAR:
        2619                 :         {
        2620               0 :             const cairo_linear_pattern_t *linear =
        2621                 :                 (const cairo_linear_pattern_t *) pattern;
        2622                 :
        2623               0 :             if (pattern->extend != CAIRO_EXTEND_NONE)
        2624               0 :                 goto UNBOUNDED;
        2625                 :
        2626               0 :             if (linear->p1.x == linear->p2.x && linear->p1.y == linear->p2.y)
        2627               0 :                 goto EMPTY;
        2628                 :
        2629               0 :             if (pattern->matrix.xy != 0. || pattern->matrix.yx != 0.)
        2630                 :                 goto UNBOUNDED;
        2631                 :
        2632               0 :             if (linear->p1.x == linear->p2.x) {
        2633               0 :                 x1 = -HUGE_VAL;
        2634               0 :                 x2 = HUGE_VAL;
        2635               0 :                 y1 = _cairo_fixed_to_double (MIN (linear->p1.y, linear->p2.y));
        2636               0 :                 y2 = _cairo_fixed_to_double (MAX (linear->p1.y, linear->p2.y));
        2637               0 :             } else if (linear->p1.y == linear->p2.y) {
        2638               0 :                 x1 = _cairo_fixed_to_double (MIN (linear->p1.x, linear->p2.x));
        2639               0 :                 x2 = _cairo_fixed_to_double (MAX (linear->p1.x, linear->p2.x));
        2640               0 :                 y1 = -HUGE_VAL;
        2641               0 :                 y2 = HUGE_VAL;
        2642                 :             } else {
        2643               0 :                 goto  UNBOUNDED;
        2644                 :             }
        2645                 :         }
        2646               0 :         break;
        2647                 :
        2648                 :     default:
        2649               0 :         ASSERT_NOT_REACHED;
        2650                 :     }
        2651                 :
        2652              47 :     if (_cairo_matrix_is_translation (&pattern->matrix)) {
        2653              37 :         x1 -= pattern->matrix.x0; x2 -= pattern->matrix.x0;
        2654              37 :         y1 -= pattern->matrix.y0; y2 -= pattern->matrix.y0;
        2655                 :     } else {
        2656                 :         cairo_matrix_t imatrix;
        2657                 :
        2658              10 :         imatrix = pattern->matrix;
        2659              10 :         status = cairo_matrix_invert (&imatrix);
        2660                 :         /* cairo_pattern_set_matrix ensures the matrix is invertible */
        2661              10 :         assert (status == CAIRO_STATUS_SUCCESS);
        2662                 :
        2663              10 :         _cairo_matrix_transform_bounding_box (&imatrix,
        2664                 :                                               &x1, &y1, &x2, &y2,
        2665                 :                                               NULL);
        2666                 :     }
        2667                 :
        2668              47 :     x1 = floor (x1);
        2669              47 :     if (x1 < CAIRO_RECT_INT_MIN)
        2670               0 :         x1 = CAIRO_RECT_INT_MIN;
        2671              47 :     y1 = floor (y1);
        2672              47 :     if (y1 < CAIRO_RECT_INT_MIN)
        2673               0 :         y1 = CAIRO_RECT_INT_MIN;
        2674                 :
        2675              47 :     x2 = ceil (x2);
        2676              47 :     if (x2 > CAIRO_RECT_INT_MAX)
        2677               0 :         x2 = CAIRO_RECT_INT_MAX;
        2678              47 :     y2 = ceil (y2);
        2679              47 :     if (y2 > CAIRO_RECT_INT_MAX)
        2680               0 :         y2 = CAIRO_RECT_INT_MAX;
        2681                 :
        2682              47 :     extents->x = x1; extents->width  = x2 - x1;
        2683              47 :     extents->y = y1; extents->height = y2 - y1;
        2684              47 :     return;
        2685                 :
        2686                 :   UNBOUNDED:
        2687                 :     /* unbounded patterns -> 'infinite' extents */
        2688              17 :     _cairo_unbounded_rectangle_init (extents);
        2689              17 :     return;
        2690                 :
        2691                 :   EMPTY:
        2692               0 :     extents->x = extents->y = 0;
        2693               0 :     extents->width = extents->height = 0;
        2694               0 :     return;
        2695                 : }
        2696                 :
        2697                 :
        2698                 : static unsigned long
        2699               0 : _cairo_solid_pattern_hash (unsigned long hash,
        2700                 :                            const cairo_pattern_t *pattern)
        2701                 : {
        2702               0 :     const cairo_solid_pattern_t *solid = (cairo_solid_pattern_t *) pattern;
        2703                 :
        2704               0 :     hash = _cairo_hash_bytes (hash, &solid->color, sizeof (solid->color));
        2705                 :
        2706               0 :     return hash;
        2707                 : }
        2708                 :
        2709                 : static unsigned long
        2710               0 : _cairo_gradient_color_stops_hash (unsigned long hash,
        2711                 :                                   const cairo_gradient_pattern_t *gradient)
        2712                 : {
        2713                 :     unsigned int n;
        2714                 :
        2715               0 :     hash = _cairo_hash_bytes (hash,
        2716               0 :                               &gradient->n_stops,
        2717                 :                               sizeof (gradient->n_stops));
        2718                 :
        2719               0 :     for (n = 0; n < gradient->n_stops; n++) {
        2720               0 :         hash = _cairo_hash_bytes (hash,
        2721               0 :                                   &gradient->stops[n].offset,
        2722                 :                                   sizeof (double));
        2723               0 :         hash = _cairo_hash_bytes (hash,
        2724               0 :                                   &gradient->stops[n].color,
        2725                 :                                   sizeof (cairo_color_t));
        2726                 :     }
        2727                 :
        2728               0 :     return hash;
        2729                 : }
        2730                 :
        2731                 : unsigned long
        2732               0 : _cairo_linear_pattern_hash (unsigned long hash,
        2733                 :                             const cairo_linear_pattern_t *linear)
        2734                 : {
        2735               0 :     hash = _cairo_hash_bytes (hash, &linear->p1, sizeof (linear->p1));
        2736               0 :     hash = _cairo_hash_bytes (hash, &linear->p2, sizeof (linear->p2));
        2737                 :
        2738               0 :     return _cairo_gradient_color_stops_hash (hash, &linear->base);
        2739                 : }
        2740                 :
        2741                 : unsigned long
        2742               0 : _cairo_radial_pattern_hash (unsigned long hash,
        2743                 :                             const cairo_radial_pattern_t *radial)
        2744                 : {
        2745               0 :     hash = _cairo_hash_bytes (hash, &radial->c1, sizeof (radial->c1));
        2746               0 :     hash = _cairo_hash_bytes (hash, &radial->r1, sizeof (radial->r1));
        2747               0 :     hash = _cairo_hash_bytes (hash, &radial->c2, sizeof (radial->c2));
        2748               0 :     hash = _cairo_hash_bytes (hash, &radial->r2, sizeof (radial->r2));
        2749                 :
        2750               0 :     return _cairo_gradient_color_stops_hash (hash, &radial->base);
        2751                 : }
        2752                 :
        2753                 : static unsigned long
        2754               0 : _cairo_surface_pattern_hash (unsigned long hash,
        2755                 :                              const cairo_pattern_t *pattern)
        2756                 : {
        2757               0 :     const cairo_surface_pattern_t *surface = (cairo_surface_pattern_t *) pattern;
        2758                 :
        2759               0 :     hash ^= surface->surface->unique_id;
        2760                 :
        2761               0 :     return hash;
        2762                 : }
        2763                 :
        2764                 : unsigned long
        2765               0 : _cairo_pattern_hash (const cairo_pattern_t *pattern)
        2766                 : {
        2767               0 :     unsigned long hash = _CAIRO_HASH_INIT_VALUE;
        2768                 :
        2769               0 :     if (pattern->status)
        2770               0 :         return 0;
        2771                 :
        2772               0 :     hash = _cairo_hash_bytes (hash, &pattern->type, sizeof (pattern->type));
        2773               0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID) {
        2774               0 :         hash = _cairo_hash_bytes (hash,
        2775               0 :                                   &pattern->matrix, sizeof (pattern->matrix));
        2776               0 :         hash = _cairo_hash_bytes (hash,
        2777               0 :                                   &pattern->filter, sizeof (pattern->filter));
        2778               0 :         hash = _cairo_hash_bytes (hash,
        2779               0 :                                   &pattern->extend, sizeof (pattern->extend));
        2780               0 :         hash = _cairo_hash_bytes (hash,
        2781               0 :                                   &pattern->has_component_alpha,
        2782                 :                                   sizeof (pattern->has_component_alpha));
        2783                 :     }
        2784                 :
        2785               0 :     switch (pattern->type) {
        2786                 :     case CAIRO_PATTERN_TYPE_SOLID:
        2787               0 :         return _cairo_solid_pattern_hash (hash, pattern);
        2788                 :     case CAIRO_PATTERN_TYPE_LINEAR:
        2789               0 :         return _cairo_linear_pattern_hash (hash, (cairo_linear_pattern_t *) pattern);
        2790                 :     case CAIRO_PATTERN_TYPE_RADIAL:
        2791               0 :         return _cairo_radial_pattern_hash (hash, (cairo_radial_pattern_t *) pattern);
        2792                 :     case CAIRO_PATTERN_TYPE_SURFACE:
        2793               0 :         return _cairo_surface_pattern_hash (hash, pattern);
        2794                 :     default:
        2795               0 :         ASSERT_NOT_REACHED;
        2796               0 :         return FALSE;
        2797                 :     }
        2798                 : }
        2799                 :
        2800                 : static unsigned long
        2801               0 : _cairo_gradient_pattern_color_stops_size (const cairo_pattern_t *pattern)
        2802                 : {
        2803               0 :     cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t *) pattern;
        2804                 :
        2805               0 :     return gradient->n_stops * (sizeof (double) + sizeof (cairo_color_t));
        2806                 : }
        2807                 :
        2808                 : unsigned long
        2809               0 : _cairo_pattern_size (const cairo_pattern_t *pattern)
        2810                 : {
        2811               0 :     if (pattern->status)
        2812               0 :         return 0;
        2813                 :
        2814                 :     /* XXX */
        2815               0 :     switch (pattern->type) {
        2816                 :     case CAIRO_PATTERN_TYPE_SOLID:
        2817               0 :         return sizeof (cairo_solid_pattern_t);
        2818                 :         break;
        2819                 :     case CAIRO_PATTERN_TYPE_SURFACE:
        2820               0 :         return sizeof (cairo_surface_pattern_t);
        2821                 :         break;
        2822                 :     case CAIRO_PATTERN_TYPE_LINEAR:
        2823               0 :         return sizeof (cairo_linear_pattern_t) +
        2824               0 :             _cairo_gradient_pattern_color_stops_size (pattern);
        2825                 :         break;
        2826                 :     case CAIRO_PATTERN_TYPE_RADIAL:
        2827               0 :         return sizeof (cairo_radial_pattern_t) +
        2828               0 :             _cairo_gradient_pattern_color_stops_size (pattern);
        2829                 :     default:
        2830               0 :         ASSERT_NOT_REACHED;
        2831               0 :         return 0;
        2832                 :     }
        2833                 : }
        2834                 :
        2835                 :
        2836                 : static cairo_bool_t
        2837               0 : _cairo_solid_pattern_equal (const cairo_pattern_t *A,
        2838                 :                             const cairo_pattern_t *B)
        2839                 : {
        2840               0 :     const cairo_solid_pattern_t *a = (cairo_solid_pattern_t *) A;
        2841               0 :     const cairo_solid_pattern_t *b = (cairo_solid_pattern_t *) B;
        2842                 :
        2843               0 :     return _cairo_color_equal (&a->color, &b->color);
        2844                 : }
        2845                 :
        2846                 : static cairo_bool_t
        2847               0 : _cairo_gradient_color_stops_equal (const cairo_gradient_pattern_t *a,
        2848                 :                                    const cairo_gradient_pattern_t *b)
        2849                 : {
        2850                 :     unsigned int n;
        2851                 :
        2852               0 :     if (a->n_stops != b->n_stops)
        2853               0 :         return FALSE;
        2854                 :
        2855               0 :     for (n = 0; n < a->n_stops; n++) {
        2856               0 :         if (a->stops[n].offset != b->stops[n].offset)
        2857               0 :             return FALSE;
        2858               0 :         if (! _cairo_color_stop_equal (&a->stops[n].color, &b->stops[n].color))
        2859               0 :             return FALSE;
        2860                 :     }
        2861                 :
        2862               0 :     return TRUE;
        2863                 : }
        2864                 :
        2865                 : cairo_bool_t
        2866               0 : _cairo_linear_pattern_equal (const cairo_linear_pattern_t *a,
        2867                 :                              const cairo_linear_pattern_t *b)
        2868                 : {
        2869               0 :     if (a->p1.x != b->p1.x)
        2870               0 :         return FALSE;
        2871                 :
        2872               0 :     if (a->p1.y != b->p1.y)
        2873               0 :         return FALSE;
        2874                 :
        2875               0 :     if (a->p2.x != b->p2.x)
        2876               0 :         return FALSE;
        2877                 :
        2878               0 :     if (a->p2.y != b->p2.y)
        2879               0 :         return FALSE;
        2880                 :
        2881               0 :     return _cairo_gradient_color_stops_equal (&a->base, &b->base);
        2882                 : }
        2883                 :
        2884                 : cairo_bool_t
        2885               0 : _cairo_radial_pattern_equal (const cairo_radial_pattern_t *a,
        2886                 :                              const cairo_radial_pattern_t *b)
        2887                 : {
        2888               0 :     if (a->c1.x != b->c1.x)
        2889               0 :         return FALSE;
        2890                 :
        2891               0 :     if (a->c1.y != b->c1.y)
        2892               0 :         return FALSE;
        2893                 :
        2894               0 :     if (a->r1 != b->r1)
        2895               0 :         return FALSE;
        2896                 :
        2897               0 :     if (a->c2.x != b->c2.x)
        2898               0 :         return FALSE;
        2899                 :
        2900               0 :     if (a->c2.y != b->c2.y)
        2901               0 :         return FALSE;
        2902                 :
        2903               0 :     if (a->r2 != b->r2)
        2904               0 :         return FALSE;
        2905                 :
        2906               0 :     return _cairo_gradient_color_stops_equal (&a->base, &b->base);
        2907                 : }
        2908                 :
        2909                 : static cairo_bool_t
        2910               0 : _cairo_surface_pattern_equal (const cairo_pattern_t *A,
        2911                 :                               const cairo_pattern_t *B)
        2912                 : {
        2913               0 :     const cairo_surface_pattern_t *a = (cairo_surface_pattern_t *) A;
        2914               0 :     const cairo_surface_pattern_t *b = (cairo_surface_pattern_t *) B;
        2915                 :
        2916               0 :     return a->surface->unique_id == b->surface->unique_id;
        2917                 : }
        2918                 :
        2919                 : cairo_bool_t
        2920               0 : _cairo_pattern_equal (const cairo_pattern_t *a, const cairo_pattern_t *b)
        2921                 : {
        2922               0 :     if (a->status || b->status)
        2923               0 :         return FALSE;
        2924                 :
        2925               0 :     if (a == b)
        2926               0 :         return TRUE;
        2927                 :
        2928               0 :     if (a->type != b->type)
        2929               0 :         return FALSE;
        2930                 :
        2931               0 :     if (a->has_component_alpha != b->has_component_alpha)
        2932               0 :         return FALSE;
        2933                 :
        2934               0 :     if (a->type != CAIRO_PATTERN_TYPE_SOLID) {
        2935               0 :         if (memcmp (&a->matrix, &b->matrix, sizeof (cairo_matrix_t)))
        2936               0 :             return FALSE;
        2937                 :
        2938               0 :         if (a->filter != b->filter)
        2939               0 :             return FALSE;
        2940                 :
        2941               0 :         if (a->extend != b->extend)
        2942               0 :             return FALSE;
        2943                 :     }
        2944                 :
        2945               0 :     switch (a->type) {
        2946                 :     case CAIRO_PATTERN_TYPE_SOLID:
        2947               0 :         return _cairo_solid_pattern_equal (a, b);
        2948                 :     case CAIRO_PATTERN_TYPE_LINEAR:
        2949               0 :         return _cairo_linear_pattern_equal ((cairo_linear_pattern_t *) a,
        2950                 :                                             (cairo_linear_pattern_t *) b);
        2951                 :     case CAIRO_PATTERN_TYPE_RADIAL:
        2952               0 :         return _cairo_radial_pattern_equal ((cairo_radial_pattern_t *) a,
        2953                 :                                             (cairo_radial_pattern_t *) b);
        2954                 :     case CAIRO_PATTERN_TYPE_SURFACE:
        2955               0 :         return _cairo_surface_pattern_equal (a, b);
        2956                 :     default:
        2957               0 :         ASSERT_NOT_REACHED;
        2958               0 :         return FALSE;
        2959                 :     }
        2960                 : }
        2961                 :
        2962                 : /**
        2963                 :  * cairo_pattern_get_rgba
        2964                 :  * @pattern: a #cairo_pattern_t
        2965                 :  * @red: return value for red component of color, or %NULL
        2966                 :  * @green: return value for green component of color, or %NULL
        2967                 :  * @blue: return value for blue component of color, or %NULL
        2968                 :  * @alpha: return value for alpha component of color, or %NULL
        2969                 :  *
        2970                 :  * Gets the solid color for a solid color pattern.
        2971                 :  *
        2972                 :  * Return value: %CAIRO_STATUS_SUCCESS, or
        2973                 :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a solid
        2974                 :  * color pattern.
        2975                 :  *
        2976                 :  * Since: 1.4
        2977                 :  **/
        2978                 : cairo_status_t
        2979               0 : cairo_pattern_get_rgba (cairo_pattern_t *pattern,
        2980                 :                         double *red, double *green,
        2981                 :                         double *blue, double *alpha)
        2982                 : {
        2983               0 :     cairo_solid_pattern_t *solid = (cairo_solid_pattern_t*) pattern;
        2984                 :     double r0, g0, b0, a0;
        2985                 :
        2986               0 :     if (pattern->status)
        2987               0 :         return pattern->status;
        2988                 :
        2989               0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SOLID)
        2990               0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
        2991                 :
        2992               0 :     _cairo_color_get_rgba (&solid->color, &r0, &g0, &b0, &a0);
        2993                 :
        2994               0 :     if (red)
        2995               0 :         *red = r0;
        2996               0 :     if (green)
        2997               0 :         *green = g0;
        2998               0 :     if (blue)
        2999               0 :         *blue = b0;
        3000               0 :     if (alpha)
        3001               0 :         *alpha = a0;
        3002                 :
        3003               0 :     return CAIRO_STATUS_SUCCESS;
        3004                 : }
        3005                 :
        3006                 : /**
        3007                 :  * cairo_pattern_get_surface
        3008                 :  * @pattern: a #cairo_pattern_t
        3009                 :  * @surface: return value for surface of pattern, or %NULL
        3010                 :  *
        3011                 :  * Gets the surface of a surface pattern.  The reference returned in
        3012                 :  * @surface is owned by the pattern; the caller should call
        3013                 :  * cairo_surface_reference() if the surface is to be retained.
        3014                 :  *
        3015                 :  * Return value: %CAIRO_STATUS_SUCCESS, or
        3016                 :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if the pattern is not a surface
        3017                 :  * pattern.
        3018                 :  *
        3019                 :  * Since: 1.4
        3020                 :  **/
        3021                 : cairo_status_t
        3022               0 : cairo_pattern_get_surface (cairo_pattern_t *pattern,
        3023                 :                            cairo_surface_t **surface)
        3024                 : {
        3025               0 :     cairo_surface_pattern_t *spat = (cairo_surface_pattern_t*) pattern;
        3026                 :
        3027               0 :     if (pattern->status)
        3028               0 :         return pattern->status;
        3029                 :
        3030               0 :     if (pattern->type != CAIRO_PATTERN_TYPE_SURFACE)
        3031               0 :         return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
        3032                 :
        3033               0 :     if (surface)
        3034               0 :         *surface = spat->surface;
        3035                 :
        3036               0 :     return CAIRO_STATUS_SUCCESS;
        3037                 : }
        3038                 :
        3039                 : /**
        3040                 :  * cairo_pattern_get_color_stop_rgba
        3041                 :  * @pattern: a #cairo_pattern_t
        3042                 :  * @index: index of the stop to return data for
        3043                 :  * @offset: return value for the offset of the stop, or %NULL
        3044                 :  * @red: return value for red component of color, or %NULL
        3045                 :  * @green: return value for green component of color, or %NULL
        3046                 :  * @blue: return value for blue component of color, or %NULL
        3047                 :  * @alpha: return value for alpha component of color, or %NULL
        3048                 :  *
        3049                 :  * Gets the color and offset information at the given @index for a
        3050                 :  * gradient pattern.  Values of @index are 0 to 1 less than the number
        3051                 :  * returned by cairo_pattern_get_color_stop_count().
        3052                 :  *
        3053                 :  * Return value: %CAIRO_STATUS_SUCCESS, or %CAIRO_STATUS_INVALID_INDEX
        3054                 :  * if @index is not valid for the given pattern.  If the pattern is
        3055                 :  * not a gradient pattern, %CAIRO_STATUS_PATTERN_TYPE_MISMATCH is
        3056                 :  * returned.
        3057                 :  *
        3058                 :  * Since: 1.4
        3059                 :  **/
        3060                 : cairo_status_t
        3061               0 : cairo_pattern_get_color_stop_rgba (cairo_pattern_t *pattern,
        3062                 :                                    int index, double *offset,
        3063                 :                                    double *red, double *green,
        3064                 :                                    double *blue, double *alpha)
        3065                 : {
        3066               0 :     cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
        3067                 :
        3068               0 :     if (pattern->status)
        3069               0 :         return pattern->status;
        3070                 :
        3071               0 :     if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
        3072               0 :         pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
        3073               0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
        3074                 :
        3075               0 :     if (index < 0 || (unsigned int) index >= gradient->n_stops)
        3076               0 :         return _cairo_error (CAIRO_STATUS_INVALID_INDEX);
        3077                 :
        3078               0 :     if (offset)
        3079               0 :         *offset = gradient->stops[index].offset;
        3080               0 :     if (red)
        3081               0 :         *red = gradient->stops[index].color.red;
        3082               0 :     if (green)
        3083               0 :         *green = gradient->stops[index].color.green;
        3084               0 :     if (blue)
        3085               0 :         *blue = gradient->stops[index].color.blue;
        3086               0 :     if (alpha)
        3087               0 :         *alpha = gradient->stops[index].color.alpha;
        3088                 :
        3089               0 :     return CAIRO_STATUS_SUCCESS;
        3090                 : }
        3091                 :
        3092                 : /**
        3093                 :  * cairo_pattern_get_color_stop_count
        3094                 :  * @pattern: a #cairo_pattern_t
        3095                 :  * @count: return value for the number of color stops, or %NULL
        3096                 :  *
        3097                 :  * Gets the number of color stops specified in the given gradient
        3098                 :  * pattern.
        3099                 :  *
        3100                 :  * Return value: %CAIRO_STATUS_SUCCESS, or
        3101                 :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a gradient
        3102                 :  * pattern.
        3103                 :  *
        3104                 :  * Since: 1.4
        3105                 :  */
        3106                 : cairo_status_t
        3107               0 : cairo_pattern_get_color_stop_count (cairo_pattern_t *pattern,
        3108                 :                                     int *count)
        3109                 : {
        3110               0 :     cairo_gradient_pattern_t *gradient = (cairo_gradient_pattern_t*) pattern;
        3111                 :
        3112               0 :     if (pattern->status)
        3113               0 :         return pattern->status;
        3114                 :
        3115               0 :     if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR &&
        3116               0 :         pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
        3117               0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
        3118                 :
        3119               0 :     if (count)
        3120               0 :         *count = gradient->n_stops;
        3121                 :
        3122               0 :     return CAIRO_STATUS_SUCCESS;
        3123                 : }
        3124                 :
        3125                 : /**
        3126                 :  * cairo_pattern_get_linear_points
        3127                 :  * @pattern: a #cairo_pattern_t
        3128                 :  * @x0: return value for the x coordinate of the first point, or %NULL
        3129                 :  * @y0: return value for the y coordinate of the first point, or %NULL
        3130                 :  * @x1: return value for the x coordinate of the second point, or %NULL
        3131                 :  * @y1: return value for the y coordinate of the second point, or %NULL
        3132                 :  *
        3133                 :  * Gets the gradient endpoints for a linear gradient.
        3134                 :  *
        3135                 :  * Return value: %CAIRO_STATUS_SUCCESS, or
        3136                 :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a linear
        3137                 :  * gradient pattern.
        3138                 :  *
        3139                 :  * Since: 1.4
        3140                 :  **/
        3141                 : cairo_status_t
        3142               0 : cairo_pattern_get_linear_points (cairo_pattern_t *pattern,
        3143                 :                                  double *x0, double *y0,
        3144                 :                                  double *x1, double *y1)
        3145                 : {
        3146               0 :     cairo_linear_pattern_t *linear = (cairo_linear_pattern_t*) pattern;
        3147                 :
        3148               0 :     if (pattern->status)
        3149               0 :         return pattern->status;
        3150                 :
        3151               0 :     if (pattern->type != CAIRO_PATTERN_TYPE_LINEAR)
        3152               0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
        3153                 :
        3154               0 :     if (x0)
        3155               0 :         *x0 = _cairo_fixed_to_double (linear->p1.x);
        3156               0 :     if (y0)
        3157               0 :         *y0 = _cairo_fixed_to_double (linear->p1.y);
        3158               0 :     if (x1)
        3159               0 :         *x1 = _cairo_fixed_to_double (linear->p2.x);
        3160               0 :     if (y1)
        3161               0 :         *y1 = _cairo_fixed_to_double (linear->p2.y);
        3162                 :
        3163               0 :     return CAIRO_STATUS_SUCCESS;
        3164                 : }
        3165                 :
        3166                 : /**
        3167                 :  * cairo_pattern_get_radial_circles
        3168                 :  * @pattern: a #cairo_pattern_t
        3169                 :  * @x0: return value for the x coordinate of the center of the first circle, or %NULL
        3170                 :  * @y0: return value for the y coordinate of the center of the first circle, or %NULL
        3171                 :  * @r0: return value for the radius of the first circle, or %NULL
        3172                 :  * @x1: return value for the x coordinate of the center of the second circle, or %NULL
        3173                 :  * @y1: return value for the y coordinate of the center of the second circle, or %NULL
        3174                 :  * @r1: return value for the radius of the second circle, or %NULL
        3175                 :  *
        3176                 :  * Gets the gradient endpoint circles for a radial gradient, each
        3177                 :  * specified as a center coordinate and a radius.
        3178                 :  *
        3179                 :  * Return value: %CAIRO_STATUS_SUCCESS, or
        3180                 :  * %CAIRO_STATUS_PATTERN_TYPE_MISMATCH if @pattern is not a radial
        3181                 :  * gradient pattern.
        3182                 :  *
        3183                 :  * Since: 1.4
        3184                 :  **/
        3185                 : cairo_status_t
        3186               0 : cairo_pattern_get_radial_circles (cairo_pattern_t *pattern,
        3187                 :                                   double *x0, double *y0, double *r0,
        3188                 :                                   double *x1, double *y1, double *r1)
        3189                 : {
        3190               0 :     cairo_radial_pattern_t *radial = (cairo_radial_pattern_t*) pattern;
        3191                 :
        3192               0 :     if (pattern->status)
        3193               0 :         return pattern->status;
        3194                 :
        3195               0 :     if (pattern->type != CAIRO_PATTERN_TYPE_RADIAL)
        3196               0 :         return _cairo_error (CAIRO_STATUS_PATTERN_TYPE_MISMATCH);
        3197                 :
        3198               0 :     if (x0)
        3199               0 :         *x0 = _cairo_fixed_to_double (radial->c1.x);
        3200               0 :     if (y0)
        3201               0 :         *y0 = _cairo_fixed_to_double (radial->c1.y);
        3202               0 :     if (r0)
        3203               0 :         *r0 = _cairo_fixed_to_double (radial->r1);
        3204               0 :     if (x1)
        3205               0 :         *x1 = _cairo_fixed_to_double (radial->c2.x);
        3206               0 :     if (y1)
        3207               0 :         *y1 = _cairo_fixed_to_double (radial->c2.y);
        3208               0 :     if (r1)
        3209               0 :         *r1 = _cairo_fixed_to_double (radial->r2);
        3210                 :
        3211               0 :     return CAIRO_STATUS_SUCCESS;
        3212                 : }
        3213                 :
        3214                 : void
        3215               3 : _cairo_pattern_reset_static_data (void)
        3216                 : {
        3217                 : #if HAS_FREED_POOL
        3218                 :     int i;
        3219                 :
        3220                 :     for (i = 0; i < ARRAY_LENGTH (freed_pattern_pool); i++)
        3221                 :         _freed_pool_reset (&freed_pattern_pool[i]);
        3222                 : #endif
        3223                 :
        3224               3 :     _cairo_pattern_reset_solid_surface_cache ();
        3225               3 : }

Generated by: LCOV version 1.7