tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

pixman-image.c (25614B)


      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 }