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:
parent
526972ecb5
commit
34efb70398
@ -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();
|
||||
|
@ -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}}},
|
||||
|
||||
|
@ -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),
|
||||
|
@ -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
Loading…
Reference in New Issue
Block a user