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