LCOV - code coverage report
Current view: top level - gfx/cairo/libpixman/src - pixman-image.c (source / functions) Hit Total Coverage
Test: output.info Lines: 103 396 26.0 %
Date: 2017-07-14 16:53:18 Functions: 13 34 38.2 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*
       2             :  * Copyright © 2000 SuSE, Inc.
       3             :  * Copyright © 2007 Red Hat, Inc.
       4             :  *
       5             :  * Permission to use, copy, modify, distribute, and sell this software and its
       6             :  * documentation for any purpose is hereby granted without fee, provided that
       7             :  * the above copyright notice appear in all copies and that both that
       8             :  * copyright notice and this permission notice appear in supporting
       9             :  * documentation, and that the name of SuSE not be used in advertising or
      10             :  * publicity pertaining to distribution of the software without specific,
      11             :  * written prior permission.  SuSE makes no representations about the
      12             :  * suitability of this software for any purpose.  It is provided "as is"
      13             :  * without express or implied warranty.
      14             :  *
      15             :  * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
      16             :  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
      17             :  * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
      18             :  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
      19             :  * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
      20             :  * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
      21             :  */
      22             : 
      23             : #ifdef HAVE_CONFIG_H
      24             : #include <config.h>
      25             : #endif
      26             : 
      27             : #include <stdlib.h>
      28             : #include <stdio.h>
      29             : #include <string.h>
      30             : #include <assert.h>
      31             : 
      32             : #include "pixman-private.h"
      33             : 
      34             : static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
      35             : 
      36             : /**
      37             :  ** bug 1293598 - clean up every pointer after free to avoid
      38             :  ** "dereferencing freed memory" problem
      39             :  **/
      40             : #define PIXMAN_POSION
      41             : 
      42             : static void
      43         132 : free_memory (void** p)
      44             : {
      45             : #ifdef PIXMAN_POISON
      46             :     if (*p) {
      47             : #endif
      48         132 :         free (*p);
      49             : #ifdef PIXMAN_POISON
      50             :         *p = NULL;
      51             :     }
      52             : #endif
      53         132 : }
      54             : 
      55             : static void
      56           0 : gradient_property_changed (pixman_image_t *image)
      57             : {
      58           0 :     gradient_t *gradient = &image->gradient;
      59           0 :     int n = gradient->n_stops;
      60           0 :     pixman_gradient_stop_t *stops = gradient->stops;
      61           0 :     pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
      62           0 :     pixman_gradient_stop_t *end = &(gradient->stops[n]);
      63             : 
      64           0 :     switch (gradient->common.repeat)
      65             :     {
      66             :     default:
      67             :     case PIXMAN_REPEAT_NONE:
      68           0 :         begin->x = INT32_MIN;
      69           0 :         begin->color = transparent_black;
      70           0 :         end->x = INT32_MAX;
      71           0 :         end->color = transparent_black;
      72           0 :         break;
      73             : 
      74             :     case PIXMAN_REPEAT_NORMAL:
      75           0 :         begin->x = stops[n - 1].x - pixman_fixed_1;
      76           0 :         begin->color = stops[n - 1].color;
      77           0 :         end->x = stops[0].x + pixman_fixed_1;
      78           0 :         end->color = stops[0].color;
      79           0 :         break;
      80             : 
      81             :     case PIXMAN_REPEAT_REFLECT:
      82           0 :         begin->x = - stops[0].x;
      83           0 :         begin->color = stops[0].color;
      84           0 :         end->x = pixman_int_to_fixed (2) - stops[n - 1].x;
      85           0 :         end->color = stops[n - 1].color;
      86           0 :         break;
      87             : 
      88             :     case PIXMAN_REPEAT_PAD:
      89           0 :         begin->x = INT32_MIN;
      90           0 :         begin->color = stops[0].color;
      91           0 :         end->x = INT32_MAX;
      92           0 :         end->color = stops[n - 1].color;
      93           0 :         break;
      94             :     }
      95           0 : }
      96             : 
      97             : pixman_bool_t
      98           0 : _pixman_init_gradient (gradient_t *                  gradient,
      99             :                        const pixman_gradient_stop_t *stops,
     100             :                        int                           n_stops)
     101             : {
     102           0 :     return_val_if_fail (n_stops > 0, FALSE);
     103             : 
     104             :     /* We allocate two extra stops, one before the beginning of the stop list,
     105             :      * and one after the end. These stops are initialized to whatever color
     106             :      * would be used for positions outside the range of the stop list.
     107             :      *
     108             :      * This saves a bit of computation in the gradient walker.
     109             :      *
     110             :      * The pointer we store in the gradient_t struct still points to the
     111             :      * first user-supplied struct, so when freeing, we will have to
     112             :      * subtract one.
     113             :      */
     114           0 :     gradient->stops =
     115           0 :         pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
     116           0 :     if (!gradient->stops)
     117           0 :         return FALSE;
     118             : 
     119           0 :     gradient->stops += 1;
     120           0 :     memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
     121           0 :     gradient->n_stops = n_stops;
     122             : 
     123           0 :     gradient->common.property_changed = gradient_property_changed;
     124             : 
     125           0 :     return TRUE;
     126             : }
     127             : 
     128             : void
     129          94 : _pixman_image_init (pixman_image_t *image)
     130             : {
     131          94 :     image_common_t *common = &image->common;
     132             : 
     133          94 :     pixman_region32_init (&common->clip_region);
     134             : 
     135          94 :     common->alpha_count = 0;
     136          94 :     common->have_clip_region = FALSE;
     137          94 :     common->clip_sources = FALSE;
     138          94 :     common->transform = NULL;
     139          94 :     common->repeat = PIXMAN_REPEAT_NONE;
     140          94 :     common->filter = PIXMAN_FILTER_NEAREST;
     141          94 :     common->filter_params = NULL;
     142          94 :     common->n_filter_params = 0;
     143          94 :     common->alpha_map = NULL;
     144          94 :     common->component_alpha = FALSE;
     145          94 :     common->ref_count = 1;
     146          94 :     common->property_changed = NULL;
     147          94 :     common->client_clip = FALSE;
     148          94 :     common->destroy_func = NULL;
     149          94 :     common->destroy_data = NULL;
     150          94 :     common->dirty = TRUE;
     151          94 : }
     152             : 
     153             : pixman_bool_t
     154          44 : _pixman_image_fini (pixman_image_t *image)
     155             : {
     156          44 :     image_common_t *common = (image_common_t *)image;
     157             : 
     158          44 :     common->ref_count--;
     159             : 
     160          44 :     if (common->ref_count == 0)
     161             :     {
     162          44 :         if (image->common.destroy_func)
     163           0 :             image->common.destroy_func (image, image->common.destroy_data);
     164             : 
     165          44 :         pixman_region32_fini (&common->clip_region);
     166             : 
     167          44 :         free_memory (&common->transform);
     168          44 :         free_memory (&common->filter_params);
     169             : 
     170          44 :         if (common->alpha_map)
     171           0 :             pixman_image_unref ((pixman_image_t *)common->alpha_map);
     172             : 
     173          88 :         if (image->type == LINEAR ||
     174          88 :             image->type == RADIAL ||
     175          44 :             image->type == CONICAL)
     176             :         {
     177           0 :             if (image->gradient.stops)
     178             :             {
     179             :                 /* See _pixman_init_gradient() for an explanation of the - 1 */
     180           0 :                 void *addr = image->gradient.stops - 1;
     181           0 :                 free_memory (&addr);
     182             :             }
     183             : 
     184             :             /* This will trigger if someone adds a property_changed
     185             :              * method to the linear/radial/conical gradient overwriting
     186             :              * the general one.
     187             :              */
     188           0 :             assert (
     189             :                 image->common.property_changed == gradient_property_changed);
     190             :         }
     191             : 
     192          44 :         if (image->type == BITS && image->bits.free_me) {
     193           0 :             free_memory (&image->bits.free_me);
     194           0 :             image->bits.bits = NULL;
     195             :         }
     196             : 
     197             : 
     198          44 :         return TRUE;
     199             :     }
     200             : 
     201           0 :     return FALSE;
     202             : }
     203             : 
     204             : pixman_image_t *
     205          47 : _pixman_image_allocate (void)
     206             : {
     207          47 :     pixman_image_t *image = malloc (sizeof (pixman_image_t));
     208             : 
     209          47 :     if (image)
     210          47 :         _pixman_image_init (image);
     211             : 
     212          47 :     return image;
     213             : }
     214             : 
     215             : static void
     216           0 : image_property_changed (pixman_image_t *image)
     217             : {
     218           0 :     image->common.dirty = TRUE;
     219           0 : }
     220             : 
     221             : /* Ref Counting */
     222             : PIXMAN_EXPORT pixman_image_t *
     223           0 : pixman_image_ref (pixman_image_t *image)
     224             : {
     225           0 :     image->common.ref_count++;
     226             : 
     227           0 :     return image;
     228             : }
     229             : 
     230             : /* returns TRUE when the image is freed */
     231             : PIXMAN_EXPORT pixman_bool_t
     232          44 : pixman_image_unref (pixman_image_t *image)
     233             : {
     234          44 :     if (_pixman_image_fini (image))
     235             :     {
     236          44 :         free_memory (&image);
     237          44 :         return TRUE;
     238             :     }
     239             : 
     240           0 :     return FALSE;
     241             : }
     242             : 
     243             : PIXMAN_EXPORT void
     244           0 : pixman_image_set_destroy_function (pixman_image_t *            image,
     245             :                                    pixman_image_destroy_func_t func,
     246             :                                    void *                      data)
     247             : {
     248           0 :     image->common.destroy_func = func;
     249           0 :     image->common.destroy_data = data;
     250           0 : }
     251             : 
     252             : PIXMAN_EXPORT void *
     253           0 : pixman_image_get_destroy_data (pixman_image_t *image)
     254             : {
     255           0 :   return image->common.destroy_data;
     256             : }
     257             : 
     258             : void
     259          47 : _pixman_image_reset_clip_region (pixman_image_t *image)
     260             : {
     261          47 :     image->common.have_clip_region = FALSE;
     262          47 : }
     263             : 
     264             : /* Executive Summary: This function is a no-op that only exists
     265             :  * for historical reasons.
     266             :  *
     267             :  * There used to be a bug in the X server where it would rely on
     268             :  * out-of-bounds accesses when it was asked to composite with a
     269             :  * window as the source. It would create a pixman image pointing
     270             :  * to some bogus position in memory, but then set a clip region
     271             :  * to the position where the actual bits were.
     272             :  *
     273             :  * Due to a bug in old versions of pixman, where it would not clip
     274             :  * against the image bounds when a clip region was set, this would
     275             :  * actually work. So when the pixman bug was fixed, a workaround was
     276             :  * added to allow certain out-of-bound accesses. This function disabled
     277             :  * those workarounds.
     278             :  *
     279             :  * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
     280             :  * this function is a no-op.
     281             :  */
     282             : PIXMAN_EXPORT void
     283           0 : pixman_disable_out_of_bounds_workaround (void)
     284             : {
     285           0 : }
     286             : 
     287             : static void
     288          44 : compute_image_info (pixman_image_t *image)
     289             : {
     290             :     pixman_format_code_t code;
     291          44 :     uint32_t flags = 0;
     292             : 
     293             :     /* Transform */
     294          44 :     if (!image->common.transform)
     295             :     {
     296          44 :         flags |= (FAST_PATH_ID_TRANSFORM        |
     297             :                   FAST_PATH_X_UNIT_POSITIVE     |
     298             :                   FAST_PATH_Y_UNIT_ZERO         |
     299             :                   FAST_PATH_AFFINE_TRANSFORM);
     300             :     }
     301             :     else
     302             :     {
     303           0 :         flags |= FAST_PATH_HAS_TRANSFORM;
     304             : 
     305           0 :         if (image->common.transform->matrix[2][0] == 0                    &&
     306           0 :             image->common.transform->matrix[2][1] == 0                    &&
     307           0 :             image->common.transform->matrix[2][2] == pixman_fixed_1)
     308             :         {
     309           0 :             flags |= FAST_PATH_AFFINE_TRANSFORM;
     310             : 
     311           0 :             if (image->common.transform->matrix[0][1] == 0 &&
     312           0 :                 image->common.transform->matrix[1][0] == 0)
     313             :             {
     314           0 :                 if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
     315           0 :                     image->common.transform->matrix[1][1] == -pixman_fixed_1)
     316             :                 {
     317           0 :                     flags |= FAST_PATH_ROTATE_180_TRANSFORM;
     318             :                 }
     319           0 :                 flags |= FAST_PATH_SCALE_TRANSFORM;
     320             :             }
     321           0 :             else if (image->common.transform->matrix[0][0] == 0 &&
     322           0 :                      image->common.transform->matrix[1][1] == 0)
     323             :             {
     324           0 :                 pixman_fixed_t m01 = image->common.transform->matrix[0][1];
     325           0 :                 pixman_fixed_t m10 = image->common.transform->matrix[1][0];
     326             : 
     327           0 :                 if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
     328           0 :                     flags |= FAST_PATH_ROTATE_90_TRANSFORM;
     329           0 :                 else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
     330           0 :                     flags |= FAST_PATH_ROTATE_270_TRANSFORM;
     331             :             }
     332             :         }
     333             : 
     334           0 :         if (image->common.transform->matrix[0][0] > 0)
     335           0 :             flags |= FAST_PATH_X_UNIT_POSITIVE;
     336             : 
     337           0 :         if (image->common.transform->matrix[1][0] == 0)
     338           0 :             flags |= FAST_PATH_Y_UNIT_ZERO;
     339             :     }
     340             : 
     341             :     /* Filter */
     342          44 :     switch (image->common.filter)
     343             :     {
     344             :     case PIXMAN_FILTER_NEAREST:
     345             :     case PIXMAN_FILTER_FAST:
     346          44 :         flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
     347          44 :         break;
     348             : 
     349             :     case PIXMAN_FILTER_BILINEAR:
     350             :     case PIXMAN_FILTER_GOOD:
     351             :     case PIXMAN_FILTER_BEST:
     352           0 :         flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
     353             : 
     354             :         /* Here we have a chance to optimize BILINEAR filter to NEAREST if
     355             :          * they are equivalent for the currently used transformation matrix.
     356             :          */
     357           0 :         if (flags & FAST_PATH_ID_TRANSFORM)
     358             :         {
     359           0 :             flags |= FAST_PATH_NEAREST_FILTER;
     360             :         }
     361           0 :         else if (
     362             :             /* affine and integer translation components in matrix ... */
     363           0 :             ((flags & FAST_PATH_AFFINE_TRANSFORM) &&
     364           0 :              !pixman_fixed_frac (image->common.transform->matrix[0][2] |
     365           0 :                                  image->common.transform->matrix[1][2])) &&
     366             :             (
     367             :                 /* ... combined with a simple rotation */
     368           0 :                 (flags & (FAST_PATH_ROTATE_90_TRANSFORM |
     369             :                           FAST_PATH_ROTATE_180_TRANSFORM |
     370           0 :                           FAST_PATH_ROTATE_270_TRANSFORM)) ||
     371             :                 /* ... or combined with a simple non-rotated translation */
     372           0 :                 (image->common.transform->matrix[0][0] == pixman_fixed_1 &&
     373           0 :                  image->common.transform->matrix[1][1] == pixman_fixed_1 &&
     374           0 :                  image->common.transform->matrix[0][1] == 0 &&
     375           0 :                  image->common.transform->matrix[1][0] == 0)
     376             :                 )
     377             :             )
     378             :         {
     379             :             /* FIXME: there are some affine-test failures, showing that
     380             :              * handling of BILINEAR and NEAREST filter is not quite
     381             :              * equivalent when getting close to 32K for the translation
     382             :              * components of the matrix. That's likely some bug, but for
     383             :              * now just skip BILINEAR->NEAREST optimization in this case.
     384             :              */
     385           0 :             pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
     386           0 :             if (image->common.transform->matrix[0][2] <= magic_limit  &&
     387           0 :                 image->common.transform->matrix[1][2] <= magic_limit  &&
     388           0 :                 image->common.transform->matrix[0][2] >= -magic_limit &&
     389           0 :                 image->common.transform->matrix[1][2] >= -magic_limit)
     390             :             {
     391           0 :                 flags |= FAST_PATH_NEAREST_FILTER;
     392             :             }
     393             :         }
     394           0 :         break;
     395             : 
     396             :     case PIXMAN_FILTER_CONVOLUTION:
     397           0 :         break;
     398             : 
     399             :     case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
     400           0 :         flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
     401           0 :         break;
     402             : 
     403             :     default:
     404           0 :         flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
     405           0 :         break;
     406             :     }
     407             : 
     408             :     /* Repeat mode */
     409          44 :     switch (image->common.repeat)
     410             :     {
     411             :     case PIXMAN_REPEAT_NONE:
     412          44 :         flags |=
     413             :             FAST_PATH_NO_REFLECT_REPEAT         |
     414             :             FAST_PATH_NO_PAD_REPEAT             |
     415             :             FAST_PATH_NO_NORMAL_REPEAT;
     416          44 :         break;
     417             : 
     418             :     case PIXMAN_REPEAT_REFLECT:
     419           0 :         flags |=
     420             :             FAST_PATH_NO_PAD_REPEAT             |
     421             :             FAST_PATH_NO_NONE_REPEAT            |
     422             :             FAST_PATH_NO_NORMAL_REPEAT;
     423           0 :         break;
     424             : 
     425             :     case PIXMAN_REPEAT_PAD:
     426           0 :         flags |=
     427             :             FAST_PATH_NO_REFLECT_REPEAT         |
     428             :             FAST_PATH_NO_NONE_REPEAT            |
     429             :             FAST_PATH_NO_NORMAL_REPEAT;
     430           0 :         break;
     431             : 
     432             :     default:
     433           0 :         flags |=
     434             :             FAST_PATH_NO_REFLECT_REPEAT         |
     435             :             FAST_PATH_NO_PAD_REPEAT             |
     436             :             FAST_PATH_NO_NONE_REPEAT;
     437           0 :         break;
     438             :     }
     439             : 
     440             :     /* Component alpha */
     441          44 :     if (image->common.component_alpha)
     442           0 :         flags |= FAST_PATH_COMPONENT_ALPHA;
     443             :     else
     444          44 :         flags |= FAST_PATH_UNIFIED_ALPHA;
     445             : 
     446          44 :     flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
     447             : 
     448             :     /* Type specific checks */
     449          44 :     switch (image->type)
     450             :     {
     451             :     case SOLID:
     452           0 :         code = PIXMAN_solid;
     453             : 
     454           0 :         if (image->solid.color.alpha == 0xffff)
     455           0 :             flags |= FAST_PATH_IS_OPAQUE;
     456           0 :         break;
     457             : 
     458             :     case BITS:
     459          44 :         if (image->bits.width == 1   &&
     460           0 :             image->bits.height == 1  &&
     461           0 :             image->common.repeat != PIXMAN_REPEAT_NONE)
     462             :         {
     463           0 :             code = PIXMAN_solid;
     464             :         }
     465             :         else
     466             :         {
     467          44 :             code = image->bits.format;
     468          44 :             flags |= FAST_PATH_BITS_IMAGE;
     469             :         }
     470             : 
     471          44 :         if (!PIXMAN_FORMAT_A (image->bits.format)                            &&
     472           0 :             PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY              &&
     473           0 :             PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
     474             :         {
     475           0 :             flags |= FAST_PATH_SAMPLES_OPAQUE;
     476             : 
     477           0 :             if (image->common.repeat != PIXMAN_REPEAT_NONE)
     478           0 :                 flags |= FAST_PATH_IS_OPAQUE;
     479             :         }
     480             : 
     481          44 :         if (image->bits.read_func || image->bits.write_func)
     482           0 :             flags &= ~FAST_PATH_NO_ACCESSORS;
     483             : 
     484          44 :         if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
     485           0 :             flags &= ~FAST_PATH_NARROW_FORMAT;
     486             : 
     487          44 :         if (image->bits.format == PIXMAN_r5g6b5)
     488           0 :             flags |= FAST_PATH_16_FORMAT;
     489             : 
     490          44 :         break;
     491             : 
     492             :     case RADIAL:
     493           0 :         code = PIXMAN_unknown;
     494             : 
     495             :         /*
     496             :          * As explained in pixman-radial-gradient.c, every point of
     497             :          * the plane has a valid associated radius (and thus will be
     498             :          * colored) if and only if a is negative (i.e. one of the two
     499             :          * circles contains the other one).
     500             :          */
     501             : 
     502           0 :         if (image->radial.a >= 0)
     503           0 :             break;
     504             : 
     505             :         /* Fall through */
     506             : 
     507             :     case CONICAL:
     508             :     case LINEAR:
     509           0 :         code = PIXMAN_unknown;
     510             : 
     511           0 :         if (image->common.repeat != PIXMAN_REPEAT_NONE)
     512             :         {
     513             :             int i;
     514             : 
     515           0 :             flags |= FAST_PATH_IS_OPAQUE;
     516           0 :             for (i = 0; i < image->gradient.n_stops; ++i)
     517             :             {
     518           0 :                 if (image->gradient.stops[i].color.alpha != 0xffff)
     519             :                 {
     520           0 :                     flags &= ~FAST_PATH_IS_OPAQUE;
     521           0 :                     break;
     522             :                 }
     523             :             }
     524             :         }
     525           0 :         break;
     526             : 
     527             :     default:
     528           0 :         code = PIXMAN_unknown;
     529           0 :         break;
     530             :     }
     531             : 
     532             :     /* Alpha map */
     533          44 :     if (!image->common.alpha_map)
     534             :     {
     535          44 :         flags |= FAST_PATH_NO_ALPHA_MAP;
     536             :     }
     537             :     else
     538             :     {
     539           0 :         if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
     540           0 :             flags &= ~FAST_PATH_NARROW_FORMAT;
     541             :     }
     542             : 
     543             :     /* Both alpha maps and convolution filters can introduce
     544             :      * non-opaqueness in otherwise opaque images. Also
     545             :      * an image with component alpha turned on is only opaque
     546             :      * if all channels are opaque, so we simply turn it off
     547             :      * unconditionally for those images.
     548             :      */
     549          88 :     if (image->common.alpha_map                                              ||
     550          88 :         image->common.filter == PIXMAN_FILTER_CONVOLUTION            ||
     551          88 :         image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION     ||
     552          44 :         image->common.component_alpha)
     553             :     {
     554           0 :         flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
     555             :     }
     556             : 
     557          44 :     image->common.flags = flags;
     558          44 :     image->common.extended_format_code = code;
     559          44 : }
     560             : 
     561             : void
     562          44 : _pixman_image_validate (pixman_image_t *image)
     563             : {
     564          44 :     if (image->common.dirty)
     565             :     {
     566          44 :         compute_image_info (image);
     567             : 
     568             :         /* It is important that property_changed is
     569             :          * called *after* compute_image_info() because
     570             :          * property_changed() can make use of the flags
     571             :          * to set up accessors etc.
     572             :          */
     573          44 :         if (image->common.property_changed)
     574          44 :             image->common.property_changed (image);
     575             : 
     576          44 :         image->common.dirty = FALSE;
     577             :     }
     578             : 
     579          44 :     if (image->common.alpha_map)
     580           0 :         _pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
     581          44 : }
     582             : 
     583             : PIXMAN_EXPORT pixman_bool_t
     584           0 : pixman_image_set_clip_region32 (pixman_image_t *   image,
     585             :                                 pixman_region32_t *region)
     586             : {
     587           0 :     image_common_t *common = (image_common_t *)image;
     588             :     pixman_bool_t result;
     589             : 
     590           0 :     if (region)
     591             :     {
     592           0 :         if ((result = pixman_region32_copy (&common->clip_region, region)))
     593           0 :             image->common.have_clip_region = TRUE;
     594             :     }
     595             :     else
     596             :     {
     597           0 :         _pixman_image_reset_clip_region (image);
     598             : 
     599           0 :         result = TRUE;
     600             :     }
     601             : 
     602           0 :     image_property_changed (image);
     603             : 
     604           0 :     return result;
     605             : }
     606             : 
     607             : PIXMAN_EXPORT pixman_bool_t
     608           0 : pixman_image_set_clip_region (pixman_image_t *   image,
     609             :                               pixman_region16_t *region)
     610             : {
     611           0 :     image_common_t *common = (image_common_t *)image;
     612             :     pixman_bool_t result;
     613             : 
     614           0 :     if (region)
     615             :     {
     616           0 :         if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
     617           0 :             image->common.have_clip_region = TRUE;
     618             :     }
     619             :     else
     620             :     {
     621           0 :         _pixman_image_reset_clip_region (image);
     622             : 
     623           0 :         result = TRUE;
     624             :     }
     625             : 
     626           0 :     image_property_changed (image);
     627             : 
     628           0 :     return result;
     629             : }
     630             : 
     631             : PIXMAN_EXPORT void
     632           0 : pixman_image_set_has_client_clip (pixman_image_t *image,
     633             :                                   pixman_bool_t   client_clip)
     634             : {
     635           0 :     image->common.client_clip = client_clip;
     636           0 : }
     637             : 
     638             : PIXMAN_EXPORT pixman_bool_t
     639           0 : pixman_image_set_transform (pixman_image_t *          image,
     640             :                             const pixman_transform_t *transform)
     641             : {
     642             :     static const pixman_transform_t id =
     643             :     {
     644             :         { { pixman_fixed_1, 0, 0 },
     645             :           { 0, pixman_fixed_1, 0 },
     646             :           { 0, 0, pixman_fixed_1 } }
     647             :     };
     648             : 
     649           0 :     image_common_t *common = (image_common_t *)image;
     650             :     pixman_bool_t result;
     651             : 
     652           0 :     if (common->transform == transform)
     653           0 :         return TRUE;
     654             : 
     655           0 :     if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
     656             :     {
     657           0 :         free (common->transform);
     658           0 :         common->transform = NULL;
     659           0 :         result = TRUE;
     660             : 
     661           0 :         goto out;
     662             :     }
     663             : 
     664           0 :     if (common->transform &&
     665           0 :         memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
     666             :     {
     667           0 :         return TRUE;
     668             :     }
     669             : 
     670           0 :     if (common->transform == NULL)
     671           0 :         common->transform = malloc (sizeof (pixman_transform_t));
     672             : 
     673           0 :     if (common->transform == NULL)
     674             :     {
     675           0 :         result = FALSE;
     676             : 
     677           0 :         goto out;
     678             :     }
     679             : 
     680           0 :     memcpy (common->transform, transform, sizeof(pixman_transform_t));
     681             : 
     682           0 :     result = TRUE;
     683             : 
     684             : out:
     685           0 :     image_property_changed (image);
     686             : 
     687           0 :     return result;
     688             : }
     689             : 
     690             : PIXMAN_EXPORT void
     691           0 : pixman_image_set_repeat (pixman_image_t *image,
     692             :                          pixman_repeat_t repeat)
     693             : {
     694           0 :     if (image->common.repeat == repeat)
     695           0 :         return;
     696             : 
     697           0 :     image->common.repeat = repeat;
     698             : 
     699           0 :     image_property_changed (image);
     700             : }
     701             : 
     702             : PIXMAN_EXPORT pixman_bool_t
     703           0 : pixman_image_set_filter (pixman_image_t *      image,
     704             :                          pixman_filter_t       filter,
     705             :                          const pixman_fixed_t *params,
     706             :                          int                   n_params)
     707             : {
     708           0 :     image_common_t *common = (image_common_t *)image;
     709             :     pixman_fixed_t *new_params;
     710             : 
     711           0 :     if (params == common->filter_params && filter == common->filter)
     712           0 :         return TRUE;
     713             : 
     714           0 :     if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
     715             :     {
     716           0 :         int width = pixman_fixed_to_int (params[0]);
     717           0 :         int height = pixman_fixed_to_int (params[1]);
     718           0 :         int x_phase_bits = pixman_fixed_to_int (params[2]);
     719           0 :         int y_phase_bits = pixman_fixed_to_int (params[3]);
     720           0 :         int n_x_phases = (1 << x_phase_bits);
     721           0 :         int n_y_phases = (1 << y_phase_bits);
     722             : 
     723           0 :         return_val_if_fail (
     724             :             n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
     725             :     }
     726             :     
     727           0 :     new_params = NULL;
     728           0 :     if (params)
     729             :     {
     730           0 :         new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
     731           0 :         if (!new_params)
     732           0 :             return FALSE;
     733             : 
     734           0 :         memcpy (new_params,
     735             :                 params, n_params * sizeof (pixman_fixed_t));
     736             :     }
     737             : 
     738           0 :     common->filter = filter;
     739             : 
     740           0 :     if (common->filter_params)
     741           0 :         free (common->filter_params);
     742             : 
     743           0 :     common->filter_params = new_params;
     744           0 :     common->n_filter_params = n_params;
     745             : 
     746           0 :     image_property_changed (image);
     747           0 :     return TRUE;
     748             : }
     749             : 
     750             : PIXMAN_EXPORT void
     751           0 : pixman_image_set_source_clipping (pixman_image_t *image,
     752             :                                   pixman_bool_t   clip_sources)
     753             : {
     754           0 :     if (image->common.clip_sources == clip_sources)
     755           0 :         return;
     756             : 
     757           0 :     image->common.clip_sources = clip_sources;
     758             : 
     759           0 :     image_property_changed (image);
     760             : }
     761             : 
     762             : /* Unlike all the other property setters, this function does not
     763             :  * copy the content of indexed. Doing this copying is simply
     764             :  * way, way too expensive.
     765             :  */
     766             : PIXMAN_EXPORT void
     767           0 : pixman_image_set_indexed (pixman_image_t *        image,
     768             :                           const pixman_indexed_t *indexed)
     769             : {
     770           0 :     bits_image_t *bits = (bits_image_t *)image;
     771             : 
     772           0 :     if (bits->indexed == indexed)
     773           0 :         return;
     774             : 
     775           0 :     bits->indexed = indexed;
     776             : 
     777           0 :     image_property_changed (image);
     778             : }
     779             : 
     780             : PIXMAN_EXPORT void
     781           0 : pixman_image_set_alpha_map (pixman_image_t *image,
     782             :                             pixman_image_t *alpha_map,
     783             :                             int16_t         x,
     784             :                             int16_t         y)
     785             : {
     786           0 :     image_common_t *common = (image_common_t *)image;
     787             : 
     788           0 :     return_if_fail (!alpha_map || alpha_map->type == BITS);
     789             : 
     790           0 :     if (alpha_map && common->alpha_count > 0)
     791             :     {
     792             :         /* If this image is being used as an alpha map itself,
     793             :          * then you can't give it an alpha map of its own.
     794             :          */
     795           0 :         return;
     796             :     }
     797             : 
     798           0 :     if (alpha_map && alpha_map->common.alpha_map)
     799             :     {
     800             :         /* If the image has an alpha map of its own,
     801             :          * then it can't be used as an alpha map itself
     802             :          */
     803           0 :         return;
     804             :     }
     805             : 
     806           0 :     if (common->alpha_map != (bits_image_t *)alpha_map)
     807             :     {
     808           0 :         if (common->alpha_map)
     809             :         {
     810           0 :             common->alpha_map->common.alpha_count--;
     811             : 
     812           0 :             pixman_image_unref ((pixman_image_t *)common->alpha_map);
     813             :         }
     814             : 
     815           0 :         if (alpha_map)
     816             :         {
     817           0 :             common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
     818             : 
     819           0 :             common->alpha_map->common.alpha_count++;
     820             :         }
     821             :         else
     822             :         {
     823           0 :             common->alpha_map = NULL;
     824             :         }
     825             :     }
     826             : 
     827           0 :     common->alpha_origin_x = x;
     828           0 :     common->alpha_origin_y = y;
     829             : 
     830           0 :     image_property_changed (image);
     831             : }
     832             : 
     833             : PIXMAN_EXPORT void
     834           0 : pixman_image_set_component_alpha   (pixman_image_t *image,
     835             :                                     pixman_bool_t   component_alpha)
     836             : {
     837           0 :     if (image->common.component_alpha == component_alpha)
     838           0 :         return;
     839             : 
     840           0 :     image->common.component_alpha = component_alpha;
     841             : 
     842           0 :     image_property_changed (image);
     843             : }
     844             : 
     845             : PIXMAN_EXPORT pixman_bool_t
     846           0 : pixman_image_get_component_alpha   (pixman_image_t       *image)
     847             : {
     848           0 :     return image->common.component_alpha;
     849             : }
     850             : 
     851             : PIXMAN_EXPORT void
     852           0 : pixman_image_set_accessors (pixman_image_t *           image,
     853             :                             pixman_read_memory_func_t  read_func,
     854             :                             pixman_write_memory_func_t write_func)
     855             : {
     856           0 :     return_if_fail (image != NULL);
     857             : 
     858           0 :     if (image->type == BITS)
     859             :     {
     860           0 :         image->bits.read_func = read_func;
     861           0 :         image->bits.write_func = write_func;
     862             : 
     863           0 :         image_property_changed (image);
     864             :     }
     865             : }
     866             : 
     867             : PIXMAN_EXPORT uint32_t *
     868           3 : pixman_image_get_data (pixman_image_t *image)
     869             : {
     870           3 :     if (image->type == BITS)
     871           3 :         return image->bits.bits;
     872             : 
     873           0 :     return NULL;
     874             : }
     875             : 
     876             : PIXMAN_EXPORT int
     877           3 : pixman_image_get_width (pixman_image_t *image)
     878             : {
     879           3 :     if (image->type == BITS)
     880           3 :         return image->bits.width;
     881             : 
     882           0 :     return 0;
     883             : }
     884             : 
     885             : PIXMAN_EXPORT int
     886           3 : pixman_image_get_height (pixman_image_t *image)
     887             : {
     888           3 :     if (image->type == BITS)
     889           3 :         return image->bits.height;
     890             : 
     891           0 :     return 0;
     892             : }
     893             : 
     894             : PIXMAN_EXPORT int
     895           3 : pixman_image_get_stride (pixman_image_t *image)
     896             : {
     897           3 :     if (image->type == BITS)
     898           3 :         return image->bits.rowstride * (int) sizeof (uint32_t);
     899             : 
     900           0 :     return 0;
     901             : }
     902             : 
     903             : PIXMAN_EXPORT int
     904           3 : pixman_image_get_depth (pixman_image_t *image)
     905             : {
     906           3 :     if (image->type == BITS)
     907           3 :         return PIXMAN_FORMAT_DEPTH (image->bits.format);
     908             : 
     909           0 :     return 0;
     910             : }
     911             : 
     912             : PIXMAN_EXPORT pixman_format_code_t
     913           0 : pixman_image_get_format (pixman_image_t *image)
     914             : {
     915           0 :     if (image->type == BITS)
     916           0 :         return image->bits.format;
     917             : 
     918           0 :     return PIXMAN_null;
     919             : }
     920             : 
     921             : uint32_t
     922           0 : _pixman_image_get_solid (pixman_implementation_t *imp,
     923             :                          pixman_image_t *         image,
     924             :                          pixman_format_code_t     format)
     925             : {
     926             :     uint32_t result;
     927             : 
     928           0 :     if (image->type == SOLID)
     929             :     {
     930           0 :         result = image->solid.color_32;
     931             :     }
     932           0 :     else if (image->type == BITS)
     933             :     {
     934           0 :         if (image->bits.format == PIXMAN_a8r8g8b8)
     935           0 :             result = image->bits.bits[0];
     936           0 :         else if (image->bits.format == PIXMAN_x8r8g8b8)
     937           0 :             result = image->bits.bits[0] | 0xff000000;
     938           0 :         else if (image->bits.format == PIXMAN_a8)
     939           0 :             result = (*(uint8_t *)image->bits.bits) << 24;
     940             :         else
     941           0 :             goto otherwise;
     942             :     }
     943             :     else
     944             :     {
     945             :         pixman_iter_t iter;
     946             : 
     947             :     otherwise:
     948           0 :         _pixman_implementation_src_iter_init (
     949             :             imp, &iter, image, 0, 0, 1, 1,
     950             :             (uint8_t *)&result,
     951             :             ITER_NARROW, image->common.flags);
     952             :         
     953           0 :         result = *iter.get_scanline (&iter, NULL);
     954             :     }
     955             : 
     956             :     /* If necessary, convert RGB <--> BGR. */
     957           0 :     if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
     958           0 :         && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
     959             :     {
     960           0 :         result = (((result & 0xff000000) >>  0) |
     961           0 :                   ((result & 0x00ff0000) >> 16) |
     962           0 :                   ((result & 0x0000ff00) >>  0) |
     963           0 :                   ((result & 0x000000ff) << 16));
     964             :     }
     965             : 
     966           0 :     return result;
     967             : }

Generated by: LCOV version 1.13