| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2015 Google Inc. | 2 * Copyright 2015 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "GrTessellatingPathRenderer.h" | 8 #include "GrTessellatingPathRenderer.h" |
| 9 | 9 |
| 10 #include "GrBatch.h" | 10 #include "GrBatch.h" |
| (...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 60 * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Not
e that it | 60 * Equivalent Problems" (Fournier and Montuno); also a line-sweep algorithm. Not
e that it |
| 61 * currently uses a linked list for the active edge list, rather than a 2-3 tree
as the | 61 * currently uses a linked list for the active edge list, rather than a 2-3 tree
as the |
| 62 * paper describes. The 2-3 tree gives O(lg N) lookups, but insertion and remova
l also | 62 * paper describes. The 2-3 tree gives O(lg N) lookups, but insertion and remova
l also |
| 63 * become O(lg N). In all the test cases, it was found that the cost of frequent
O(lg N) | 63 * become O(lg N). In all the test cases, it was found that the cost of frequent
O(lg N) |
| 64 * insertions and removals was greater than the cost of infrequent O(N) lookups
with the | 64 * insertions and removals was greater than the cost of infrequent O(N) lookups
with the |
| 65 * linked list implementation. With the latter, all removals are O(1), and most
insertions | 65 * linked list implementation. With the latter, all removals are O(1), and most
insertions |
| 66 * are O(1), since we know the adjacent edge in the active edge list based on th
e topology. | 66 * are O(1), since we know the adjacent edge in the active edge list based on th
e topology. |
| 67 * Only type 2 vertices (see paper) require the O(N) lookups, and these are much
less | 67 * Only type 2 vertices (see paper) require the O(N) lookups, and these are much
less |
| 68 * frequent. There may be other data structures worth investigating, however. | 68 * frequent. There may be other data structures worth investigating, however. |
| 69 * | 69 * |
| 70 * Note that there is a compile-time flag (SWEEP_IN_X) which changes the orienta
tion of the | 70 * Note that the orientation of the line sweep algorithms is determined by the a
spect ratio of the |
| 71 * line sweep algorithms. When SWEEP_IN_X is unset, we sort vertices based on in
creasing | 71 * path bounds. When the path is taller than it is wide, we sort vertices based
on increasing Y |
| 72 * Y coordinate, and secondarily by increasing X coordinate. When SWEEP_IN_X is
set, we sort by | 72 * coordinate, and secondarily by increasing X coordinate. When the path is wide
r than it is tall, |
| 73 * increasing X coordinate, but secondarily by *decreasing* Y coordinate. This i
s so that the | 73 * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordin
ate. This is so |
| 74 * "left" and "right" orientation in the code remains correct (edges to the left
are increasing | 74 * that the "left" and "right" orientation in the code remains correct (edges to
the left are |
| 75 * in Y; edges to the right are decreasing in Y). That is, the setting rotates 9
0 degrees | 75 * increasing in Y; edges to the right are decreasing in Y). That is, the settin
g rotates 90 |
| 76 * counterclockwise, rather that transposing. | 76 * degrees counterclockwise, rather that transposing. |
| 77 * | |
| 78 * The choice is arbitrary, but most test cases are wider than they are tall, so
the | |
| 79 * default is to sweep in X. In the future, we may want to make this a runtime p
arameter | |
| 80 * and base it on the aspect ratio of the clip bounds. | |
| 81 */ | 77 */ |
| 82 #define LOGGING_ENABLED 0 | 78 #define LOGGING_ENABLED 0 |
| 83 #define WIREFRAME 0 | 79 #define WIREFRAME 0 |
| 84 #define SWEEP_IN_X 1 | |
| 85 | 80 |
| 86 #if LOGGING_ENABLED | 81 #if LOGGING_ENABLED |
| 87 #define LOG printf | 82 #define LOG printf |
| 88 #else | 83 #else |
| 89 #define LOG(...) | 84 #define LOG(...) |
| 90 #endif | 85 #endif |
| 91 | 86 |
| 92 #define ALLOC_NEW(Type, args, alloc) \ | 87 #define ALLOC_NEW(Type, args, alloc) \ |
| 93 SkNEW_PLACEMENT_ARGS(alloc.allocThrow(sizeof(Type)), Type, args) | 88 SkNEW_PLACEMENT_ARGS(alloc.allocThrow(sizeof(Type)), Type, args) |
| 94 | 89 |
| (...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 158 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex. | 153 Edge* fFirstEdgeBelow; // Linked list of edges below this vertex. |
| 159 Edge* fLastEdgeBelow; // " | 154 Edge* fLastEdgeBelow; // " |
| 160 bool fProcessed; // Has this vertex been seen in simplify()? | 155 bool fProcessed; // Has this vertex been seen in simplify()? |
| 161 #if LOGGING_ENABLED | 156 #if LOGGING_ENABLED |
| 162 float fID; // Identifier used for logging. | 157 float fID; // Identifier used for logging. |
| 163 #endif | 158 #endif |
| 164 }; | 159 }; |
| 165 | 160 |
| 166 /*******************************************************************************
********/ | 161 /*******************************************************************************
********/ |
| 167 | 162 |
| 168 bool sweep_lt(const SkPoint& a, const SkPoint& b) { | 163 typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b); |
| 169 #if SWEEP_IN_X | 164 |
| 165 struct Comparator { |
| 166 CompareFunc sweep_lt; |
| 167 CompareFunc sweep_gt; |
| 168 }; |
| 169 |
| 170 bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) { |
| 170 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX; | 171 return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX; |
| 171 #else | |
| 172 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY; | |
| 173 #endif | |
| 174 } | 172 } |
| 175 | 173 |
| 176 bool sweep_gt(const SkPoint& a, const SkPoint& b) { | 174 bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) { |
| 177 #if SWEEP_IN_X | 175 return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY; |
| 176 } |
| 177 |
| 178 bool sweep_gt_horiz(const SkPoint& a, const SkPoint& b) { |
| 178 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX; | 179 return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX; |
| 179 #else | 180 } |
| 181 |
| 182 bool sweep_gt_vert(const SkPoint& a, const SkPoint& b) { |
| 180 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY; | 183 return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY; |
| 181 #endif | |
| 182 } | 184 } |
| 183 | 185 |
| 184 inline void* emit_vertex(Vertex* v, void* data) { | 186 inline void* emit_vertex(Vertex* v, void* data) { |
| 185 SkPoint* d = static_cast<SkPoint*>(data); | 187 SkPoint* d = static_cast<SkPoint*>(data); |
| 186 *d++ = v->fPoint; | 188 *d++ = v->fPoint; |
| 187 return d; | 189 return d; |
| 188 } | 190 } |
| 189 | 191 |
| 190 void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, void* data) { | 192 void* emit_triangle(Vertex* v0, Vertex* v1, Vertex* v2, void* data) { |
| 191 #if WIREFRAME | 193 #if WIREFRAME |
| (...skipping 426 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 618 case SkPath::kInverseWinding_FillType: | 620 case SkPath::kInverseWinding_FillType: |
| 619 return winding == 1; | 621 return winding == 1; |
| 620 case SkPath::kInverseEvenOdd_FillType: | 622 case SkPath::kInverseEvenOdd_FillType: |
| 621 return (winding & 1) == 1; | 623 return (winding & 1) == 1; |
| 622 default: | 624 default: |
| 623 SkASSERT(false); | 625 SkASSERT(false); |
| 624 return false; | 626 return false; |
| 625 } | 627 } |
| 626 } | 628 } |
| 627 | 629 |
| 628 Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc) { | 630 Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c) { |
| 629 int winding = sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1; | 631 int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1; |
| 630 Vertex* top = winding < 0 ? next : prev; | 632 Vertex* top = winding < 0 ? next : prev; |
| 631 Vertex* bottom = winding < 0 ? prev : next; | 633 Vertex* bottom = winding < 0 ? prev : next; |
| 632 return ALLOC_NEW(Edge, (top, bottom, winding), alloc); | 634 return ALLOC_NEW(Edge, (top, bottom, winding), alloc); |
| 633 } | 635 } |
| 634 | 636 |
| 635 void remove_edge(Edge* edge, Edge** head) { | 637 void remove_edge(Edge* edge, Edge** head) { |
| 636 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); | 638 LOG("removing edge %g -> %g\n", edge->fTop->fID, edge->fBottom->fID); |
| 637 SkASSERT(edge->isActive(head)); | 639 SkASSERT(edge->isActive(head)); |
| 638 remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, head, NULL); | 640 remove<Edge, &Edge::fLeft, &Edge::fRight>(edge, head, NULL); |
| 639 } | 641 } |
| (...skipping 17 matching lines...) Expand all Loading... |
| 657 if (next->isRightOf(v)) { | 659 if (next->isRightOf(v)) { |
| 658 break; | 660 break; |
| 659 } | 661 } |
| 660 prev = next; | 662 prev = next; |
| 661 } | 663 } |
| 662 *left = prev; | 664 *left = prev; |
| 663 *right = next; | 665 *right = next; |
| 664 return; | 666 return; |
| 665 } | 667 } |
| 666 | 668 |
| 667 void find_enclosing_edges(Edge* edge, Edge* head, Edge** left, Edge** right) { | 669 void find_enclosing_edges(Edge* edge, Edge* head, Comparator& c, Edge** left, Ed
ge** right) { |
| 668 Edge* prev = NULL; | 670 Edge* prev = NULL; |
| 669 Edge* next; | 671 Edge* next; |
| 670 for (next = head; next != NULL; next = next->fRight) { | 672 for (next = head; next != NULL; next = next->fRight) { |
| 671 if ((sweep_gt(edge->fTop->fPoint, next->fTop->fPoint) && next->isRightOf
(edge->fTop)) || | 673 if ((c.sweep_gt(edge->fTop->fPoint, next->fTop->fPoint) && next->isRight
Of(edge->fTop)) || |
| 672 (sweep_gt(next->fTop->fPoint, edge->fTop->fPoint) && edge->isLeftOf(
next->fTop)) || | 674 (c.sweep_gt(next->fTop->fPoint, edge->fTop->fPoint) && edge->isLeftO
f(next->fTop)) || |
| 673 (sweep_lt(edge->fBottom->fPoint, next->fBottom->fPoint) && | 675 (c.sweep_lt(edge->fBottom->fPoint, next->fBottom->fPoint) && |
| 674 next->isRightOf(edge->fBottom)) || | 676 next->isRightOf(edge->fBottom)) || |
| 675 (sweep_lt(next->fBottom->fPoint, edge->fBottom->fPoint) && | 677 (c.sweep_lt(next->fBottom->fPoint, edge->fBottom->fPoint) && |
| 676 edge->isLeftOf(next->fBottom))) { | 678 edge->isLeftOf(next->fBottom))) { |
| 677 break; | 679 break; |
| 678 } | 680 } |
| 679 prev = next; | 681 prev = next; |
| 680 } | 682 } |
| 681 *left = prev; | 683 *left = prev; |
| 682 *right = next; | 684 *right = next; |
| 683 return; | 685 return; |
| 684 } | 686 } |
| 685 | 687 |
| 686 void fix_active_state(Edge* edge, Edge** activeEdges) { | 688 void fix_active_state(Edge* edge, Edge** activeEdges, Comparator& c) { |
| 687 if (edge->isActive(activeEdges)) { | 689 if (edge->isActive(activeEdges)) { |
| 688 if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) { | 690 if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) { |
| 689 remove_edge(edge, activeEdges); | 691 remove_edge(edge, activeEdges); |
| 690 } | 692 } |
| 691 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) { | 693 } else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) { |
| 692 Edge* left; | 694 Edge* left; |
| 693 Edge* right; | 695 Edge* right; |
| 694 find_enclosing_edges(edge, *activeEdges, &left, &right); | 696 find_enclosing_edges(edge, *activeEdges, c, &left, &right); |
| 695 insert_edge(edge, left, activeEdges); | 697 insert_edge(edge, left, activeEdges); |
| 696 } | 698 } |
| 697 } | 699 } |
| 698 | 700 |
| 699 void insert_edge_above(Edge* edge, Vertex* v) { | 701 void insert_edge_above(Edge* edge, Vertex* v, Comparator& c) { |
| 700 if (edge->fTop->fPoint == edge->fBottom->fPoint || | 702 if (edge->fTop->fPoint == edge->fBottom->fPoint || |
| 701 sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) { | 703 c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) { |
| 702 return; | 704 return; |
| 703 } | 705 } |
| 704 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBott
om->fID, v->fID); | 706 LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBott
om->fID, v->fID); |
| 705 Edge* prev = NULL; | 707 Edge* prev = NULL; |
| 706 Edge* next; | 708 Edge* next; |
| 707 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) { | 709 for (next = v->fFirstEdgeAbove; next; next = next->fNextEdgeAbove) { |
| 708 if (next->isRightOf(edge->fTop)) { | 710 if (next->isRightOf(edge->fTop)) { |
| 709 break; | 711 break; |
| 710 } | 712 } |
| 711 prev = next; | 713 prev = next; |
| 712 } | 714 } |
| 713 insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>( | 715 insert<Edge, &Edge::fPrevEdgeAbove, &Edge::fNextEdgeAbove>( |
| 714 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove); | 716 edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove); |
| 715 } | 717 } |
| 716 | 718 |
| 717 void insert_edge_below(Edge* edge, Vertex* v) { | 719 void insert_edge_below(Edge* edge, Vertex* v, Comparator& c) { |
| 718 if (edge->fTop->fPoint == edge->fBottom->fPoint || | 720 if (edge->fTop->fPoint == edge->fBottom->fPoint || |
| 719 sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) { | 721 c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) { |
| 720 return; | 722 return; |
| 721 } | 723 } |
| 722 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBott
om->fID, v->fID); | 724 LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBott
om->fID, v->fID); |
| 723 Edge* prev = NULL; | 725 Edge* prev = NULL; |
| 724 Edge* next; | 726 Edge* next; |
| 725 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) { | 727 for (next = v->fFirstEdgeBelow; next; next = next->fNextEdgeBelow) { |
| 726 if (next->isRightOf(edge->fBottom)) { | 728 if (next->isRightOf(edge->fBottom)) { |
| 727 break; | 729 break; |
| 728 } | 730 } |
| 729 prev = next; | 731 prev = next; |
| (...skipping 21 matching lines...) Expand all Loading... |
| 751 return; | 753 return; |
| 752 } | 754 } |
| 753 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID); | 755 LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID); |
| 754 remove_edge_above(edge); | 756 remove_edge_above(edge); |
| 755 remove_edge_below(edge); | 757 remove_edge_below(edge); |
| 756 if (edge->isActive(head)) { | 758 if (edge->isActive(head)) { |
| 757 remove_edge(edge, head); | 759 remove_edge(edge, head); |
| 758 } | 760 } |
| 759 } | 761 } |
| 760 | 762 |
| 761 void merge_collinear_edges(Edge* edge, Edge** activeEdges); | 763 void merge_collinear_edges(Edge* edge, Edge** activeEdges, Comparator& c); |
| 762 | 764 |
| 763 void set_top(Edge* edge, Vertex* v, Edge** activeEdges) { | 765 void set_top(Edge* edge, Vertex* v, Edge** activeEdges, Comparator& c) { |
| 764 remove_edge_below(edge); | 766 remove_edge_below(edge); |
| 765 edge->fTop = v; | 767 edge->fTop = v; |
| 766 edge->recompute(); | 768 edge->recompute(); |
| 767 insert_edge_below(edge, v); | 769 insert_edge_below(edge, v, c); |
| 768 fix_active_state(edge, activeEdges); | 770 fix_active_state(edge, activeEdges, c); |
| 769 merge_collinear_edges(edge, activeEdges); | 771 merge_collinear_edges(edge, activeEdges, c); |
| 770 } | 772 } |
| 771 | 773 |
| 772 void set_bottom(Edge* edge, Vertex* v, Edge** activeEdges) { | 774 void set_bottom(Edge* edge, Vertex* v, Edge** activeEdges, Comparator& c) { |
| 773 remove_edge_above(edge); | 775 remove_edge_above(edge); |
| 774 edge->fBottom = v; | 776 edge->fBottom = v; |
| 775 edge->recompute(); | 777 edge->recompute(); |
| 776 insert_edge_above(edge, v); | 778 insert_edge_above(edge, v, c); |
| 777 fix_active_state(edge, activeEdges); | 779 fix_active_state(edge, activeEdges, c); |
| 778 merge_collinear_edges(edge, activeEdges); | 780 merge_collinear_edges(edge, activeEdges, c); |
| 779 } | 781 } |
| 780 | 782 |
| 781 void merge_edges_above(Edge* edge, Edge* other, Edge** activeEdges) { | 783 void merge_edges_above(Edge* edge, Edge* other, Edge** activeEdges, Comparator&
c) { |
| 782 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) { | 784 if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) { |
| 783 LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n", | 785 LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n", |
| 784 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY, | 786 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY, |
| 785 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY); | 787 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY); |
| 786 other->fWinding += edge->fWinding; | 788 other->fWinding += edge->fWinding; |
| 787 erase_edge_if_zero_winding(other, activeEdges); | 789 erase_edge_if_zero_winding(other, activeEdges); |
| 788 edge->fWinding = 0; | 790 edge->fWinding = 0; |
| 789 erase_edge_if_zero_winding(edge, activeEdges); | 791 erase_edge_if_zero_winding(edge, activeEdges); |
| 790 } else if (sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) { | 792 } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) { |
| 791 other->fWinding += edge->fWinding; | 793 other->fWinding += edge->fWinding; |
| 792 erase_edge_if_zero_winding(other, activeEdges); | 794 erase_edge_if_zero_winding(other, activeEdges); |
| 793 set_bottom(edge, other->fTop, activeEdges); | 795 set_bottom(edge, other->fTop, activeEdges, c); |
| 794 } else { | 796 } else { |
| 795 edge->fWinding += other->fWinding; | 797 edge->fWinding += other->fWinding; |
| 796 erase_edge_if_zero_winding(edge, activeEdges); | 798 erase_edge_if_zero_winding(edge, activeEdges); |
| 797 set_bottom(other, edge->fTop, activeEdges); | 799 set_bottom(other, edge->fTop, activeEdges, c); |
| 798 } | 800 } |
| 799 } | 801 } |
| 800 | 802 |
| 801 void merge_edges_below(Edge* edge, Edge* other, Edge** activeEdges) { | 803 void merge_edges_below(Edge* edge, Edge* other, Edge** activeEdges, Comparator&
c) { |
| 802 if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) { | 804 if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) { |
| 803 LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n", | 805 LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n", |
| 804 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY, | 806 edge->fTop->fPoint.fX, edge->fTop->fPoint.fY, |
| 805 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY); | 807 edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY); |
| 806 other->fWinding += edge->fWinding; | 808 other->fWinding += edge->fWinding; |
| 807 erase_edge_if_zero_winding(other, activeEdges); | 809 erase_edge_if_zero_winding(other, activeEdges); |
| 808 edge->fWinding = 0; | 810 edge->fWinding = 0; |
| 809 erase_edge_if_zero_winding(edge, activeEdges); | 811 erase_edge_if_zero_winding(edge, activeEdges); |
| 810 } else if (sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) { | 812 } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) { |
| 811 edge->fWinding += other->fWinding; | 813 edge->fWinding += other->fWinding; |
| 812 erase_edge_if_zero_winding(edge, activeEdges); | 814 erase_edge_if_zero_winding(edge, activeEdges); |
| 813 set_top(other, edge->fBottom, activeEdges); | 815 set_top(other, edge->fBottom, activeEdges, c); |
| 814 } else { | 816 } else { |
| 815 other->fWinding += edge->fWinding; | 817 other->fWinding += edge->fWinding; |
| 816 erase_edge_if_zero_winding(other, activeEdges); | 818 erase_edge_if_zero_winding(other, activeEdges); |
| 817 set_top(edge, other->fBottom, activeEdges); | 819 set_top(edge, other->fBottom, activeEdges, c); |
| 818 } | 820 } |
| 819 } | 821 } |
| 820 | 822 |
| 821 void merge_collinear_edges(Edge* edge, Edge** activeEdges) { | 823 void merge_collinear_edges(Edge* edge, Edge** activeEdges, Comparator& c) { |
| 822 if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop || | 824 if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop || |
| 823 !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) { | 825 !edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) { |
| 824 merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges); | 826 merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges, c); |
| 825 } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop
|| | 827 } else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop
|| |
| 826 !edge->isLeftOf(edge->fNextEdgeAbove->fT
op))) { | 828 !edge->isLeftOf(edge->fNextEdgeAbove->fT
op))) { |
| 827 merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges); | 829 merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges, c); |
| 828 } | 830 } |
| 829 if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom
|| | 831 if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom
|| |
| 830 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))
) { | 832 !edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))
) { |
| 831 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges); | 833 merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, c); |
| 832 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->f
Bottom || | 834 } else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->f
Bottom || |
| 833 !edge->isLeftOf(edge->fNextEdgeBelow->fB
ottom))) { | 835 !edge->isLeftOf(edge->fNextEdgeBelow->fB
ottom))) { |
| 834 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges); | 836 merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, c); |
| 835 } | 837 } |
| 836 } | 838 } |
| 837 | 839 |
| 838 void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc); | 840 void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, Comparator& c, SkChun
kAlloc& alloc); |
| 839 | 841 |
| 840 void cleanup_active_edges(Edge* edge, Edge** activeEdges, SkChunkAlloc& alloc) { | 842 void cleanup_active_edges(Edge* edge, Edge** activeEdges, Comparator& c, SkChunk
Alloc& alloc) { |
| 841 Vertex* top = edge->fTop; | 843 Vertex* top = edge->fTop; |
| 842 Vertex* bottom = edge->fBottom; | 844 Vertex* bottom = edge->fBottom; |
| 843 if (edge->fLeft) { | 845 if (edge->fLeft) { |
| 844 Vertex* leftTop = edge->fLeft->fTop; | 846 Vertex* leftTop = edge->fLeft->fTop; |
| 845 Vertex* leftBottom = edge->fLeft->fBottom; | 847 Vertex* leftBottom = edge->fLeft->fBottom; |
| 846 if (sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(top
)) { | 848 if (c.sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(t
op)) { |
| 847 split_edge(edge->fLeft, edge->fTop, activeEdges, alloc); | 849 split_edge(edge->fLeft, edge->fTop, activeEdges, c, alloc); |
| 848 } else if (sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(le
ftTop)) { | 850 } else if (c.sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(
leftTop)) { |
| 849 split_edge(edge, leftTop, activeEdges, alloc); | 851 split_edge(edge, leftTop, activeEdges, c, alloc); |
| 850 } else if (sweep_lt(bottom->fPoint, leftBottom->fPoint) && !edge->fLeft-
>isLeftOf(bottom)) { | 852 } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) && |
| 851 split_edge(edge->fLeft, bottom, activeEdges, alloc); | 853 !edge->fLeft->isLeftOf(bottom)) { |
| 852 } else if (sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRigh
tOf(leftBottom)) { | 854 split_edge(edge->fLeft, bottom, activeEdges, c, alloc); |
| 853 split_edge(edge, leftBottom, activeEdges, alloc); | 855 } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRi
ghtOf(leftBottom)) { |
| 856 split_edge(edge, leftBottom, activeEdges, c, alloc); |
| 854 } | 857 } |
| 855 } | 858 } |
| 856 if (edge->fRight) { | 859 if (edge->fRight) { |
| 857 Vertex* rightTop = edge->fRight->fTop; | 860 Vertex* rightTop = edge->fRight->fTop; |
| 858 Vertex* rightBottom = edge->fRight->fBottom; | 861 Vertex* rightBottom = edge->fRight->fBottom; |
| 859 if (sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightOf(
top)) { | 862 if (c.sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightO
f(top)) { |
| 860 split_edge(edge->fRight, top, activeEdges, alloc); | 863 split_edge(edge->fRight, top, activeEdges, c, alloc); |
| 861 } else if (sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(ri
ghtTop)) { | 864 } else if (c.sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(
rightTop)) { |
| 862 split_edge(edge, rightTop, activeEdges, alloc); | 865 split_edge(edge, rightTop, activeEdges, c, alloc); |
| 863 } else if (sweep_lt(bottom->fPoint, rightBottom->fPoint) && | 866 } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) && |
| 864 !edge->fRight->isRightOf(bottom)) { | 867 !edge->fRight->isRightOf(bottom)) { |
| 865 split_edge(edge->fRight, bottom, activeEdges, alloc); | 868 split_edge(edge->fRight, bottom, activeEdges, c, alloc); |
| 866 } else if (sweep_lt(rightBottom->fPoint, bottom->fPoint) && | 869 } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) && |
| 867 !edge->isLeftOf(rightBottom)) { | 870 !edge->isLeftOf(rightBottom)) { |
| 868 split_edge(edge, rightBottom, activeEdges, alloc); | 871 split_edge(edge, rightBottom, activeEdges, c, alloc); |
| 869 } | 872 } |
| 870 } | 873 } |
| 871 } | 874 } |
| 872 | 875 |
| 873 void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc)
{ | 876 void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, Comparator& c, SkChun
kAlloc& alloc) { |
| 874 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n", | 877 LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n", |
| 875 edge->fTop->fID, edge->fBottom->fID, | 878 edge->fTop->fID, edge->fBottom->fID, |
| 876 v->fID, v->fPoint.fX, v->fPoint.fY); | 879 v->fID, v->fPoint.fX, v->fPoint.fY); |
| 877 if (sweep_lt(v->fPoint, edge->fTop->fPoint)) { | 880 if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) { |
| 878 set_top(edge, v, activeEdges); | 881 set_top(edge, v, activeEdges, c); |
| 879 } else if (sweep_gt(v->fPoint, edge->fBottom->fPoint)) { | 882 } else if (c.sweep_gt(v->fPoint, edge->fBottom->fPoint)) { |
| 880 set_bottom(edge, v, activeEdges); | 883 set_bottom(edge, v, activeEdges, c); |
| 881 } else { | 884 } else { |
| 882 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), allo
c); | 885 Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), allo
c); |
| 883 insert_edge_below(newEdge, v); | 886 insert_edge_below(newEdge, v, c); |
| 884 insert_edge_above(newEdge, edge->fBottom); | 887 insert_edge_above(newEdge, edge->fBottom, c); |
| 885 set_bottom(edge, v, activeEdges); | 888 set_bottom(edge, v, activeEdges, c); |
| 886 cleanup_active_edges(edge, activeEdges, alloc); | 889 cleanup_active_edges(edge, activeEdges, c, alloc); |
| 887 fix_active_state(newEdge, activeEdges); | 890 fix_active_state(newEdge, activeEdges, c); |
| 888 merge_collinear_edges(newEdge, activeEdges); | 891 merge_collinear_edges(newEdge, activeEdges, c); |
| 889 } | 892 } |
| 890 } | 893 } |
| 891 | 894 |
| 892 void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, SkChunkAlloc& alloc
) { | 895 void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkCh
unkAlloc& alloc) { |
| 893 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX
, src->fPoint.fY, | 896 LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX
, src->fPoint.fY, |
| 894 src->fID, dst->fID); | 897 src->fID, dst->fID); |
| 895 for (Edge* edge = src->fFirstEdgeAbove; edge;) { | 898 for (Edge* edge = src->fFirstEdgeAbove; edge;) { |
| 896 Edge* next = edge->fNextEdgeAbove; | 899 Edge* next = edge->fNextEdgeAbove; |
| 897 set_bottom(edge, dst, NULL); | 900 set_bottom(edge, dst, NULL, c); |
| 898 edge = next; | 901 edge = next; |
| 899 } | 902 } |
| 900 for (Edge* edge = src->fFirstEdgeBelow; edge;) { | 903 for (Edge* edge = src->fFirstEdgeBelow; edge;) { |
| 901 Edge* next = edge->fNextEdgeBelow; | 904 Edge* next = edge->fNextEdgeBelow; |
| 902 set_top(edge, dst, NULL); | 905 set_top(edge, dst, NULL, c); |
| 903 edge = next; | 906 edge = next; |
| 904 } | 907 } |
| 905 remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, NULL); | 908 remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, NULL); |
| 906 } | 909 } |
| 907 | 910 |
| 908 Vertex* check_for_intersection(Edge* edge, Edge* other, Edge** activeEdges, SkCh
unkAlloc& alloc) { | 911 Vertex* check_for_intersection(Edge* edge, Edge* other, Edge** activeEdges, Comp
arator& c, |
| 912 SkChunkAlloc& alloc) { |
| 909 SkPoint p; | 913 SkPoint p; |
| 910 if (!edge || !other) { | 914 if (!edge || !other) { |
| 911 return NULL; | 915 return NULL; |
| 912 } | 916 } |
| 913 if (edge->intersect(*other, &p)) { | 917 if (edge->intersect(*other, &p)) { |
| 914 Vertex* v; | 918 Vertex* v; |
| 915 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY); | 919 LOG("found intersection, pt is %g, %g\n", p.fX, p.fY); |
| 916 if (p == edge->fTop->fPoint || sweep_lt(p, edge->fTop->fPoint)) { | 920 if (p == edge->fTop->fPoint || c.sweep_lt(p, edge->fTop->fPoint)) { |
| 917 split_edge(other, edge->fTop, activeEdges, alloc); | 921 split_edge(other, edge->fTop, activeEdges, c, alloc); |
| 918 v = edge->fTop; | 922 v = edge->fTop; |
| 919 } else if (p == edge->fBottom->fPoint || sweep_gt(p, edge->fBottom->fPoi
nt)) { | 923 } else if (p == edge->fBottom->fPoint || c.sweep_gt(p, edge->fBottom->fP
oint)) { |
| 920 split_edge(other, edge->fBottom, activeEdges, alloc); | 924 split_edge(other, edge->fBottom, activeEdges, c, alloc); |
| 921 v = edge->fBottom; | 925 v = edge->fBottom; |
| 922 } else if (p == other->fTop->fPoint || sweep_lt(p, other->fTop->fPoint))
{ | 926 } else if (p == other->fTop->fPoint || c.sweep_lt(p, other->fTop->fPoint
)) { |
| 923 split_edge(edge, other->fTop, activeEdges, alloc); | 927 split_edge(edge, other->fTop, activeEdges, c, alloc); |
| 924 v = other->fTop; | 928 v = other->fTop; |
| 925 } else if (p == other->fBottom->fPoint || sweep_gt(p, other->fBottom->fP
oint)) { | 929 } else if (p == other->fBottom->fPoint || c.sweep_gt(p, other->fBottom->
fPoint)) { |
| 926 split_edge(edge, other->fBottom, activeEdges, alloc); | 930 split_edge(edge, other->fBottom, activeEdges, c, alloc); |
| 927 v = other->fBottom; | 931 v = other->fBottom; |
| 928 } else { | 932 } else { |
| 929 Vertex* nextV = edge->fTop; | 933 Vertex* nextV = edge->fTop; |
| 930 while (sweep_lt(p, nextV->fPoint)) { | 934 while (c.sweep_lt(p, nextV->fPoint)) { |
| 931 nextV = nextV->fPrev; | 935 nextV = nextV->fPrev; |
| 932 } | 936 } |
| 933 while (sweep_lt(nextV->fPoint, p)) { | 937 while (c.sweep_lt(nextV->fPoint, p)) { |
| 934 nextV = nextV->fNext; | 938 nextV = nextV->fNext; |
| 935 } | 939 } |
| 936 Vertex* prevV = nextV->fPrev; | 940 Vertex* prevV = nextV->fPrev; |
| 937 if (coincident(prevV->fPoint, p)) { | 941 if (coincident(prevV->fPoint, p)) { |
| 938 v = prevV; | 942 v = prevV; |
| 939 } else if (coincident(nextV->fPoint, p)) { | 943 } else if (coincident(nextV->fPoint, p)) { |
| 940 v = nextV; | 944 v = nextV; |
| 941 } else { | 945 } else { |
| 942 v = ALLOC_NEW(Vertex, (p), alloc); | 946 v = ALLOC_NEW(Vertex, (p), alloc); |
| 943 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n", | 947 LOG("inserting between %g (%g, %g) and %g (%g, %g)\n", |
| 944 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY, | 948 prevV->fID, prevV->fPoint.fX, prevV->fPoint.fY, |
| 945 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY); | 949 nextV->fID, nextV->fPoint.fX, nextV->fPoint.fY); |
| 946 #if LOGGING_ENABLED | 950 #if LOGGING_ENABLED |
| 947 v->fID = (nextV->fID + prevV->fID) * 0.5f; | 951 v->fID = (nextV->fID + prevV->fID) * 0.5f; |
| 948 #endif | 952 #endif |
| 949 v->fPrev = prevV; | 953 v->fPrev = prevV; |
| 950 v->fNext = nextV; | 954 v->fNext = nextV; |
| 951 prevV->fNext = v; | 955 prevV->fNext = v; |
| 952 nextV->fPrev = v; | 956 nextV->fPrev = v; |
| 953 } | 957 } |
| 954 split_edge(edge, v, activeEdges, alloc); | 958 split_edge(edge, v, activeEdges, c, alloc); |
| 955 split_edge(other, v, activeEdges, alloc); | 959 split_edge(other, v, activeEdges, c, alloc); |
| 956 } | 960 } |
| 957 return v; | 961 return v; |
| 958 } | 962 } |
| 959 return NULL; | 963 return NULL; |
| 960 } | 964 } |
| 961 | 965 |
| 962 void sanitize_contours(Vertex** contours, int contourCnt) { | 966 void sanitize_contours(Vertex** contours, int contourCnt) { |
| 963 for (int i = 0; i < contourCnt; ++i) { | 967 for (int i = 0; i < contourCnt; ++i) { |
| 964 SkASSERT(contours[i]); | 968 SkASSERT(contours[i]); |
| 965 for (Vertex* v = contours[i];;) { | 969 for (Vertex* v = contours[i];;) { |
| (...skipping 10 matching lines...) Expand all Loading... |
| 976 } | 980 } |
| 977 v = v->fPrev; | 981 v = v->fPrev; |
| 978 } else { | 982 } else { |
| 979 v = v->fNext; | 983 v = v->fNext; |
| 980 if (v == contours[i]) break; | 984 if (v == contours[i]) break; |
| 981 } | 985 } |
| 982 } | 986 } |
| 983 } | 987 } |
| 984 } | 988 } |
| 985 | 989 |
| 986 void merge_coincident_vertices(Vertex** vertices, SkChunkAlloc& alloc) { | 990 void merge_coincident_vertices(Vertex** vertices, Comparator& c, SkChunkAlloc& a
lloc) { |
| 987 for (Vertex* v = (*vertices)->fNext; v != NULL; v = v->fNext) { | 991 for (Vertex* v = (*vertices)->fNext; v != NULL; v = v->fNext) { |
| 988 if (sweep_lt(v->fPoint, v->fPrev->fPoint)) { | 992 if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) { |
| 989 v->fPoint = v->fPrev->fPoint; | 993 v->fPoint = v->fPrev->fPoint; |
| 990 } | 994 } |
| 991 if (coincident(v->fPrev->fPoint, v->fPoint)) { | 995 if (coincident(v->fPrev->fPoint, v->fPoint)) { |
| 992 merge_vertices(v->fPrev, v, vertices, alloc); | 996 merge_vertices(v->fPrev, v, vertices, c, alloc); |
| 993 } | 997 } |
| 994 } | 998 } |
| 995 } | 999 } |
| 996 | 1000 |
| 997 // Stage 2: convert the contours to a mesh of edges connecting the vertices. | 1001 // Stage 2: convert the contours to a mesh of edges connecting the vertices. |
| 998 | 1002 |
| 999 Vertex* build_edges(Vertex** contours, int contourCnt, SkChunkAlloc& alloc) { | 1003 Vertex* build_edges(Vertex** contours, int contourCnt, Comparator& c, SkChunkAll
oc& alloc) { |
| 1000 Vertex* vertices = NULL; | 1004 Vertex* vertices = NULL; |
| 1001 Vertex* prev = NULL; | 1005 Vertex* prev = NULL; |
| 1002 for (int i = 0; i < contourCnt; ++i) { | 1006 for (int i = 0; i < contourCnt; ++i) { |
| 1003 for (Vertex* v = contours[i]; v != NULL;) { | 1007 for (Vertex* v = contours[i]; v != NULL;) { |
| 1004 Vertex* vNext = v->fNext; | 1008 Vertex* vNext = v->fNext; |
| 1005 Edge* edge = new_edge(v->fPrev, v, alloc); | 1009 Edge* edge = new_edge(v->fPrev, v, alloc, c); |
| 1006 if (edge->fWinding > 0) { | 1010 if (edge->fWinding > 0) { |
| 1007 insert_edge_below(edge, v->fPrev); | 1011 insert_edge_below(edge, v->fPrev, c); |
| 1008 insert_edge_above(edge, v); | 1012 insert_edge_above(edge, v, c); |
| 1009 } else { | 1013 } else { |
| 1010 insert_edge_below(edge, v); | 1014 insert_edge_below(edge, v, c); |
| 1011 insert_edge_above(edge, v->fPrev); | 1015 insert_edge_above(edge, v->fPrev, c); |
| 1012 } | 1016 } |
| 1013 merge_collinear_edges(edge, NULL); | 1017 merge_collinear_edges(edge, NULL, c); |
| 1014 if (prev) { | 1018 if (prev) { |
| 1015 prev->fNext = v; | 1019 prev->fNext = v; |
| 1016 v->fPrev = prev; | 1020 v->fPrev = prev; |
| 1017 } else { | 1021 } else { |
| 1018 vertices = v; | 1022 vertices = v; |
| 1019 } | 1023 } |
| 1020 prev = v; | 1024 prev = v; |
| 1021 v = vNext; | 1025 v = vNext; |
| 1022 if (v == contours[i]) break; | 1026 if (v == contours[i]) break; |
| 1023 } | 1027 } |
| 1024 } | 1028 } |
| 1025 if (prev) { | 1029 if (prev) { |
| 1026 prev->fNext = vertices->fPrev = NULL; | 1030 prev->fNext = vertices->fPrev = NULL; |
| 1027 } | 1031 } |
| 1028 return vertices; | 1032 return vertices; |
| 1029 } | 1033 } |
| 1030 | 1034 |
| 1031 // Stage 3: sort the vertices by increasing Y (or X if SWEEP_IN_X is on). | 1035 // Stage 3: sort the vertices by increasing sweep direction. |
| 1032 | 1036 |
| 1033 Vertex* sorted_merge(Vertex* a, Vertex* b); | 1037 Vertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c); |
| 1034 | 1038 |
| 1035 void front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack) { | 1039 void front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack) { |
| 1036 Vertex* fast; | 1040 Vertex* fast; |
| 1037 Vertex* slow; | 1041 Vertex* slow; |
| 1038 if (!v || !v->fNext) { | 1042 if (!v || !v->fNext) { |
| 1039 *pFront = v; | 1043 *pFront = v; |
| 1040 *pBack = NULL; | 1044 *pBack = NULL; |
| 1041 } else { | 1045 } else { |
| 1042 slow = v; | 1046 slow = v; |
| 1043 fast = v->fNext; | 1047 fast = v->fNext; |
| 1044 | 1048 |
| 1045 while (fast != NULL) { | 1049 while (fast != NULL) { |
| 1046 fast = fast->fNext; | 1050 fast = fast->fNext; |
| 1047 if (fast != NULL) { | 1051 if (fast != NULL) { |
| 1048 slow = slow->fNext; | 1052 slow = slow->fNext; |
| 1049 fast = fast->fNext; | 1053 fast = fast->fNext; |
| 1050 } | 1054 } |
| 1051 } | 1055 } |
| 1052 | 1056 |
| 1053 *pFront = v; | 1057 *pFront = v; |
| 1054 *pBack = slow->fNext; | 1058 *pBack = slow->fNext; |
| 1055 slow->fNext->fPrev = NULL; | 1059 slow->fNext->fPrev = NULL; |
| 1056 slow->fNext = NULL; | 1060 slow->fNext = NULL; |
| 1057 } | 1061 } |
| 1058 } | 1062 } |
| 1059 | 1063 |
| 1060 void merge_sort(Vertex** head) { | 1064 void merge_sort(Vertex** head, Comparator& c) { |
| 1061 if (!*head || !(*head)->fNext) { | 1065 if (!*head || !(*head)->fNext) { |
| 1062 return; | 1066 return; |
| 1063 } | 1067 } |
| 1064 | 1068 |
| 1065 Vertex* a; | 1069 Vertex* a; |
| 1066 Vertex* b; | 1070 Vertex* b; |
| 1067 front_back_split(*head, &a, &b); | 1071 front_back_split(*head, &a, &b); |
| 1068 | 1072 |
| 1069 merge_sort(&a); | 1073 merge_sort(&a, c); |
| 1070 merge_sort(&b); | 1074 merge_sort(&b, c); |
| 1071 | 1075 |
| 1072 *head = sorted_merge(a, b); | 1076 *head = sorted_merge(a, b, c); |
| 1073 } | 1077 } |
| 1074 | 1078 |
| 1075 inline void append_vertex(Vertex* v, Vertex** head, Vertex** tail) { | 1079 inline void append_vertex(Vertex* v, Vertex** head, Vertex** tail) { |
| 1076 insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, NULL, head, tail); | 1080 insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, NULL, head, tail); |
| 1077 } | 1081 } |
| 1078 | 1082 |
| 1079 inline void append_vertex_list(Vertex* v, Vertex** head, Vertex** tail) { | 1083 inline void append_vertex_list(Vertex* v, Vertex** head, Vertex** tail) { |
| 1080 insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, v->fNext, head, tai
l); | 1084 insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, v->fNext, head, tai
l); |
| 1081 } | 1085 } |
| 1082 | 1086 |
| 1083 Vertex* sorted_merge(Vertex* a, Vertex* b) { | 1087 Vertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c) { |
| 1084 Vertex* head = NULL; | 1088 Vertex* head = NULL; |
| 1085 Vertex* tail = NULL; | 1089 Vertex* tail = NULL; |
| 1086 | 1090 |
| 1087 while (a && b) { | 1091 while (a && b) { |
| 1088 if (sweep_lt(a->fPoint, b->fPoint)) { | 1092 if (c.sweep_lt(a->fPoint, b->fPoint)) { |
| 1089 Vertex* next = a->fNext; | 1093 Vertex* next = a->fNext; |
| 1090 append_vertex(a, &head, &tail); | 1094 append_vertex(a, &head, &tail); |
| 1091 a = next; | 1095 a = next; |
| 1092 } else { | 1096 } else { |
| 1093 Vertex* next = b->fNext; | 1097 Vertex* next = b->fNext; |
| 1094 append_vertex(b, &head, &tail); | 1098 append_vertex(b, &head, &tail); |
| 1095 b = next; | 1099 b = next; |
| 1096 } | 1100 } |
| 1097 } | 1101 } |
| 1098 if (a) { | 1102 if (a) { |
| 1099 append_vertex_list(a, &head, &tail); | 1103 append_vertex_list(a, &head, &tail); |
| 1100 } | 1104 } |
| 1101 if (b) { | 1105 if (b) { |
| 1102 append_vertex_list(b, &head, &tail); | 1106 append_vertex_list(b, &head, &tail); |
| 1103 } | 1107 } |
| 1104 return head; | 1108 return head; |
| 1105 } | 1109 } |
| 1106 | 1110 |
| 1107 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges. | 1111 // Stage 4: Simplify the mesh by inserting new vertices at intersecting edges. |
| 1108 | 1112 |
| 1109 void simplify(Vertex* vertices, SkChunkAlloc& alloc) { | 1113 void simplify(Vertex* vertices, Comparator& c, SkChunkAlloc& alloc) { |
| 1110 LOG("simplifying complex polygons\n"); | 1114 LOG("simplifying complex polygons\n"); |
| 1111 Edge* activeEdges = NULL; | 1115 Edge* activeEdges = NULL; |
| 1112 for (Vertex* v = vertices; v != NULL; v = v->fNext) { | 1116 for (Vertex* v = vertices; v != NULL; v = v->fNext) { |
| 1113 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { | 1117 if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) { |
| 1114 continue; | 1118 continue; |
| 1115 } | 1119 } |
| 1116 #if LOGGING_ENABLED | 1120 #if LOGGING_ENABLED |
| 1117 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); | 1121 LOG("\nvertex %g: (%g,%g)\n", v->fID, v->fPoint.fX, v->fPoint.fY); |
| 1118 #endif | 1122 #endif |
| 1119 Edge* leftEnclosingEdge = NULL; | 1123 Edge* leftEnclosingEdge = NULL; |
| 1120 Edge* rightEnclosingEdge = NULL; | 1124 Edge* rightEnclosingEdge = NULL; |
| 1121 bool restartChecks; | 1125 bool restartChecks; |
| 1122 do { | 1126 do { |
| 1123 restartChecks = false; | 1127 restartChecks = false; |
| 1124 find_enclosing_edges(v, activeEdges, &leftEnclosingEdge, &rightEnclo
singEdge); | 1128 find_enclosing_edges(v, activeEdges, &leftEnclosingEdge, &rightEnclo
singEdge); |
| 1125 if (v->fFirstEdgeBelow) { | 1129 if (v->fFirstEdgeBelow) { |
| 1126 for (Edge* edge = v->fFirstEdgeBelow; edge != NULL; edge = edge-
>fNextEdgeBelow) { | 1130 for (Edge* edge = v->fFirstEdgeBelow; edge != NULL; edge = edge-
>fNextEdgeBelow) { |
| 1127 if (check_for_intersection(edge, leftEnclosingEdge, &activeE
dges, alloc)) { | 1131 if (check_for_intersection(edge, leftEnclosingEdge, &activeE
dges, c, alloc)) { |
| 1128 restartChecks = true; | 1132 restartChecks = true; |
| 1129 break; | 1133 break; |
| 1130 } | 1134 } |
| 1131 if (check_for_intersection(edge, rightEnclosingEdge, &active
Edges, alloc)) { | 1135 if (check_for_intersection(edge, rightEnclosingEdge, &active
Edges, c, alloc)) { |
| 1132 restartChecks = true; | 1136 restartChecks = true; |
| 1133 break; | 1137 break; |
| 1134 } | 1138 } |
| 1135 } | 1139 } |
| 1136 } else { | 1140 } else { |
| 1137 if (Vertex* pv = check_for_intersection(leftEnclosingEdge, right
EnclosingEdge, | 1141 if (Vertex* pv = check_for_intersection(leftEnclosingEdge, right
EnclosingEdge, |
| 1138 &activeEdges, alloc)) { | 1142 &activeEdges, c, alloc))
{ |
| 1139 if (sweep_lt(pv->fPoint, v->fPoint)) { | 1143 if (c.sweep_lt(pv->fPoint, v->fPoint)) { |
| 1140 v = pv; | 1144 v = pv; |
| 1141 } | 1145 } |
| 1142 restartChecks = true; | 1146 restartChecks = true; |
| 1143 } | 1147 } |
| 1144 | 1148 |
| 1145 } | 1149 } |
| 1146 } while (restartChecks); | 1150 } while (restartChecks); |
| 1147 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) { | 1151 for (Edge* e = v->fFirstEdgeAbove; e; e = e->fNextEdgeAbove) { |
| 1148 remove_edge(e, &activeEdges); | 1152 remove_edge(e, &activeEdges); |
| 1149 } | 1153 } |
| (...skipping 119 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1269 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, | 1273 LOG("%g -> %g, lpoly %d, rpoly %d\n", e->fTop->fID, e->fBottom->fID, |
| 1270 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight
Poly->fID : -1); | 1274 e->fLeftPoly ? e->fLeftPoly->fID : -1, e->fRightPoly ? e->fRight
Poly->fID : -1); |
| 1271 } | 1275 } |
| 1272 #endif | 1276 #endif |
| 1273 } | 1277 } |
| 1274 return polys; | 1278 return polys; |
| 1275 } | 1279 } |
| 1276 | 1280 |
| 1277 // This is a driver function which calls stages 2-5 in turn. | 1281 // This is a driver function which calls stages 2-5 in turn. |
| 1278 | 1282 |
| 1279 Poly* contours_to_polys(Vertex** contours, int contourCnt, SkChunkAlloc& alloc)
{ | 1283 Poly* contours_to_polys(Vertex** contours, int contourCnt, Comparator& c, SkChun
kAlloc& alloc) { |
| 1280 #if LOGGING_ENABLED | 1284 #if LOGGING_ENABLED |
| 1281 for (int i = 0; i < contourCnt; ++i) { | 1285 for (int i = 0; i < contourCnt; ++i) { |
| 1282 Vertex* v = contours[i]; | 1286 Vertex* v = contours[i]; |
| 1283 SkASSERT(v); | 1287 SkASSERT(v); |
| 1284 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); | 1288 LOG("path.moveTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); |
| 1285 for (v = v->fNext; v != contours[i]; v = v->fNext) { | 1289 for (v = v->fNext; v != contours[i]; v = v->fNext) { |
| 1286 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); | 1290 LOG("path.lineTo(%20.20g, %20.20g);\n", v->fPoint.fX, v->fPoint.fY); |
| 1287 } | 1291 } |
| 1288 } | 1292 } |
| 1289 #endif | 1293 #endif |
| 1290 sanitize_contours(contours, contourCnt); | 1294 sanitize_contours(contours, contourCnt); |
| 1291 Vertex* vertices = build_edges(contours, contourCnt, alloc); | 1295 Vertex* vertices = build_edges(contours, contourCnt, c, alloc); |
| 1292 if (!vertices) { | 1296 if (!vertices) { |
| 1293 return NULL; | 1297 return NULL; |
| 1294 } | 1298 } |
| 1295 | 1299 |
| 1296 // Sort vertices in Y (secondarily in X). | 1300 // Sort vertices in Y (secondarily in X). |
| 1297 merge_sort(&vertices); | 1301 merge_sort(&vertices, c); |
| 1298 merge_coincident_vertices(&vertices, alloc); | 1302 merge_coincident_vertices(&vertices, c, alloc); |
| 1299 #if LOGGING_ENABLED | 1303 #if LOGGING_ENABLED |
| 1300 for (Vertex* v = vertices; v != NULL; v = v->fNext) { | 1304 for (Vertex* v = vertices; v != NULL; v = v->fNext) { |
| 1301 static float gID = 0.0f; | 1305 static float gID = 0.0f; |
| 1302 v->fID = gID++; | 1306 v->fID = gID++; |
| 1303 } | 1307 } |
| 1304 #endif | 1308 #endif |
| 1305 simplify(vertices, alloc); | 1309 simplify(vertices, c, alloc); |
| 1306 return tessellate(vertices, alloc); | 1310 return tessellate(vertices, alloc); |
| 1307 } | 1311 } |
| 1308 | 1312 |
| 1309 // Stage 6: Triangulate the monotone polygons into a vertex buffer. | 1313 // Stage 6: Triangulate the monotone polygons into a vertex buffer. |
| 1310 | 1314 |
| 1311 void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, void* data) { | 1315 void* polys_to_triangles(Poly* polys, SkPath::FillType fillType, void* data) { |
| 1312 void* d = data; | 1316 void* d = data; |
| 1313 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1317 for (Poly* poly = polys; poly; poly = poly->fNext) { |
| 1314 if (apply_fill_type(fillType, poly->fWinding)) { | 1318 if (apply_fill_type(fillType, poly->fWinding)) { |
| 1315 d = poly->emit(d); | 1319 d = poly->emit(d); |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1366 // Handle any color overrides | 1370 // Handle any color overrides |
| 1367 if (init.fColorIgnored) { | 1371 if (init.fColorIgnored) { |
| 1368 fColor = GrColor_ILLEGAL; | 1372 fColor = GrColor_ILLEGAL; |
| 1369 } else if (GrColor_ILLEGAL != init.fOverrideColor) { | 1373 } else if (GrColor_ILLEGAL != init.fOverrideColor) { |
| 1370 fColor = init.fOverrideColor; | 1374 fColor = init.fOverrideColor; |
| 1371 } | 1375 } |
| 1372 fPipelineInfo = init; | 1376 fPipelineInfo = init; |
| 1373 } | 1377 } |
| 1374 | 1378 |
| 1375 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) override { | 1379 void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline
) override { |
| 1376 SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, fViewMatrix,
fPath.getBounds()); | 1380 SkRect pathBounds = fPath.getBounds(); |
| 1381 Comparator c; |
| 1382 if (pathBounds.width() > pathBounds.height()) { |
| 1383 c.sweep_lt = sweep_lt_horiz; |
| 1384 c.sweep_gt = sweep_gt_horiz; |
| 1385 } else { |
| 1386 c.sweep_lt = sweep_lt_vert; |
| 1387 c.sweep_gt = sweep_gt_vert; |
| 1388 } |
| 1389 SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, fViewMatrix,
pathBounds); |
| 1377 int contourCnt; | 1390 int contourCnt; |
| 1378 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); | 1391 int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol); |
| 1379 if (maxPts <= 0) { | 1392 if (maxPts <= 0) { |
| 1380 return; | 1393 return; |
| 1381 } | 1394 } |
| 1382 if (maxPts > ((int)SK_MaxU16 + 1)) { | 1395 if (maxPts > ((int)SK_MaxU16 + 1)) { |
| 1383 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); | 1396 SkDebugf("Path not rendered, too many verts (%d)\n", maxPts); |
| 1384 return; | 1397 return; |
| 1385 } | 1398 } |
| 1386 SkPath::FillType fillType = fPath.getFillType(); | 1399 SkPath::FillType fillType = fPath.getFillType(); |
| (...skipping 10 matching lines...) Expand all Loading... |
| 1397 | 1410 |
| 1398 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); | 1411 SkAutoTDeleteArray<Vertex*> contours(SkNEW_ARRAY(Vertex *, contourCnt)); |
| 1399 | 1412 |
| 1400 // For the initial size of the chunk allocator, estimate based on the po
int count: | 1413 // For the initial size of the chunk allocator, estimate based on the po
int count: |
| 1401 // one vertex per point for the initial passes, plus two for the vertice
s in the | 1414 // one vertex per point for the initial passes, plus two for the vertice
s in the |
| 1402 // resulting Polys, since the same point may end up in two Polys. Assum
e minimal | 1415 // resulting Polys, since the same point may end up in two Polys. Assum
e minimal |
| 1403 // connectivity of one Edge per Vertex (will grow for intersections). | 1416 // connectivity of one Edge per Vertex (will grow for intersections). |
| 1404 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); | 1417 SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge))); |
| 1405 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc); | 1418 path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc); |
| 1406 Poly* polys; | 1419 Poly* polys; |
| 1407 polys = contours_to_polys(contours.get(), contourCnt, alloc); | 1420 polys = contours_to_polys(contours.get(), contourCnt, c, alloc); |
| 1408 int count = 0; | 1421 int count = 0; |
| 1409 for (Poly* poly = polys; poly; poly = poly->fNext) { | 1422 for (Poly* poly = polys; poly; poly = poly->fNext) { |
| 1410 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3)
{ | 1423 if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3)
{ |
| 1411 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); | 1424 count += (poly->fCount - 2) * (WIREFRAME ? 6 : 3); |
| 1412 } | 1425 } |
| 1413 } | 1426 } |
| 1414 if (0 == count) { | 1427 if (0 == count) { |
| 1415 return; | 1428 return; |
| 1416 } | 1429 } |
| 1417 | 1430 |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1492 SkMatrix vmi; | 1505 SkMatrix vmi; |
| 1493 if (!viewM.invert(&vmi)) { | 1506 if (!viewM.invert(&vmi)) { |
| 1494 return false; | 1507 return false; |
| 1495 } | 1508 } |
| 1496 vmi.mapRect(&clipBounds); | 1509 vmi.mapRect(&clipBounds); |
| 1497 SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(color, path, viewM
, clipBounds)); | 1510 SkAutoTUnref<GrBatch> batch(TessellatingPathBatch::Create(color, path, viewM
, clipBounds)); |
| 1498 target->drawBatch(pipelineBuilder, batch); | 1511 target->drawBatch(pipelineBuilder, batch); |
| 1499 | 1512 |
| 1500 return true; | 1513 return true; |
| 1501 } | 1514 } |
| OLD | NEW |