nc seal breaks simplify

This test has nearly coincident lines that are missorted.
The underlying bug is caused when a pair of curves
are coincident when reduced to line segments, but the
end points aren't detected.

The error was generated by running nanobench over all svg
sample data with the distance field patch installed.

TBR=reed@google.com
GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2440043003

Review-Url: https://codereview.chromium.org/2440043003
This commit is contained in:
caryclark 2016-10-24 08:19:06 -07:00 committed by Commit bot
parent 526972ecb5
commit 34efb70398
5 changed files with 1366 additions and 1367 deletions

View File

@ -315,6 +315,12 @@ private:
bool removeSpan(SkTSpan<TCurve, OppCurve>* span);
void removeSpanRange(SkTSpan<TCurve, OppCurve>* first, SkTSpan<TCurve, OppCurve>* last);
void removeSpans(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
void removedEndCheck(SkTSpan<TCurve, OppCurve>* span);
void resetRemovedEnds() {
fRemovedStartT = fRemovedEndT = false;
}
SkTSpan<TCurve, OppCurve>* spanAtT(double t, SkTSpan<TCurve, OppCurve>** priorSpan);
SkTSpan<TCurve, OppCurve>* tail();
bool trim(SkTSpan<TCurve, OppCurve>* span, SkTSect<OppCurve, TCurve>* opp);
@ -865,7 +871,8 @@ SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c
PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugAllocatedCount(0))
{
fHead = addOne();
this->resetRemovedEnds();
fHead = this->addOne();
SkDEBUGCODE(fHead->debugSetGlobalState(debugGlobalState));
fHead->init(c);
}
@ -1360,7 +1367,9 @@ int SkTSect<TCurve, OppCurve>::intersects(SkTSpan<TCurve, OppCurve>* span,
if (!sects) {
return -1;
}
this->removedEndCheck(span);
span->fStartT = span->fEndT = i[0][0];
opp->removedEndCheck(oppSpan);
oppSpan->fStartT = oppSpan->fEndT = i[1][0];
return *oppResult = 2;
}
@ -1735,13 +1744,18 @@ void SkTSect<TCurve, OppCurve>::removeCoincident(SkTSpan<TCurve, OppCurve>* span
}
template<typename TCurve, typename OppCurve>
bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {
void SkTSect<TCurve, OppCurve>::removedEndCheck(SkTSpan<TCurve, OppCurve>* span) {
if (!span->fStartT) {
fRemovedStartT = true;
}
if (1 == span->fEndT) {
fRemovedEndT = true;
}
}
template<typename TCurve, typename OppCurve>
bool SkTSect<TCurve, OppCurve>::removeSpan(SkTSpan<TCurve, OppCurve>* span) {\
this->removedEndCheck(span);
this->unlinkSpan(span);
return this->markSpanGone(span);
}
@ -2141,14 +2155,14 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
break;
}
SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
sect1->fRemovedStartT = sect1->fRemovedEndT = false;
sect2->fRemovedStartT = sect2->fRemovedEndT = false;
// split it
if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
|| (!largest1->fCollapsed && largest2->fCollapsed)))) {
if (largest1->fCollapsed) {
break;
}
sect1->resetRemovedEnds();
sect2->resetRemovedEnds();
// trim parts that don't intersect the opposite
SkTSpan<TCurve, OppCurve>* half1 = sect1->addOne();
SkDEBUGCODE(half1->debugSetGlobalState(sect1->globalState()));
@ -2167,6 +2181,8 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
if (largest2->fCollapsed) {
break;
}
sect1->resetRemovedEnds();
sect2->resetRemovedEnds();
// trim parts that don't intersect the opposite
SkTSpan<OppCurve, TCurve>* half2 = sect2->addOne();
SkDEBUGCODE(half2->debugSetGlobalState(sect2->globalState()));
@ -2262,7 +2278,7 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
} while ((coincident = coincident->fNext));
}
int zeroOneSet = EndsEqual(sect1, sect2, intersections);
if (!sect1->fHead || !sect2->fHead) {
// if (!sect1->fHead || !sect2->fHead) {
// if the final iteration contains an end (0 or 1),
if (sect1->fRemovedStartT && !(zeroOneSet & kZeroS1Set)) {
SkTCoincident<TCurve, OppCurve> perp; // intersect perpendicular with opposite curve
@ -2292,6 +2308,8 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
intersections->insert(perp.perpT(), 1, perp.perpPt());
}
}
// }
if (!sect1->fHead || !sect2->fHead) {
return;
}
sect1->recoverCollapsed();

