X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=pixman%2Fpixman-image.c;h=8599a1eb100047ffb3d2f49274e345da89138f9f;hb=17acc7a4c707db4804b6bf47db30883745049fdb;hp=f95bf3f76b13007a73e6122e5b32aef5ec704ad8;hpb=0db0430d1d410855863e669f0de9e8b5d26db7fd;p=profile%2Fivi%2Fpixman.git diff --git a/pixman/pixman-image.c b/pixman/pixman-image.c index f95bf3f..8599a1e 100644 --- a/pixman/pixman-image.c +++ b/pixman/pixman-image.c @@ -30,130 +30,169 @@ #include #include "pixman-private.h" -#include "pixman-combine32.h" + +static const pixman_color_t transparent_black = { 0, 0, 0, 0 }; + +static void +gradient_property_changed (pixman_image_t *image) +{ + gradient_t *gradient = &image->gradient; + int n = gradient->n_stops; + pixman_gradient_stop_t *stops = gradient->stops; + pixman_gradient_stop_t *begin = &(gradient->stops[-1]); + pixman_gradient_stop_t *end = &(gradient->stops[n]); + + switch (gradient->common.repeat) + { + default: + case PIXMAN_REPEAT_NONE: + begin->x = INT32_MIN; + begin->color = transparent_black; + end->x = INT32_MAX; + end->color = transparent_black; + break; + + case PIXMAN_REPEAT_NORMAL: + begin->x = stops[n - 1].x - pixman_fixed_1; + begin->color = stops[n - 1].color; + end->x = stops[0].x + pixman_fixed_1; + end->color = stops[0].color; + break; + + case PIXMAN_REPEAT_REFLECT: + begin->x = - stops[0].x; + begin->color = stops[0].color; + end->x = pixman_int_to_fixed (2) - stops[n - 1].x; + end->color = stops[n - 1].color; + break; + + case PIXMAN_REPEAT_PAD: + begin->x = INT32_MIN; + begin->color = stops[0].color; + end->x = INT32_MAX; + end->color = stops[n - 1].color; + break; + } +} pixman_bool_t -_pixman_init_gradient (gradient_t *gradient, - const pixman_gradient_stop_t *stops, - int n_stops) +_pixman_init_gradient (gradient_t * gradient, + const pixman_gradient_stop_t *stops, + int n_stops) { return_val_if_fail (n_stops > 0, FALSE); - gradient->stops = pixman_malloc_ab (n_stops, sizeof (pixman_gradient_stop_t)); + /* We allocate two extra stops, one before the beginning of the stop list, + * and one after the end. These stops are initialized to whatever color + * would be used for positions outside the range of the stop list. + * + * This saves a bit of computation in the gradient walker. + * + * The pointer we store in the gradient_t struct still points to the + * first user-supplied struct, so when freeing, we will have to + * subtract one. + */ + gradient->stops = + pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t)); if (!gradient->stops) return FALSE; + gradient->stops += 1; memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t)); - gradient->n_stops = n_stops; - gradient->stop_range = 0xffff; - gradient->color_table = NULL; - gradient->color_table_size = 0; - gradient->common.class = SOURCE_IMAGE_CLASS_UNKNOWN; + gradient->common.property_changed = gradient_property_changed; return TRUE; } -/* - * By default, just evaluate the image at 32bpp and expand. Individual image - * types can plug in a better scanline getter if they want to. For example - * we could produce smoother gradients by evaluating them at higher color - * depth, but that's a project for the future. - */ void -_pixman_image_get_scanline_generic_64 (pixman_image_t * pict, int x, int y, - int width, uint32_t *buffer, - const uint32_t *mask, uint32_t mask_bits) -{ - uint32_t *mask8 = NULL; - - // Contract the mask image, if one exists, so that the 32-bit fetch - // function can use it. - if (mask) { - mask8 = pixman_malloc_ab(width, sizeof(uint32_t)); - if (!mask8) - return; - - pixman_contract (mask8, (uint64_t *)mask, width); - } - - // Fetch the source image into the first half of buffer. - _pixman_image_get_scanline_32 (pict, x, y, width, (uint32_t*)buffer, mask8, - mask_bits); - - // Expand from 32bpp to 64bpp in place. - pixman_expand ((uint64_t *)buffer, buffer, PIXMAN_a8r8g8b8, width); - - free (mask8); +_pixman_image_init (pixman_image_t *image) +{ + image_common_t *common = &image->common; + + pixman_region32_init (&common->clip_region); + + common->alpha_count = 0; + common->have_clip_region = FALSE; + common->clip_sources = FALSE; + common->transform = NULL; + common->repeat = PIXMAN_REPEAT_NONE; + common->filter = PIXMAN_FILTER_NEAREST; + common->filter_params = NULL; + common->n_filter_params = 0; + common->alpha_map = NULL; + common->component_alpha = FALSE; + common->ref_count = 1; + common->property_changed = NULL; + common->client_clip = FALSE; + common->destroy_func = NULL; + common->destroy_data = NULL; + common->dirty = TRUE; } -pixman_image_t * -_pixman_image_allocate (void) +pixman_bool_t +_pixman_image_fini (pixman_image_t *image) { - pixman_image_t *image = malloc (sizeof (pixman_image_t)); + image_common_t *common = (image_common_t *)image; - if (image) + common->ref_count--; + + if (common->ref_count == 0) { - image_common_t *common = &image->common; + if (image->common.destroy_func) + image->common.destroy_func (image, image->common.destroy_data); - pixman_region32_init (&common->clip_region); + pixman_region32_fini (&common->clip_region); - common->have_clip_region = FALSE; - common->clip_sources = FALSE; - common->transform = NULL; - common->repeat = PIXMAN_REPEAT_NONE; - common->filter = PIXMAN_FILTER_NEAREST; - common->filter_params = NULL; - common->n_filter_params = 0; - common->alpha_map = NULL; - common->component_alpha = FALSE; - common->ref_count = 1; - common->read_func = NULL; - common->write_func = NULL; - common->classify = NULL; - common->client_clip = FALSE; - common->destroy_func = NULL; - common->destroy_data = NULL; + free (common->transform); + free (common->filter_params); + + if (common->alpha_map) + pixman_image_unref ((pixman_image_t *)common->alpha_map); + + if (image->type == LINEAR || + image->type == RADIAL || + image->type == CONICAL) + { + if (image->gradient.stops) + { + /* See _pixman_init_gradient() for an explanation of the - 1 */ + free (image->gradient.stops - 1); + } + + /* This will trigger if someone adds a property_changed + * method to the linear/radial/conical gradient overwriting + * the general one. + */ + assert ( + image->common.property_changed == gradient_property_changed); + } + + if (image->type == BITS && image->bits.free_me) + free (image->bits.free_me); + + return TRUE; } - return image; + return FALSE; } -source_pict_class_t -_pixman_image_classify (pixman_image_t *image, - int x, - int y, - int width, - int height) +pixman_image_t * +_pixman_image_allocate (void) { - if (image->common.classify) - return image->common.classify (image, x, y, width, height); - else - return SOURCE_IMAGE_CLASS_UNKNOWN; -} + pixman_image_t *image = malloc (sizeof (pixman_image_t)); -void -_pixman_image_get_scanline_32 (pixman_image_t *image, int x, int y, int width, uint32_t *buffer, - const uint32_t *mask, uint32_t mask_bits) -{ - image->common.get_scanline_32 (image, x, y, width, buffer, mask, mask_bits); -} + if (image) + _pixman_image_init (image); -/* Even thought the type of buffer is uint32_t *, the function actually expects - * a uint64_t *buffer. - */ -void -_pixman_image_get_scanline_64 (pixman_image_t *image, int x, int y, int width, uint32_t *buffer, - const uint32_t *unused, uint32_t unused2) -{ - image->common.get_scanline_64 (image, x, y, width, buffer, unused, unused2); + return image; } static void image_property_changed (pixman_image_t *image) { - image->common.property_changed (image); + image->common.dirty = TRUE; } /* Ref Counting */ @@ -169,73 +208,349 @@ pixman_image_ref (pixman_image_t *image) PIXMAN_EXPORT pixman_bool_t pixman_image_unref (pixman_image_t *image) { - image_common_t *common = (image_common_t *)image; + if (_pixman_image_fini (image)) + { + free (image); + return TRUE; + } - common->ref_count--; + return FALSE; +} - if (common->ref_count == 0) +PIXMAN_EXPORT void +pixman_image_set_destroy_function (pixman_image_t * image, + pixman_image_destroy_func_t func, + void * data) +{ + image->common.destroy_func = func; + image->common.destroy_data = data; +} + +PIXMAN_EXPORT void * +pixman_image_get_destroy_data (pixman_image_t *image) +{ + return image->common.destroy_data; +} + +void +_pixman_image_reset_clip_region (pixman_image_t *image) +{ + image->common.have_clip_region = FALSE; +} + +/* Executive Summary: This function is a no-op that only exists + * for historical reasons. + * + * There used to be a bug in the X server where it would rely on + * out-of-bounds accesses when it was asked to composite with a + * window as the source. It would create a pixman image pointing + * to some bogus position in memory, but then set a clip region + * to the position where the actual bits were. + * + * Due to a bug in old versions of pixman, where it would not clip + * against the image bounds when a clip region was set, this would + * actually work. So when the pixman bug was fixed, a workaround was + * added to allow certain out-of-bound accesses. This function disabled + * those workarounds. + * + * Since 0.21.2, pixman doesn't do these workarounds anymore, so now + * this function is a no-op. + */ +PIXMAN_EXPORT void +pixman_disable_out_of_bounds_workaround (void) +{ +} + +static void +compute_image_info (pixman_image_t *image) +{ + pixman_format_code_t code; + uint32_t flags = 0; + + /* Transform */ + if (!image->common.transform) { - if (image->common.destroy_func) - image->common.destroy_func (image, image->common.destroy_data); - - pixman_region32_fini (&common->clip_region); + flags |= (FAST_PATH_ID_TRANSFORM | + FAST_PATH_X_UNIT_POSITIVE | + FAST_PATH_Y_UNIT_ZERO | + FAST_PATH_AFFINE_TRANSFORM); + } + else + { + flags |= FAST_PATH_HAS_TRANSFORM; - if (common->transform) - free (common->transform); + if (image->common.transform->matrix[2][0] == 0 && + image->common.transform->matrix[2][1] == 0 && + image->common.transform->matrix[2][2] == pixman_fixed_1) + { + flags |= FAST_PATH_AFFINE_TRANSFORM; + + if (image->common.transform->matrix[0][1] == 0 && + image->common.transform->matrix[1][0] == 0) + { + if (image->common.transform->matrix[0][0] == -pixman_fixed_1 && + image->common.transform->matrix[1][1] == -pixman_fixed_1) + { + flags |= FAST_PATH_ROTATE_180_TRANSFORM; + } + flags |= FAST_PATH_SCALE_TRANSFORM; + } + else if (image->common.transform->matrix[0][0] == 0 && + image->common.transform->matrix[1][1] == 0) + { + pixman_fixed_t m01 = image->common.transform->matrix[0][1]; + pixman_fixed_t m10 = image->common.transform->matrix[1][0]; + + if (m01 == -1 && m10 == 1) + flags |= FAST_PATH_ROTATE_90_TRANSFORM; + else if (m01 == 1 && m10 == -1) + flags |= FAST_PATH_ROTATE_270_TRANSFORM; + } + } - if (common->filter_params) - free (common->filter_params); + if (image->common.transform->matrix[0][0] > 0) + flags |= FAST_PATH_X_UNIT_POSITIVE; - if (common->alpha_map) - pixman_image_unref ((pixman_image_t *)common->alpha_map); + if (image->common.transform->matrix[1][0] == 0) + flags |= FAST_PATH_Y_UNIT_ZERO; + } -#if 0 - if (image->type == BITS && image->bits.indexed) - free (image->bits.indexed); -#endif + /* Filter */ + switch (image->common.filter) + { + case PIXMAN_FILTER_NEAREST: + case PIXMAN_FILTER_FAST: + flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER); + break; -#if 0 - memset (image, 0xaa, sizeof (pixman_image_t)); -#endif - if (image->type == LINEAR || image->type == RADIAL || image->type == CONICAL) + case PIXMAN_FILTER_BILINEAR: + case PIXMAN_FILTER_GOOD: + case PIXMAN_FILTER_BEST: + flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER); + + /* Here we have a chance to optimize BILINEAR filter to NEAREST if + * they are equivalent for the currently used transformation matrix. + */ + if (flags & FAST_PATH_ID_TRANSFORM) { - if (image->gradient.stops) - free (image->gradient.stops); + flags |= FAST_PATH_NEAREST_FILTER; + } + else if ( + /* affine and integer translation components in matrix ... */ + ((flags & FAST_PATH_AFFINE_TRANSFORM) && + !pixman_fixed_frac (image->common.transform->matrix[0][2] | + image->common.transform->matrix[1][2])) && + ( + /* ... combined with a simple rotation */ + (flags & (FAST_PATH_ROTATE_90_TRANSFORM | + FAST_PATH_ROTATE_180_TRANSFORM | + FAST_PATH_ROTATE_270_TRANSFORM)) || + /* ... or combined with a simple non-rotated translation */ + (image->common.transform->matrix[0][0] == pixman_fixed_1 && + image->common.transform->matrix[1][1] == pixman_fixed_1 && + image->common.transform->matrix[0][1] == 0 && + image->common.transform->matrix[1][0] == 0) + ) + ) + { + /* FIXME: there are some affine-test failures, showing that + * handling of BILINEAR and NEAREST filter is not quite + * equivalent when getting close to 32K for the translation + * components of the matrix. That's likely some bug, but for + * now just skip BILINEAR->NEAREST optimization in this case. + */ + pixman_fixed_t magic_limit = pixman_int_to_fixed (30000); + if (image->common.transform->matrix[0][2] <= magic_limit && + image->common.transform->matrix[1][2] <= magic_limit && + image->common.transform->matrix[0][2] >= -magic_limit && + image->common.transform->matrix[1][2] >= -magic_limit) + { + flags |= FAST_PATH_NEAREST_FILTER; + } } + break; + case PIXMAN_FILTER_CONVOLUTION: + break; - if (image->type == BITS && image->bits.free_me) - free (image->bits.free_me); + default: + flags |= FAST_PATH_NO_CONVOLUTION_FILTER; + break; + } - free (image); + /* Repeat mode */ + switch (image->common.repeat) + { + case PIXMAN_REPEAT_NONE: + flags |= + FAST_PATH_NO_REFLECT_REPEAT | + FAST_PATH_NO_PAD_REPEAT | + FAST_PATH_NO_NORMAL_REPEAT; + break; - return TRUE; + case PIXMAN_REPEAT_REFLECT: + flags |= + FAST_PATH_NO_PAD_REPEAT | + FAST_PATH_NO_NONE_REPEAT | + FAST_PATH_NO_NORMAL_REPEAT; + break; + + case PIXMAN_REPEAT_PAD: + flags |= + FAST_PATH_NO_REFLECT_REPEAT | + FAST_PATH_NO_NONE_REPEAT | + FAST_PATH_NO_NORMAL_REPEAT; + break; + + default: + flags |= + FAST_PATH_NO_REFLECT_REPEAT | + FAST_PATH_NO_PAD_REPEAT | + FAST_PATH_NO_NONE_REPEAT; + break; } - return FALSE; -} + /* Component alpha */ + if (image->common.component_alpha) + flags |= FAST_PATH_COMPONENT_ALPHA; + else + flags |= FAST_PATH_UNIFIED_ALPHA; -PIXMAN_EXPORT void -pixman_image_set_destroy_function (pixman_image_t *image, - pixman_image_destroy_func_t func, - void *data) -{ - image->common.destroy_func = func; - image->common.destroy_data = data; -} - + flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT); + + /* Type specific checks */ + switch (image->type) + { + case SOLID: + code = PIXMAN_solid; + + if (image->solid.color.alpha == 0xffff) + flags |= FAST_PATH_IS_OPAQUE; + break; + + case BITS: + if (image->bits.width == 1 && + image->bits.height == 1 && + image->common.repeat != PIXMAN_REPEAT_NONE) + { + code = PIXMAN_solid; + } + else + { + code = image->bits.format; + flags |= FAST_PATH_BITS_IMAGE; + } + + if (!PIXMAN_FORMAT_A (image->bits.format) && + PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY && + PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR) + { + flags |= FAST_PATH_SAMPLES_OPAQUE; + + if (image->common.repeat != PIXMAN_REPEAT_NONE) + flags |= FAST_PATH_IS_OPAQUE; + } + + if (image->bits.read_func || image->bits.write_func) + flags &= ~FAST_PATH_NO_ACCESSORS; + + if (PIXMAN_FORMAT_IS_WIDE (image->bits.format)) + flags &= ~FAST_PATH_NARROW_FORMAT; + break; + + case RADIAL: + code = PIXMAN_unknown; + + /* + * As explained in pixman-radial-gradient.c, every point of + * the plane has a valid associated radius (and thus will be + * colored) if and only if a is negative (i.e. one of the two + * circles contains the other one). + */ + + if (image->radial.a >= 0) + break; + + /* Fall through */ + + case CONICAL: + case LINEAR: + code = PIXMAN_unknown; + + if (image->common.repeat != PIXMAN_REPEAT_NONE) + { + int i; + + flags |= FAST_PATH_IS_OPAQUE; + for (i = 0; i < image->gradient.n_stops; ++i) + { + if (image->gradient.stops[i].color.alpha != 0xffff) + { + flags &= ~FAST_PATH_IS_OPAQUE; + break; + } + } + } + break; -/* Constructors */ + default: + code = PIXMAN_unknown; + break; + } + + /* Alpha map */ + if (!image->common.alpha_map) + { + flags |= FAST_PATH_NO_ALPHA_MAP; + } + else + { + if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format)) + flags &= ~FAST_PATH_NARROW_FORMAT; + } + + /* Both alpha maps and convolution filters can introduce + * non-opaqueness in otherwise opaque images. Also + * an image with component alpha turned on is only opaque + * if all channels are opaque, so we simply turn it off + * unconditionally for those images. + */ + if (image->common.alpha_map || + image->common.filter == PIXMAN_FILTER_CONVOLUTION || + image->common.component_alpha) + { + flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE); + } + + image->common.flags = flags; + image->common.extended_format_code = code; +} void -_pixman_image_reset_clip_region (pixman_image_t *image) +_pixman_image_validate (pixman_image_t *image) { - image->common.have_clip_region = FALSE; + if (image->common.dirty) + { + compute_image_info (image); + + /* It is important that property_changed is + * called *after* compute_image_info() because + * property_changed() can make use of the flags + * to set up accessors etc. + */ + if (image->common.property_changed) + image->common.property_changed (image); + + image->common.dirty = FALSE; + } + + if (image->common.alpha_map) + _pixman_image_validate ((pixman_image_t *)image->common.alpha_map); } PIXMAN_EXPORT pixman_bool_t -pixman_image_set_clip_region32 (pixman_image_t *image, - pixman_region32_t *region) +pixman_image_set_clip_region32 (pixman_image_t * image, + pixman_region32_t *region) { image_common_t *common = (image_common_t *)image; pixman_bool_t result; @@ -257,10 +572,9 @@ pixman_image_set_clip_region32 (pixman_image_t *image, return result; } - PIXMAN_EXPORT pixman_bool_t -pixman_image_set_clip_region (pixman_image_t *image, - pixman_region16_t *region) +pixman_image_set_clip_region (pixman_image_t * image, + pixman_region16_t *region) { image_common_t *common = (image_common_t *)image; pixman_bool_t result; @@ -284,21 +598,20 @@ pixman_image_set_clip_region (pixman_image_t *image, PIXMAN_EXPORT void pixman_image_set_has_client_clip (pixman_image_t *image, - pixman_bool_t client_clip) + pixman_bool_t client_clip) { image->common.client_clip = client_clip; } PIXMAN_EXPORT pixman_bool_t -pixman_image_set_transform (pixman_image_t *image, - const pixman_transform_t *transform) +pixman_image_set_transform (pixman_image_t * image, + const pixman_transform_t *transform) { static const pixman_transform_t id = { { { pixman_fixed_1, 0, 0 }, { 0, pixman_fixed_1, 0 }, - { 0, 0, pixman_fixed_1 } - } + { 0, 0, pixman_fixed_1 } } }; image_common_t *common = (image_common_t *)image; @@ -307,45 +620,58 @@ pixman_image_set_transform (pixman_image_t *image, if (common->transform == transform) return TRUE; - if (memcmp (&id, transform, sizeof (pixman_transform_t)) == 0) + if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0) { - free(common->transform); + free (common->transform); common->transform = NULL; result = TRUE; + goto out; } + if (common->transform && + memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0) + { + return TRUE; + } + if (common->transform == NULL) common->transform = malloc (sizeof (pixman_transform_t)); if (common->transform == NULL) { result = FALSE; + goto out; } - memcpy(common->transform, transform, sizeof(pixman_transform_t)); + memcpy (common->transform, transform, sizeof(pixman_transform_t)); + + result = TRUE; out: image_property_changed (image); - - return TRUE; + + return result; } PIXMAN_EXPORT void -pixman_image_set_repeat (pixman_image_t *image, - pixman_repeat_t repeat) +pixman_image_set_repeat (pixman_image_t *image, + pixman_repeat_t repeat) { + if (image->common.repeat == repeat) + return; + image->common.repeat = repeat; image_property_changed (image); } PIXMAN_EXPORT pixman_bool_t -pixman_image_set_filter (pixman_image_t *image, - pixman_filter_t filter, - const pixman_fixed_t *params, - int n_params) +pixman_image_set_filter (pixman_image_t * image, + pixman_filter_t filter, + const pixman_fixed_t *params, + int n_params) { image_common_t *common = (image_common_t *)image; pixman_fixed_t *new_params; @@ -361,7 +687,7 @@ pixman_image_set_filter (pixman_image_t *image, return FALSE; memcpy (new_params, - params, n_params * sizeof (pixman_fixed_t)); + params, n_params * sizeof (pixman_fixed_t)); } common->filter = filter; @@ -377,10 +703,15 @@ pixman_image_set_filter (pixman_image_t *image, } PIXMAN_EXPORT void -pixman_image_set_source_clipping (pixman_image_t *image, - pixman_bool_t clip_sources) +pixman_image_set_source_clipping (pixman_image_t *image, + pixman_bool_t clip_sources) { + if (image->common.clip_sources == clip_sources) + return; + image->common.clip_sources = clip_sources; + + image_property_changed (image); } /* Unlike all the other property setters, this function does not @@ -388,11 +719,14 @@ pixman_image_set_source_clipping (pixman_image_t *image, * way, way too expensive. */ PIXMAN_EXPORT void -pixman_image_set_indexed (pixman_image_t *image, - const pixman_indexed_t *indexed) +pixman_image_set_indexed (pixman_image_t * image, + const pixman_indexed_t *indexed) { bits_image_t *bits = (bits_image_t *)image; + if (bits->indexed == indexed) + return; + bits->indexed = indexed; image_property_changed (image); @@ -400,23 +734,49 @@ pixman_image_set_indexed (pixman_image_t *image, PIXMAN_EXPORT void pixman_image_set_alpha_map (pixman_image_t *image, - pixman_image_t *alpha_map, - int16_t x, - int16_t y) + pixman_image_t *alpha_map, + int16_t x, + int16_t y) { image_common_t *common = (image_common_t *)image; return_if_fail (!alpha_map || alpha_map->type == BITS); + if (alpha_map && common->alpha_count > 0) + { + /* If this image is being used as an alpha map itself, + * then you can't give it an alpha map of its own. + */ + return; + } + + if (alpha_map && alpha_map->common.alpha_map) + { + /* If the image has an alpha map of its own, + * then it can't be used as an alpha map itself + */ + return; + } + if (common->alpha_map != (bits_image_t *)alpha_map) { if (common->alpha_map) + { + common->alpha_map->common.alpha_count--; + pixman_image_unref ((pixman_image_t *)common->alpha_map); + } if (alpha_map) + { common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map); + + common->alpha_map->common.alpha_count++; + } else + { common->alpha_map = NULL; + } } common->alpha_origin_x = x; @@ -426,26 +786,37 @@ pixman_image_set_alpha_map (pixman_image_t *image, } PIXMAN_EXPORT void -pixman_image_set_component_alpha (pixman_image_t *image, - pixman_bool_t component_alpha) +pixman_image_set_component_alpha (pixman_image_t *image, + pixman_bool_t component_alpha) { + if (image->common.component_alpha == component_alpha) + return; + image->common.component_alpha = component_alpha; image_property_changed (image); } +PIXMAN_EXPORT pixman_bool_t +pixman_image_get_component_alpha (pixman_image_t *image) +{ + return image->common.component_alpha; +} PIXMAN_EXPORT void -pixman_image_set_accessors (pixman_image_t *image, - pixman_read_memory_func_t read_func, - pixman_write_memory_func_t write_func) +pixman_image_set_accessors (pixman_image_t * image, + pixman_read_memory_func_t read_func, + pixman_write_memory_func_t write_func) { return_if_fail (image != NULL); - image->common.read_func = read_func; - image->common.write_func = write_func; + if (image->type == BITS) + { + image->bits.read_func = read_func; + image->bits.write_func = write_func; - image_property_changed (image); + image_property_changed (image); + } } PIXMAN_EXPORT uint32_t * @@ -493,90 +864,37 @@ pixman_image_get_depth (pixman_image_t *image) return 0; } -pixman_bool_t -_pixman_image_is_solid (pixman_image_t *image) +PIXMAN_EXPORT pixman_format_code_t +pixman_image_get_format (pixman_image_t *image) { - if (image->type == SOLID) - return TRUE; - - if (image->type != BITS || - image->bits.width != 1 || - image->bits.height != 1) - { - return FALSE; - } - - if (image->common.repeat == PIXMAN_REPEAT_NONE) - return FALSE; + if (image->type == BITS) + return image->bits.format; - return TRUE; + return 0; } uint32_t -_pixman_image_get_solid (pixman_image_t *image, pixman_format_code_t format) +_pixman_image_get_solid (pixman_implementation_t *imp, + pixman_image_t * image, + pixman_format_code_t format) { uint32_t result; - - _pixman_image_get_scanline_32 (image, 0, 0, 1, &result, NULL, 0); - - /* If necessary, convert RGB <--> BGR. */ - if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB) - { - result = (((result & 0xff000000) >> 0) | - ((result & 0x00ff0000) >> 16) | - ((result & 0x0000ff00) >> 0) | - ((result & 0x000000ff) << 16)); - } - - return result; -} + pixman_iter_t iter; -pixman_bool_t -_pixman_image_is_opaque (pixman_image_t *image) -{ - int i; + _pixman_implementation_src_iter_init ( + imp, &iter, image, 0, 0, 1, 1, + (uint8_t *)&result, ITER_NARROW); - if (image->common.alpha_map) - return FALSE; + result = *iter.get_scanline (&iter, NULL); - switch (image->type) + /* If necessary, convert RGB <--> BGR. */ + if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB) { - case BITS: - if (image->common.repeat == PIXMAN_REPEAT_NONE) - return FALSE; - - if (PIXMAN_FORMAT_A (image->bits.format)) - return FALSE; - break; - - case LINEAR: - case RADIAL: - if (image->common.repeat == PIXMAN_REPEAT_NONE) - return FALSE; - - for (i = 0; i < image->gradient.n_stops; ++i) - { - if (image->gradient.stops[i].color.alpha != 0xffff) - return FALSE; - } - break; - - case CONICAL: - /* Conical gradients always have a transparent border */ - return FALSE; - break; - - case SOLID: - if (ALPHA_8 (image->solid.color) != 0xff) - return FALSE; - break; + result = (((result & 0xff000000) >> 0) | + ((result & 0x00ff0000) >> 16) | + ((result & 0x0000ff00) >> 0) | + ((result & 0x000000ff) << 16)); } - /* Convolution filters can introduce translucency if the sum of the - * weights is lower than 1. - */ - if (image->common.filter == PIXMAN_FILTER_CONVOLUTION) - return FALSE; - - return TRUE; + return result; }