pixman-image.c (25614B)
1 /* 2 * Copyright © 2000 SuSE, Inc. 3 * Copyright © 2007 Red Hat, Inc. 4 * 5 * Permission to use, copy, modify, distribute, and sell this software and its 6 * documentation for any purpose is hereby granted without fee, provided that 7 * the above copyright notice appear in all copies and that both that 8 * copyright notice and this permission notice appear in supporting 9 * documentation, and that the name of SuSE not be used in advertising or 10 * publicity pertaining to distribution of the software without specific, 11 * written prior permission. SuSE makes no representations about the 12 * suitability of this software for any purpose. It is provided "as is" 13 * without express or implied warranty. 14 * 15 * SuSE DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL SuSE 17 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 18 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 19 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 21 */ 22 23 #ifdef HAVE_CONFIG_H 24 #include <pixman-config.h> 25 #endif 26 27 #include <stdlib.h> 28 #include <stdio.h> 29 #include <string.h> 30 #include <assert.h> 31 32 #include "pixman-private.h" 33 34 static const pixman_color_t transparent_black = { 0, 0, 0, 0 }; 35 36 static void 37 gradient_property_changed (pixman_image_t *image) 38 { 39 gradient_t *gradient = &image->gradient; 40 int n = gradient->n_stops; 41 pixman_gradient_stop_t *stops = gradient->stops; 42 pixman_gradient_stop_t *begin = &(gradient->stops[-1]); 43 pixman_gradient_stop_t *end = &(gradient->stops[n]); 44 45 switch (gradient->common.repeat) 46 { 47 default: 48 case PIXMAN_REPEAT_NONE: 49 begin->x = INT32_MIN; 50 begin->color = transparent_black; 51 end->x = INT32_MAX; 52 end->color = transparent_black; 53 break; 54 55 case PIXMAN_REPEAT_NORMAL: 56 begin->x = stops[n - 1].x - pixman_fixed_1; 57 begin->color = stops[n - 1].color; 58 end->x = stops[0].x + pixman_fixed_1; 59 end->color = stops[0].color; 60 break; 61 62 case PIXMAN_REPEAT_REFLECT: 63 begin->x = - stops[0].x; 64 begin->color = stops[0].color; 65 end->x = pixman_int_to_fixed (2) - stops[n - 1].x; 66 end->color = stops[n - 1].color; 67 break; 68 69 case PIXMAN_REPEAT_PAD: 70 begin->x = INT32_MIN; 71 begin->color = stops[0].color; 72 end->x = INT32_MAX; 73 end->color = stops[n - 1].color; 74 break; 75 } 76 } 77 78 pixman_bool_t 79 _pixman_init_gradient (gradient_t * gradient, 80 const pixman_gradient_stop_t *stops, 81 int n_stops) 82 { 83 return_val_if_fail (n_stops > 0, FALSE); 84 85 /* We allocate two extra stops, one before the beginning of the stop list, 86 * and one after the end. These stops are initialized to whatever color 87 * would be used for positions outside the range of the stop list. 88 * 89 * This saves a bit of computation in the gradient walker. 90 * 91 * The pointer we store in the gradient_t struct still points to the 92 * first user-supplied struct, so when freeing, we will have to 93 * subtract one. 94 */ 95 gradient->stops = 96 pixman_malloc_ab (n_stops + 2, sizeof (pixman_gradient_stop_t)); 97 if (!gradient->stops) 98 return FALSE; 99 100 gradient->stops += 1; 101 memcpy (gradient->stops, stops, n_stops * sizeof (pixman_gradient_stop_t)); 102 gradient->n_stops = n_stops; 103 104 gradient->common.property_changed = gradient_property_changed; 105 106 return TRUE; 107 } 108 109 void 110 _pixman_image_init (pixman_image_t *image) 111 { 112 image_common_t *common = &image->common; 113 114 pixman_region32_init (&common->clip_region); 115 116 common->alpha_count = 0; 117 common->have_clip_region = FALSE; 118 common->clip_sources = FALSE; 119 common->transform = NULL; 120 common->repeat = PIXMAN_REPEAT_NONE; 121 common->filter = PIXMAN_FILTER_NEAREST; 122 common->filter_params = NULL; 123 common->n_filter_params = 0; 124 common->alpha_map = NULL; 125 common->component_alpha = FALSE; 126 common->ref_count = 1; 127 common->property_changed = NULL; 128 common->client_clip = FALSE; 129 common->destroy_func = NULL; 130 common->destroy_data = NULL; 131 common->dirty = TRUE; 132 } 133 134 pixman_bool_t 135 _pixman_image_fini (pixman_image_t *image) 136 { 137 image_common_t *common = (image_common_t *)image; 138 139 common->ref_count--; 140 141 if (common->ref_count == 0) 142 { 143 if (image->common.destroy_func) 144 image->common.destroy_func (image, image->common.destroy_data); 145 146 pixman_region32_fini (&common->clip_region); 147 148 free (common->transform); 149 free (common->filter_params); 150 151 if (common->alpha_map) 152 pixman_image_unref ((pixman_image_t *)common->alpha_map); 153 154 if (image->type == LINEAR || 155 image->type == RADIAL || 156 image->type == CONICAL) 157 { 158 if (image->gradient.stops) 159 { 160 /* See _pixman_init_gradient() for an explanation of the - 1 */ 161 free (image->gradient.stops - 1); 162 } 163 164 /* This will trigger if someone adds a property_changed 165 * method to the linear/radial/conical gradient overwriting 166 * the general one. 167 */ 168 assert ( 169 image->common.property_changed == gradient_property_changed); 170 } 171 172 if (image->type == BITS && image->bits.free_me) 173 free (image->bits.free_me); 174 175 return TRUE; 176 } 177 178 return FALSE; 179 } 180 181 pixman_image_t * 182 _pixman_image_allocate (void) 183 { 184 pixman_image_t *image = malloc (sizeof (pixman_image_t)); 185 186 if (image) 187 _pixman_image_init (image); 188 189 return image; 190 } 191 192 static void 193 image_property_changed (pixman_image_t *image) 194 { 195 image->common.dirty = TRUE; 196 } 197 198 /* Ref Counting */ 199 PIXMAN_EXPORT pixman_image_t * 200 pixman_image_ref (pixman_image_t *image) 201 { 202 image->common.ref_count++; 203 204 return image; 205 } 206 207 /* returns TRUE when the image is freed */ 208 PIXMAN_EXPORT pixman_bool_t 209 pixman_image_unref (pixman_image_t *image) 210 { 211 if (_pixman_image_fini (image)) 212 { 213 free (image); 214 return TRUE; 215 } 216 217 return FALSE; 218 } 219 220 PIXMAN_EXPORT void 221 pixman_image_set_destroy_function (pixman_image_t * image, 222 pixman_image_destroy_func_t func, 223 void * data) 224 { 225 image->common.destroy_func = func; 226 image->common.destroy_data = data; 227 } 228 229 PIXMAN_EXPORT void * 230 pixman_image_get_destroy_data (pixman_image_t *image) 231 { 232 return image->common.destroy_data; 233 } 234 235 void 236 _pixman_image_reset_clip_region (pixman_image_t *image) 237 { 238 image->common.have_clip_region = FALSE; 239 } 240 241 /* Executive Summary: This function is a no-op that only exists 242 * for historical reasons. 243 * 244 * There used to be a bug in the X server where it would rely on 245 * out-of-bounds accesses when it was asked to composite with a 246 * window as the source. It would create a pixman image pointing 247 * to some bogus position in memory, but then set a clip region 248 * to the position where the actual bits were. 249 * 250 * Due to a bug in old versions of pixman, where it would not clip 251 * against the image bounds when a clip region was set, this would 252 * actually work. So when the pixman bug was fixed, a workaround was 253 * added to allow certain out-of-bound accesses. This function disabled 254 * those workarounds. 255 * 256 * Since 0.21.2, pixman doesn't do these workarounds anymore, so now 257 * this function is a no-op. 258 */ 259 PIXMAN_EXPORT void 260 pixman_disable_out_of_bounds_workaround (void) 261 { 262 } 263 264 static void 265 compute_image_info (pixman_image_t *image) 266 { 267 pixman_format_code_t code; 268 uint32_t flags = 0; 269 270 /* Transform */ 271 if (!image->common.transform) 272 { 273 flags |= (FAST_PATH_ID_TRANSFORM | 274 FAST_PATH_X_UNIT_POSITIVE | 275 FAST_PATH_Y_UNIT_ZERO | 276 FAST_PATH_AFFINE_TRANSFORM); 277 } 278 else 279 { 280 flags |= FAST_PATH_HAS_TRANSFORM; 281 282 if (image->common.transform->matrix[2][0] == 0 && 283 image->common.transform->matrix[2][1] == 0 && 284 image->common.transform->matrix[2][2] == pixman_fixed_1) 285 { 286 flags |= FAST_PATH_AFFINE_TRANSFORM; 287 288 if (image->common.transform->matrix[0][1] == 0 && 289 image->common.transform->matrix[1][0] == 0) 290 { 291 if (image->common.transform->matrix[0][0] == -pixman_fixed_1 && 292 image->common.transform->matrix[1][1] == -pixman_fixed_1) 293 { 294 flags |= FAST_PATH_ROTATE_180_TRANSFORM; 295 } 296 flags |= FAST_PATH_SCALE_TRANSFORM; 297 } 298 else if (image->common.transform->matrix[0][0] == 0 && 299 image->common.transform->matrix[1][1] == 0) 300 { 301 pixman_fixed_t m01 = image->common.transform->matrix[0][1]; 302 pixman_fixed_t m10 = image->common.transform->matrix[1][0]; 303 304 if (m01 == -pixman_fixed_1 && m10 == pixman_fixed_1) 305 flags |= FAST_PATH_ROTATE_90_TRANSFORM; 306 else if (m01 == pixman_fixed_1 && m10 == -pixman_fixed_1) 307 flags |= FAST_PATH_ROTATE_270_TRANSFORM; 308 } 309 } 310 311 if (image->common.transform->matrix[0][0] > 0) 312 flags |= FAST_PATH_X_UNIT_POSITIVE; 313 314 if (image->common.transform->matrix[1][0] == 0) 315 flags |= FAST_PATH_Y_UNIT_ZERO; 316 } 317 318 /* Filter */ 319 switch (image->common.filter) 320 { 321 case PIXMAN_FILTER_NEAREST: 322 case PIXMAN_FILTER_FAST: 323 flags |= (FAST_PATH_NEAREST_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER); 324 break; 325 326 case PIXMAN_FILTER_BILINEAR: 327 case PIXMAN_FILTER_GOOD: 328 case PIXMAN_FILTER_BEST: 329 flags |= (FAST_PATH_BILINEAR_FILTER | FAST_PATH_NO_CONVOLUTION_FILTER); 330 331 /* Here we have a chance to optimize BILINEAR filter to NEAREST if 332 * they are equivalent for the currently used transformation matrix. 333 */ 334 if (flags & FAST_PATH_ID_TRANSFORM) 335 { 336 flags |= FAST_PATH_NEAREST_FILTER; 337 } 338 else if (flags & FAST_PATH_AFFINE_TRANSFORM) 339 { 340 /* Suppose the transform is 341 * 342 * [ t00, t01, t02 ] 343 * [ t10, t11, t12 ] 344 * [ 0, 0, 1 ] 345 * 346 * and the destination coordinates are (n + 0.5, m + 0.5). Then 347 * the transformed x coordinate is: 348 * 349 * tx = t00 * (n + 0.5) + t01 * (m + 0.5) + t02 350 * = t00 * n + t01 * m + t02 + (t00 + t01) * 0.5 351 * 352 * which implies that if t00, t01 and t02 are all integers 353 * and (t00 + t01) is odd, then tx will be an integer plus 0.5, 354 * which means a BILINEAR filter will reduce to NEAREST. The same 355 * applies in the y direction 356 */ 357 pixman_fixed_t (*t)[3] = image->common.transform->matrix; 358 359 if ((pixman_fixed_frac ( 360 t[0][0] | t[0][1] | t[0][2] | 361 t[1][0] | t[1][1] | t[1][2]) == 0) && 362 (pixman_fixed_to_int ( 363 (t[0][0] + t[0][1]) & (t[1][0] + t[1][1])) % 2) == 1) 364 { 365 /* FIXME: there are some affine-test failures, showing that 366 * handling of BILINEAR and NEAREST filter is not quite 367 * equivalent when getting close to 32K for the translation 368 * components of the matrix. That's likely some bug, but for 369 * now just skip BILINEAR->NEAREST optimization in this case. 370 */ 371 pixman_fixed_t magic_limit = pixman_int_to_fixed (30000); 372 if (image->common.transform->matrix[0][2] <= magic_limit && 373 image->common.transform->matrix[1][2] <= magic_limit && 374 image->common.transform->matrix[0][2] >= -magic_limit && 375 image->common.transform->matrix[1][2] >= -magic_limit) 376 { 377 flags |= FAST_PATH_NEAREST_FILTER; 378 } 379 } 380 } 381 break; 382 383 case PIXMAN_FILTER_CONVOLUTION: 384 break; 385 386 case PIXMAN_FILTER_SEPARABLE_CONVOLUTION: 387 flags |= FAST_PATH_SEPARABLE_CONVOLUTION_FILTER; 388 break; 389 390 default: 391 flags |= FAST_PATH_NO_CONVOLUTION_FILTER; 392 break; 393 } 394 395 /* Repeat mode */ 396 switch (image->common.repeat) 397 { 398 case PIXMAN_REPEAT_NONE: 399 flags |= 400 FAST_PATH_NO_REFLECT_REPEAT | 401 FAST_PATH_NO_PAD_REPEAT | 402 FAST_PATH_NO_NORMAL_REPEAT; 403 break; 404 405 case PIXMAN_REPEAT_REFLECT: 406 flags |= 407 FAST_PATH_NO_PAD_REPEAT | 408 FAST_PATH_NO_NONE_REPEAT | 409 FAST_PATH_NO_NORMAL_REPEAT; 410 break; 411 412 case PIXMAN_REPEAT_PAD: 413 flags |= 414 FAST_PATH_NO_REFLECT_REPEAT | 415 FAST_PATH_NO_NONE_REPEAT | 416 FAST_PATH_NO_NORMAL_REPEAT; 417 break; 418 419 default: 420 flags |= 421 FAST_PATH_NO_REFLECT_REPEAT | 422 FAST_PATH_NO_PAD_REPEAT | 423 FAST_PATH_NO_NONE_REPEAT; 424 break; 425 } 426 427 /* Component alpha */ 428 if (image->common.component_alpha) 429 flags |= FAST_PATH_COMPONENT_ALPHA; 430 else 431 flags |= FAST_PATH_UNIFIED_ALPHA; 432 433 flags |= (FAST_PATH_NO_ACCESSORS | FAST_PATH_NARROW_FORMAT); 434 435 /* Type specific checks */ 436 switch (image->type) 437 { 438 case SOLID: 439 code = PIXMAN_solid; 440 441 if (image->solid.color.alpha == 0xffff) 442 flags |= FAST_PATH_IS_OPAQUE; 443 break; 444 445 case BITS: 446 if (image->bits.width == 1 && 447 image->bits.height == 1 && 448 image->common.repeat != PIXMAN_REPEAT_NONE) 449 { 450 code = PIXMAN_solid; 451 } 452 else 453 { 454 code = image->bits.format; 455 flags |= FAST_PATH_BITS_IMAGE; 456 } 457 458 if (!PIXMAN_FORMAT_A (image->bits.format) && 459 PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_GRAY && 460 PIXMAN_FORMAT_TYPE (image->bits.format) != PIXMAN_TYPE_COLOR) 461 { 462 flags |= FAST_PATH_SAMPLES_OPAQUE; 463 464 if (image->common.repeat != PIXMAN_REPEAT_NONE) 465 flags |= FAST_PATH_IS_OPAQUE; 466 } 467 468 if (image->bits.read_func || image->bits.write_func) 469 flags &= ~FAST_PATH_NO_ACCESSORS; 470 471 if (PIXMAN_FORMAT_IS_WIDE (image->bits.format)) 472 flags &= ~FAST_PATH_NARROW_FORMAT; 473 break; 474 475 case RADIAL: 476 code = PIXMAN_unknown; 477 478 /* 479 * As explained in pixman-radial-gradient.c, every point of 480 * the plane has a valid associated radius (and thus will be 481 * colored) if and only if a is negative (i.e. one of the two 482 * circles contains the other one). 483 */ 484 485 if (image->radial.a >= 0) 486 break; 487 488 /* Fall through */ 489 490 case CONICAL: 491 case LINEAR: 492 code = PIXMAN_unknown; 493 494 if (image->common.repeat != PIXMAN_REPEAT_NONE) 495 { 496 int i; 497 498 flags |= FAST_PATH_IS_OPAQUE; 499 for (i = 0; i < image->gradient.n_stops; ++i) 500 { 501 if (image->gradient.stops[i].color.alpha != 0xffff) 502 { 503 flags &= ~FAST_PATH_IS_OPAQUE; 504 break; 505 } 506 } 507 } 508 break; 509 510 default: 511 code = PIXMAN_unknown; 512 break; 513 } 514 515 /* Alpha maps are only supported for BITS images, so it's always 516 * safe to ignore their presense for non-BITS images 517 */ 518 if (!image->common.alpha_map || image->type != BITS) 519 { 520 flags |= FAST_PATH_NO_ALPHA_MAP; 521 } 522 else 523 { 524 if (PIXMAN_FORMAT_IS_WIDE (image->common.alpha_map->format)) 525 flags &= ~FAST_PATH_NARROW_FORMAT; 526 } 527 528 /* Both alpha maps and convolution filters can introduce 529 * non-opaqueness in otherwise opaque images. Also 530 * an image with component alpha turned on is only opaque 531 * if all channels are opaque, so we simply turn it off 532 * unconditionally for those images. 533 */ 534 if (image->common.alpha_map || 535 image->common.filter == PIXMAN_FILTER_CONVOLUTION || 536 image->common.filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION || 537 image->common.component_alpha) 538 { 539 flags &= ~(FAST_PATH_IS_OPAQUE | FAST_PATH_SAMPLES_OPAQUE); 540 } 541 542 image->common.flags = flags; 543 image->common.extended_format_code = code; 544 } 545 546 void 547 _pixman_image_validate (pixman_image_t *image) 548 { 549 if (image->common.dirty) 550 { 551 compute_image_info (image); 552 553 /* It is important that property_changed is 554 * called *after* compute_image_info() because 555 * property_changed() can make use of the flags 556 * to set up accessors etc. 557 */ 558 if (image->common.property_changed) 559 image->common.property_changed (image); 560 561 image->common.dirty = FALSE; 562 } 563 564 if (image->common.alpha_map) 565 _pixman_image_validate ((pixman_image_t *)image->common.alpha_map); 566 } 567 568 PIXMAN_EXPORT pixman_bool_t 569 pixman_image_set_clip_region32 (pixman_image_t * image, 570 const pixman_region32_t *region) 571 { 572 image_common_t *common = (image_common_t *)image; 573 pixman_bool_t result; 574 575 if (region) 576 { 577 if ((result = pixman_region32_copy (&common->clip_region, region))) 578 image->common.have_clip_region = TRUE; 579 } 580 else 581 { 582 _pixman_image_reset_clip_region (image); 583 584 result = TRUE; 585 } 586 587 image_property_changed (image); 588 589 return result; 590 } 591 592 PIXMAN_EXPORT pixman_bool_t 593 pixman_image_set_clip_region (pixman_image_t * image, 594 const pixman_region16_t *region) 595 { 596 image_common_t *common = (image_common_t *)image; 597 pixman_bool_t result; 598 599 if (region) 600 { 601 if ((result = pixman_region32_copy_from_region16 (&common->clip_region, region))) 602 image->common.have_clip_region = TRUE; 603 } 604 else 605 { 606 _pixman_image_reset_clip_region (image); 607 608 result = TRUE; 609 } 610 611 image_property_changed (image); 612 613 return result; 614 } 615 616 PIXMAN_EXPORT pixman_bool_t 617 pixman_image_set_clip_region64f (pixman_image_t * image, 618 const pixman_region64f_t *region) 619 { 620 image_common_t *common = (image_common_t *)image; 621 pixman_bool_t result; 622 623 if (region) 624 { 625 if ((result = pixman_region32_copy_from_region64f (&common->clip_region, region))) 626 image->common.have_clip_region = TRUE; 627 } 628 else 629 { 630 _pixman_image_reset_clip_region (image); 631 632 result = TRUE; 633 } 634 635 image_property_changed (image); 636 637 return result; 638 } 639 640 PIXMAN_EXPORT void 641 pixman_image_set_has_client_clip (pixman_image_t *image, 642 pixman_bool_t client_clip) 643 { 644 image->common.client_clip = client_clip; 645 } 646 647 PIXMAN_EXPORT pixman_bool_t 648 pixman_image_set_transform (pixman_image_t * image, 649 const pixman_transform_t *transform) 650 { 651 static const pixman_transform_t id = 652 { 653 { { pixman_fixed_1, 0, 0 }, 654 { 0, pixman_fixed_1, 0 }, 655 { 0, 0, pixman_fixed_1 } } 656 }; 657 658 image_common_t *common = (image_common_t *)image; 659 pixman_bool_t result; 660 661 if (common->transform == transform) 662 return TRUE; 663 664 if (!transform || memcmp (&id, transform, sizeof (pixman_transform_t)) == 0) 665 { 666 free (common->transform); 667 common->transform = NULL; 668 result = TRUE; 669 670 goto out; 671 } 672 673 if (common->transform && 674 memcmp (common->transform, transform, sizeof (pixman_transform_t)) == 0) 675 { 676 return TRUE; 677 } 678 679 if (common->transform == NULL) 680 common->transform = malloc (sizeof (pixman_transform_t)); 681 682 if (common->transform == NULL) 683 { 684 result = FALSE; 685 686 goto out; 687 } 688 689 memcpy (common->transform, transform, sizeof(pixman_transform_t)); 690 691 result = TRUE; 692 693 out: 694 image_property_changed (image); 695 696 return result; 697 } 698 699 PIXMAN_EXPORT void 700 pixman_image_set_repeat (pixman_image_t *image, 701 pixman_repeat_t repeat) 702 { 703 if (image->common.repeat == repeat) 704 return; 705 706 image->common.repeat = repeat; 707 708 image_property_changed (image); 709 } 710 711 PIXMAN_EXPORT void 712 pixman_image_set_dither (pixman_image_t *image, 713 pixman_dither_t dither) 714 { 715 if (image->type == BITS) 716 { 717 if (image->bits.dither == dither) 718 return; 719 720 image->bits.dither = dither; 721 722 image_property_changed (image); 723 } 724 } 725 726 PIXMAN_EXPORT void 727 pixman_image_set_dither_offset (pixman_image_t *image, 728 int offset_x, 729 int offset_y) 730 { 731 if (image->type == BITS) 732 { 733 if (image->bits.dither_offset_x == offset_x && 734 image->bits.dither_offset_y == offset_y) 735 { 736 return; 737 } 738 739 image->bits.dither_offset_x = offset_x; 740 image->bits.dither_offset_y = offset_y; 741 742 image_property_changed (image); 743 } 744 } 745 746 PIXMAN_EXPORT pixman_bool_t 747 pixman_image_set_filter (pixman_image_t * image, 748 pixman_filter_t filter, 749 const pixman_fixed_t *params, 750 int n_params) 751 { 752 image_common_t *common = (image_common_t *)image; 753 pixman_fixed_t *new_params; 754 755 if (params == common->filter_params && filter == common->filter) 756 return TRUE; 757 758 if (filter == PIXMAN_FILTER_SEPARABLE_CONVOLUTION) 759 { 760 int width = pixman_fixed_to_int (params[0]); 761 int height = pixman_fixed_to_int (params[1]); 762 int x_phase_bits = pixman_fixed_to_int (params[2]); 763 int y_phase_bits = pixman_fixed_to_int (params[3]); 764 int n_x_phases = (1 << x_phase_bits); 765 int n_y_phases = (1 << y_phase_bits); 766 767 return_val_if_fail ( 768 n_params == 4 + n_x_phases * width + n_y_phases * height, FALSE); 769 } 770 771 new_params = NULL; 772 if (params) 773 { 774 new_params = pixman_malloc_ab (n_params, sizeof (pixman_fixed_t)); 775 if (!new_params) 776 return FALSE; 777 778 memcpy (new_params, 779 params, n_params * sizeof (pixman_fixed_t)); 780 } 781 782 common->filter = filter; 783 784 if (common->filter_params) 785 free (common->filter_params); 786 787 common->filter_params = new_params; 788 common->n_filter_params = n_params; 789 790 image_property_changed (image); 791 return TRUE; 792 } 793 794 PIXMAN_EXPORT void 795 pixman_image_set_source_clipping (pixman_image_t *image, 796 pixman_bool_t clip_sources) 797 { 798 if (image->common.clip_sources == clip_sources) 799 return; 800 801 image->common.clip_sources = clip_sources; 802 803 image_property_changed (image); 804 } 805 806 /* Unlike all the other property setters, this function does not 807 * copy the content of indexed. Doing this copying is simply 808 * way, way too expensive. 809 */ 810 PIXMAN_EXPORT void 811 pixman_image_set_indexed (pixman_image_t * image, 812 const pixman_indexed_t *indexed) 813 { 814 bits_image_t *bits = (bits_image_t *)image; 815 816 if (bits->indexed == indexed) 817 return; 818 819 bits->indexed = indexed; 820 821 image_property_changed (image); 822 } 823 824 PIXMAN_EXPORT void 825 pixman_image_set_alpha_map (pixman_image_t *image, 826 pixman_image_t *alpha_map, 827 int16_t x, 828 int16_t y) 829 { 830 image_common_t *common = (image_common_t *)image; 831 832 return_if_fail (!alpha_map || alpha_map->type == BITS); 833 834 if (alpha_map && common->alpha_count > 0) 835 { 836 /* If this image is being used as an alpha map itself, 837 * then you can't give it an alpha map of its own. 838 */ 839 return; 840 } 841 842 if (alpha_map && alpha_map->common.alpha_map) 843 { 844 /* If the image has an alpha map of its own, 845 * then it can't be used as an alpha map itself 846 */ 847 return; 848 } 849 850 if (common->alpha_map != (bits_image_t *)alpha_map) 851 { 852 if (common->alpha_map) 853 { 854 common->alpha_map->common.alpha_count--; 855 856 pixman_image_unref ((pixman_image_t *)common->alpha_map); 857 } 858 859 if (alpha_map) 860 { 861 common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map); 862 863 common->alpha_map->common.alpha_count++; 864 } 865 else 866 { 867 common->alpha_map = NULL; 868 } 869 } 870 871 common->alpha_origin_x = x; 872 common->alpha_origin_y = y; 873 874 image_property_changed (image); 875 } 876 877 PIXMAN_EXPORT void 878 pixman_image_set_component_alpha (pixman_image_t *image, 879 pixman_bool_t component_alpha) 880 { 881 if (image->common.component_alpha == component_alpha) 882 return; 883 884 image->common.component_alpha = component_alpha; 885 886 image_property_changed (image); 887 } 888 889 PIXMAN_EXPORT pixman_bool_t 890 pixman_image_get_component_alpha (pixman_image_t *image) 891 { 892 return image->common.component_alpha; 893 } 894 895 PIXMAN_EXPORT void 896 pixman_image_set_accessors (pixman_image_t * image, 897 pixman_read_memory_func_t read_func, 898 pixman_write_memory_func_t write_func) 899 { 900 return_if_fail (image != NULL); 901 902 if (image->type == BITS) 903 { 904 /* Accessors only work for <= 32 bpp. */ 905 if (PIXMAN_FORMAT_BPP(image->bits.format) > 32) 906 return_if_fail (!read_func && !write_func); 907 908 image->bits.read_func = read_func; 909 image->bits.write_func = write_func; 910 911 image_property_changed (image); 912 } 913 } 914 915 PIXMAN_EXPORT uint32_t * 916 pixman_image_get_data (pixman_image_t *image) 917 { 918 if (image->type == BITS) 919 return image->bits.bits; 920 921 return NULL; 922 } 923 924 PIXMAN_EXPORT int 925 pixman_image_get_width (pixman_image_t *image) 926 { 927 if (image->type == BITS) 928 return image->bits.width; 929 930 return 0; 931 } 932 933 PIXMAN_EXPORT int 934 pixman_image_get_height (pixman_image_t *image) 935 { 936 if (image->type == BITS) 937 return image->bits.height; 938 939 return 0; 940 } 941 942 PIXMAN_EXPORT int 943 pixman_image_get_stride (pixman_image_t *image) 944 { 945 if (image->type == BITS) 946 return image->bits.rowstride * (int) sizeof (uint32_t); 947 948 return 0; 949 } 950 951 PIXMAN_EXPORT int 952 pixman_image_get_depth (pixman_image_t *image) 953 { 954 if (image->type == BITS) 955 return PIXMAN_FORMAT_DEPTH (image->bits.format); 956 957 return 0; 958 } 959 960 PIXMAN_EXPORT pixman_format_code_t 961 pixman_image_get_format (pixman_image_t *image) 962 { 963 if (image->type == BITS) 964 return image->bits.format; 965 966 return PIXMAN_null; 967 } 968 969 uint32_t 970 _pixman_image_get_solid (pixman_implementation_t *imp, 971 pixman_image_t * image, 972 pixman_format_code_t format) 973 { 974 uint32_t result; 975 976 if (image->type == SOLID) 977 { 978 result = image->solid.color_32; 979 } 980 else if (image->type == BITS) 981 { 982 if (image->bits.format == PIXMAN_a8r8g8b8) 983 result = image->bits.bits[0]; 984 else if (image->bits.format == PIXMAN_x8r8g8b8) 985 result = image->bits.bits[0] | 0xff000000; 986 else if (image->bits.format == PIXMAN_a8) 987 result = (uint32_t)(*(uint8_t *)image->bits.bits) << 24; 988 else 989 goto otherwise; 990 } 991 else 992 { 993 pixman_iter_t iter; 994 995 otherwise: 996 _pixman_implementation_iter_init ( 997 imp, &iter, image, 0, 0, 1, 1, 998 (uint8_t *)&result, 999 ITER_NARROW | ITER_SRC, image->common.flags); 1000 1001 result = *iter.get_scanline (&iter, NULL); 1002 1003 if (iter.fini) 1004 iter.fini (&iter); 1005 } 1006 1007 /* If necessary, convert RGB <--> BGR. */ 1008 if (PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB 1009 && PIXMAN_FORMAT_TYPE (format) != PIXMAN_TYPE_ARGB_SRGB) 1010 { 1011 result = (((result & 0xff000000) >> 0) | 1012 ((result & 0x00ff0000) >> 16) | 1013 ((result & 0x0000ff00) >> 0) | 1014 ((result & 0x000000ff) << 16)); 1015 } 1016 1017 return result; 1018 }