aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu/GrTessellator.cpp
diff options
context:
space:
mode:
authorGravatar Stephen White <senorblanco@chromium.org>2018-06-05 09:15:59 -0400
committerGravatar Skia Commit-Bot <skia-commit-bot@chromium.org>2018-06-05 13:58:59 +0000
commit77169c8fd6d8b035fb113fdf6b85def0617b94a4 (patch)
tree9cfec01e9e2d086a6b069329f8b2d688b0741649 /src/gpu/GrTessellator.cpp
parent35f06df995240ca93b844d770ff019c2aa182ba1 (diff)
GrTessellator: fix for overlapping outer boundary edges in AA case.
When inflating outer path boundaries for edge AA, two outer boundary edges may be collinear. In this case, they form part of the overlap region, but they must not be removed on collapse, since they form part of the outer boundary of the shape. Bug: 846655 Change-Id: I4808b570cc4f82d6202862f7a8ecf0f8add771ef Reviewed-on: https://skia-review.googlesource.com/132084 Reviewed-by: Robert Phillips <robertphillips@google.com> Commit-Queue: Stephen White <senorblanco@chromium.org>
Diffstat (limited to 'src/gpu/GrTessellator.cpp')
-rw-r--r--src/gpu/GrTessellator.cpp25
1 files changed, 19 insertions, 6 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp
index 820011ccc0..7664fc96bb 100644
--- a/src/gpu/GrTessellator.cpp
+++ b/src/gpu/GrTessellator.cpp
@@ -479,10 +479,12 @@ struct EdgeList {
};
struct Event {
- Event(Edge* edge, const SkPoint& point, uint8_t alpha)
- : fEdge(edge), fPoint(point), fAlpha(alpha), fPrev(nullptr), fNext(nullptr) {
+ Event(Edge* edge, bool isOuterBoundary, const SkPoint& point, uint8_t alpha)
+ : fEdge(edge), fIsOuterBoundary(isOuterBoundary), fPoint(point), fAlpha(alpha)
+ , fPrev(nullptr), fNext(nullptr) {
}
Edge* fEdge;
+ bool fIsOuterBoundary;
SkPoint fPoint;
uint8_t fAlpha;
Event* fPrev;
@@ -496,7 +498,7 @@ bool compare(Event* const& e1, Event* const& e2) {
struct EventList : public SkTDPQueue<Event*, &compare> {};
-void create_event(Edge* e, EventList* events, SkArenaAlloc& alloc) {
+void create_event(Edge* e, bool isOuterBoundary, EventList* events, SkArenaAlloc& alloc) {
Edge bisector1(e->fTop, e->fTop->fPartner, 1, Edge::Type::kConnector);
Edge bisector2(e->fBottom, e->fBottom->fPartner, 1, Edge::Type::kConnector);
SkPoint p;
@@ -504,7 +506,7 @@ void create_event(Edge* e, EventList* events, SkArenaAlloc& alloc) {
if (bisector1.intersect(bisector2, &p, &alpha)) {
LOG("found overlap edge %g -> %g, will collapse to %g,%g alpha %d\n",
e->fTop->fID, e->fBottom->fID, p.fX, p.fY, alpha);
- e->fEvent = alloc.make<Event>(e, p, alpha);
+ e->fEvent = alloc.make<Event>(e, isOuterBoundary, p, alpha);
events->insert(e->fEvent);
}
}
@@ -1691,7 +1693,15 @@ void Event::apply(VertexList* mesh, Comparator& c, SkArenaAlloc& alloc) {
// Since the destination has multiple partners, give it none.
dest->fPartner = nullptr;
- disconnect(fEdge);
+
+ // Disconnect all collapsed edges except outer boundaries.
+ // Those are required to preserve shape coverage and winding correctness.
+ if (!fIsOuterBoundary) {
+ disconnect(fEdge);
+ } else {
+ LOG("edge %g -> %g is outer boundary; not disconnecting.\n",
+ fEdge->fTop->fID, fEdge->fBottom->fID);
+ }
// If top still has some connected edges, set its partner to dest.
top->fPartner = top->fFirstEdgeAbove || top->fFirstEdgeBelow ? dest : nullptr;
@@ -1738,7 +1748,10 @@ bool collapse_overlap_regions(VertexList* mesh, Comparator& c, SkArenaAlloc& all
}
e->fOverlap = e->fOverlap || is_overlap_edge(e);
if (e->fOverlap) {
- create_event(e, &events, alloc);
+ // If this edge borders a zero-winding area, it's a boundary; don't disconnect it.
+ bool isOuterBoundary = e->fType == Edge::Type::kOuter &&
+ (!prev || prev->fWinding == 0 || e->fWinding == 0);
+ create_event(e, isOuterBoundary, &events, alloc);
}
insert_edge(e, prev, &activeEdges);
prev = e;