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

Unified 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: src/gpu/GrTessellatingPathRenderer.cpp
diff --git a/src/gpu/GrTessellatingPathRenderer.cpp b/src/gpu/GrTessellatingPathRenderer.cpp
index 14176db4ecef0e2b2dbd7c31f2c3ed3658e0a41b..5c3f45e7a478789c362cac49477ce7ee2fea0af8 100644
--- a/src/gpu/GrTessellatingPathRenderer.cpp
+++ b/src/gpu/GrTessellatingPathRenderer.cpp
@@ -67,21 +67,16 @@
* Only type 2 vertices (see paper) require the O(N) lookups, and these are much less
* frequent. There may be other data structures worth investigating, however.
*
- * Note that there is a compile-time flag (SWEEP_IN_X) which changes the orientation of the
- * line sweep algorithms. When SWEEP_IN_X is unset, we sort vertices based on increasing
- * Y coordinate, and secondarily by increasing X coordinate. When SWEEP_IN_X is set, we sort by
- * increasing X coordinate, but secondarily by *decreasing* Y coordinate. This is so that the
- * "left" and "right" orientation in the code remains correct (edges to the left are increasing
- * in Y; edges to the right are decreasing in Y). That is, the setting rotates 90 degrees
- * counterclockwise, rather that transposing.
- *
- * The choice is arbitrary, but most test cases are wider than they are tall, so the
- * default is to sweep in X. In the future, we may want to make this a runtime parameter
- * and base it on the aspect ratio of the clip bounds.
+ * Note that the orientation of the line sweep algorithms is determined by the aspect ratio of the
+ * path bounds. When the path is taller than it is wide, we sort vertices based on increasing Y
+ * coordinate, and secondarily by increasing X coordinate. When the path is wider than it is tall,
+ * we sort by increasing X coordinate, but secondarily by *decreasing* Y coordinate. This is so
+ * that the "left" and "right" orientation in the code remains correct (edges to the left are
+ * increasing in Y; edges to the right are decreasing in Y). That is, the setting rotates 90
+ * degrees counterclockwise, rather that transposing.
*/
#define LOGGING_ENABLED 0
#define WIREFRAME 0
-#define SWEEP_IN_X 1
#if LOGGING_ENABLED
#define LOG printf
@@ -165,20 +160,27 @@ struct Vertex {
/***************************************************************************************/
-bool sweep_lt(const SkPoint& a, const SkPoint& b) {
-#if SWEEP_IN_X
+typedef bool (*CompareFunc)(const SkPoint& a, const SkPoint& b);
+
+struct Comparator {
+ CompareFunc sweep_lt;
+ CompareFunc sweep_gt;
+};
+
+bool sweep_lt_horiz(const SkPoint& a, const SkPoint& b) {
return a.fX == b.fX ? a.fY > b.fY : a.fX < b.fX;
-#else
+}
+
+bool sweep_lt_vert(const SkPoint& a, const SkPoint& b) {
return a.fY == b.fY ? a.fX < b.fX : a.fY < b.fY;
-#endif
}
-bool sweep_gt(const SkPoint& a, const SkPoint& b) {
-#if SWEEP_IN_X
+bool sweep_gt_horiz(const SkPoint& a, const SkPoint& b) {
return a.fX == b.fX ? a.fY < b.fY : a.fX > b.fX;
-#else
+}
+
+bool sweep_gt_vert(const SkPoint& a, const SkPoint& b) {
return a.fY == b.fY ? a.fX > b.fX : a.fY > b.fY;
-#endif
}
inline void* emit_vertex(Vertex* v, void* data) {
@@ -625,8 +627,8 @@ inline bool apply_fill_type(SkPath::FillType fillType, int winding) {
}
}
-Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc) {
- int winding = sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
+Edge* new_edge(Vertex* prev, Vertex* next, SkChunkAlloc& alloc, Comparator& c) {
+ int winding = c.sweep_lt(prev->fPoint, next->fPoint) ? 1 : -1;
Vertex* top = winding < 0 ? next : prev;
Vertex* bottom = winding < 0 ? prev : next;
return ALLOC_NEW(Edge, (top, bottom, winding), alloc);
@@ -664,15 +666,15 @@ void find_enclosing_edges(Vertex* v, Edge* head, Edge** left, Edge** right) {
return;
}
-void find_enclosing_edges(Edge* edge, Edge* head, Edge** left, Edge** right) {
+void find_enclosing_edges(Edge* edge, Edge* head, Comparator& c, Edge** left, Edge** right) {
Edge* prev = NULL;
Edge* next;
for (next = head; next != NULL; next = next->fRight) {
- if ((sweep_gt(edge->fTop->fPoint, next->fTop->fPoint) && next->isRightOf(edge->fTop)) ||
- (sweep_gt(next->fTop->fPoint, edge->fTop->fPoint) && edge->isLeftOf(next->fTop)) ||
- (sweep_lt(edge->fBottom->fPoint, next->fBottom->fPoint) &&
+ if ((c.sweep_gt(edge->fTop->fPoint, next->fTop->fPoint) && next->isRightOf(edge->fTop)) ||
+ (c.sweep_gt(next->fTop->fPoint, edge->fTop->fPoint) && edge->isLeftOf(next->fTop)) ||
+ (c.sweep_lt(edge->fBottom->fPoint, next->fBottom->fPoint) &&
next->isRightOf(edge->fBottom)) ||
- (sweep_lt(next->fBottom->fPoint, edge->fBottom->fPoint) &&
+ (c.sweep_lt(next->fBottom->fPoint, edge->fBottom->fPoint) &&
edge->isLeftOf(next->fBottom))) {
break;
}
@@ -683,7 +685,7 @@ void find_enclosing_edges(Edge* edge, Edge* head, Edge** left, Edge** right) {
return;
}
-void fix_active_state(Edge* edge, Edge** activeEdges) {
+void fix_active_state(Edge* edge, Edge** activeEdges, Comparator& c) {
if (edge->isActive(activeEdges)) {
if (edge->fBottom->fProcessed || !edge->fTop->fProcessed) {
remove_edge(edge, activeEdges);
@@ -691,14 +693,14 @@ void fix_active_state(Edge* edge, Edge** activeEdges) {
} else if (edge->fTop->fProcessed && !edge->fBottom->fProcessed) {
Edge* left;
Edge* right;
- find_enclosing_edges(edge, *activeEdges, &left, &right);
+ find_enclosing_edges(edge, *activeEdges, c, &left, &right);
insert_edge(edge, left, activeEdges);
}
}
-void insert_edge_above(Edge* edge, Vertex* v) {
+void insert_edge_above(Edge* edge, Vertex* v, Comparator& c) {
if (edge->fTop->fPoint == edge->fBottom->fPoint ||
- sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
+ c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
return;
}
LOG("insert edge (%g -> %g) above vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
@@ -714,9 +716,9 @@ void insert_edge_above(Edge* edge, Vertex* v) {
edge, prev, next, &v->fFirstEdgeAbove, &v->fLastEdgeAbove);
}
-void insert_edge_below(Edge* edge, Vertex* v) {
+void insert_edge_below(Edge* edge, Vertex* v, Comparator& c) {
if (edge->fTop->fPoint == edge->fBottom->fPoint ||
- sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
+ c.sweep_gt(edge->fTop->fPoint, edge->fBottom->fPoint)) {
return;
}
LOG("insert edge (%g -> %g) below vertex %g\n", edge->fTop->fID, edge->fBottom->fID, v->fID);
@@ -758,27 +760,27 @@ void erase_edge_if_zero_winding(Edge* edge, Edge** head) {
}
}
-void merge_collinear_edges(Edge* edge, Edge** activeEdges);
+void merge_collinear_edges(Edge* edge, Edge** activeEdges, Comparator& c);
-void set_top(Edge* edge, Vertex* v, Edge** activeEdges) {
+void set_top(Edge* edge, Vertex* v, Edge** activeEdges, Comparator& c) {
remove_edge_below(edge);
edge->fTop = v;
edge->recompute();
- insert_edge_below(edge, v);
- fix_active_state(edge, activeEdges);
- merge_collinear_edges(edge, activeEdges);
+ insert_edge_below(edge, v, c);
+ fix_active_state(edge, activeEdges, c);
+ merge_collinear_edges(edge, activeEdges, c);
}
-void set_bottom(Edge* edge, Vertex* v, Edge** activeEdges) {
+void set_bottom(Edge* edge, Vertex* v, Edge** activeEdges, Comparator& c) {
remove_edge_above(edge);
edge->fBottom = v;
edge->recompute();
- insert_edge_above(edge, v);
- fix_active_state(edge, activeEdges);
- merge_collinear_edges(edge, activeEdges);
+ insert_edge_above(edge, v, c);
+ fix_active_state(edge, activeEdges, c);
+ merge_collinear_edges(edge, activeEdges, c);
}
-void merge_edges_above(Edge* edge, Edge* other, Edge** activeEdges) {
+void merge_edges_above(Edge* edge, Edge* other, Edge** activeEdges, Comparator& c) {
if (coincident(edge->fTop->fPoint, other->fTop->fPoint)) {
LOG("merging coincident above edges (%g, %g) -> (%g, %g)\n",
edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
@@ -787,18 +789,18 @@ void merge_edges_above(Edge* edge, Edge* other, Edge** activeEdges) {
erase_edge_if_zero_winding(other, activeEdges);
edge->fWinding = 0;
erase_edge_if_zero_winding(edge, activeEdges);
- } else if (sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
+ } else if (c.sweep_lt(edge->fTop->fPoint, other->fTop->fPoint)) {
other->fWinding += edge->fWinding;
erase_edge_if_zero_winding(other, activeEdges);
- set_bottom(edge, other->fTop, activeEdges);
+ set_bottom(edge, other->fTop, activeEdges, c);
} else {
edge->fWinding += other->fWinding;
erase_edge_if_zero_winding(edge, activeEdges);
- set_bottom(other, edge->fTop, activeEdges);
+ set_bottom(other, edge->fTop, activeEdges, c);
}
}
-void merge_edges_below(Edge* edge, Edge* other, Edge** activeEdges) {
+void merge_edges_below(Edge* edge, Edge* other, Edge** activeEdges, Comparator& c) {
if (coincident(edge->fBottom->fPoint, other->fBottom->fPoint)) {
LOG("merging coincident below edges (%g, %g) -> (%g, %g)\n",
edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
@@ -807,105 +809,107 @@ void merge_edges_below(Edge* edge, Edge* other, Edge** activeEdges) {
erase_edge_if_zero_winding(other, activeEdges);
edge->fWinding = 0;
erase_edge_if_zero_winding(edge, activeEdges);
- } else if (sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
+ } else if (c.sweep_lt(edge->fBottom->fPoint, other->fBottom->fPoint)) {
edge->fWinding += other->fWinding;
erase_edge_if_zero_winding(edge, activeEdges);
- set_top(other, edge->fBottom, activeEdges);
+ set_top(other, edge->fBottom, activeEdges, c);
} else {
other->fWinding += edge->fWinding;
erase_edge_if_zero_winding(other, activeEdges);
- set_top(edge, other->fBottom, activeEdges);
+ set_top(edge, other->fBottom, activeEdges, c);
}
}
-void merge_collinear_edges(Edge* edge, Edge** activeEdges) {
+void merge_collinear_edges(Edge* edge, Edge** activeEdges, Comparator& c) {
if (edge->fPrevEdgeAbove && (edge->fTop == edge->fPrevEdgeAbove->fTop ||
!edge->fPrevEdgeAbove->isLeftOf(edge->fTop))) {
- merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges);
+ merge_edges_above(edge, edge->fPrevEdgeAbove, activeEdges, c);
} else if (edge->fNextEdgeAbove && (edge->fTop == edge->fNextEdgeAbove->fTop ||
!edge->isLeftOf(edge->fNextEdgeAbove->fTop))) {
- merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges);
+ merge_edges_above(edge, edge->fNextEdgeAbove, activeEdges, c);
}
if (edge->fPrevEdgeBelow && (edge->fBottom == edge->fPrevEdgeBelow->fBottom ||
!edge->fPrevEdgeBelow->isLeftOf(edge->fBottom))) {
- merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges);
+ merge_edges_below(edge, edge->fPrevEdgeBelow, activeEdges, c);
} else if (edge->fNextEdgeBelow && (edge->fBottom == edge->fNextEdgeBelow->fBottom ||
!edge->isLeftOf(edge->fNextEdgeBelow->fBottom))) {
- merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges);
+ merge_edges_below(edge, edge->fNextEdgeBelow, activeEdges, c);
}
}
-void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc);
+void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, Comparator& c, SkChunkAlloc& alloc);
-void cleanup_active_edges(Edge* edge, Edge** activeEdges, SkChunkAlloc& alloc) {
+void cleanup_active_edges(Edge* edge, Edge** activeEdges, Comparator& c, SkChunkAlloc& alloc) {
Vertex* top = edge->fTop;
Vertex* bottom = edge->fBottom;
if (edge->fLeft) {
Vertex* leftTop = edge->fLeft->fTop;
Vertex* leftBottom = edge->fLeft->fBottom;
- if (sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(top)) {
- split_edge(edge->fLeft, edge->fTop, activeEdges, alloc);
- } else if (sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(leftTop)) {
- split_edge(edge, leftTop, activeEdges, alloc);
- } else if (sweep_lt(bottom->fPoint, leftBottom->fPoint) && !edge->fLeft->isLeftOf(bottom)) {
- split_edge(edge->fLeft, bottom, activeEdges, alloc);
- } else if (sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
- split_edge(edge, leftBottom, activeEdges, alloc);
+ if (c.sweep_gt(top->fPoint, leftTop->fPoint) && !edge->fLeft->isLeftOf(top)) {
+ split_edge(edge->fLeft, edge->fTop, activeEdges, c, alloc);
+ } else if (c.sweep_gt(leftTop->fPoint, top->fPoint) && !edge->isRightOf(leftTop)) {
+ split_edge(edge, leftTop, activeEdges, c, alloc);
+ } else if (c.sweep_lt(bottom->fPoint, leftBottom->fPoint) &&
+ !edge->fLeft->isLeftOf(bottom)) {
+ split_edge(edge->fLeft, bottom, activeEdges, c, alloc);
+ } else if (c.sweep_lt(leftBottom->fPoint, bottom->fPoint) && !edge->isRightOf(leftBottom)) {
+ split_edge(edge, leftBottom, activeEdges, c, alloc);
}
}
if (edge->fRight) {
Vertex* rightTop = edge->fRight->fTop;
Vertex* rightBottom = edge->fRight->fBottom;
- if (sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightOf(top)) {
- split_edge(edge->fRight, top, activeEdges, alloc);
- } else if (sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(rightTop)) {
- split_edge(edge, rightTop, activeEdges, alloc);
- } else if (sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
+ if (c.sweep_gt(top->fPoint, rightTop->fPoint) && !edge->fRight->isRightOf(top)) {
+ split_edge(edge->fRight, top, activeEdges, c, alloc);
+ } else if (c.sweep_gt(rightTop->fPoint, top->fPoint) && !edge->isLeftOf(rightTop)) {
+ split_edge(edge, rightTop, activeEdges, c, alloc);
+ } else if (c.sweep_lt(bottom->fPoint, rightBottom->fPoint) &&
!edge->fRight->isRightOf(bottom)) {
- split_edge(edge->fRight, bottom, activeEdges, alloc);
- } else if (sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
+ split_edge(edge->fRight, bottom, activeEdges, c, alloc);
+ } else if (c.sweep_lt(rightBottom->fPoint, bottom->fPoint) &&
!edge->isLeftOf(rightBottom)) {
- split_edge(edge, rightBottom, activeEdges, alloc);
+ split_edge(edge, rightBottom, activeEdges, c, alloc);
}
}
}
-void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, SkChunkAlloc& alloc) {
+void split_edge(Edge* edge, Vertex* v, Edge** activeEdges, Comparator& c, SkChunkAlloc& alloc) {
LOG("splitting edge (%g -> %g) at vertex %g (%g, %g)\n",
edge->fTop->fID, edge->fBottom->fID,
v->fID, v->fPoint.fX, v->fPoint.fY);
- if (sweep_lt(v->fPoint, edge->fTop->fPoint)) {
- set_top(edge, v, activeEdges);
- } else if (sweep_gt(v->fPoint, edge->fBottom->fPoint)) {
- set_bottom(edge, v, activeEdges);
+ if (c.sweep_lt(v->fPoint, edge->fTop->fPoint)) {
+ set_top(edge, v, activeEdges, c);
+ } else if (c.sweep_gt(v->fPoint, edge->fBottom->fPoint)) {
+ set_bottom(edge, v, activeEdges, c);
} else {
Edge* newEdge = ALLOC_NEW(Edge, (v, edge->fBottom, edge->fWinding), alloc);
- insert_edge_below(newEdge, v);
- insert_edge_above(newEdge, edge->fBottom);
- set_bottom(edge, v, activeEdges);
- cleanup_active_edges(edge, activeEdges, alloc);
- fix_active_state(newEdge, activeEdges);
- merge_collinear_edges(newEdge, activeEdges);
+ insert_edge_below(newEdge, v, c);
+ insert_edge_above(newEdge, edge->fBottom, c);
+ set_bottom(edge, v, activeEdges, c);
+ cleanup_active_edges(edge, activeEdges, c, alloc);
+ fix_active_state(newEdge, activeEdges, c);
+ merge_collinear_edges(newEdge, activeEdges, c);
}
}
-void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, SkChunkAlloc& alloc) {
+void merge_vertices(Vertex* src, Vertex* dst, Vertex** head, Comparator& c, SkChunkAlloc& alloc) {
LOG("found coincident verts at %g, %g; merging %g into %g\n", src->fPoint.fX, src->fPoint.fY,
src->fID, dst->fID);
for (Edge* edge = src->fFirstEdgeAbove; edge;) {
Edge* next = edge->fNextEdgeAbove;
- set_bottom(edge, dst, NULL);
+ set_bottom(edge, dst, NULL, c);
edge = next;
}
for (Edge* edge = src->fFirstEdgeBelow; edge;) {
Edge* next = edge->fNextEdgeBelow;
- set_top(edge, dst, NULL);
+ set_top(edge, dst, NULL, c);
edge = next;
}
remove<Vertex, &Vertex::fPrev, &Vertex::fNext>(src, head, NULL);
}
-Vertex* check_for_intersection(Edge* edge, Edge* other, Edge** activeEdges, SkChunkAlloc& alloc) {
+Vertex* check_for_intersection(Edge* edge, Edge* other, Edge** activeEdges, Comparator& c,
+ SkChunkAlloc& alloc) {
SkPoint p;
if (!edge || !other) {
return NULL;
@@ -913,24 +917,24 @@ Vertex* check_for_intersection(Edge* edge, Edge* other, Edge** activeEdges, SkCh
if (edge->intersect(*other, &p)) {
Vertex* v;
LOG("found intersection, pt is %g, %g\n", p.fX, p.fY);
- if (p == edge->fTop->fPoint || sweep_lt(p, edge->fTop->fPoint)) {
- split_edge(other, edge->fTop, activeEdges, alloc);
+ if (p == edge->fTop->fPoint || c.sweep_lt(p, edge->fTop->fPoint)) {
+ split_edge(other, edge->fTop, activeEdges, c, alloc);
v = edge->fTop;
- } else if (p == edge->fBottom->fPoint || sweep_gt(p, edge->fBottom->fPoint)) {
- split_edge(other, edge->fBottom, activeEdges, alloc);
+ } else if (p == edge->fBottom->fPoint || c.sweep_gt(p, edge->fBottom->fPoint)) {
+ split_edge(other, edge->fBottom, activeEdges, c, alloc);
v = edge->fBottom;
- } else if (p == other->fTop->fPoint || sweep_lt(p, other->fTop->fPoint)) {
- split_edge(edge, other->fTop, activeEdges, alloc);
+ } else if (p == other->fTop->fPoint || c.sweep_lt(p, other->fTop->fPoint)) {
+ split_edge(edge, other->fTop, activeEdges, c, alloc);
v = other->fTop;
- } else if (p == other->fBottom->fPoint || sweep_gt(p, other->fBottom->fPoint)) {
- split_edge(edge, other->fBottom, activeEdges, alloc);
+ } else if (p == other->fBottom->fPoint || c.sweep_gt(p, other->fBottom->fPoint)) {
+ split_edge(edge, other->fBottom, activeEdges, c, alloc);
v = other->fBottom;
} else {
Vertex* nextV = edge->fTop;
- while (sweep_lt(p, nextV->fPoint)) {
+ while (c.sweep_lt(p, nextV->fPoint)) {
nextV = nextV->fPrev;
}
- while (sweep_lt(nextV->fPoint, p)) {
+ while (c.sweep_lt(nextV->fPoint, p)) {
nextV = nextV->fNext;
}
Vertex* prevV = nextV->fPrev;
@@ -951,8 +955,8 @@ Vertex* check_for_intersection(Edge* edge, Edge* other, Edge** activeEdges, SkCh
prevV->fNext = v;
nextV->fPrev = v;
}
- split_edge(edge, v, activeEdges, alloc);
- split_edge(other, v, activeEdges, alloc);
+ split_edge(edge, v, activeEdges, c, alloc);
+ split_edge(other, v, activeEdges, c, alloc);
}
return v;
}
@@ -983,34 +987,34 @@ void sanitize_contours(Vertex** contours, int contourCnt) {
}
}
-void merge_coincident_vertices(Vertex** vertices, SkChunkAlloc& alloc) {
+void merge_coincident_vertices(Vertex** vertices, Comparator& c, SkChunkAlloc& alloc) {
for (Vertex* v = (*vertices)->fNext; v != NULL; v = v->fNext) {
- if (sweep_lt(v->fPoint, v->fPrev->fPoint)) {
+ if (c.sweep_lt(v->fPoint, v->fPrev->fPoint)) {
v->fPoint = v->fPrev->fPoint;
}
if (coincident(v->fPrev->fPoint, v->fPoint)) {
- merge_vertices(v->fPrev, v, vertices, alloc);
+ merge_vertices(v->fPrev, v, vertices, c, alloc);
}
}
}
// Stage 2: convert the contours to a mesh of edges connecting the vertices.
-Vertex* build_edges(Vertex** contours, int contourCnt, SkChunkAlloc& alloc) {
+Vertex* build_edges(Vertex** contours, int contourCnt, Comparator& c, SkChunkAlloc& alloc) {
Vertex* vertices = NULL;
Vertex* prev = NULL;
for (int i = 0; i < contourCnt; ++i) {
for (Vertex* v = contours[i]; v != NULL;) {
Vertex* vNext = v->fNext;
- Edge* edge = new_edge(v->fPrev, v, alloc);
+ Edge* edge = new_edge(v->fPrev, v, alloc, c);
if (edge->fWinding > 0) {
- insert_edge_below(edge, v->fPrev);
- insert_edge_above(edge, v);
+ insert_edge_below(edge, v->fPrev, c);
+ insert_edge_above(edge, v, c);
} else {
- insert_edge_below(edge, v);
- insert_edge_above(edge, v->fPrev);
+ insert_edge_below(edge, v, c);
+ insert_edge_above(edge, v->fPrev, c);
}
- merge_collinear_edges(edge, NULL);
+ merge_collinear_edges(edge, NULL, c);
if (prev) {
prev->fNext = v;
v->fPrev = prev;
@@ -1028,9 +1032,9 @@ Vertex* build_edges(Vertex** contours, int contourCnt, SkChunkAlloc& alloc) {
return vertices;
}
-// Stage 3: sort the vertices by increasing Y (or X if SWEEP_IN_X is on).
+// Stage 3: sort the vertices by increasing sweep direction.
-Vertex* sorted_merge(Vertex* a, Vertex* b);
+Vertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c);
void front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack) {
Vertex* fast;
@@ -1057,7 +1061,7 @@ void front_back_split(Vertex* v, Vertex** pFront, Vertex** pBack) {
}
}
-void merge_sort(Vertex** head) {
+void merge_sort(Vertex** head, Comparator& c) {
if (!*head || !(*head)->fNext) {
return;
}
@@ -1066,10 +1070,10 @@ void merge_sort(Vertex** head) {
Vertex* b;
front_back_split(*head, &a, &b);
- merge_sort(&a);
- merge_sort(&b);
+ merge_sort(&a, c);
+ merge_sort(&b, c);
- *head = sorted_merge(a, b);
+ *head = sorted_merge(a, b, c);
}
inline void append_vertex(Vertex* v, Vertex** head, Vertex** tail) {
@@ -1080,12 +1084,12 @@ inline void append_vertex_list(Vertex* v, Vertex** head, Vertex** tail) {
insert<Vertex, &Vertex::fPrev, &Vertex::fNext>(v, *tail, v->fNext, head, tail);
}
-Vertex* sorted_merge(Vertex* a, Vertex* b) {
+Vertex* sorted_merge(Vertex* a, Vertex* b, Comparator& c) {
Vertex* head = NULL;
Vertex* tail = NULL;
while (a && b) {
- if (sweep_lt(a->fPoint, b->fPoint)) {
+ if (c.sweep_lt(a->fPoint, b->fPoint)) {
Vertex* next = a->fNext;
append_vertex(a, &head, &tail);
a = next;
@@ -1106,7 +1110,7 @@ Vertex* sorted_merge(Vertex* a, Vertex* b) {
// Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
-void simplify(Vertex* vertices, SkChunkAlloc& alloc) {
+void simplify(Vertex* vertices, Comparator& c, SkChunkAlloc& alloc) {
LOG("simplifying complex polygons\n");
Edge* activeEdges = NULL;
for (Vertex* v = vertices; v != NULL; v = v->fNext) {
@@ -1124,19 +1128,19 @@ void simplify(Vertex* vertices, SkChunkAlloc& alloc) {
find_enclosing_edges(v, activeEdges, &leftEnclosingEdge, &rightEnclosingEdge);
if (v->fFirstEdgeBelow) {
for (Edge* edge = v->fFirstEdgeBelow; edge != NULL; edge = edge->fNextEdgeBelow) {
- if (check_for_intersection(edge, leftEnclosingEdge, &activeEdges, alloc)) {
+ if (check_for_intersection(edge, leftEnclosingEdge, &activeEdges, c, alloc)) {
restartChecks = true;
break;
}
- if (check_for_intersection(edge, rightEnclosingEdge, &activeEdges, alloc)) {
+ if (check_for_intersection(edge, rightEnclosingEdge, &activeEdges, c, alloc)) {
restartChecks = true;
break;
}
}
} else {
if (Vertex* pv = check_for_intersection(leftEnclosingEdge, rightEnclosingEdge,
- &activeEdges, alloc)) {
- if (sweep_lt(pv->fPoint, v->fPoint)) {
+ &activeEdges, c, alloc)) {
+ if (c.sweep_lt(pv->fPoint, v->fPoint)) {
v = pv;
}
restartChecks = true;
@@ -1276,7 +1280,7 @@ Poly* tessellate(Vertex* vertices, SkChunkAlloc& alloc) {
// This is a driver function which calls stages 2-5 in turn.
-Poly* contours_to_polys(Vertex** contours, int contourCnt, SkChunkAlloc& alloc) {
+Poly* contours_to_polys(Vertex** contours, int contourCnt, Comparator& c, SkChunkAlloc& alloc) {
#if LOGGING_ENABLED
for (int i = 0; i < contourCnt; ++i) {
Vertex* v = contours[i];
@@ -1288,21 +1292,21 @@ Poly* contours_to_polys(Vertex** contours, int contourCnt, SkChunkAlloc& alloc)
}
#endif
sanitize_contours(contours, contourCnt);
- Vertex* vertices = build_edges(contours, contourCnt, alloc);
+ Vertex* vertices = build_edges(contours, contourCnt, c, alloc);
if (!vertices) {
return NULL;
}
// Sort vertices in Y (secondarily in X).
- merge_sort(&vertices);
- merge_coincident_vertices(&vertices, alloc);
+ merge_sort(&vertices, c);
+ merge_coincident_vertices(&vertices, c, alloc);
#if LOGGING_ENABLED
for (Vertex* v = vertices; v != NULL; v = v->fNext) {
static float gID = 0.0f;
v->fID = gID++;
}
#endif
- simplify(vertices, alloc);
+ simplify(vertices, c, alloc);
return tessellate(vertices, alloc);
}
@@ -1373,7 +1377,16 @@ public:
}
void generateGeometry(GrBatchTarget* batchTarget, const GrPipeline* pipeline) override {
- SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, fViewMatrix, fPath.getBounds());
+ SkRect pathBounds = fPath.getBounds();
+ Comparator c;
+ if (pathBounds.width() > pathBounds.height()) {
+ c.sweep_lt = sweep_lt_horiz;
+ c.sweep_gt = sweep_gt_horiz;
+ } else {
+ c.sweep_lt = sweep_lt_vert;
+ c.sweep_gt = sweep_gt_vert;
+ }
+ SkScalar tol = GrPathUtils::scaleToleranceToSrc(SK_Scalar1, fViewMatrix, pathBounds);
int contourCnt;
int maxPts = GrPathUtils::worstCasePointCount(fPath, &contourCnt, tol);
if (maxPts <= 0) {
@@ -1404,7 +1417,7 @@ public:
SkChunkAlloc alloc(maxPts * (3 * sizeof(Vertex) + sizeof(Edge)));
path_to_contours(fPath, tol, fClipBounds, contours.get(), alloc);
Poly* polys;
- polys = contours_to_polys(contours.get(), contourCnt, alloc);
+ polys = contours_to_polys(contours.get(), contourCnt, c, alloc);
int count = 0;
for (Poly* poly = polys; poly; poly = poly->fNext) {
if (apply_fill_type(fillType, poly->fWinding) && poly->fCount >= 3) {
« 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