aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTessellator.cpp
diff options
context:
space:
mode:
authorGravatar Stephen White <senorblanco@chromium.org>2017-06-08 14:41:01 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-06-08 20:07:04 +0000
commit0cb31675f3aa9cc878aa3a9e1a7ad09efdb350fc (patch)
treea1bb8cd30663f1972731a6a4ec6b622daac8a684 /src/gpu/GrTessellator.cpp
parentdc792701012a99d3b7499952df1e55031fa4b795 (diff)
GrTessellator: fix intersection above the first vertex.
Handle the case where the an intersection falls not only above both edge endpoints, but above the first vertex in the mesh. This requires passing the mesh into check_for_intersection(), in order to modify the head. We also need to rewind the mesh after insertion, since we need to rewind to the newly-inserted vertex. This also cleans up vertex ID computation a little (for logging), so that vertices before the first vertex or after the last have a reasonable ID. It also cleans up the intersection-on-endpoint special cases by refactoring the calls to split_edge(). BUG=730687 Change-Id: Idea736eca7b7c3c5d8a470b1373a16ad8e649e80 Reviewed-on: https://skia-review.googlesource.com/19069 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Stephen White <senorblanco@chromium.org>
Diffstat (limited to 'src/gpu/GrTessellator.cpp')
-rw-r--r--src/gpu/GrTessellator.cpp52
1 files changed, 24 insertions, 28 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index 6e9665f7c7..645befebf2 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -1006,6 +1006,9 @@ void merge_collinear_edges(Edge* edge, EdgeList* activeEdges, Vertex** current,
void split_edge(Edge* edge, Vertex* v, EdgeList* activeEdges, Vertex** current, Comparator& c,
SkArenaAlloc& alloc) {
+ if (v == edge->fTop || v == edge->fBottom) {
+ return;
+ }
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);
@@ -1073,7 +1076,7 @@ uint8_t max_edge_alpha(Edge* a, Edge* b) {
}
bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vertex** current,
- Comparator& c, SkArenaAlloc& alloc) {
+ VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
if (!edge || !other) {
return false;
}
@@ -1085,25 +1088,20 @@ bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vert
Vertex* top = *current;
// If the intersection point is above the current vertex, rewind to the vertex above the
// intersection.
- while (c.sweep_lt(p, top->fPoint) && top->fPrev) {
+ while (top && c.sweep_lt(p, top->fPoint)) {
top = top->fPrev;
}
- rewind(activeEdges, current, top, c);
if (p == edge->fTop->fPoint) {
- split_edge(other, edge->fTop, activeEdges, current, c, alloc);
v = edge->fTop;
} else if (p == edge->fBottom->fPoint) {
- split_edge(other, edge->fBottom, activeEdges, current, c, alloc);
v = edge->fBottom;
} else if (p == other->fTop->fPoint) {
- split_edge(edge, other->fTop, activeEdges, current, c, alloc);
v = other->fTop;
} else if (p == other->fBottom->fPoint) {
- split_edge(edge, other->fBottom, activeEdges, current, c, alloc);
v = other->fBottom;
} else {
Vertex* prevV = top;
- Vertex* nextV = top->fNext;
+ Vertex* nextV = top ? top->fNext : mesh->fHead;
while (nextV && c.sweep_lt(nextV->fPoint, p)) {
prevV = nextV;
nextV = nextV->fNext;
@@ -1115,22 +1113,20 @@ bool check_for_intersection(Edge* edge, Edge* other, EdgeList* activeEdges, Vert
} else {
v = alloc.make<Vertex>(p, alpha);
#if LOGGING_ENABLED
- float prevID = prevV ? prevV->fID : 0.0f;
- float nextID = nextV ? nextV->fID : prevV->fID + 1.0f;
- v->fID = (prevID + nextID) * 0.5f;
-#endif
- v->fPrev = prevV;
- v->fNext = nextV;
- if (prevV) {
- prevV->fNext = v;
- }
- if (nextV) {
- nextV->fPrev = v;
+ if (!prevV) {
+ v->fID = mesh->fHead - 1.0f;
+ } else if (!nextV) {
+ v->fID = mesh->fTail + 1.0f;
+ } else {
+ v->fID = (prevV->fID + nextV->fID) * 0.5f;
}
+#endif
+ mesh->insert(v, prevV, nextV);
}
- split_edge(edge, v, activeEdges, current, c, alloc);
- split_edge(other, v, activeEdges, current, c, alloc);
}
+ rewind(activeEdges, current, top ? top : v, c);
+ split_edge(edge, v, activeEdges, current, c, alloc);
+ split_edge(other, v, activeEdges, current, c, alloc);
v->fAlpha = SkTMax(v->fAlpha, alpha);
return true;
}
@@ -1265,10 +1261,10 @@ void merge_sort(VertexList* vertices) {
// Stage 4: Simplify the mesh by inserting new vertices at intersecting edges.
-void simplify(const VertexList& vertices, Comparator& c, SkArenaAlloc& alloc) {
+void simplify(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
LOG("simplifying complex polygons\n");
EdgeList activeEdges;
- for (Vertex* v = vertices.fHead; v != nullptr; v = v->fNext) {
+ for (Vertex* v = mesh->fHead; v != nullptr; v = v->fNext) {
if (!v->fFirstEdgeAbove && !v->fFirstEdgeBelow) {
continue;
}
@@ -1289,12 +1285,12 @@ void simplify(const VertexList& vertices, Comparator& c, SkArenaAlloc& alloc) {
v->fRightEnclosingEdge = rightEnclosingEdge;
if (v->fFirstEdgeBelow) {
for (Edge* edge = v->fFirstEdgeBelow; edge; edge = edge->fNextEdgeBelow) {
- if (check_for_intersection(edge, leftEnclosingEdge, &activeEdges, &v, c,
+ if (check_for_intersection(edge, leftEnclosingEdge, &activeEdges, &v, mesh, c,
alloc)) {
restartChecks = true;
break;
}
- if (check_for_intersection(edge, rightEnclosingEdge, &activeEdges, &v, c,
+ if (check_for_intersection(edge, rightEnclosingEdge, &activeEdges, &v, mesh, c,
alloc)) {
restartChecks = true;
break;
@@ -1302,7 +1298,7 @@ void simplify(const VertexList& vertices, Comparator& c, SkArenaAlloc& alloc) {
}
} else {
if (check_for_intersection(leftEnclosingEdge, rightEnclosingEdge,
- &activeEdges, &v, c, alloc)) {
+ &activeEdges, &v, mesh, c, alloc)) {
restartChecks = true;
}
@@ -1729,7 +1725,7 @@ Poly* contours_to_polys(VertexList* contours, int contourCnt, SkPath::FillType f
contours_to_mesh(contours, contourCnt, antialias, &mesh, c, alloc);
sort_mesh(&mesh, c, alloc);
merge_coincident_vertices(&mesh, c, alloc);
- simplify(mesh, c, alloc);
+ simplify(&mesh, c, alloc);
if (antialias) {
VertexList innerMesh;
extract_boundaries(mesh, &innerMesh, outerMesh, fillType, c, alloc);
@@ -1741,7 +1737,7 @@ Poly* contours_to_polys(VertexList* contours, int contourCnt, SkPath::FillType f
connect_partners(outerMesh, c, alloc);
sorted_merge(&innerMesh, outerMesh, &aaMesh, c);
merge_coincident_vertices(&aaMesh, c, alloc);
- simplify(aaMesh, c, alloc);
+ simplify(&aaMesh, c, alloc);
outerMesh->fHead = outerMesh->fTail = nullptr;
return tessellate(aaMesh, alloc);
} else {