aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTessellator.cpp
diff options
context:
space:
mode:
authorGravatar Stephen White <senorblanco@chromium.org>2017-01-11 16:19:26 -0500
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2017-01-12 05:28:22 +0000
commite7a364d435843a868dcac2c61d78c34e5d3e326c (patch)
tree84721c5bdee36d75db59c18677812cc0006b14f8 /src/gpu/GrTessellator.cpp
parente4ca362259a36458cce94a5e643a11306037e8d6 (diff)
GrTessellator: fix artifact with exactly-1-px-wide edges.
When path features are exactly a pixel wide, the extruded inner edges can become collinear and then be removed, since their winding is zero. We need these edges to be preserved through triangulation, otherwise opaque portions of the geometry can become transparent. Since the simplify() pass can handle zero-winding edges just fine, the the fix is to simply not remove them. In addition, this changes refactors out disconnect() from all the calls to remove_edge_above()/remove_edge_below(). It also renames the remaining function erase_edge() (since it's now unconditional). Add a new test to a new "thinconcavepaths" GM. BUG=680260 NOTRY=true Change-Id: I1d3a436c95a01c4d4ef5dc05503de4312677f65d Reviewed-on: https://skia-review.googlesource.com/6902 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Stephan White <senorblanco@chromium.org>
Diffstat (limited to 'src/gpu/GrTessellator.cpp')
-rw-r--r--src/gpu/GrTessellator.cpp30
1 files changed, 11 insertions, 19 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index 5a60e7a14a..09a5662f8d 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -896,13 +896,15 @@ void remove_edge_below(Edge* edge) {
edge, &edge->fTop->fFirstEdgeBelow, &edge->fTop->fLastEdgeBelow);
}
-void erase_edge_if_zero_winding(Edge* edge, EdgeList* edges) {
- if (edge->fWinding != 0) {
- return;
- }
- LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
+void disconnect(Edge* edge)
+{
remove_edge_above(edge);
remove_edge_below(edge);
+}
+
+void erase_edge(Edge* edge, EdgeList* edges) {
+ LOG("erasing edge (%g -> %g)\n", edge->fTop->fID, edge->fBottom->fID);
+ disconnect(edge);
if (edges && edges->contains(edge)) {
remove_edge(edge, edges);
}
@@ -934,16 +936,12 @@ void merge_edges_above(Edge* edge, Edge* other, EdgeList* activeEdges, Comparato
edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
other->fWinding += edge->fWinding;
- erase_edge_if_zero_winding(other, activeEdges);
- edge->fWinding = 0;
- erase_edge_if_zero_winding(edge, activeEdges);
+ erase_edge(edge, activeEdges);
} 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, c);
} else {
edge->fWinding += other->fWinding;
- erase_edge_if_zero_winding(edge, activeEdges);
set_bottom(other, edge->fTop, activeEdges, c);
}
}
@@ -954,16 +952,12 @@ void merge_edges_below(Edge* edge, Edge* other, EdgeList* activeEdges, Comparato
edge->fTop->fPoint.fX, edge->fTop->fPoint.fY,
edge->fBottom->fPoint.fX, edge->fBottom->fPoint.fY);
other->fWinding += edge->fWinding;
- erase_edge_if_zero_winding(other, activeEdges);
- edge->fWinding = 0;
- erase_edge_if_zero_winding(edge, activeEdges);
+ erase_edge(edge, activeEdges);
} 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, c);
} else {
other->fWinding += edge->fWinding;
- erase_edge_if_zero_winding(other, activeEdges);
set_top(edge, other->fBottom, activeEdges, c);
}
}
@@ -1455,8 +1449,7 @@ void remove_non_boundary_edges(const VertexList& mesh, SkPath::FillType fillType
for (Edge* e = v->fFirstEdgeBelow; e != nullptr;) {
Edge* next = e->fNextEdgeBelow;
if (!is_boundary_edge(e, fillType)) {
- remove_edge_above(e);
- remove_edge_below(e);
+ disconnect(e);
}
e = next;
}
@@ -1612,8 +1605,7 @@ void extract_boundary(EdgeList* boundary, Edge* e, SkPath::FillType fillType, Sk
down = true;
}
}
- remove_edge_above(e);
- remove_edge_below(e);
+ disconnect(e);
e = next;
}
}