diff options
author | 2016-08-17 14:56:22 -0700 | |
---|---|---|
committer | 2016-08-17 14:56:22 -0700 | |
commit | 70f5251cc59191040a14cd0f1567aa2129e1f7c6 (patch) | |
tree | e0843dcb556d1ad159f064b02e64dc38780347d1 /src/gpu/GrTessellator.cpp | |
parent | 280e282d2a89ba3b9ff05dd2475d7452b7dccdbe (diff) |
Fix assert caused by floating point error in tessellating path renderer.
In rare cases, floating point error causes the tesselator to add the
same Vertex to more than one Poly on the same side. This was not a big
problem when we were allocating new vertices when constructing Polys,
but after https://codereview.chromium.org/2029243002 it causes more serious
issues, since each Edge can only belong to two Polys, and violating this
condition messes up the linked list of Edges used for left & right Polys
and the associated estimated vertex count.
The fix is to simply let the first Poly win, and skip that vertex for
subsequent Polys. Since this only occurs in cases where vertices are very
close to each other, it should have little visual effect.
This is also exercised by Nebraska-StateSeal.svg.
BUG=skia:5636
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2259493002
Review-Url: https://codereview.chromium.org/2259493002
Diffstat (limited to 'src/gpu/GrTessellator.cpp')
-rw-r--r-- | src/gpu/GrTessellator.cpp | 19 |
1 files changed, 15 insertions, 4 deletions
diff --git a/src/gpu/GrTessellator.cpp b/src/gpu/GrTessellator.cpp index cefe4cd65b..50d4af6148 100644 --- a/src/gpu/GrTessellator.cpp +++ b/src/gpu/GrTessellator.cpp @@ -253,7 +253,9 @@ struct Edge { , fLeftPolyPrev(nullptr) , fLeftPolyNext(nullptr) , fRightPolyPrev(nullptr) - , fRightPolyNext(nullptr) { + , fRightPolyNext(nullptr) + , fUsedInLeftPoly(false) + , fUsedInRightPoly(false) { recompute(); } int fWinding; // 1 == edge goes downward; -1 = edge goes upward. @@ -271,6 +273,8 @@ struct Edge { Edge* fLeftPolyNext; Edge* fRightPolyPrev; Edge* fRightPolyNext; + bool fUsedInLeftPoly; + bool fUsedInRightPoly; double fDX; // The line equation for this edge, in implicit form. double fDY; // fDY * x + fDX * y + fC = 0, for point (x, y) on the line. double fC; @@ -356,11 +360,19 @@ struct Poly { MonotonePoly* fNext; void addEdge(Edge* edge) { if (fSide == kRight_Side) { + if (edge->fUsedInRightPoly) { + return; + } list_insert<Edge, &Edge::fRightPolyPrev, &Edge::fRightPolyNext>( edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge); + edge->fUsedInRightPoly = true; } else { + if (edge->fUsedInLeftPoly) { + return; + } list_insert<Edge, &Edge::fLeftPolyPrev, &Edge::fLeftPolyNext>( edge, fLastEdge, nullptr, &fFirstEdge, &fLastEdge); + edge->fUsedInLeftPoly = true; } } @@ -407,9 +419,8 @@ struct Poly { } }; Poly* addEdge(Edge* e, Side side, SkChunkAlloc& alloc) { - LOG("addEdge (%g,%g)-(%g,%g) to poly %d, %s side\n", - e->fTop->fPoint.fX, e->fTop->fPoint.fY, e->fBottom->fPoint.fX, e->fBottom->fPoint.fY, - fID, side == kLeft_Side ? "left" : "right"); + LOG("addEdge (%g -> %g) to poly %d, %s side\n", + e->fTop->fID, e->fBottom->fID, fID, side == kLeft_Side ? "left" : "right"); Poly* partner = fPartner; Poly* poly = this; if (partner) { |