Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1)

Side by Side Diff: src/gpu/GrTessellatingPathRenderer.cpp

Issue 1089073002: Change tessellator sweep direction to depend on path aspect ratio. (Closed) Base URL: https://skia.googlesource.com/skia.git@master
Patch Set: Fix formatting Created 5 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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
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
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
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
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
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
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 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698