View File

@ -57,6 +57,9 @@ static void standardTestCases(skiatest::Reporter* reporter) {
}
static const QuadPts testSet[] = {
{{{123.637985f, 102.405312f}, {125.172699f, 104.575714f}, {123.387383f, 106.91227f}}},
{{{123.388428f, 106.910896f}, {123.365623f, 106.94088f}, {123.320007f, 107.000946f}}},
{{{-0.001019871095195412636, -0.008523519150912761688}, {-0.005396408028900623322, -0.005396373569965362549}, {-0.02855382487177848816, -0.02855364233255386353}}},
{{{-0.004567248281091451645, -0.01482933573424816132}, {-0.01142475008964538574, -0.01140109263360500336}, {-0.02852955088019371033, -0.02847047336399555206}}},

View File

@ -5578,11 +5578,57 @@ path.close();
testSimplify(reporter, path, filename);
}
static void simplifyTest_1(skiatest::Reporter* reporter, const char* filename) {
SkPath path;
path.setFillType((SkPath::FillType) 0);
path.moveTo(SkBits2Float(0x42bfefd4), SkBits2Float(0x42ef80ef)); // 95.9684f, 119.752f
path.quadTo(SkBits2Float(0x42c26810), SkBits2Float(0x42e214b8), SkBits2Float(0x42cdcad5), SkBits2Float(0x42d82aa2)); // 97.2032f, 113.04f, 102.896f, 108.083f
path.lineTo(SkBits2Float(0x42cdcb21), SkBits2Float(0x42d82a61)); // 102.897f, 108.083f
path.quadTo(SkBits2Float(0x42d5e3c8), SkBits2Float(0x42d12140), SkBits2Float(0x42e20ee8), SkBits2Float(0x42cdc937)); // 106.945f, 104.565f, 113.029f, 102.893f
path.lineTo(SkBits2Float(0x42e256e3), SkBits2Float(0x42cdbc92)); // 113.17f, 102.868f
path.lineTo(SkBits2Float(0x42f5eadb), SkBits2Float(0x42cc2cb3)); // 122.959f, 102.087f
path.lineTo(SkBits2Float(0x42f746a6), SkBits2Float(0x42cccf85)); // 123.638f, 102.405f
path.quadTo(SkBits2Float(0x42fa586c), SkBits2Float(0x42d126c4), SkBits2Float(0x42f6c657), SkBits2Float(0x42d5d315)); // 125.173f, 104.576f, 123.387f, 106.912f
path.lineTo(SkBits2Float(0x42f591eb), SkBits2Float(0x42d4e76d)); // 122.785f, 106.452f
path.lineTo(SkBits2Float(0x42f6c6e0), SkBits2Float(0x42d5d261)); // 123.388f, 106.911f
path.quadTo(SkBits2Float(0x42f6bb33), SkBits2Float(0x42d5e1bb), SkBits2Float(0x42f6a3d8), SkBits2Float(0x42d6007c)); // 123.366f, 106.941f, 123.32f, 107.001f
path.quadTo(SkBits2Float(0x42ea3850), SkBits2Float(0x42e65af0), SkBits2Float(0x42d97a6e), SkBits2Float(0x42ed841c)); // 117.11f, 115.178f, 108.739f, 118.758f
path.lineTo(SkBits2Float(0x42d91d92), SkBits2Float(0x42ed9ec0)); // 108.558f, 118.81f
path.lineTo(SkBits2Float(0x42c1a959), SkBits2Float(0x42f146b0)); // 96.8308f, 120.638f
path.lineTo(SkBits2Float(0x42bfefd4), SkBits2Float(0x42ef80f0)); // 95.9684f, 119.752f
path.lineTo(SkBits2Float(0x42bfefd4), SkBits2Float(0x42ef80ef)); // 95.9684f, 119.752f
path.close();
path.moveTo(SkBits2Float(0x42c2eb4e), SkBits2Float(0x42f00d68)); // 97.4596f, 120.026f
path.lineTo(SkBits2Float(0x42c16d91), SkBits2Float(0x42efc72c)); // 96.714f, 119.889f
path.lineTo(SkBits2Float(0x42c131c9), SkBits2Float(0x42ee47a8)); // 96.5972f, 119.14f
path.lineTo(SkBits2Float(0x42d8a602), SkBits2Float(0x42ea9fb8)); // 108.324f, 117.312f
path.lineTo(SkBits2Float(0x42d8e1ca), SkBits2Float(0x42ec1f3c)); // 108.441f, 118.061f
path.lineTo(SkBits2Float(0x42d84926), SkBits2Float(0x42eaba5c)); // 108.143f, 117.364f
path.quadTo(SkBits2Float(0x42e84a40), SkBits2Float(0x42e3e1f0), SkBits2Float(0x42f439a2), SkBits2Float(0x42d42af8)); // 116.145f, 113.941f, 122.113f, 106.084f
path.quadTo(SkBits2Float(0x42f45121), SkBits2Float(0x42d40c08), SkBits2Float(0x42f45cf6), SkBits2Float(0x42d3fc79)); // 122.158f, 106.023f, 122.182f, 105.993f
path.lineTo(SkBits2Float(0x42f45d7f), SkBits2Float(0x42d3fbc5)); // 122.183f, 105.992f
path.quadTo(SkBits2Float(0x42f69510), SkBits2Float(0x42d114f4), SkBits2Float(0x42f4ccce), SkBits2Float(0x42ce8fb7)); // 123.291f, 104.541f, 122.4f, 103.281f
path.lineTo(SkBits2Float(0x42f609ba), SkBits2Float(0x42cdaf9e)); // 123.019f, 102.843f
path.lineTo(SkBits2Float(0x42f62899), SkBits2Float(0x42cf3289)); // 123.079f, 103.599f
path.lineTo(SkBits2Float(0x42e294a1), SkBits2Float(0x42d0c268)); // 113.29f, 104.38f
path.lineTo(SkBits2Float(0x42e275c2), SkBits2Float(0x42cf3f7d)); // 113.23f, 103.624f
path.lineTo(SkBits2Float(0x42e2dc9c), SkBits2Float(0x42d0b5c3)); // 113.431f, 104.355f
path.quadTo(SkBits2Float(0x42d75bb8), SkBits2Float(0x42d3df08), SkBits2Float(0x42cfc853), SkBits2Float(0x42da7457)); // 107.679f, 105.936f, 103.891f, 109.227f
path.lineTo(SkBits2Float(0x42cec9ba), SkBits2Float(0x42d94f5c)); // 103.394f, 108.655f
path.lineTo(SkBits2Float(0x42cfc89f), SkBits2Float(0x42da7416)); // 103.892f, 109.227f
path.quadTo(SkBits2Float(0x42c53268), SkBits2Float(0x42e3ac00), SkBits2Float(0x42c2eb4e), SkBits2Float(0x42f00d67)); // 98.5984f, 113.836f, 97.4596f, 120.026f
path.lineTo(SkBits2Float(0x42c2eb4e), SkBits2Float(0x42f00d68)); // 97.4596f, 120.026f
path.close();
testSimplify(reporter, path, filename);
}
static void (*skipTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = 0;
static void (*firstTest)(skiatest::Reporter* , const char* filename) = testQuads69;
static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
static TestDesc tests[] = {
TEST(simplifyTest_1),
TEST(carsvg_1),
TEST(tiger8_393),
TEST(bug5169),

View File

@ -7,15 +7,22 @@
<div style="height:0">
<div id="cubics">
{{{304.159515380859375, 463.82958984375}, {300.6310658029279352, 464.7318629437696131}, {299.9421006231858087, 465.564118056070356}, {320.21270751953125, 463.004913330078125}}} id=13
{{{304.159515380859375, 463.82958984375}, {307.5818980570784902, 462.9544395097227039}, {313.6756188676930037, 462.0134236159228749}, {305.906097412109375, 464.037353515625}}} id=13
{{{304.159515380859375, 463.82958984375}, {305.906097412109375, 464.037353515625}}} id=14</div>
{{{123.637985f, 102.405312f}, {125.172699f, 104.575714f}, {123.387383f, 106.91227f}}} id=7
{{{123.387383f, 106.91227f}, {122.784996f, 106.452003f}}} id=8
{{{122.784996f, 106.452003f}, {123.388428f, 106.910896f}}} id=9
{{{123.388428f, 106.910896f}, {123.365623f, 106.94088f}, {123.320007f, 107.000946f}}} id=10
</div>
<div id="q1">
{{{123.637985f, 102.405312f}, {125.172699f, 104.575714f}, {123.387383f, 106.91227f}}} id=7
{{{123.388428f, 106.910896f}, {123.365623f, 106.94088f}, {123.320007f, 107.000946f}}} id=10
</div>
</div>
<script type="text/javascript">
var testDivs = [
var testDivs = [
q1,
cubics
];

File diff suppressed because it is too large Load Diff