Rev 1891 | Go to most recent revision | Show entire file | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 1891 | Rev 3931 | ||
---|---|---|---|
Line 1... | Line 1... | ||
1 | /* |
1 | /* |
- | 2 | * Copyright © 2002 Keith Packard, member of The XFree86 Project, Inc. |
|
2 | * Copyright © 2004 Keith Packard |
3 | * Copyright © 2004 Keith Packard |
3 | * |
4 | * |
4 | * Permission to use, copy, modify, distribute, and sell this software and its |
5 | * Permission to use, copy, modify, distribute, and sell this software and its |
5 | * documentation for any purpose is hereby granted without fee, provided that |
6 | * documentation for any purpose is hereby granted without fee, provided that |
6 | * the above copyright notice appear in all copies and that both that |
7 | * the above copyright notice appear in all copies and that both that |
Line 23... | Line 24... | ||
23 | #ifdef HAVE_CONFIG_H |
24 | #ifdef HAVE_CONFIG_H |
24 | #include |
25 | #include |
25 | #endif |
26 | #endif |
Line 26... | Line 27... | ||
26 | 27 | ||
- | 28 | #include |
|
27 | #include |
29 | #include |
Line 28... | Line 30... | ||
28 | #include "pixman-private.h" |
30 | #include "pixman-private.h" |
29 | 31 | ||
30 | /* |
32 | /* |
Line 135... | Line 137... | ||
135 | stepx = n * e->stepx; |
137 | stepx = n * e->stepx; |
Line 136... | Line 138... | ||
136 | 138 | ||
137 | if (ne > 0) |
139 | if (ne > 0) |
138 | { |
140 | { |
139 | int nx = ne / e->dy; |
141 | int nx = ne / e->dy; |
140 | ne -= nx * e->dy; |
142 | ne -= nx * (pixman_fixed_48_16_t)e->dy; |
141 | stepx += nx * e->signdx; |
143 | stepx += nx * e->signdx; |
Line 142... | Line 144... | ||
142 | } |
144 | } |
143 | 145 | ||
Line 230... | Line 232... | ||
230 | PIXMAN_EXPORT void |
232 | PIXMAN_EXPORT void |
231 | pixman_add_traps (pixman_image_t * image, |
233 | pixman_add_traps (pixman_image_t * image, |
232 | int16_t x_off, |
234 | int16_t x_off, |
233 | int16_t y_off, |
235 | int16_t y_off, |
234 | int ntrap, |
236 | int ntrap, |
235 | pixman_trap_t * traps) |
237 | const pixman_trap_t *traps) |
236 | { |
238 | { |
237 | int bpp; |
239 | int bpp; |
238 | int width; |
- | |
239 | int height; |
240 | int height; |
Line 240... | Line 241... | ||
240 | 241 | ||
241 | pixman_fixed_t x_off_fixed; |
242 | pixman_fixed_t x_off_fixed; |
242 | pixman_fixed_t y_off_fixed; |
243 | pixman_fixed_t y_off_fixed; |
243 | pixman_edge_t l, r; |
244 | pixman_edge_t l, r; |
Line 244... | Line 245... | ||
244 | pixman_fixed_t t, b; |
245 | pixman_fixed_t t, b; |
Line 245... | Line -... | ||
245 | - | ||
246 | _pixman_image_validate (image); |
246 | |
247 | 247 | _pixman_image_validate (image); |
|
Line 248... | Line 248... | ||
248 | width = image->bits.width; |
248 | |
249 | height = image->bits.height; |
249 | height = image->bits.height; |
Line 347... | Line 347... | ||
347 | const pixman_trapezoid_t *trap, |
347 | const pixman_trapezoid_t *trap, |
348 | int x_off, |
348 | int x_off, |
349 | int y_off) |
349 | int y_off) |
350 | { |
350 | { |
351 | int bpp; |
351 | int bpp; |
352 | int width; |
- | |
353 | int height; |
352 | int height; |
Line 354... | Line -... | ||
354 | - | ||
355 | pixman_fixed_t x_off_fixed; |
353 | |
356 | pixman_fixed_t y_off_fixed; |
354 | pixman_fixed_t y_off_fixed; |
357 | pixman_edge_t l, r; |
355 | pixman_edge_t l, r; |
Line 358... | Line 356... | ||
358 | pixman_fixed_t t, b; |
356 | pixman_fixed_t t, b; |
Line 362... | Line 360... | ||
362 | _pixman_image_validate (image); |
360 | _pixman_image_validate (image); |
Line 363... | Line 361... | ||
363 | 361 | ||
364 | if (!pixman_trapezoid_valid (trap)) |
362 | if (!pixman_trapezoid_valid (trap)) |
Line 365... | Line -... | ||
365 | return; |
- | |
366 | 363 | return; |
|
367 | width = image->bits.width; |
364 | |
Line 368... | Line -... | ||
368 | height = image->bits.height; |
- | |
369 | bpp = PIXMAN_FORMAT_BPP (image->bits.format); |
365 | height = image->bits.height; |
Line 370... | Line 366... | ||
370 | 366 | bpp = PIXMAN_FORMAT_BPP (image->bits.format); |
|
371 | x_off_fixed = pixman_int_to_fixed (x_off); |
367 | |
372 | y_off_fixed = pixman_int_to_fixed (y_off); |
368 | y_off_fixed = pixman_int_to_fixed (y_off); |
Line 388... | Line 384... | ||
388 | pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off); |
384 | pixman_line_fixed_edge_init (&r, bpp, t, &trap->right, x_off, y_off); |
Line 389... | Line 385... | ||
389 | 385 | ||
390 | pixman_rasterize_edges (image, &l, &r, t, b); |
386 | pixman_rasterize_edges (image, &l, &r, t, b); |
391 | } |
387 | } |
- | 388 | } |
|
- | 389 | ||
- | 390 | static const pixman_bool_t zero_src_has_no_effect[PIXMAN_N_OPERATORS] = |
|
- | 391 | { |
|
- | 392 | FALSE, /* Clear 0 0 */ |
|
- | 393 | FALSE, /* Src 1 0 */ |
|
- | 394 | TRUE, /* Dst 0 1 */ |
|
- | 395 | TRUE, /* Over 1 1-Aa */ |
|
- | 396 | TRUE, /* OverReverse 1-Ab 1 */ |
|
- | 397 | FALSE, /* In Ab 0 */ |
|
- | 398 | FALSE, /* InReverse 0 Aa */ |
|
- | 399 | FALSE, /* Out 1-Ab 0 */ |
|
- | 400 | TRUE, /* OutReverse 0 1-Aa */ |
|
- | 401 | TRUE, /* Atop Ab 1-Aa */ |
|
- | 402 | FALSE, /* AtopReverse 1-Ab Aa */ |
|
- | 403 | TRUE, /* Xor 1-Ab 1-Aa */ |
|
- | 404 | TRUE, /* Add 1 1 */ |
|
- | 405 | }; |
|
- | 406 | ||
- | 407 | static pixman_bool_t |
|
- | 408 | get_trap_extents (pixman_op_t op, pixman_image_t *dest, |
|
- | 409 | const pixman_trapezoid_t *traps, int n_traps, |
|
- | 410 | pixman_box32_t *box) |
|
- | 411 | { |
|
- | 412 | int i; |
|
- | 413 | ||
- | 414 | /* When the operator is such that a zero source has an |
|
- | 415 | * effect on the underlying image, we have to |
|
- | 416 | * composite across the entire destination |
|
- | 417 | */ |
|
- | 418 | if (!zero_src_has_no_effect [op]) |
|
- | 419 | { |
|
- | 420 | box->x1 = 0; |
|
- | 421 | box->y1 = 0; |
|
- | 422 | box->x2 = dest->bits.width; |
|
- | 423 | box->y2 = dest->bits.height; |
|
- | 424 | return TRUE; |
|
- | 425 | } |
|
- | 426 | ||
- | 427 | box->x1 = INT32_MAX; |
|
- | 428 | box->y1 = INT32_MAX; |
|
- | 429 | box->x2 = INT32_MIN; |
|
- | 430 | box->y2 = INT32_MIN; |
|
- | 431 | ||
- | 432 | for (i = 0; i < n_traps; ++i) |
|
- | 433 | { |
|
- | 434 | const pixman_trapezoid_t *trap = &(traps[i]); |
|
- | 435 | int y1, y2; |
|
- | 436 | ||
- | 437 | if (!pixman_trapezoid_valid (trap)) |
|
- | 438 | continue; |
|
- | 439 | ||
- | 440 | y1 = pixman_fixed_to_int (trap->top); |
|
- | 441 | if (y1 < box->y1) |
|
- | 442 | box->y1 = y1; |
|
- | 443 | ||
- | 444 | y2 = pixman_fixed_to_int (pixman_fixed_ceil (trap->bottom)); |
|
- | 445 | if (y2 > box->y2) |
|
- | 446 | box->y2 = y2; |
|
- | 447 | ||
- | 448 | #define EXTEND_MIN(x) \ |
|
- | 449 | if (pixman_fixed_to_int ((x)) < box->x1) \ |
|
- | 450 | box->x1 = pixman_fixed_to_int ((x)); |
|
- | 451 | #define EXTEND_MAX(x) \ |
|
- | 452 | if (pixman_fixed_to_int (pixman_fixed_ceil ((x))) > box->x2) \ |
|
- | 453 | box->x2 = pixman_fixed_to_int (pixman_fixed_ceil ((x))); |
|
- | 454 | ||
- | 455 | #define EXTEND(x) \ |
|
- | 456 | EXTEND_MIN(x); \ |
|
- | 457 | EXTEND_MAX(x); |
|
- | 458 | ||
- | 459 | EXTEND(trap->left.p1.x); |
|
- | 460 | EXTEND(trap->left.p2.x); |
|
- | 461 | EXTEND(trap->right.p1.x); |
|
- | 462 | EXTEND(trap->right.p2.x); |
|
- | 463 | } |
|
- | 464 | ||
- | 465 | if (box->x1 >= box->x2 || box->y1 >= box->y2) |
|
- | 466 | return FALSE; |
|
- | 467 | ||
- | 468 | return TRUE; |
|
- | 469 | } |
|
- | 470 | ||
- | 471 | /* |
|
- | 472 | * pixman_composite_trapezoids() |
|
- | 473 | * |
|
- | 474 | * All the trapezoids are conceptually rendered to an infinitely big image. |
|
- | 475 | * The (0, 0) coordinates of this image are then aligned with the (x, y) |
|
- | 476 | * coordinates of the source image, and then both images are aligned with |
|
- | 477 | * the (x, y) coordinates of the destination. Then these three images are |
|
- | 478 | * composited across the entire destination. |
|
- | 479 | */ |
|
- | 480 | PIXMAN_EXPORT void |
|
- | 481 | pixman_composite_trapezoids (pixman_op_t op, |
|
- | 482 | pixman_image_t * src, |
|
- | 483 | pixman_image_t * dst, |
|
- | 484 | pixman_format_code_t mask_format, |
|
- | 485 | int x_src, |
|
- | 486 | int y_src, |
|
- | 487 | int x_dst, |
|
- | 488 | int y_dst, |
|
- | 489 | int n_traps, |
|
- | 490 | const pixman_trapezoid_t * traps) |
|
- | 491 | { |
|
- | 492 | int i; |
|
- | 493 | ||
- | 494 | return_if_fail (PIXMAN_FORMAT_TYPE (mask_format) == PIXMAN_TYPE_A); |
|
- | 495 | ||
- | 496 | if (n_traps <= 0) |
|
- | 497 | return; |
|
- | 498 | ||
- | 499 | _pixman_image_validate (src); |
|
- | 500 | _pixman_image_validate (dst); |
|
- | 501 | ||
- | 502 | if (op == PIXMAN_OP_ADD && |
|
- | 503 | (src->common.flags & FAST_PATH_IS_OPAQUE) && |
|
- | 504 | (mask_format == dst->common.extended_format_code) && |
|
- | 505 | !(dst->common.have_clip_region)) |
|
- | 506 | { |
|
- | 507 | for (i = 0; i < n_traps; ++i) |
|
- | 508 | { |
|
- | 509 | const pixman_trapezoid_t *trap = &(traps[i]); |
|
- | 510 | ||
- | 511 | if (!pixman_trapezoid_valid (trap)) |
|
- | 512 | continue; |
|
- | 513 | ||
- | 514 | pixman_rasterize_trapezoid (dst, trap, x_dst, y_dst); |
|
- | 515 | } |
|
- | 516 | } |
|
- | 517 | else |
|
- | 518 | { |
|
- | 519 | pixman_image_t *tmp; |
|
- | 520 | pixman_box32_t box; |
|
- | 521 | int i; |
|
- | 522 | ||
- | 523 | if (!get_trap_extents (op, dst, traps, n_traps, &box)) |
|
- | 524 | return; |
|
- | 525 | ||
- | 526 | if (!(tmp = pixman_image_create_bits ( |
|
- | 527 | mask_format, box.x2 - box.x1, box.y2 - box.y1, NULL, -1))) |
|
- | 528 | return; |
|
- | 529 | ||
- | 530 | for (i = 0; i < n_traps; ++i) |
|
- | 531 | { |
|
- | 532 | const pixman_trapezoid_t *trap = &(traps[i]); |
|
- | 533 | ||
- | 534 | if (!pixman_trapezoid_valid (trap)) |
|
- | 535 | continue; |
|
- | 536 | ||
- | 537 | pixman_rasterize_trapezoid (tmp, trap, - box.x1, - box.y1); |
|
- | 538 | } |
|
- | 539 | ||
- | 540 | pixman_image_composite (op, src, tmp, dst, |
|
- | 541 | x_src + box.x1, y_src + box.y1, |
|
- | 542 | 0, 0, |
|
- | 543 | x_dst + box.x1, y_dst + box.y1, |
|
- | 544 | box.x2 - box.x1, box.y2 - box.y1); |
|
- | 545 | ||
- | 546 | pixman_image_unref (tmp); |
|
- | 547 | } |
|
- | 548 | } |
|
- | 549 | ||
- | 550 | static int |
|
- | 551 | greater_y (const pixman_point_fixed_t *a, const pixman_point_fixed_t *b) |
|
- | 552 | { |
|
- | 553 | if (a->y == b->y) |
|
- | 554 | return a->x > b->x; |
|
- | 555 | return a->y > b->y; |
|
- | 556 | } |
|
- | 557 | ||
- | 558 | /* |
|
- | 559 | * Note that the definition of this function is a bit odd because |
|
- | 560 | * of the X coordinate space (y increasing downwards). |
|
- | 561 | */ |
|
- | 562 | static int |
|
- | 563 | clockwise (const pixman_point_fixed_t *ref, |
|
- | 564 | const pixman_point_fixed_t *a, |
|
- | 565 | const pixman_point_fixed_t *b) |
|
- | 566 | { |
|
- | 567 | pixman_point_fixed_t ad, bd; |
|
- | 568 | ||
- | 569 | ad.x = a->x - ref->x; |
|
- | 570 | ad.y = a->y - ref->y; |
|
- | 571 | bd.x = b->x - ref->x; |
|
- | 572 | bd.y = b->y - ref->y; |
|
- | 573 | ||
- | 574 | return ((pixman_fixed_32_32_t) bd.y * ad.x - |
|
- | 575 | (pixman_fixed_32_32_t) ad.y * bd.x) < 0; |
|
- | 576 | } |
|
- | 577 | ||
- | 578 | static void |
|
- | 579 | triangle_to_trapezoids (const pixman_triangle_t *tri, pixman_trapezoid_t *traps) |
|
- | 580 | { |
|
- | 581 | const pixman_point_fixed_t *top, *left, *right, *tmp; |
|
- | 582 | ||
- | 583 | top = &tri->p1; |
|
- | 584 | left = &tri->p2; |
|
- | 585 | right = &tri->p3; |
|
- | 586 | ||
- | 587 | if (greater_y (top, left)) |
|
- | 588 | { |
|
- | 589 | tmp = left; |
|
- | 590 | left = top; |
|
- | 591 | top = tmp; |
|
- | 592 | } |
|
- | 593 | ||
- | 594 | if (greater_y (top, right)) |
|
- | 595 | { |
|
- | 596 | tmp = right; |
|
- | 597 | right = top; |
|
- | 598 | top = tmp; |
|
- | 599 | } |
|
- | 600 | ||
- | 601 | if (clockwise (top, right, left)) |
|
- | 602 | { |
|
- | 603 | tmp = right; |
|
- | 604 | right = left; |
|
- | 605 | left = tmp; |
|
- | 606 | } |
|
- | 607 | ||
- | 608 | /* |
|
- | 609 | * Two cases: |
|
- | 610 | * |
|
- | 611 | * + + |
|
- | 612 | * / \ / \ |
|
- | 613 | * / \ / \ |
|
- | 614 | * / + + \ |
|
- | 615 | * / -- -- \ |
|
- | 616 | * / -- -- \ |
|
- | 617 | * / --- --- \ |
|
- | 618 | * +-- --+ |
|
- | 619 | */ |
|
- | 620 | ||
- | 621 | traps->top = top->y; |
|
- | 622 | traps->left.p1 = *top; |
|
- | 623 | traps->left.p2 = *left; |
|
- | 624 | traps->right.p1 = *top; |
|
- | 625 | traps->right.p2 = *right; |
|
- | 626 | ||
- | 627 | if (right->y < left->y) |
|
- | 628 | traps->bottom = right->y; |
|
- | 629 | else |
|
- | 630 | traps->bottom = left->y; |
|
- | 631 | ||
- | 632 | traps++; |
|
- | 633 | ||
- | 634 | *traps = *(traps - 1); |
|
- | 635 | ||
- | 636 | if (right->y < left->y) |
|
- | 637 | { |
|
- | 638 | traps->top = right->y; |
|
- | 639 | traps->bottom = left->y; |
|
- | 640 | traps->right.p1 = *right; |
|
- | 641 | traps->right.p2 = *left; |
|
- | 642 | } |
|
- | 643 | else |
|
- | 644 | { |
|
- | 645 | traps->top = left->y; |
|
- | 646 | traps->bottom = right->y; |
|
- | 647 | traps->left.p1 = *left; |
|
- | 648 | traps->left.p2 = *right; |
|
- | 649 | } |
|
- | 650 | } |
|
- | 651 | ||
- | 652 | static pixman_trapezoid_t * |
|
- | 653 | convert_triangles (int n_tris, const pixman_triangle_t *tris) |
|
- | 654 | { |
|
- | 655 | pixman_trapezoid_t *traps; |
|
- | 656 | int i; |
|
- | 657 | ||
- | 658 | if (n_tris <= 0) |
|
- | 659 | return NULL; |
|
- | 660 | ||
- | 661 | traps = pixman_malloc_ab (n_tris, 2 * sizeof (pixman_trapezoid_t)); |
|
- | 662 | if (!traps) |
|
- | 663 | return NULL; |
|
- | 664 | ||
- | 665 | for (i = 0; i < n_tris; ++i) |
|
- | 666 | triangle_to_trapezoids (&(tris[i]), traps + 2 * i); |
|
- | 667 | ||
- | 668 | return traps; |
|
- | 669 | } |
|
- | 670 | ||
- | 671 | PIXMAN_EXPORT void |
|
- | 672 | pixman_composite_triangles (pixman_op_t op, |
|
- | 673 | pixman_image_t * src, |
|
- | 674 | pixman_image_t * dst, |
|
- | 675 | pixman_format_code_t mask_format, |
|
- | 676 | int x_src, |
|
- | 677 | int y_src, |
|
- | 678 | int x_dst, |
|
- | 679 | int y_dst, |
|
- | 680 | int n_tris, |
|
- | 681 | const pixman_triangle_t * tris) |
|
- | 682 | { |
|
- | 683 | pixman_trapezoid_t *traps; |
|
- | 684 | ||
- | 685 | if ((traps = convert_triangles (n_tris, tris))) |
|
- | 686 | { |
|
- | 687 | pixman_composite_trapezoids (op, src, dst, mask_format, |
|
- | 688 | x_src, y_src, x_dst, y_dst, |
|
- | 689 | n_tris * 2, traps); |
|
- | 690 | ||
- | 691 | free (traps); |
|
- | 692 | } |
|
- | 693 | } |
|
- | 694 | ||
- | 695 | PIXMAN_EXPORT void |
|
- | 696 | pixman_add_triangles (pixman_image_t *image, |
|
- | 697 | int32_t x_off, |
|
- | 698 | int32_t y_off, |
|
- | 699 | int n_tris, |
|
- | 700 | const pixman_triangle_t *tris) |
|
- | 701 | { |
|
- | 702 | pixman_trapezoid_t *traps; |
|
- | 703 | ||
- | 704 | if ((traps = convert_triangles (n_tris, tris))) |
|
- | 705 | { |
|
- | 706 | pixman_add_trapezoids (image, x_off, y_off, |
|
- | 707 | n_tris * 2, traps); |
|
- | 708 | ||
- | 709 | free (traps); |
|
- | 710 | } |