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 +}