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 |