pixman-utils.c revision d0321353
1/* 2 * Copyright © 2000 SuSE, Inc. 3 * Copyright © 1999 Keith Packard 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 * Author: Keith Packard, SuSE, Inc. 23 */ 24 25#ifdef HAVE_CONFIG_H 26#include <config.h> 27#endif 28#include <stdio.h> 29#include <stdlib.h> 30 31#include "pixman-private.h" 32 33/* 34 * Computing composite region 35 */ 36#define BOUND(v) (int16_t) ((v) < INT16_MIN ? INT16_MIN : (v) > INT16_MAX ? INT16_MAX : (v)) 37 38static inline pixman_bool_t 39clip_general_image (pixman_region32_t * region, 40 pixman_region32_t * clip, 41 int dx, 42 int dy) 43{ 44 if (pixman_region32_n_rects (region) == 1 && 45 pixman_region32_n_rects (clip) == 1) 46 { 47 pixman_box32_t * rbox = pixman_region32_rectangles (region, NULL); 48 pixman_box32_t * cbox = pixman_region32_rectangles (clip, NULL); 49 int v; 50 51 if (rbox->x1 < (v = cbox->x1 + dx)) 52 rbox->x1 = BOUND (v); 53 if (rbox->x2 > (v = cbox->x2 + dx)) 54 rbox->x2 = BOUND (v); 55 if (rbox->y1 < (v = cbox->y1 + dy)) 56 rbox->y1 = BOUND (v); 57 if (rbox->y2 > (v = cbox->y2 + dy)) 58 rbox->y2 = BOUND (v); 59 if (rbox->x1 >= rbox->x2 || 60 rbox->y1 >= rbox->y2) 61 { 62 pixman_region32_init (region); 63 } 64 } 65 else if (!pixman_region32_not_empty (clip)) 66 { 67 return FALSE; 68 } 69 else 70 { 71 if (dx || dy) 72 pixman_region32_translate (region, -dx, -dy); 73 if (!pixman_region32_intersect (region, region, clip)) 74 return FALSE; 75 if (dx || dy) 76 pixman_region32_translate (region, dx, dy); 77 } 78 return pixman_region32_not_empty (region); 79} 80 81static inline pixman_bool_t 82clip_source_image (pixman_region32_t * region, 83 pixman_image_t * picture, 84 int dx, 85 int dy) 86{ 87 /* The workaround lets certain fast paths run even when they 88 * would normally be rejected because of out-of-bounds access. 89 * We need to clip against the source geometry in that case 90 */ 91 if (!picture->common.need_workaround) 92 { 93 /* Source clips are ignored, unless they are explicitly turned on 94 * and the clip in question was set by an X client. (Because if 95 * the clip was not set by a client, then it is a hierarchy 96 * clip and those should always be ignored for sources). 97 */ 98 if (!picture->common.clip_sources || !picture->common.client_clip) 99 return TRUE; 100 } 101 102 return clip_general_image (region, 103 &picture->common.clip_region, 104 dx, dy); 105} 106 107/* 108 * returns FALSE if the final region is empty. Indistinguishable from 109 * an allocation failure, but rendering ignores those anyways. 110 */ 111static pixman_bool_t 112pixman_compute_composite_region32 (pixman_region32_t * region, 113 pixman_image_t * src_image, 114 pixman_image_t * mask_image, 115 pixman_image_t * dst_image, 116 int16_t src_x, 117 int16_t src_y, 118 int16_t mask_x, 119 int16_t mask_y, 120 int16_t dest_x, 121 int16_t dest_y, 122 uint16_t width, 123 uint16_t height) 124{ 125 int v; 126 127 region->extents.x1 = dest_x; 128 v = dest_x + width; 129 region->extents.x2 = BOUND (v); 130 region->extents.y1 = dest_y; 131 v = dest_y + height; 132 region->extents.y2 = BOUND (v); 133 134 region->extents.x1 = MAX (region->extents.x1, 0); 135 region->extents.y1 = MAX (region->extents.y1, 0); 136 137 /* Some X servers rely on an old bug, where pixman would just believe the 138 * set clip_region and not clip against the destination geometry. So, 139 * since only X servers set "source clip", we don't clip against 140 * destination geometry when that is set and when the workaround has 141 * not been explicitly disabled by 142 * 143 * pixman_disable_out_of_bounds_workaround(); 144 * 145 */ 146 if (!(dst_image->common.need_workaround)) 147 { 148 region->extents.x2 = MIN (region->extents.x2, dst_image->bits.width); 149 region->extents.y2 = MIN (region->extents.y2, dst_image->bits.height); 150 } 151 152 region->data = 0; 153 154 /* Check for empty operation */ 155 if (region->extents.x1 >= region->extents.x2 || 156 region->extents.y1 >= region->extents.y2) 157 { 158 pixman_region32_init (region); 159 return FALSE; 160 } 161 162 if (dst_image->common.have_clip_region) 163 { 164 if (!clip_general_image (region, &dst_image->common.clip_region, 0, 0)) 165 { 166 pixman_region32_fini (region); 167 return FALSE; 168 } 169 } 170 171 if (dst_image->common.alpha_map && dst_image->common.alpha_map->common.have_clip_region) 172 { 173 if (!clip_general_image (region, &dst_image->common.alpha_map->common.clip_region, 174 -dst_image->common.alpha_origin_x, 175 -dst_image->common.alpha_origin_y)) 176 { 177 pixman_region32_fini (region); 178 return FALSE; 179 } 180 } 181 182 /* clip against src */ 183 if (src_image->common.have_clip_region) 184 { 185 if (!clip_source_image (region, src_image, dest_x - src_x, dest_y - src_y)) 186 { 187 pixman_region32_fini (region); 188 return FALSE; 189 } 190 } 191 if (src_image->common.alpha_map && src_image->common.alpha_map->common.have_clip_region) 192 { 193 if (!clip_source_image (region, (pixman_image_t *)src_image->common.alpha_map, 194 dest_x - (src_x - src_image->common.alpha_origin_x), 195 dest_y - (src_y - src_image->common.alpha_origin_y))) 196 { 197 pixman_region32_fini (region); 198 return FALSE; 199 } 200 } 201 /* clip against mask */ 202 if (mask_image && mask_image->common.have_clip_region) 203 { 204 if (!clip_source_image (region, mask_image, dest_x - mask_x, dest_y - mask_y)) 205 { 206 pixman_region32_fini (region); 207 return FALSE; 208 } 209 if (mask_image->common.alpha_map && mask_image->common.alpha_map->common.have_clip_region) 210 { 211 if (!clip_source_image (region, (pixman_image_t *)mask_image->common.alpha_map, 212 dest_x - (mask_x - mask_image->common.alpha_origin_x), 213 dest_y - (mask_y - mask_image->common.alpha_origin_y))) 214 { 215 pixman_region32_fini (region); 216 return FALSE; 217 } 218 } 219 } 220 221 return TRUE; 222} 223 224PIXMAN_EXPORT pixman_bool_t 225pixman_compute_composite_region (pixman_region16_t * region, 226 pixman_image_t * src_image, 227 pixman_image_t * mask_image, 228 pixman_image_t * dst_image, 229 int16_t src_x, 230 int16_t src_y, 231 int16_t mask_x, 232 int16_t mask_y, 233 int16_t dest_x, 234 int16_t dest_y, 235 uint16_t width, 236 uint16_t height) 237{ 238 pixman_region32_t r32; 239 pixman_bool_t retval; 240 241 pixman_region32_init (&r32); 242 243 retval = pixman_compute_composite_region32 ( 244 &r32, src_image, mask_image, dst_image, 245 src_x, src_y, mask_x, mask_y, dest_x, dest_y, 246 width, height); 247 248 if (retval) 249 { 250 if (!pixman_region16_copy_from_region32 (region, &r32)) 251 retval = FALSE; 252 } 253 254 pixman_region32_fini (&r32); 255 return retval; 256} 257 258pixman_bool_t 259pixman_multiply_overflows_int (unsigned int a, 260 unsigned int b) 261{ 262 return a >= INT32_MAX / b; 263} 264 265pixman_bool_t 266pixman_addition_overflows_int (unsigned int a, 267 unsigned int b) 268{ 269 return a > INT32_MAX - b; 270} 271 272void * 273pixman_malloc_ab (unsigned int a, 274 unsigned int b) 275{ 276 if (a >= INT32_MAX / b) 277 return NULL; 278 279 return malloc (a * b); 280} 281 282void * 283pixman_malloc_abc (unsigned int a, 284 unsigned int b, 285 unsigned int c) 286{ 287 if (a >= INT32_MAX / b) 288 return NULL; 289 else if (a * b >= INT32_MAX / c) 290 return NULL; 291 else 292 return malloc (a * b * c); 293} 294 295/* 296 * Helper routine to expand a color component from 0 < n <= 8 bits to 16 297 * bits by replication. 298 */ 299static inline uint64_t 300expand16 (const uint8_t val, int nbits) 301{ 302 /* Start out with the high bit of val in the high bit of result. */ 303 uint16_t result = (uint16_t)val << (16 - nbits); 304 305 if (nbits == 0) 306 return 0; 307 308 /* Copy the bits in result, doubling the number of bits each time, until 309 * we fill all 16 bits. 310 */ 311 while (nbits < 16) 312 { 313 result |= result >> nbits; 314 nbits *= 2; 315 } 316 317 return result; 318} 319 320/* 321 * This function expands images from ARGB8 format to ARGB16. To preserve 322 * precision, it needs to know the original source format. For example, if the 323 * source was PIXMAN_x1r5g5b5 and the red component contained bits 12345, then 324 * the expanded value is 12345123. To correctly expand this to 16 bits, it 325 * should be 1234512345123451 and not 1234512312345123. 326 */ 327void 328pixman_expand (uint64_t * dst, 329 const uint32_t * src, 330 pixman_format_code_t format, 331 int width) 332{ 333 /* 334 * Determine the sizes of each component and the masks and shifts 335 * required to extract them from the source pixel. 336 */ 337 const int a_size = PIXMAN_FORMAT_A (format), 338 r_size = PIXMAN_FORMAT_R (format), 339 g_size = PIXMAN_FORMAT_G (format), 340 b_size = PIXMAN_FORMAT_B (format); 341 const int a_shift = 32 - a_size, 342 r_shift = 24 - r_size, 343 g_shift = 16 - g_size, 344 b_shift = 8 - b_size; 345 const uint8_t a_mask = ~(~0 << a_size), 346 r_mask = ~(~0 << r_size), 347 g_mask = ~(~0 << g_size), 348 b_mask = ~(~0 << b_size); 349 int i; 350 351 /* Start at the end so that we can do the expansion in place 352 * when src == dst 353 */ 354 for (i = width - 1; i >= 0; i--) 355 { 356 const uint32_t pixel = src[i]; 357 const uint8_t a = (pixel >> a_shift) & a_mask, 358 r = (pixel >> r_shift) & r_mask, 359 g = (pixel >> g_shift) & g_mask, 360 b = (pixel >> b_shift) & b_mask; 361 const uint64_t a16 = a_size ? expand16 (a, a_size) : 0xffff, 362 r16 = expand16 (r, r_size), 363 g16 = expand16 (g, g_size), 364 b16 = expand16 (b, b_size); 365 366 dst[i] = a16 << 48 | r16 << 32 | g16 << 16 | b16; 367 } 368} 369 370/* 371 * Contracting is easier than expanding. We just need to truncate the 372 * components. 373 */ 374void 375pixman_contract (uint32_t * dst, 376 const uint64_t *src, 377 int width) 378{ 379 int i; 380 381 /* Start at the beginning so that we can do the contraction in 382 * place when src == dst 383 */ 384 for (i = 0; i < width; i++) 385 { 386 const uint8_t a = src[i] >> 56, 387 r = src[i] >> 40, 388 g = src[i] >> 24, 389 b = src[i] >> 8; 390 391 dst[i] = a << 24 | r << 16 | g << 8 | b; 392 } 393} 394 395static void 396walk_region_internal (pixman_implementation_t *imp, 397 pixman_op_t op, 398 pixman_image_t * src_image, 399 pixman_image_t * mask_image, 400 pixman_image_t * dst_image, 401 int16_t src_x, 402 int16_t src_y, 403 int16_t mask_x, 404 int16_t mask_y, 405 int16_t dest_x, 406 int16_t dest_y, 407 uint16_t width, 408 uint16_t height, 409 pixman_bool_t src_repeat, 410 pixman_bool_t mask_repeat, 411 pixman_region32_t * region, 412 pixman_composite_func_t composite_rect) 413{ 414 int n; 415 const pixman_box32_t *pbox; 416 int w, h, w_this, h_this; 417 int x_msk, y_msk, x_src, y_src, x_dst, y_dst; 418 419 pbox = pixman_region32_rectangles (region, &n); 420 while (n--) 421 { 422 h = pbox->y2 - pbox->y1; 423 y_src = pbox->y1 - dest_y + src_y; 424 y_msk = pbox->y1 - dest_y + mask_y; 425 y_dst = pbox->y1; 426 427 while (h) 428 { 429 h_this = h; 430 w = pbox->x2 - pbox->x1; 431 x_src = pbox->x1 - dest_x + src_x; 432 x_msk = pbox->x1 - dest_x + mask_x; 433 x_dst = pbox->x1; 434 435 if (mask_repeat) 436 { 437 y_msk = MOD (y_msk, mask_image->bits.height); 438 if (h_this > mask_image->bits.height - y_msk) 439 h_this = mask_image->bits.height - y_msk; 440 } 441 442 if (src_repeat) 443 { 444 y_src = MOD (y_src, src_image->bits.height); 445 if (h_this > src_image->bits.height - y_src) 446 h_this = src_image->bits.height - y_src; 447 } 448 449 while (w) 450 { 451 w_this = w; 452 453 if (mask_repeat) 454 { 455 x_msk = MOD (x_msk, mask_image->bits.width); 456 if (w_this > mask_image->bits.width - x_msk) 457 w_this = mask_image->bits.width - x_msk; 458 } 459 460 if (src_repeat) 461 { 462 x_src = MOD (x_src, src_image->bits.width); 463 if (w_this > src_image->bits.width - x_src) 464 w_this = src_image->bits.width - x_src; 465 } 466 467 (*composite_rect) (imp, op, 468 src_image, mask_image, dst_image, 469 x_src, y_src, x_msk, y_msk, x_dst, y_dst, 470 w_this, h_this); 471 w -= w_this; 472 473 x_src += w_this; 474 x_msk += w_this; 475 x_dst += w_this; 476 } 477 478 h -= h_this; 479 y_src += h_this; 480 y_msk += h_this; 481 y_dst += h_this; 482 } 483 484 pbox++; 485 } 486} 487 488void 489_pixman_walk_composite_region (pixman_implementation_t *imp, 490 pixman_op_t op, 491 pixman_image_t * src_image, 492 pixman_image_t * mask_image, 493 pixman_image_t * dst_image, 494 int16_t src_x, 495 int16_t src_y, 496 int16_t mask_x, 497 int16_t mask_y, 498 int16_t dest_x, 499 int16_t dest_y, 500 uint16_t width, 501 uint16_t height, 502 pixman_composite_func_t composite_rect) 503{ 504 pixman_region32_t region; 505 506 pixman_region32_init (®ion); 507 508 if (pixman_compute_composite_region32 ( 509 ®ion, src_image, mask_image, dst_image, 510 src_x, src_y, mask_x, mask_y, dest_x, dest_y, 511 width, height)) 512 { 513 walk_region_internal (imp, op, 514 src_image, mask_image, dst_image, 515 src_x, src_y, mask_x, mask_y, dest_x, dest_y, 516 width, height, FALSE, FALSE, 517 ®ion, 518 composite_rect); 519 520 pixman_region32_fini (®ion); 521 } 522} 523 524static pixman_bool_t 525mask_is_solid (pixman_image_t *mask) 526{ 527 if (mask->type == SOLID) 528 return TRUE; 529 530 if (mask->type == BITS && 531 mask->common.repeat == PIXMAN_REPEAT_NORMAL && 532 mask->bits.width == 1 && 533 mask->bits.height == 1) 534 { 535 return TRUE; 536 } 537 538 return FALSE; 539} 540 541static const pixman_fast_path_t * 542get_fast_path (const pixman_fast_path_t *fast_paths, 543 pixman_op_t op, 544 pixman_image_t * src_image, 545 pixman_image_t * mask_image, 546 pixman_image_t * dst_image, 547 pixman_bool_t is_pixbuf) 548{ 549 const pixman_fast_path_t *info; 550 551 for (info = fast_paths; info->op != PIXMAN_OP_NONE; info++) 552 { 553 pixman_bool_t valid_src = FALSE; 554 pixman_bool_t valid_mask = FALSE; 555 556 if (info->op != op) 557 continue; 558 559 if ((info->src_format == PIXMAN_solid && 560 _pixman_image_is_solid (src_image)) || 561 (src_image->type == BITS && 562 info->src_format == src_image->bits.format)) 563 { 564 valid_src = TRUE; 565 } 566 567 if (!valid_src) 568 continue; 569 570 if ((info->mask_format == PIXMAN_null && !mask_image) || 571 (mask_image && mask_image->type == BITS && 572 info->mask_format == mask_image->bits.format)) 573 { 574 valid_mask = TRUE; 575 576 if (info->flags & NEED_SOLID_MASK) 577 { 578 if (!mask_image || !mask_is_solid (mask_image)) 579 valid_mask = FALSE; 580 } 581 582 if (info->flags & NEED_COMPONENT_ALPHA) 583 { 584 if (!mask_image || !mask_image->common.component_alpha) 585 valid_mask = FALSE; 586 } 587 } 588 589 if (!valid_mask) 590 continue; 591 592 if (info->dest_format != dst_image->bits.format) 593 continue; 594 595 if ((info->flags & NEED_PIXBUF) && !is_pixbuf) 596 continue; 597 598 return info; 599 } 600 601 return NULL; 602} 603 604static force_inline pixman_bool_t 605image_covers (pixman_image_t *image, 606 pixman_box32_t *extents, 607 int x, 608 int y) 609{ 610 if (image->common.type == BITS && 611 image->common.repeat == PIXMAN_REPEAT_NONE) 612 { 613 if (x > extents->x1 || y > extents->y1 || 614 x + image->bits.width < extents->x2 || 615 y + image->bits.height < extents->y2) 616 { 617 return FALSE; 618 } 619 } 620 621 return TRUE; 622} 623 624static force_inline pixman_bool_t 625sources_cover (pixman_image_t *src, 626 pixman_image_t *mask, 627 pixman_box32_t *extents, 628 int src_x, 629 int src_y, 630 int mask_x, 631 int mask_y, 632 int dest_x, 633 int dest_y) 634{ 635 if (!image_covers (src, extents, dest_x - src_x, dest_y - src_y)) 636 return FALSE; 637 638 if (!mask) 639 return TRUE; 640 641 if (!image_covers (mask, extents, dest_x - mask_x, dest_y - mask_y)) 642 return FALSE; 643 644 return TRUE; 645} 646 647pixman_bool_t 648_pixman_run_fast_path (const pixman_fast_path_t *paths, 649 pixman_implementation_t * imp, 650 pixman_op_t op, 651 pixman_image_t * src, 652 pixman_image_t * mask, 653 pixman_image_t * dest, 654 int32_t src_x, 655 int32_t src_y, 656 int32_t mask_x, 657 int32_t mask_y, 658 int32_t dest_x, 659 int32_t dest_y, 660 int32_t width, 661 int32_t height) 662{ 663 pixman_composite_func_t func = NULL; 664 pixman_bool_t src_repeat = 665 src->common.repeat == PIXMAN_REPEAT_NORMAL; 666 pixman_bool_t mask_repeat = 667 mask && mask->common.repeat == PIXMAN_REPEAT_NORMAL; 668 pixman_bool_t result; 669 670 if ((src->type == BITS || _pixman_image_is_solid (src)) && 671 (!mask || mask->type == BITS) 672 && !src->common.transform && !(mask && mask->common.transform) 673 && !src->common.alpha_map && !dest->common.alpha_map 674 && !(mask && mask->common.alpha_map) 675 && (src->common.filter != PIXMAN_FILTER_CONVOLUTION) 676 && (src->common.repeat != PIXMAN_REPEAT_PAD) 677 && (src->common.repeat != PIXMAN_REPEAT_REFLECT) 678 && (!mask || (mask->common.filter != PIXMAN_FILTER_CONVOLUTION && 679 mask->common.repeat != PIXMAN_REPEAT_PAD && 680 mask->common.repeat != PIXMAN_REPEAT_REFLECT)) 681 && !src->common.read_func && !src->common.write_func 682 && !(mask && mask->common.read_func) 683 && !(mask && mask->common.write_func) 684 && !dest->common.read_func 685 && !dest->common.write_func) 686 { 687 const pixman_fast_path_t *info; 688 pixman_bool_t pixbuf; 689 690 pixbuf = 691 src && src->type == BITS && 692 mask && mask->type == BITS && 693 src->bits.bits == mask->bits.bits && 694 src_x == mask_x && 695 src_y == mask_y && 696 !mask->common.component_alpha && 697 !mask_repeat; 698 699 info = get_fast_path (paths, op, src, mask, dest, pixbuf); 700 701 if (info) 702 { 703 func = info->func; 704 705 if (info->src_format == PIXMAN_solid) 706 src_repeat = FALSE; 707 708 if (info->mask_format == PIXMAN_solid || 709 info->flags & NEED_SOLID_MASK) 710 { 711 mask_repeat = FALSE; 712 } 713 714 if ((src_repeat && 715 src->bits.width == 1 && 716 src->bits.height == 1) || 717 (mask_repeat && 718 mask->bits.width == 1 && 719 mask->bits.height == 1)) 720 { 721 /* If src or mask are repeating 1x1 images and src_repeat or 722 * mask_repeat are still TRUE, it means the fast path we 723 * selected does not actually handle repeating images. 724 * 725 * So rather than call the "fast path" with a zillion 726 * 1x1 requests, we just fall back to the general code (which 727 * does do something sensible with 1x1 repeating images). 728 */ 729 func = NULL; 730 } 731 } 732 } 733 734 result = FALSE; 735 736 if (func) 737 { 738 pixman_region32_t region; 739 pixman_region32_init (®ion); 740 741 if (pixman_compute_composite_region32 ( 742 ®ion, src, mask, dest, 743 src_x, src_y, mask_x, mask_y, dest_x, dest_y, width, height)) 744 { 745 pixman_box32_t *extents = pixman_region32_extents (®ion); 746 747 if (sources_cover ( 748 src, mask, extents, 749 src_x, src_y, mask_x, mask_y, dest_x, dest_y)) 750 { 751 walk_region_internal (imp, op, 752 src, mask, dest, 753 src_x, src_y, mask_x, mask_y, 754 dest_x, dest_y, 755 width, height, 756 src_repeat, mask_repeat, 757 ®ion, 758 func); 759 760 result = TRUE; 761 } 762 763 pixman_region32_fini (®ion); 764 } 765 } 766 767 return result; 768} 769 770#define N_TMP_BOXES (16) 771 772pixman_bool_t 773pixman_region16_copy_from_region32 (pixman_region16_t *dst, 774 pixman_region32_t *src) 775{ 776 int n_boxes, i; 777 pixman_box32_t *boxes32; 778 pixman_box16_t *boxes16; 779 pixman_bool_t retval; 780 781 boxes32 = pixman_region32_rectangles (src, &n_boxes); 782 783 boxes16 = pixman_malloc_ab (n_boxes, sizeof (pixman_box16_t)); 784 785 if (!boxes16) 786 return FALSE; 787 788 for (i = 0; i < n_boxes; ++i) 789 { 790 boxes16[i].x1 = boxes32[i].x1; 791 boxes16[i].y1 = boxes32[i].y1; 792 boxes16[i].x2 = boxes32[i].x2; 793 boxes16[i].y2 = boxes32[i].y2; 794 } 795 796 pixman_region_fini (dst); 797 retval = pixman_region_init_rects (dst, boxes16, n_boxes); 798 free (boxes16); 799 return retval; 800} 801 802pixman_bool_t 803pixman_region32_copy_from_region16 (pixman_region32_t *dst, 804 pixman_region16_t *src) 805{ 806 int n_boxes, i; 807 pixman_box16_t *boxes16; 808 pixman_box32_t *boxes32; 809 pixman_box32_t tmp_boxes[N_TMP_BOXES]; 810 pixman_bool_t retval; 811 812 boxes16 = pixman_region_rectangles (src, &n_boxes); 813 814 if (n_boxes > N_TMP_BOXES) 815 boxes32 = pixman_malloc_ab (n_boxes, sizeof (pixman_box32_t)); 816 else 817 boxes32 = tmp_boxes; 818 819 if (!boxes32) 820 return FALSE; 821 822 for (i = 0; i < n_boxes; ++i) 823 { 824 boxes32[i].x1 = boxes16[i].x1; 825 boxes32[i].y1 = boxes16[i].y1; 826 boxes32[i].x2 = boxes16[i].x2; 827 boxes32[i].y2 = boxes16[i].y2; 828 } 829 830 pixman_region32_fini (dst); 831 retval = pixman_region32_init_rects (dst, boxes32, n_boxes); 832 833 if (boxes32 != tmp_boxes) 834 free (boxes32); 835 836 return retval; 837} 838