Home | History | Annotate | 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 <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 (
    339 	    /* affine and integer translation components in matrix ... */
    340 	    ((flags & FAST_PATH_AFFINE_TRANSFORM) &&
    341 	     !pixman_fixed_frac (image->common.transform->matrix[0][2] |
    342 				 image->common.transform->matrix[1][2])) &&
    343 	    (
    344 		/* ... combined with a simple rotation */
    345 		(flags & (FAST_PATH_ROTATE_90_TRANSFORM |
    346 			  FAST_PATH_ROTATE_180_TRANSFORM |
    347 			  FAST_PATH_ROTATE_270_TRANSFORM)) ||
    348 		/* ... or combined with a simple non-rotated translation */
    349 		(image->common.transform->matrix[0][0] == pixman_fixed_1 &&
    350 		 image->common.transform->matrix[1][1] == pixman_fixed_1 &&
    351 		 image->common.transform->matrix[0][1] == 0 &&
    352 		 image->common.transform->matrix[1][0] == 0)
    353 		)
    354 	    )
    355 	{
    356 	    /* FIXME: there are some affine-test failures, showing that
    357 	     * handling of BILINEAR and NEAREST filter is not quite
    358 	     * equivalent when getting close to 32K for the translation
    359 	     * components of the matrix. That's likely some bug, but for
    360 	     * now just skip BILINEAR->NEAREST optimization in this case.
    361 	     */
    362 	    pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
    363 	    if (image->common.transform->matrix[0][2] <= magic_limit  &&
    364 	        image->common.transform->matrix[1][2] <= magic_limit  &&
    365 	        image->common.transform->matrix[0][2] >= -magic_limit &&
    366 	        image->common.transform->matrix[1][2] >= -magic_limit)
    367 	    {
    368 		flags |= FAST_PATH_NEAREST_FILTER;
    369 	    }
    370 	}
    371 	break;
    372 
    373     case PIXMAN_FILTER_CONVOLUTION:
    374 	break;
    375 
    376     case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
    377 	flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
    378 	break;
    379 
    380     default:
    381 	flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
    382 	break;
    383     }
    384 
    385     /* Repeat mode */
    386     switch (image->common.repeat)
    387     {
    388     case PIXMAN_REPEAT_NONE:
    389 	flags |=
    390 	    FAST_PATH_NO_REFLECT_REPEAT		|
    391 	    FAST_PATH_NO_PAD_REPEAT		|
    392 	    FAST_PATH_NO_NORMAL_REPEAT;
    393 	break;
    394 
    395     case PIXMAN_REPEAT_REFLECT:
    396 	flags |=
    397 	    FAST_PATH_NO_PAD_REPEAT		|
    398 	    FAST_PATH_NO_NONE_REPEAT		|
    399 	    FAST_PATH_NO_NORMAL_REPEAT;
    400 	break;
    401 
    402     case PIXMAN_REPEAT_PAD:
    403 	flags |=
    404 	    FAST_PATH_NO_REFLECT_REPEAT		|
    405 	    FAST_PATH_NO_NONE_REPEAT		|
    406 	    FAST_PATH_NO_NORMAL_REPEAT;
    407 	break;
    408 
    409     default:
    410 	flags |=
    411 	    FAST_PATH_NO_REFLECT_REPEAT		|
    412 	    FAST_PATH_NO_PAD_REPEAT		|
    413 	    FAST_PATH_NO_NONE_REPEAT;
    414 	break;
    415     }
    416 
    417     /* Component alpha */
    418     if (image->common.component_alpha)
    419 	flags |= FAST_PATH_COMPONENT_ALPHA;
    420     else
    421 	flags |= FAST_PATH_UNIFIED_ALPHA;
    422 
    423     flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
    424 
    425     /* Type specific checks */
    426     switch (image->type)
    427     {
    428     case SOLID:
    429 	code = PIXMAN_solid;
    430 
    431 	if (image->solid.color.alpha == 0xffff)
    432 	    flags |= FAST_PATH_IS_OPAQUE;
    433 	break;
    434 
    435     case BITS:
    436 	if (image->bits.width == 1	&&
    437 	    image->bits.height == 1	&&
    438 	    image->common.repeat != PIXMAN_REPEAT_NONE)
    439 	{
    440 	    code = PIXMAN_solid;
    441 	}
    442 	else
    443 	{
    444 	    code = image->bits.format;
    445 	    flags |= FAST_PATH_BITS_IMAGE;
    446 	}
    447 
    448 	if (!PIXMAN_FORMAT_A (image->bits.format)				&&
    449 	    PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY		&&
    450 	    PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
    451 	{
    452 	    flags |= FAST_PATH_SAMPLES_OPAQUE;
    453 
    454 	    if (image->common.repeat != PIXMAN_REPEAT_NONE)
    455 		flags |= FAST_PATH_IS_OPAQUE;
    456 	}
    457 
    458 	if (image->bits.read_func || image->bits.write_func)
    459 	    flags &= ~FAST_PATH_NO_ACCESSORS;
    460 
    461 	if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
    462 	    flags &= ~FAST_PATH_NARROW_FORMAT;
    463 	break;
    464 
    465     case RADIAL:
    466 	code = PIXMAN_unknown;
    467 
    468 	/*
    469 	 * As explained in pixman-radial-gradient.c, every point of
    470 	 * the plane has a valid associated radius (and thus will be
    471 	 * colored) if and only if a is negative (i.e. one of the two
    472 	 * circles contains the other one).
    473 	 */
    474 
    475         if (image->radial.a >= 0)
    476 	    break;
    477 
    478 	/* Fall through */
    479 
    480     case CONICAL:
    481     case LINEAR:
    482 	code = PIXMAN_unknown;
    483 
    484 	if (image->common.repeat != PIXMAN_REPEAT_NONE)
    485 	{
    486 	    int i;
    487 
    488 	    flags |= FAST_PATH_IS_OPAQUE;
    489 	    for (i = 0; i < image->gradient.n_stops; ++i)
    490 	    {
    491 		if (image->gradient.stops[i].color.alpha != 0xffff)
    492 		{
    493 		    flags &= ~FAST_PATH_IS_OPAQUE;
    494 		    break;
    495 		}
    496 	    }
    497 	}
    498 	break;
    499 
    500     default:
    501 	code = PIXMAN_unknown;
    502 	break;
    503     }
    504 
    505     /* Alpha map */
    506     if (!image->common.alpha_map)
    507     {
    508 	flags |= FAST_PATH_NO_ALPHA_MAP;
    509     }
    510     else
    511     {
    512 	if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
    513 	    flags &= ~FAST_PATH_NARROW_FORMAT;
    514     }
    515 
    516     /* Both alpha maps and convolution filters can introduce
    517      * non-opaqueness in otherwise opaque images. Also
    518      * an image with component alpha turned on is only opaque
    519      * if all channels are opaque, so we simply turn it off
    520      * unconditionally for those images.
    521      */
    522     if (image->common.alpha_map						||
    523 	image->common.filter == PIXMAN_FILTER_CONVOLUTION		||
    524         image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION     ||
    525 	image->common.component_alpha)
    526     {
    527 	flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
    528     }
    529 
    530     image->common.flags = flags;
    531     image->common.extended_format_code = code;
    532 }
    533 
    534 void
    535 _pixman_image_validate (pixman_image_t *image)
    536 {
    537     if (image->common.dirty)
    538     {
    539 	compute_image_info (image);
    540 
    541 	/* It is important that property_changed is
    542 	 * called *after* compute_image_info() because
    543 	 * property_changed() can make use of the flags
    544 	 * to set up accessors etc.
    545 	 */
    546 	if (image->common.property_changed)
    547 	    image->common.property_changed (image);
    548 
    549 	image->common.dirty = FALSE;
    550     }
    551 
    552     if (image->common.alpha_map)
    553 	_pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
    554 }
    555 
    556 PIXMAN_EXPORT pixman_bool_t
    557 pixman_image_set_clip_region32 (pixman_image_t *   image,
    558                                 pixman_region32_t *region)
    559 {
    560     image_common_t *common = (image_common_t *)image;
    561     pixman_bool_t result;
    562 
    563     if (region)
    564     {
    565 	if ((result = pixman_region32_copy (&common->clip_region, region)))
    566 	    image->common.have_clip_region = TRUE;
    567     }
    568     else
    569     {
    570 	_pixman_image_reset_clip_region (image);
    571 
    572 	result = TRUE;
    573     }
    574 
    575     image_property_changed (image);
    576 
    577     return result;
    578 }
    579 
    580 PIXMAN_EXPORT pixman_bool_t
    581 pixman_image_set_clip_region (pixman_image_t *   image,
    582                               pixman_region16_t *region)
    583 {
    584     image_common_t *common = (image_common_t *)image;
    585     pixman_bool_t result;
    586 
    587     if (region)
    588     {
    589 	if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
    590 	    image->common.have_clip_region = TRUE;
    591     }
    592     else
    593     {
    594 	_pixman_image_reset_clip_region (image);
    595 
    596 	result = TRUE;
    597     }
    598 
    599     image_property_changed (image);
    600 
    601     return result;
    602 }
    603 
    604 PIXMAN_EXPORT void
    605 pixman_image_set_has_client_clip (pixman_image_t *image,
    606                                   pixman_bool_t   client_clip)
    607 {
    608     image->common.client_clip = client_clip;
    609 }
    610 
    611 PIXMAN_EXPORT pixman_bool_t
    612 pixman_image_set_transform (pixman_image_t *          image,
    613                             const pixman_transform_t *transform)
    614 {
    615     static const pixman_transform_t id =
    616     {
    617 	{ { pixman_fixed_1, 0, 0 },
    618 	  { 0, pixman_fixed_1, 0 },
    619 	  { 0, 0, pixman_fixed_1 } }
    620     };
    621 
    622     image_common_t *common = (image_common_t *)image;
    623     pixman_bool_t result;
    624 
    625     if (common->transform == transform)
    626 	return TRUE;
    627 
    628     if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
    629     {
    630 	free (common->transform);
    631 	common->transform = NULL;
    632 	result = TRUE;
    633 
    634 	goto out;
    635     }
    636 
    637     if (common->transform &&
    638 	memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
    639     {
    640 	return TRUE;
    641     }
    642 
    643     if (common->transform == NULL)
    644 	common->transform = malloc (sizeof (pixman_transform_t));
    645 
    646     if (common->transform == NULL)
    647     {
    648 	result = FALSE;
    649 
    650 	goto out;
    651     }
    652 
    653     memcpy (common->transform, transform, sizeof(pixman_transform_t));
    654 
    655     result = TRUE;
    656 
    657 out:
    658     image_property_changed (image);
    659 
    660     return result;
    661 }
    662 
    663 PIXMAN_EXPORT void
    664 pixman_image_set_repeat (pixman_image_t *image,
    665                          pixman_repeat_t repeat)
    666 {
    667     if (image->common.repeat == repeat)
    668 	return;
    669 
    670     image->common.repeat = repeat;
    671 
    672     image_property_changed (image);
    673 }
    674 
    675 PIXMAN_EXPORT pixman_bool_t
    676 pixman_image_set_filter (pixman_image_t *      image,
    677                          pixman_filter_t       filter,
    678                          const pixman_fixed_t *params,
    679                          int                   n_params)
    680 {
    681     image_common_t *common = (image_common_t *)image;
    682     pixman_fixed_t *new_params;
    683 
    684     if (params == common->filter_params && filter == common->filter)
    685 	return TRUE;
    686 
    687     if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
    688     {
    689 	int width = pixman_fixed_to_int (params[0]);
    690 	int height = pixman_fixed_to_int (params[1]);
    691 	int x_phase_bits = pixman_fixed_to_int (params[2]);
    692 	int y_phase_bits = pixman_fixed_to_int (params[3]);
    693 	int n_x_phases = (1 << x_phase_bits);
    694 	int n_y_phases = (1 << y_phase_bits);
    695 
    696 	return_val_if_fail (
    697 	    n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
    698     }
    699 
    700     new_params = NULL;
    701     if (params)
    702     {
    703 	new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
    704 	if (!new_params)
    705 	    return FALSE;
    706 
    707 	memcpy (new_params,
    708 	        params, n_params * sizeof (pixman_fixed_t));
    709     }
    710 
    711     common->filter = filter;
    712 
    713     if (common->filter_params)
    714 	free (common->filter_params);
    715 
    716     common->filter_params = new_params;
    717     common->n_filter_params = n_params;
    718 
    719     image_property_changed (image);
    720     return TRUE;
    721 }
    722 
    723 PIXMAN_EXPORT void
    724 pixman_image_set_source_clipping (pixman_image_t *image,
    725                                   pixman_bool_t   clip_sources)
    726 {
    727     if (image->common.clip_sources == clip_sources)
    728 	return;
    729 
    730     image->common.clip_sources = clip_sources;
    731 
    732     image_property_changed (image);
    733 }
    734 
    735 /* Unlike all the other property setters, this function does not
    736  * copy the content of indexed. Doing this copying is simply
    737  * way, way too expensive.
    738  */
    739 PIXMAN_EXPORT void
    740 pixman_image_set_indexed (pixman_image_t *        image,
    741                           const pixman_indexed_t *indexed)
    742 {
    743     bits_image_t *bits = (bits_image_t *)image;
    744 
    745     if (bits->indexed == indexed)
    746 	return;
    747 
    748     bits->indexed = indexed;
    749 
    750     image_property_changed (image);
    751 }
    752 
    753 PIXMAN_EXPORT void
    754 pixman_image_set_alpha_map (pixman_image_t *image,
    755                             pixman_image_t *alpha_map,
    756                             int16_t         x,
    757                             int16_t         y)
    758 {
    759     image_common_t *common = (image_common_t *)image;
    760 
    761     return_if_fail (!alpha_map || alpha_map->type == BITS);
    762 
    763     if (alpha_map && common->alpha_count > 0)
    764     {
    765 	/* If this image is being used as an alpha map itself,
    766 	 * then you can't give it an alpha map of its own.
    767 	 */
    768 	return;
    769     }
    770 
    771     if (alpha_map && alpha_map->common.alpha_map)
    772     {
    773 	/* If the image has an alpha map of its own,
    774 	 * then it can't be used as an alpha map itself
    775 	 */
    776 	return;
    777     }
    778 
    779     if (common->alpha_map != (bits_image_t *)alpha_map)
    780     {
    781 	if (common->alpha_map)
    782 	{
    783 	    common->alpha_map->common.alpha_count--;
    784 
    785 	    pixman_image_unref ((pixman_image_t *)common->alpha_map);
    786 	}
    787 
    788 	if (alpha_map)
    789 	{
    790 	    common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
    791 
    792 	    common->alpha_map->common.alpha_count++;
    793 	}
    794 	else
    795 	{
    796 	    common->alpha_map = NULL;
    797 	}
    798     }
    799 
    800     common->alpha_origin_x = x;
    801     common->alpha_origin_y = y;
    802 
    803     image_property_changed (image);
    804 }
    805 
    806 PIXMAN_EXPORT void
    807 pixman_image_set_component_alpha   (pixman_image_t *image,
    808                                     pixman_bool_t   component_alpha)
    809 {
    810     if (image->common.component_alpha == component_alpha)
    811 	return;
    812 
    813     image->common.component_alpha = component_alpha;
    814 
    815     image_property_changed (image);
    816 }
    817 
    818 PIXMAN_EXPORT pixman_bool_t
    819 pixman_image_get_component_alpha   (pixman_image_t       *image)
    820 {
    821     return image->common.component_alpha;
    822 }
    823 
    824 PIXMAN_EXPORT void
    825 pixman_image_set_accessors (pixman_image_t *           image,
    826                             pixman_read_memory_func_t  read_func,
    827                             pixman_write_memory_func_t write_func)
    828 {
    829     return_if_fail (image != NULL);
    830 
    831     if (image->type == BITS)
    832     {
    833 	image->bits.read_func = read_func;
    834 	image->bits.write_func = write_func;
    835 
    836 	image_property_changed (image);
    837     }
    838 }
    839 
    840 PIXMAN_EXPORT uint32_t *
    841 pixman_image_get_data (pixman_image_t *image)
    842 {
    843     if (image->type == BITS)
    844 	return image->bits.bits;
    845 
    846     return NULL;
    847 }
    848 
    849 PIXMAN_EXPORT int
    850 pixman_image_get_width (pixman_image_t *image)
    851 {
    852     if (image->type == BITS)
    853 	return image->bits.width;
    854 
    855     return 0;
    856 }
    857 
    858 PIXMAN_EXPORT int
    859 pixman_image_get_height (pixman_image_t *image)
    860 {
    861     if (image->type == BITS)
    862 	return image->bits.height;
    863 
    864     return 0;
    865 }
    866 
    867 PIXMAN_EXPORT int
    868 pixman_image_get_stride (pixman_image_t *image)
    869 {
    870     if (image->type == BITS)
    871 	return image->bits.rowstride * (int) sizeof (uint32_t);
    872 
    873     return 0;
    874 }
    875 
    876 PIXMAN_EXPORT int
    877 pixman_image_get_depth (pixman_image_t *image)
    878 {
    879     if (image->type == BITS)
    880 	return PIXMAN_FORMAT_DEPTH (image->bits.format);
    881 
    882     return 0;
    883 }
    884 
    885 PIXMAN_EXPORT pixman_format_code_t
    886 pixman_image_get_format (pixman_image_t *image)
    887 {
    888     if (image->type == BITS)
    889 	return image->bits.format;
    890 
    891     return PIXMAN_null;
    892 }
    893 
    894 uint32_t
    895 _pixman_image_get_solid (pixman_implementation_t *imp,
    896 			 pixman_image_t *         image,
    897                          pixman_format_code_t     format)
    898 {
    899     uint32_t result;
    900 
    901     if (image->type == SOLID)
    902     {
    903 	result = image->solid.color_32;
    904     }
    905     else if (image->type == BITS)
    906     {
    907 	if (image->bits.format == PIXMAN_a8r8g8b8)
    908 	    result = image->bits.bits[0];
    909 	else if (image->bits.format == PIXMAN_x8r8g8b8)
    910 	    result = image->bits.bits[0] | 0xff000000;
    911 	else if (image->bits.format == PIXMAN_a8)
    912 	    result = (*(uint8_t *)image->bits.bits) << 24;
    913 	else
    914 	    goto otherwise;
    915     }
    916     else
    917     {
    918 	pixman_iter_t iter;
    919 
    920     otherwise:
    921 	_pixman_implementation_src_iter_init (
    922 	    imp, &iter, image, 0, 0, 1, 1,
    923 	    (uint8_t *)&result,
    924 	    ITER_NARROW, image->common.flags);
    925 
    926 	result = *iter.get_scanline (&iter, NULL);
    927     }
    928 
    929     /* If necessary, convert RGB <--> BGR. */
    930     if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
    931 	&& PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
    932     {
    933 	result = (((result & 0xff000000) >>  0) |
    934 	          ((result & 0x00ff0000) >> 16) |
    935 	          ((result & 0x0000ff00) >>  0) |
    936 	          ((result & 0x000000ff) << 16));
    937     }
    938 
    939     return result;
    940 }
    941