aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'src/gpu')
-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;