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

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/gfx/cairo/libpixman/src/pixman-image.c	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,944 @@
     1.4 +/*
     1.5 + * Copyright © 2000 SuSE, Inc.
     1.6 + * Copyright © 2007 Red Hat, Inc.
     1.7 + *
     1.8 + * Permission to use, copy, modify, distribute, and sell this software and its
     1.9 + * documentation for any purpose is hereby granted without fee, provided that
    1.10 + * the above copyright notice appear in all copies and that both that
    1.11 + * copyright notice and this permission notice appear in supporting
    1.12 + * documentation, and that the name of SuSE not be used in advertising or
    1.13 + * publicity pertaining to distribution of the software without specific,
    1.14 + * written prior permission.  SuSE makes no representations about the
    1.15 + * suitability of this software for any purpose.  It is provided "as is"
    1.16 + * without express or implied warranty.
    1.17 + *
    1.18 + * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
    1.19 + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE
    1.20 + * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
    1.21 + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
    1.22 + * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
    1.23 + * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
    1.24 + */
    1.25 +
    1.26 +#ifdef HAVE_CONFIG_H
    1.27 +#include <config.h>
    1.28 +#endif
    1.29 +
    1.30 +#include <stdlib.h>
    1.31 +#include <stdio.h>
    1.32 +#include <string.h>
    1.33 +#include <assert.h>
    1.34 +
    1.35 +#include "pixman-private.h"
    1.36 +
    1.37 +static const pixman_color_t transparent_black = { 0, 0, 0, 0 };
    1.38 +
    1.39 +static void
    1.40 +gradient_property_changed (pixman_image_t *image)
    1.41 +{
    1.42 +    gradient_t *gradient = &image->gradient;
    1.43 +    int n = gradient->n_stops;
    1.44 +    pixman_gradient_stop_t *stops = gradient->stops;
    1.45 +    pixman_gradient_stop_t *begin = &(gradient->stops[-1]);
    1.46 +    pixman_gradient_stop_t *end = &(gradient->stops[n]);
    1.47 +
    1.48 +    switch (gradient->common.repeat)
    1.49 +    {
    1.50 +    default:
    1.51 +    case PIXMAN_REPEAT_NONE:
    1.52 +	begin->x = INT32_MIN;
    1.53 +	begin->color = transparent_black;
    1.54 +	end->x = INT32_MAX;
    1.55 +	end->color = transparent_black;
    1.56 +	break;
    1.57 +
    1.58 +    case PIXMAN_REPEAT_NORMAL:
    1.59 +	begin->x = stops[n - 1].x - pixman_fixed_1;
    1.60 +	begin->color = stops[n - 1].color;
    1.61 +	end->x = stops[0].x + pixman_fixed_1;
    1.62 +	end->color = stops[0].color;
    1.63 +	break;
    1.64 +
    1.65 +    case PIXMAN_REPEAT_REFLECT:
    1.66 +	begin->x = - stops[0].x;
    1.67 +	begin->color = stops[0].color;
    1.68 +	end->x = pixman_int_to_fixed (2) - stops[n - 1].x;
    1.69 +	end->color = stops[n - 1].color;
    1.70 +	break;
    1.71 +
    1.72 +    case PIXMAN_REPEAT_PAD:
    1.73 +	begin->x = INT32_MIN;
    1.74 +	begin->color = stops[0].color;
    1.75 +	end->x = INT32_MAX;
    1.76 +	end->color = stops[n - 1].color;
    1.77 +	break;
    1.78 +    }
    1.79 +}
    1.80 +
    1.81 +pixman_bool_t
    1.82 +_pixman_init_gradient (gradient_t *                  gradient,
    1.83 +                       const pixman_gradient_stop_t *stops,
    1.84 +                       int                           n_stops)
    1.85 +{
    1.86 +    return_val_if_fail (n_stops > 0, FALSE);
    1.87 +
    1.88 +    /* We allocate two extra stops, one before the beginning of the stop list,
    1.89 +     * and one after the end. These stops are initialized to whatever color
    1.90 +     * would be used for positions outside the range of the stop list.
    1.91 +     *
    1.92 +     * This saves a bit of computation in the gradient walker.
    1.93 +     *
    1.94 +     * The pointer we store in the gradient_t struct still points to the
    1.95 +     * first user-supplied struct, so when freeing, we will have to
    1.96 +     * subtract one.
    1.97 +     */
    1.98 +    gradient->stops =
    1.99 +	pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t));
   1.100 +    if (!gradient->stops)
   1.101 +	return FALSE;
   1.102 +
   1.103 +    gradient->stops += 1;
   1.104 +    memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t));
   1.105 +    gradient->n_stops = n_stops;
   1.106 +
   1.107 +    gradient->common.property_changed = gradient_property_changed;
   1.108 +
   1.109 +    return TRUE;
   1.110 +}
   1.111 +
   1.112 +void
   1.113 +_pixman_image_init (pixman_image_t *image)
   1.114 +{
   1.115 +    image_common_t *common = &image->common;
   1.116 +
   1.117 +    pixman_region32_init (&common->clip_region);
   1.118 +
   1.119 +    common->alpha_count = 0;
   1.120 +    common->have_clip_region = FALSE;
   1.121 +    common->clip_sources = FALSE;
   1.122 +    common->transform = NULL;
   1.123 +    common->repeat = PIXMAN_REPEAT_NONE;
   1.124 +    common->filter = PIXMAN_FILTER_NEAREST;
   1.125 +    common->filter_params = NULL;
   1.126 +    common->n_filter_params = 0;
   1.127 +    common->alpha_map = NULL;
   1.128 +    common->component_alpha = FALSE;
   1.129 +    common->ref_count = 1;
   1.130 +    common->property_changed = NULL;
   1.131 +    common->client_clip = FALSE;
   1.132 +    common->destroy_func = NULL;
   1.133 +    common->destroy_data = NULL;
   1.134 +    common->dirty = TRUE;
   1.135 +}
   1.136 +
   1.137 +pixman_bool_t
   1.138 +_pixman_image_fini (pixman_image_t *image)
   1.139 +{
   1.140 +    image_common_t *common = (image_common_t *)image;
   1.141 +
   1.142 +    common->ref_count--;
   1.143 +
   1.144 +    if (common->ref_count == 0)
   1.145 +    {
   1.146 +	if (image->common.destroy_func)
   1.147 +	    image->common.destroy_func (image, image->common.destroy_data);
   1.148 +
   1.149 +	pixman_region32_fini (&common->clip_region);
   1.150 +
   1.151 +	free (common->transform);
   1.152 +	free (common->filter_params);
   1.153 +
   1.154 +	if (common->alpha_map)
   1.155 +	    pixman_image_unref ((pixman_image_t *)common->alpha_map);
   1.156 +
   1.157 +	if (image->type == LINEAR ||
   1.158 +	    image->type == RADIAL ||
   1.159 +	    image->type == CONICAL)
   1.160 +	{
   1.161 +	    if (image->gradient.stops)
   1.162 +	    {
   1.163 +		/* See _pixman_init_gradient() for an explanation of the - 1 */
   1.164 +		free (image->gradient.stops - 1);
   1.165 +	    }
   1.166 +
   1.167 +	    /* This will trigger if someone adds a property_changed
   1.168 +	     * method to the linear/radial/conical gradient overwriting
   1.169 +	     * the general one.
   1.170 +	     */
   1.171 +	    assert (
   1.172 +		image->common.property_changed == gradient_property_changed);
   1.173 +	}
   1.174 +
   1.175 +	if (image->type == BITS && image->bits.free_me)
   1.176 +	    free (image->bits.free_me);
   1.177 +
   1.178 +	return TRUE;
   1.179 +    }
   1.180 +
   1.181 +    return FALSE;
   1.182 +}
   1.183 +
   1.184 +pixman_image_t *
   1.185 +_pixman_image_allocate (void)
   1.186 +{
   1.187 +    pixman_image_t *image = malloc (sizeof (pixman_image_t));
   1.188 +
   1.189 +    if (image)
   1.190 +	_pixman_image_init (image);
   1.191 +
   1.192 +    return image;
   1.193 +}
   1.194 +
   1.195 +static void
   1.196 +image_property_changed (pixman_image_t *image)
   1.197 +{
   1.198 +    image->common.dirty = TRUE;
   1.199 +}
   1.200 +
   1.201 +/* Ref Counting */
   1.202 +PIXMAN_EXPORT pixman_image_t *
   1.203 +pixman_image_ref (pixman_image_t *image)
   1.204 +{
   1.205 +    image->common.ref_count++;
   1.206 +
   1.207 +    return image;
   1.208 +}
   1.209 +
   1.210 +/* returns TRUE when the image is freed */
   1.211 +PIXMAN_EXPORT pixman_bool_t
   1.212 +pixman_image_unref (pixman_image_t *image)
   1.213 +{
   1.214 +    if (_pixman_image_fini (image))
   1.215 +    {
   1.216 +	free (image);
   1.217 +	return TRUE;
   1.218 +    }
   1.219 +
   1.220 +    return FALSE;
   1.221 +}
   1.222 +
   1.223 +PIXMAN_EXPORT void
   1.224 +pixman_image_set_destroy_function (pixman_image_t *            image,
   1.225 +                                   pixman_image_destroy_func_t func,
   1.226 +                                   void *                      data)
   1.227 +{
   1.228 +    image->common.destroy_func = func;
   1.229 +    image->common.destroy_data = data;
   1.230 +}
   1.231 +
   1.232 +PIXMAN_EXPORT void *
   1.233 +pixman_image_get_destroy_data (pixman_image_t *image)
   1.234 +{
   1.235 +  return image->common.destroy_data;
   1.236 +}
   1.237 +
   1.238 +void
   1.239 +_pixman_image_reset_clip_region (pixman_image_t *image)
   1.240 +{
   1.241 +    image->common.have_clip_region = FALSE;
   1.242 +}
   1.243 +
   1.244 +/* Executive Summary: This function is a no-op that only exists
   1.245 + * for historical reasons.
   1.246 + *
   1.247 + * There used to be a bug in the X server where it would rely on
   1.248 + * out-of-bounds accesses when it was asked to composite with a
   1.249 + * window as the source. It would create a pixman image pointing
   1.250 + * to some bogus position in memory, but then set a clip region
   1.251 + * to the position where the actual bits were.
   1.252 + *
   1.253 + * Due to a bug in old versions of pixman, where it would not clip
   1.254 + * against the image bounds when a clip region was set, this would
   1.255 + * actually work. So when the pixman bug was fixed, a workaround was
   1.256 + * added to allow certain out-of-bound accesses. This function disabled
   1.257 + * those workarounds.
   1.258 + *
   1.259 + * Since 0.21.2, pixman doesn't do these workarounds anymore, so now
   1.260 + * this function is a no-op.
   1.261 + */
   1.262 +PIXMAN_EXPORT void
   1.263 +pixman_disable_out_of_bounds_workaround (void)
   1.264 +{
   1.265 +}
   1.266 +
   1.267 +static void
   1.268 +compute_image_info (pixman_image_t *image)
   1.269 +{
   1.270 +    pixman_format_code_t code;
   1.271 +    uint32_t flags = 0;
   1.272 +
   1.273 +    /* Transform */
   1.274 +    if (!image->common.transform)
   1.275 +    {
   1.276 +	flags |= (FAST_PATH_ID_TRANSFORM	|
   1.277 +		  FAST_PATH_X_UNIT_POSITIVE	|
   1.278 +		  FAST_PATH_Y_UNIT_ZERO		|
   1.279 +		  FAST_PATH_AFFINE_TRANSFORM);
   1.280 +    }
   1.281 +    else
   1.282 +    {
   1.283 +	flags |= FAST_PATH_HAS_TRANSFORM;
   1.284 +
   1.285 +	if (image->common.transform->matrix[2][0] == 0			&&
   1.286 +	    image->common.transform->matrix[2][1] == 0			&&
   1.287 +	    image->common.transform->matrix[2][2] == pixman_fixed_1)
   1.288 +	{
   1.289 +	    flags |= FAST_PATH_AFFINE_TRANSFORM;
   1.290 +
   1.291 +	    if (image->common.transform->matrix[0][1] == 0 &&
   1.292 +		image->common.transform->matrix[1][0] == 0)
   1.293 +	    {
   1.294 +		if (image->common.transform->matrix[0][0] == -pixman_fixed_1 &&
   1.295 +		    image->common.transform->matrix[1][1] == -pixman_fixed_1)
   1.296 +		{
   1.297 +		    flags |= FAST_PATH_ROTATE_180_TRANSFORM;
   1.298 +		}
   1.299 +		flags |= FAST_PATH_SCALE_TRANSFORM;
   1.300 +	    }
   1.301 +	    else if (image->common.transform->matrix[0][0] == 0 &&
   1.302 +	             image->common.transform->matrix[1][1] == 0)
   1.303 +	    {
   1.304 +		pixman_fixed_t m01 = image->common.transform->matrix[0][1];
   1.305 +		pixman_fixed_t m10 = image->common.transform->matrix[1][0];
   1.306 +
   1.307 +		if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1)
   1.308 +		    flags |= FAST_PATH_ROTATE_90_TRANSFORM;
   1.309 +		else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1)
   1.310 +		    flags |= FAST_PATH_ROTATE_270_TRANSFORM;
   1.311 +	    }
   1.312 +	}
   1.313 +
   1.314 +	if (image->common.transform->matrix[0][0] > 0)
   1.315 +	    flags |= FAST_PATH_X_UNIT_POSITIVE;
   1.316 +
   1.317 +	if (image->common.transform->matrix[1][0] == 0)
   1.318 +	    flags |= FAST_PATH_Y_UNIT_ZERO;
   1.319 +    }
   1.320 +
   1.321 +    /* Filter */
   1.322 +    switch (image->common.filter)
   1.323 +    {
   1.324 +    case PIXMAN_FILTER_NEAREST:
   1.325 +    case PIXMAN_FILTER_FAST:
   1.326 +	flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
   1.327 +	break;
   1.328 +
   1.329 +    case PIXMAN_FILTER_BILINEAR:
   1.330 +    case PIXMAN_FILTER_GOOD:
   1.331 +    case PIXMAN_FILTER_BEST:
   1.332 +	flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER);
   1.333 +
   1.334 +	/* Here we have a chance to optimize BILINEAR filter to NEAREST if
   1.335 +	 * they are equivalent for the currently used transformation matrix.
   1.336 +	 */
   1.337 +	if (flags & FAST_PATH_ID_TRANSFORM)
   1.338 +	{
   1.339 +	    flags |= FAST_PATH_NEAREST_FILTER;
   1.340 +	}
   1.341 +	else if (
   1.342 +	    /* affine and integer translation components in matrix ... */
   1.343 +	    ((flags & FAST_PATH_AFFINE_TRANSFORM) &&
   1.344 +	     !pixman_fixed_frac (image->common.transform->matrix[0][2] |
   1.345 +				 image->common.transform->matrix[1][2])) &&
   1.346 +	    (
   1.347 +		/* ... combined with a simple rotation */
   1.348 +		(flags & (FAST_PATH_ROTATE_90_TRANSFORM |
   1.349 +			  FAST_PATH_ROTATE_180_TRANSFORM |
   1.350 +			  FAST_PATH_ROTATE_270_TRANSFORM)) ||
   1.351 +		/* ... or combined with a simple non-rotated translation */
   1.352 +		(image->common.transform->matrix[0][0] == pixman_fixed_1 &&
   1.353 +		 image->common.transform->matrix[1][1] == pixman_fixed_1 &&
   1.354 +		 image->common.transform->matrix[0][1] == 0 &&
   1.355 +		 image->common.transform->matrix[1][0] == 0)
   1.356 +		)
   1.357 +	    )
   1.358 +	{
   1.359 +	    /* FIXME: there are some affine-test failures, showing that
   1.360 +	     * handling of BILINEAR and NEAREST filter is not quite
   1.361 +	     * equivalent when getting close to 32K for the translation
   1.362 +	     * components of the matrix. That's likely some bug, but for
   1.363 +	     * now just skip BILINEAR->NEAREST optimization in this case.
   1.364 +	     */
   1.365 +	    pixman_fixed_t magic_limit = pixman_int_to_fixed (30000);
   1.366 +	    if (image->common.transform->matrix[0][2] <= magic_limit  &&
   1.367 +	        image->common.transform->matrix[1][2] <= magic_limit  &&
   1.368 +	        image->common.transform->matrix[0][2] >= -magic_limit &&
   1.369 +	        image->common.transform->matrix[1][2] >= -magic_limit)
   1.370 +	    {
   1.371 +		flags |= FAST_PATH_NEAREST_FILTER;
   1.372 +	    }
   1.373 +	}
   1.374 +	break;
   1.375 +
   1.376 +    case PIXMAN_FILTER_CONVOLUTION:
   1.377 +	break;
   1.378 +
   1.379 +    case PIXMAN_FILTER_SEPARABLE_CONVOLUTION:
   1.380 +	flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER;
   1.381 +	break;
   1.382 +
   1.383 +    default:
   1.384 +	flags |= FAST_PATH_NO_CONVOLUTION_FILTER;
   1.385 +	break;
   1.386 +    }
   1.387 +
   1.388 +    /* Repeat mode */
   1.389 +    switch (image->common.repeat)
   1.390 +    {
   1.391 +    case PIXMAN_REPEAT_NONE:
   1.392 +	flags |=
   1.393 +	    FAST_PATH_NO_REFLECT_REPEAT		|
   1.394 +	    FAST_PATH_NO_PAD_REPEAT		|
   1.395 +	    FAST_PATH_NO_NORMAL_REPEAT;
   1.396 +	break;
   1.397 +
   1.398 +    case PIXMAN_REPEAT_REFLECT:
   1.399 +	flags |=
   1.400 +	    FAST_PATH_NO_PAD_REPEAT		|
   1.401 +	    FAST_PATH_NO_NONE_REPEAT		|
   1.402 +	    FAST_PATH_NO_NORMAL_REPEAT;
   1.403 +	break;
   1.404 +
   1.405 +    case PIXMAN_REPEAT_PAD:
   1.406 +	flags |=
   1.407 +	    FAST_PATH_NO_REFLECT_REPEAT		|
   1.408 +	    FAST_PATH_NO_NONE_REPEAT		|
   1.409 +	    FAST_PATH_NO_NORMAL_REPEAT;
   1.410 +	break;
   1.411 +
   1.412 +    default:
   1.413 +	flags |=
   1.414 +	    FAST_PATH_NO_REFLECT_REPEAT		|
   1.415 +	    FAST_PATH_NO_PAD_REPEAT		|
   1.416 +	    FAST_PATH_NO_NONE_REPEAT;
   1.417 +	break;
   1.418 +    }
   1.419 +
   1.420 +    /* Component alpha */
   1.421 +    if (image->common.component_alpha)
   1.422 +	flags |= FAST_PATH_COMPONENT_ALPHA;
   1.423 +    else
   1.424 +	flags |= FAST_PATH_UNIFIED_ALPHA;
   1.425 +
   1.426 +    flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT);
   1.427 +
   1.428 +    /* Type specific checks */
   1.429 +    switch (image->type)
   1.430 +    {
   1.431 +    case SOLID:
   1.432 +	code = PIXMAN_solid;
   1.433 +
   1.434 +	if (image->solid.color.alpha == 0xffff)
   1.435 +	    flags |= FAST_PATH_IS_OPAQUE;
   1.436 +	break;
   1.437 +
   1.438 +    case BITS:
   1.439 +	if (image->bits.width == 1	&&
   1.440 +	    image->bits.height == 1	&&
   1.441 +	    image->common.repeat != PIXMAN_REPEAT_NONE)
   1.442 +	{
   1.443 +	    code = PIXMAN_solid;
   1.444 +	}
   1.445 +	else
   1.446 +	{
   1.447 +	    code = image->bits.format;
   1.448 +	    flags |= FAST_PATH_BITS_IMAGE;
   1.449 +	}
   1.450 +
   1.451 +	if (!PIXMAN_FORMAT_A (image->bits.format)				&&
   1.452 +	    PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY		&&
   1.453 +	    PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR)
   1.454 +	{
   1.455 +	    flags |= FAST_PATH_SAMPLES_OPAQUE;
   1.456 +
   1.457 +	    if (image->common.repeat != PIXMAN_REPEAT_NONE)
   1.458 +		flags |= FAST_PATH_IS_OPAQUE;
   1.459 +	}
   1.460 +
   1.461 +	if (image->bits.read_func || image->bits.write_func)
   1.462 +	    flags &= ~FAST_PATH_NO_ACCESSORS;
   1.463 +
   1.464 +	if (PIXMAN_FORMAT_IS_WIDE (image->bits.format))
   1.465 +	    flags &= ~FAST_PATH_NARROW_FORMAT;
   1.466 +
   1.467 +	if (image->bits.format == PIXMAN_r5g6b5)
   1.468 +	    flags |= FAST_PATH_16_FORMAT;
   1.469 +
   1.470 +	break;
   1.471 +
   1.472 +    case RADIAL:
   1.473 +	code = PIXMAN_unknown;
   1.474 +
   1.475 +	/*
   1.476 +	 * As explained in pixman-radial-gradient.c, every point of
   1.477 +	 * the plane has a valid associated radius (and thus will be
   1.478 +	 * colored) if and only if a is negative (i.e. one of the two
   1.479 +	 * circles contains the other one).
   1.480 +	 */
   1.481 +
   1.482 +        if (image->radial.a >= 0)
   1.483 +	    break;
   1.484 +
   1.485 +	/* Fall through */
   1.486 +
   1.487 +    case CONICAL:
   1.488 +    case LINEAR:
   1.489 +	code = PIXMAN_unknown;
   1.490 +
   1.491 +	if (image->common.repeat != PIXMAN_REPEAT_NONE)
   1.492 +	{
   1.493 +	    int i;
   1.494 +
   1.495 +	    flags |= FAST_PATH_IS_OPAQUE;
   1.496 +	    for (i = 0; i < image->gradient.n_stops; ++i)
   1.497 +	    {
   1.498 +		if (image->gradient.stops[i].color.alpha != 0xffff)
   1.499 +		{
   1.500 +		    flags &= ~FAST_PATH_IS_OPAQUE;
   1.501 +		    break;
   1.502 +		}
   1.503 +	    }
   1.504 +	}
   1.505 +	break;
   1.506 +
   1.507 +    default:
   1.508 +	code = PIXMAN_unknown;
   1.509 +	break;
   1.510 +    }
   1.511 +
   1.512 +    /* Alpha map */
   1.513 +    if (!image->common.alpha_map)
   1.514 +    {
   1.515 +	flags |= FAST_PATH_NO_ALPHA_MAP;
   1.516 +    }
   1.517 +    else
   1.518 +    {
   1.519 +	if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format))
   1.520 +	    flags &= ~FAST_PATH_NARROW_FORMAT;
   1.521 +    }
   1.522 +
   1.523 +    /* Both alpha maps and convolution filters can introduce
   1.524 +     * non-opaqueness in otherwise opaque images. Also
   1.525 +     * an image with component alpha turned on is only opaque
   1.526 +     * if all channels are opaque, so we simply turn it off
   1.527 +     * unconditionally for those images.
   1.528 +     */
   1.529 +    if (image->common.alpha_map						||
   1.530 +	image->common.filter == PIXMAN_FILTER_CONVOLUTION		||
   1.531 +        image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION     ||
   1.532 +	image->common.component_alpha)
   1.533 +    {
   1.534 +	flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE);
   1.535 +    }
   1.536 +
   1.537 +    image->common.flags = flags;
   1.538 +    image->common.extended_format_code = code;
   1.539 +}
   1.540 +
   1.541 +void
   1.542 +_pixman_image_validate (pixman_image_t *image)
   1.543 +{
   1.544 +    if (image->common.dirty)
   1.545 +    {
   1.546 +	compute_image_info (image);
   1.547 +
   1.548 +	/* It is important that property_changed is
   1.549 +	 * called *after* compute_image_info() because
   1.550 +	 * property_changed() can make use of the flags
   1.551 +	 * to set up accessors etc.
   1.552 +	 */
   1.553 +	if (image->common.property_changed)
   1.554 +	    image->common.property_changed (image);
   1.555 +
   1.556 +	image->common.dirty = FALSE;
   1.557 +    }
   1.558 +
   1.559 +    if (image->common.alpha_map)
   1.560 +	_pixman_image_validate ((pixman_image_t *)image->common.alpha_map);
   1.561 +}
   1.562 +
   1.563 +PIXMAN_EXPORT pixman_bool_t
   1.564 +pixman_image_set_clip_region32 (pixman_image_t *   image,
   1.565 +                                pixman_region32_t *region)
   1.566 +{
   1.567 +    image_common_t *common = (image_common_t *)image;
   1.568 +    pixman_bool_t result;
   1.569 +
   1.570 +    if (region)
   1.571 +    {
   1.572 +	if ((result = pixman_region32_copy (&common->clip_region, region)))
   1.573 +	    image->common.have_clip_region = TRUE;
   1.574 +    }
   1.575 +    else
   1.576 +    {
   1.577 +	_pixman_image_reset_clip_region (image);
   1.578 +
   1.579 +	result = TRUE;
   1.580 +    }
   1.581 +
   1.582 +    image_property_changed (image);
   1.583 +
   1.584 +    return result;
   1.585 +}
   1.586 +
   1.587 +PIXMAN_EXPORT pixman_bool_t
   1.588 +pixman_image_set_clip_region (pixman_image_t *   image,
   1.589 +                              pixman_region16_t *region)
   1.590 +{
   1.591 +    image_common_t *common = (image_common_t *)image;
   1.592 +    pixman_bool_t result;
   1.593 +
   1.594 +    if (region)
   1.595 +    {
   1.596 +	if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region)))
   1.597 +	    image->common.have_clip_region = TRUE;
   1.598 +    }
   1.599 +    else
   1.600 +    {
   1.601 +	_pixman_image_reset_clip_region (image);
   1.602 +
   1.603 +	result = TRUE;
   1.604 +    }
   1.605 +
   1.606 +    image_property_changed (image);
   1.607 +
   1.608 +    return result;
   1.609 +}
   1.610 +
   1.611 +PIXMAN_EXPORT void
   1.612 +pixman_image_set_has_client_clip (pixman_image_t *image,
   1.613 +                                  pixman_bool_t   client_clip)
   1.614 +{
   1.615 +    image->common.client_clip = client_clip;
   1.616 +}
   1.617 +
   1.618 +PIXMAN_EXPORT pixman_bool_t
   1.619 +pixman_image_set_transform (pixman_image_t *          image,
   1.620 +                            const pixman_transform_t *transform)
   1.621 +{
   1.622 +    static const pixman_transform_t id =
   1.623 +    {
   1.624 +	{ { pixman_fixed_1, 0, 0 },
   1.625 +	  { 0, pixman_fixed_1, 0 },
   1.626 +	  { 0, 0, pixman_fixed_1 } }
   1.627 +    };
   1.628 +
   1.629 +    image_common_t *common = (image_common_t *)image;
   1.630 +    pixman_bool_t result;
   1.631 +
   1.632 +    if (common->transform == transform)
   1.633 +	return TRUE;
   1.634 +
   1.635 +    if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0)
   1.636 +    {
   1.637 +	free (common->transform);
   1.638 +	common->transform = NULL;
   1.639 +	result = TRUE;
   1.640 +
   1.641 +	goto out;
   1.642 +    }
   1.643 +
   1.644 +    if (common->transform &&
   1.645 +	memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0)
   1.646 +    {
   1.647 +	return TRUE;
   1.648 +    }
   1.649 +
   1.650 +    if (common->transform == NULL)
   1.651 +	common->transform = malloc (sizeof (pixman_transform_t));
   1.652 +
   1.653 +    if (common->transform == NULL)
   1.654 +    {
   1.655 +	result = FALSE;
   1.656 +
   1.657 +	goto out;
   1.658 +    }
   1.659 +
   1.660 +    memcpy (common->transform, transform, sizeof(pixman_transform_t));
   1.661 +
   1.662 +    result = TRUE;
   1.663 +
   1.664 +out:
   1.665 +    image_property_changed (image);
   1.666 +
   1.667 +    return result;
   1.668 +}
   1.669 +
   1.670 +PIXMAN_EXPORT void
   1.671 +pixman_image_set_repeat (pixman_image_t *image,
   1.672 +                         pixman_repeat_t repeat)
   1.673 +{
   1.674 +    if (image->common.repeat == repeat)
   1.675 +	return;
   1.676 +
   1.677 +    image->common.repeat = repeat;
   1.678 +
   1.679 +    image_property_changed (image);
   1.680 +}
   1.681 +
   1.682 +PIXMAN_EXPORT pixman_bool_t
   1.683 +pixman_image_set_filter (pixman_image_t *      image,
   1.684 +                         pixman_filter_t       filter,
   1.685 +                         const pixman_fixed_t *params,
   1.686 +                         int                   n_params)
   1.687 +{
   1.688 +    image_common_t *common = (image_common_t *)image;
   1.689 +    pixman_fixed_t *new_params;
   1.690 +
   1.691 +    if (params == common->filter_params && filter == common->filter)
   1.692 +	return TRUE;
   1.693 +
   1.694 +    if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION)
   1.695 +    {
   1.696 +	int width = pixman_fixed_to_int (params[0]);
   1.697 +	int height = pixman_fixed_to_int (params[1]);
   1.698 +	int x_phase_bits = pixman_fixed_to_int (params[2]);
   1.699 +	int y_phase_bits = pixman_fixed_to_int (params[3]);
   1.700 +	int n_x_phases = (1 << x_phase_bits);
   1.701 +	int n_y_phases = (1 << y_phase_bits);
   1.702 +
   1.703 +	return_val_if_fail (
   1.704 +	    n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE);
   1.705 +    }
   1.706 +    
   1.707 +    new_params = NULL;
   1.708 +    if (params)
   1.709 +    {
   1.710 +	new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t));
   1.711 +	if (!new_params)
   1.712 +	    return FALSE;
   1.713 +
   1.714 +	memcpy (new_params,
   1.715 +	        params, n_params * sizeof (pixman_fixed_t));
   1.716 +    }
   1.717 +
   1.718 +    common->filter = filter;
   1.719 +
   1.720 +    if (common->filter_params)
   1.721 +	free (common->filter_params);
   1.722 +
   1.723 +    common->filter_params = new_params;
   1.724 +    common->n_filter_params = n_params;
   1.725 +
   1.726 +    image_property_changed (image);
   1.727 +    return TRUE;
   1.728 +}
   1.729 +
   1.730 +PIXMAN_EXPORT void
   1.731 +pixman_image_set_source_clipping (pixman_image_t *image,
   1.732 +                                  pixman_bool_t   clip_sources)
   1.733 +{
   1.734 +    if (image->common.clip_sources == clip_sources)
   1.735 +	return;
   1.736 +
   1.737 +    image->common.clip_sources = clip_sources;
   1.738 +
   1.739 +    image_property_changed (image);
   1.740 +}
   1.741 +
   1.742 +/* Unlike all the other property setters, this function does not
   1.743 + * copy the content of indexed. Doing this copying is simply
   1.744 + * way, way too expensive.
   1.745 + */
   1.746 +PIXMAN_EXPORT void
   1.747 +pixman_image_set_indexed (pixman_image_t *        image,
   1.748 +                          const pixman_indexed_t *indexed)
   1.749 +{
   1.750 +    bits_image_t *bits = (bits_image_t *)image;
   1.751 +
   1.752 +    if (bits->indexed == indexed)
   1.753 +	return;
   1.754 +
   1.755 +    bits->indexed = indexed;
   1.756 +
   1.757 +    image_property_changed (image);
   1.758 +}
   1.759 +
   1.760 +PIXMAN_EXPORT void
   1.761 +pixman_image_set_alpha_map (pixman_image_t *image,
   1.762 +                            pixman_image_t *alpha_map,
   1.763 +                            int16_t         x,
   1.764 +                            int16_t         y)
   1.765 +{
   1.766 +    image_common_t *common = (image_common_t *)image;
   1.767 +
   1.768 +    return_if_fail (!alpha_map || alpha_map->type == BITS);
   1.769 +
   1.770 +    if (alpha_map && common->alpha_count > 0)
   1.771 +    {
   1.772 +	/* If this image is being used as an alpha map itself,
   1.773 +	 * then you can't give it an alpha map of its own.
   1.774 +	 */
   1.775 +	return;
   1.776 +    }
   1.777 +
   1.778 +    if (alpha_map && alpha_map->common.alpha_map)
   1.779 +    {
   1.780 +	/* If the image has an alpha map of its own,
   1.781 +	 * then it can't be used as an alpha map itself
   1.782 +	 */
   1.783 +	return;
   1.784 +    }
   1.785 +
   1.786 +    if (common->alpha_map != (bits_image_t *)alpha_map)
   1.787 +    {
   1.788 +	if (common->alpha_map)
   1.789 +	{
   1.790 +	    common->alpha_map->common.alpha_count--;
   1.791 +
   1.792 +	    pixman_image_unref ((pixman_image_t *)common->alpha_map);
   1.793 +	}
   1.794 +
   1.795 +	if (alpha_map)
   1.796 +	{
   1.797 +	    common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
   1.798 +
   1.799 +	    common->alpha_map->common.alpha_count++;
   1.800 +	}
   1.801 +	else
   1.802 +	{
   1.803 +	    common->alpha_map = NULL;
   1.804 +	}
   1.805 +    }
   1.806 +
   1.807 +    common->alpha_origin_x = x;
   1.808 +    common->alpha_origin_y = y;
   1.809 +
   1.810 +    image_property_changed (image);
   1.811 +}
   1.812 +
   1.813 +PIXMAN_EXPORT void
   1.814 +pixman_image_set_component_alpha   (pixman_image_t *image,
   1.815 +                                    pixman_bool_t   component_alpha)
   1.816 +{
   1.817 +    if (image->common.component_alpha == component_alpha)
   1.818 +	return;
   1.819 +
   1.820 +    image->common.component_alpha = component_alpha;
   1.821 +
   1.822 +    image_property_changed (image);
   1.823 +}
   1.824 +
   1.825 +PIXMAN_EXPORT pixman_bool_t
   1.826 +pixman_image_get_component_alpha   (pixman_image_t       *image)
   1.827 +{
   1.828 +    return image->common.component_alpha;
   1.829 +}
   1.830 +
   1.831 +PIXMAN_EXPORT void
   1.832 +pixman_image_set_accessors (pixman_image_t *           image,
   1.833 +                            pixman_read_memory_func_t  read_func,
   1.834 +                            pixman_write_memory_func_t write_func)
   1.835 +{
   1.836 +    return_if_fail (image != NULL);
   1.837 +
   1.838 +    if (image->type == BITS)
   1.839 +    {
   1.840 +	image->bits.read_func = read_func;
   1.841 +	image->bits.write_func = write_func;
   1.842 +
   1.843 +	image_property_changed (image);
   1.844 +    }
   1.845 +}
   1.846 +
   1.847 +PIXMAN_EXPORT uint32_t *
   1.848 +pixman_image_get_data (pixman_image_t *image)
   1.849 +{
   1.850 +    if (image->type == BITS)
   1.851 +	return image->bits.bits;
   1.852 +
   1.853 +    return NULL;
   1.854 +}
   1.855 +
   1.856 +PIXMAN_EXPORT int
   1.857 +pixman_image_get_width (pixman_image_t *image)
   1.858 +{
   1.859 +    if (image->type == BITS)
   1.860 +	return image->bits.width;
   1.861 +
   1.862 +    return 0;
   1.863 +}
   1.864 +
   1.865 +PIXMAN_EXPORT int
   1.866 +pixman_image_get_height (pixman_image_t *image)
   1.867 +{
   1.868 +    if (image->type == BITS)
   1.869 +	return image->bits.height;
   1.870 +
   1.871 +    return 0;
   1.872 +}
   1.873 +
   1.874 +PIXMAN_EXPORT int
   1.875 +pixman_image_get_stride (pixman_image_t *image)
   1.876 +{
   1.877 +    if (image->type == BITS)
   1.878 +	return image->bits.rowstride * (int) sizeof (uint32_t);
   1.879 +
   1.880 +    return 0;
   1.881 +}
   1.882 +
   1.883 +PIXMAN_EXPORT int
   1.884 +pixman_image_get_depth (pixman_image_t *image)
   1.885 +{
   1.886 +    if (image->type == BITS)
   1.887 +	return PIXMAN_FORMAT_DEPTH (image->bits.format);
   1.888 +
   1.889 +    return 0;
   1.890 +}
   1.891 +
   1.892 +PIXMAN_EXPORT pixman_format_code_t
   1.893 +pixman_image_get_format (pixman_image_t *image)
   1.894 +{
   1.895 +    if (image->type == BITS)
   1.896 +	return image->bits.format;
   1.897 +
   1.898 +    return PIXMAN_null;
   1.899 +}
   1.900 +
   1.901 +uint32_t
   1.902 +_pixman_image_get_solid (pixman_implementation_t *imp,
   1.903 +			 pixman_image_t *         image,
   1.904 +                         pixman_format_code_t     format)
   1.905 +{
   1.906 +    uint32_t result;
   1.907 +
   1.908 +    if (image->type == SOLID)
   1.909 +    {
   1.910 +	result = image->solid.color_32;
   1.911 +    }
   1.912 +    else if (image->type == BITS)
   1.913 +    {
   1.914 +	if (image->bits.format == PIXMAN_a8r8g8b8)
   1.915 +	    result = image->bits.bits[0];
   1.916 +	else if (image->bits.format == PIXMAN_x8r8g8b8)
   1.917 +	    result = image->bits.bits[0] | 0xff000000;
   1.918 +	else if (image->bits.format == PIXMAN_a8)
   1.919 +	    result = (*(uint8_t *)image->bits.bits) << 24;
   1.920 +	else
   1.921 +	    goto otherwise;
   1.922 +    }
   1.923 +    else
   1.924 +    {
   1.925 +	pixman_iter_t iter;
   1.926 +
   1.927 +    otherwise:
   1.928 +	_pixman_implementation_src_iter_init (
   1.929 +	    imp, &iter, image, 0, 0, 1, 1,
   1.930 +	    (uint8_t *)&result,
   1.931 +	    ITER_NARROW, image->common.flags);
   1.932 +	
   1.933 +	result = *iter.get_scanline (&iter, NULL);
   1.934 +    }
   1.935 +
   1.936 +    /* If necessary, convert RGB <--> BGR. */
   1.937 +    if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB
   1.938 +	&& PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB)
   1.939 +    {
   1.940 +	result = (((result & 0xff000000) >>  0) |
   1.941 +	          ((result & 0x00ff0000) >> 16) |
   1.942 +	          ((result & 0x0000ff00) >>  0) |
   1.943 +	          ((result & 0x000000ff) << 16));
   1.944 +    }
   1.945 +
   1.946 +    return result;
   1.947 +}

mercurial