gfx/cairo/libpixman/src/pixman-image.c

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     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  */
    23 #ifdef HAVE_CONFIG_H
    24 #include <config.h>
    25 #endif
    27 #include <stdlib.h>
    28 #include <stdio.h>
    29 #include <string.h>
    30 #include <assert.h>
    32 #include "pixman-private.h"
    34 static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
    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]);
    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;
    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;
    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;
    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 }
    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);
    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;
   100     gradient->stops += 1;
   101     memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
   102     gradient->n_stops = n_stops;
   104     gradient->common.property_changed = gradient_property_changed;
   106     return TRUE;
   107 }
   109 void
   110 _pixman_image_init (pixman_image_t *image)
   111 {
   112     image_common_t *common = &image->common;
   114     pixman_region32_init (&common->clip_region);
   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 }
   134 pixman_bool_t
   135 _pixman_image_fini (pixman_image_t *image)
   136 {
   137     image_common_t *common = (image_common_t *)image;
   139     common->ref_count--;
   141     if (common->ref_count == 0)
   142     {
   143 	if (image->common.destroy_func)
   144 	    image->common.destroy_func (image, image->common.destroy_data);
   146 	pixman_region32_fini (&common->clip_region);
   148 	free (common->transform);
   149 	free (common->filter_params);
   151 	if (common->alpha_map)
   152 	    pixman_image_unref ((pixman_image_t *)common->alpha_map);
   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 	    }
   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 	}
   172 	if (image->type == BITS && image->bits.free_me)
   173 	    free (image->bits.free_me);
   175 	return TRUE;
   176     }
   178     return FALSE;
   179 }
   181 pixman_image_t *
   182 _pixman_image_allocate (void)
   183 {
   184     pixman_image_t *image = malloc (sizeof (pixman_image_t));
   186     if (image)
   187 	_pixman_image_init (image);
   189     return image;
   190 }
   192 static void
   193 image_property_changed (pixman_image_t *image)
   194 {
   195     image->common.dirty = TRUE;
   196 }
   198 /* Ref Counting */
   199 PIXMAN_EXPORT pixman_image_t *
   200 pixman_image_ref (pixman_image_t *image)
   201 {
   202     image->common.ref_count++;
   204     return image;
   205 }
   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     }
   217     return FALSE;
   218 }
   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 }
   229 PIXMAN_EXPORT void *
   230 pixman_image_get_destroy_data (pixman_image_t *image)
   231 {
   232   return image->common.destroy_data;
   233 }
   235 void
   236 _pixman_image_reset_clip_region (pixman_image_t *image)
   237 {
   238     image->common.have_clip_region = FALSE;
   239 }
   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 }
   264 static void
   265 compute_image_info (pixman_image_t *image)
   266 {
   267     pixman_format_code_t code;
   268     uint32_t flags = 0;
   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;
   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;
   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];
   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 	}
   311 	if (image->common.transform->matrix[0][0] > 0)
   312 	    flags |= FAST_PATH_X_UNIT_POSITIVE;
   314 	if (image->common.transform->matrix[1][0] == 0)
   315 	    flags |= FAST_PATH_Y_UNIT_ZERO;
   316     }
   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;
   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);
   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;
   373     case PIXMAN_FILTER_CONVOLUTION:
   374 	break;
   376     case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
   377 	flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
   378 	break;
   380     default:
   381 	flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
   382 	break;
   383     }
   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;
   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;
   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;
   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     }
   417     /* Component alpha */
   418     if (image->common.component_alpha)
   419 	flags |= FAST_PATH_COMPONENT_ALPHA;
   420     else
   421 	flags |= FAST_PATH_UNIFIED_ALPHA;
   423     flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
   425     /* Type specific checks */
   426     switch (image->type)
   427     {
   428     case SOLID:
   429 	code = PIXMAN_solid;
   431 	if (image->solid.color.alpha == 0xffff)
   432 	    flags |= FAST_PATH_IS_OPAQUE;
   433 	break;
   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 	}
   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;
   454 	    if (image->common.repeat != PIXMAN_REPEAT_NONE)
   455 		flags |= FAST_PATH_IS_OPAQUE;
   456 	}
   458 	if (image->bits.read_func || image->bits.write_func)
   459 	    flags &= ~FAST_PATH_NO_ACCESSORS;
   461 	if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
   462 	    flags &= ~FAST_PATH_NARROW_FORMAT;
   464 	if (image->bits.format == PIXMAN_r5g6b5)
   465 	    flags |= FAST_PATH_16_FORMAT;
   467 	break;
   469     case RADIAL:
   470 	code = PIXMAN_unknown;
   472 	/*
   473 	 * As explained in pixman-radial-gradient.c, every point of
   474 	 * the plane has a valid associated radius (and thus will be
   475 	 * colored) if and only if a is negative (i.e. one of the two
   476 	 * circles contains the other one).
   477 	 */
   479         if (image->radial.a >= 0)
   480 	    break;
   482 	/* Fall through */
   484     case CONICAL:
   485     case LINEAR:
   486 	code = PIXMAN_unknown;
   488 	if (image->common.repeat != PIXMAN_REPEAT_NONE)
   489 	{
   490 	    int i;
   492 	    flags |= FAST_PATH_IS_OPAQUE;
   493 	    for (i = 0; i < image->gradient.n_stops; ++i)
   494 	    {
   495 		if (image->gradient.stops[i].color.alpha != 0xffff)
   496 		{
   497 		    flags &= ~FAST_PATH_IS_OPAQUE;
   498 		    break;
   499 		}
   500 	    }
   501 	}
   502 	break;
   504     default:
   505 	code = PIXMAN_unknown;
   506 	break;
   507     }
   509     /* Alpha map */
   510     if (!image->common.alpha_map)
   511     {
   512 	flags |= FAST_PATH_NO_ALPHA_MAP;
   513     }
   514     else
   515     {
   516 	if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
   517 	    flags &= ~FAST_PATH_NARROW_FORMAT;
   518     }
   520     /* Both alpha maps and convolution filters can introduce
   521      * non-opaqueness in otherwise opaque images. Also
   522      * an image with component alpha turned on is only opaque
   523      * if all channels are opaque, so we simply turn it off
   524      * unconditionally for those images.
   525      */
   526     if (image->common.alpha_map						||
   527 	image->common.filter == PIXMAN_FILTER_CONVOLUTION		||
   528         image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION     ||
   529 	image->common.component_alpha)
   530     {
   531 	flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
   532     }
   534     image->common.flags = flags;
   535     image->common.extended_format_code = code;
   536 }
   538 void
   539 _pixman_image_validate (pixman_image_t *image)
   540 {
   541     if (image->common.dirty)
   542     {
   543 	compute_image_info (image);
   545 	/* It is important that property_changed is
   546 	 * called *after* compute_image_info() because
   547 	 * property_changed() can make use of the flags
   548 	 * to set up accessors etc.
   549 	 */
   550 	if (image->common.property_changed)
   551 	    image->common.property_changed (image);
   553 	image->common.dirty = FALSE;
   554     }
   556     if (image->common.alpha_map)
   557 	_pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
   558 }
   560 PIXMAN_EXPORT pixman_bool_t
   561 pixman_image_set_clip_region32 (pixman_image_t *   image,
   562                                 pixman_region32_t *region)
   563 {
   564     image_common_t *common = (image_common_t *)image;
   565     pixman_bool_t result;
   567     if (region)
   568     {
   569 	if ((result = pixman_region32_copy (&common->clip_region, region)))
   570 	    image->common.have_clip_region = TRUE;
   571     }
   572     else
   573     {
   574 	_pixman_image_reset_clip_region (image);
   576 	result = TRUE;
   577     }
   579     image_property_changed (image);
   581     return result;
   582 }
   584 PIXMAN_EXPORT pixman_bool_t
   585 pixman_image_set_clip_region (pixman_image_t *   image,
   586                               pixman_region16_t *region)
   587 {
   588     image_common_t *common = (image_common_t *)image;
   589     pixman_bool_t result;
   591     if (region)
   592     {
   593 	if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
   594 	    image->common.have_clip_region = TRUE;
   595     }
   596     else
   597     {
   598 	_pixman_image_reset_clip_region (image);
   600 	result = TRUE;
   601     }
   603     image_property_changed (image);
   605     return result;
   606 }
   608 PIXMAN_EXPORT void
   609 pixman_image_set_has_client_clip (pixman_image_t *image,
   610                                   pixman_bool_t   client_clip)
   611 {
   612     image->common.client_clip = client_clip;
   613 }
   615 PIXMAN_EXPORT pixman_bool_t
   616 pixman_image_set_transform (pixman_image_t *          image,
   617                             const pixman_transform_t *transform)
   618 {
   619     static const pixman_transform_t id =
   620     {
   621 	{ { pixman_fixed_1, 0, 0 },
   622 	  { 0, pixman_fixed_1, 0 },
   623 	  { 0, 0, pixman_fixed_1 } }
   624     };
   626     image_common_t *common = (image_common_t *)image;
   627     pixman_bool_t result;
   629     if (common->transform == transform)
   630 	return TRUE;
   632     if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
   633     {
   634 	free (common->transform);
   635 	common->transform = NULL;
   636 	result = TRUE;
   638 	goto out;
   639     }
   641     if (common->transform &&
   642 	memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
   643     {
   644 	return TRUE;
   645     }
   647     if (common->transform == NULL)
   648 	common->transform = malloc (sizeof (pixman_transform_t));
   650     if (common->transform == NULL)
   651     {
   652 	result = FALSE;
   654 	goto out;
   655     }
   657     memcpy (common->transform, transform, sizeof(pixman_transform_t));
   659     result = TRUE;
   661 out:
   662     image_property_changed (image);
   664     return result;
   665 }
   667 PIXMAN_EXPORT void
   668 pixman_image_set_repeat (pixman_image_t *image,
   669                          pixman_repeat_t repeat)
   670 {
   671     if (image->common.repeat == repeat)
   672 	return;
   674     image->common.repeat = repeat;
   676     image_property_changed (image);
   677 }
   679 PIXMAN_EXPORT pixman_bool_t
   680 pixman_image_set_filter (pixman_image_t *      image,
   681                          pixman_filter_t       filter,
   682                          const pixman_fixed_t *params,
   683                          int                   n_params)
   684 {
   685     image_common_t *common = (image_common_t *)image;
   686     pixman_fixed_t *new_params;
   688     if (params == common->filter_params && filter == common->filter)
   689 	return TRUE;
   691     if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
   692     {
   693 	int width = pixman_fixed_to_int (params[0]);
   694 	int height = pixman_fixed_to_int (params[1]);
   695 	int x_phase_bits = pixman_fixed_to_int (params[2]);
   696 	int y_phase_bits = pixman_fixed_to_int (params[3]);
   697 	int n_x_phases = (1 << x_phase_bits);
   698 	int n_y_phases = (1 << y_phase_bits);
   700 	return_val_if_fail (
   701 	    n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
   702     }
   704     new_params = NULL;
   705     if (params)
   706     {
   707 	new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
   708 	if (!new_params)
   709 	    return FALSE;
   711 	memcpy (new_params,
   712 	        params, n_params * sizeof (pixman_fixed_t));
   713     }
   715     common->filter = filter;
   717     if (common->filter_params)
   718 	free (common->filter_params);
   720     common->filter_params = new_params;
   721     common->n_filter_params = n_params;
   723     image_property_changed (image);
   724     return TRUE;
   725 }
   727 PIXMAN_EXPORT void
   728 pixman_image_set_source_clipping (pixman_image_t *image,
   729                                   pixman_bool_t   clip_sources)
   730 {
   731     if (image->common.clip_sources == clip_sources)
   732 	return;
   734     image->common.clip_sources = clip_sources;
   736     image_property_changed (image);
   737 }
   739 /* Unlike all the other property setters, this function does not
   740  * copy the content of indexed. Doing this copying is simply
   741  * way, way too expensive.
   742  */
   743 PIXMAN_EXPORT void
   744 pixman_image_set_indexed (pixman_image_t *        image,
   745                           const pixman_indexed_t *indexed)
   746 {
   747     bits_image_t *bits = (bits_image_t *)image;
   749     if (bits->indexed == indexed)
   750 	return;
   752     bits->indexed = indexed;
   754     image_property_changed (image);
   755 }
   757 PIXMAN_EXPORT void
   758 pixman_image_set_alpha_map (pixman_image_t *image,
   759                             pixman_image_t *alpha_map,
   760                             int16_t         x,
   761                             int16_t         y)
   762 {
   763     image_common_t *common = (image_common_t *)image;
   765     return_if_fail (!alpha_map || alpha_map->type == BITS);
   767     if (alpha_map && common->alpha_count > 0)
   768     {
   769 	/* If this image is being used as an alpha map itself,
   770 	 * then you can't give it an alpha map of its own.
   771 	 */
   772 	return;
   773     }
   775     if (alpha_map && alpha_map->common.alpha_map)
   776     {
   777 	/* If the image has an alpha map of its own,
   778 	 * then it can't be used as an alpha map itself
   779 	 */
   780 	return;
   781     }
   783     if (common->alpha_map != (bits_image_t *)alpha_map)
   784     {
   785 	if (common->alpha_map)
   786 	{
   787 	    common->alpha_map->common.alpha_count--;
   789 	    pixman_image_unref ((pixman_image_t *)common->alpha_map);
   790 	}
   792 	if (alpha_map)
   793 	{
   794 	    common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
   796 	    common->alpha_map->common.alpha_count++;
   797 	}
   798 	else
   799 	{
   800 	    common->alpha_map = NULL;
   801 	}
   802     }
   804     common->alpha_origin_x = x;
   805     common->alpha_origin_y = y;
   807     image_property_changed (image);
   808 }
   810 PIXMAN_EXPORT void
   811 pixman_image_set_component_alpha   (pixman_image_t *image,
   812                                     pixman_bool_t   component_alpha)
   813 {
   814     if (image->common.component_alpha == component_alpha)
   815 	return;
   817     image->common.component_alpha = component_alpha;
   819     image_property_changed (image);
   820 }
   822 PIXMAN_EXPORT pixman_bool_t
   823 pixman_image_get_component_alpha   (pixman_image_t       *image)
   824 {
   825     return image->common.component_alpha;
   826 }
   828 PIXMAN_EXPORT void
   829 pixman_image_set_accessors (pixman_image_t *           image,
   830                             pixman_read_memory_func_t  read_func,
   831                             pixman_write_memory_func_t write_func)
   832 {
   833     return_if_fail (image != NULL);
   835     if (image->type == BITS)
   836     {
   837 	image->bits.read_func = read_func;
   838 	image->bits.write_func = write_func;
   840 	image_property_changed (image);
   841     }
   842 }
   844 PIXMAN_EXPORT uint32_t *
   845 pixman_image_get_data (pixman_image_t *image)
   846 {
   847     if (image->type == BITS)
   848 	return image->bits.bits;
   850     return NULL;
   851 }
   853 PIXMAN_EXPORT int
   854 pixman_image_get_width (pixman_image_t *image)
   855 {
   856     if (image->type == BITS)
   857 	return image->bits.width;
   859     return 0;
   860 }
   862 PIXMAN_EXPORT int
   863 pixman_image_get_height (pixman_image_t *image)
   864 {
   865     if (image->type == BITS)
   866 	return image->bits.height;
   868     return 0;
   869 }
   871 PIXMAN_EXPORT int
   872 pixman_image_get_stride (pixman_image_t *image)
   873 {
   874     if (image->type == BITS)
   875 	return image->bits.rowstride * (int) sizeof (uint32_t);
   877     return 0;
   878 }
   880 PIXMAN_EXPORT int
   881 pixman_image_get_depth (pixman_image_t *image)
   882 {
   883     if (image->type == BITS)
   884 	return PIXMAN_FORMAT_DEPTH (image->bits.format);
   886     return 0;
   887 }
   889 PIXMAN_EXPORT pixman_format_code_t
   890 pixman_image_get_format (pixman_image_t *image)
   891 {
   892     if (image->type == BITS)
   893 	return image->bits.format;
   895     return PIXMAN_null;
   896 }
   898 uint32_t
   899 _pixman_image_get_solid (pixman_implementation_t *imp,
   900 			 pixman_image_t *         image,
   901                          pixman_format_code_t     format)
   902 {
   903     uint32_t result;
   905     if (image->type == SOLID)
   906     {
   907 	result = image->solid.color_32;
   908     }
   909     else if (image->type == BITS)
   910     {
   911 	if (image->bits.format == PIXMAN_a8r8g8b8)
   912 	    result = image->bits.bits[0];
   913 	else if (image->bits.format == PIXMAN_x8r8g8b8)
   914 	    result = image->bits.bits[0] | 0xff000000;
   915 	else if (image->bits.format == PIXMAN_a8)
   916 	    result = (*(uint8_t *)image->bits.bits) << 24;
   917 	else
   918 	    goto otherwise;
   919     }
   920     else
   921     {
   922 	pixman_iter_t iter;
   924     otherwise:
   925 	_pixman_implementation_src_iter_init (
   926 	    imp, &iter, image, 0, 0, 1, 1,
   927 	    (uint8_t *)&result,
   928 	    ITER_NARROW, image->common.flags);
   930 	result = *iter.get_scanline (&iter, NULL);
   931     }
   933     /* If necessary, convert RGB <--> BGR. */
   934     if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
   935 	&& PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
   936     {
   937 	result = (((result & 0xff000000) >>  0) |
   938 	          ((result & 0x00ff0000) >> 16) |
   939 	          ((result & 0x0000ff00) >>  0) |
   940 	          ((result & 0x000000ff) << 16));
   941     }
   943     return result;
   944 }

mercurial