remove scaling from pathops
PathOps added a cheat some time ago to reduce fuzzer bugs by scaling down very large paths, with the hope that it would make the math more sane. This had the side-effect of causing small edges to disappear altogether if the bounds is large enough. Removing the scaling causes a single regression to one fuzz-generated bug. That path succeeeded with scale by eliminating the troublesome tiny contour. Eliminating the scale may fix the CCPR-related bug discovered by Flutter, or at least uncover the next bug. I would expect more fuzzer bugs to appear with this change; paths with large and small values will no longer have the small values removed. R=csmartdalton@google.com,reed@google.com,bsalomon@google.com Bug: skia:8290 Change-Id: I3bfdb101c568e9cfa324858685eac1f9c368c291 Reviewed-on: https://skia-review.googlesource.com/150465 Commit-Queue: Cary Clark <caryclark@skia.org> Reviewed-by: Kevin Lubick <kjlubick@google.com> Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
parent
bc297beebb
commit
5de5233463
@ -1,4 +1,40 @@
|
||||
{
|
||||
"crbug_526025": {
|
||||
"p1": [[0, "0x43b40000", "0xcf000000"],
|
||||
[4, "0x4e0d628f", "0xceffffff", "0x4e800003", "0xcec6b143", "0x4e800002", "0xce7ffffc"],
|
||||
[4, "0x4e800002", "0xcde53aee", "0x4e0d6292", "0xc307820e", "0x44627d00", "0x437ffff2"],
|
||||
[1, "0x444bf3bc", "0x4460537e"],
|
||||
[1, "0x43553abd", "0x440f3cbd"],
|
||||
[1, "0x42000000", "0x41800000"],
|
||||
[1, "0x42c80000", "0x44000000"],
|
||||
[1, "0x43553abd", "0x440f3cbd"],
|
||||
[1, "0x43b40000", "0x44800000"],
|
||||
[1, "0x43b40000", "0x45816000"]],
|
||||
"fillType1": "kEvenOdd_FillType",
|
||||
"p2": [[0, "0x42fe0000", "0x43a08000"],
|
||||
[1, "0x45d5c000", "0x43870000"],
|
||||
[1, "0xd0a00000", "0x4cbebc20"],
|
||||
[1, "0x451f7000", "0x42800000"],
|
||||
[1, "0x42fe0000", "0x43a08000"],
|
||||
[5]],
|
||||
"fillType2": "kWinding_FillType",
|
||||
"op": "kUnion_SkPathOp",
|
||||
"expectSuccess": "flaky",
|
||||
"expectMatch": "flaky",
|
||||
"succeeded": true,
|
||||
"out": [[0, "0x4e800002", "0xce7ffffc"],
|
||||
[4, "0x4e800003", "0xcec6b143", "0x4e0d628f", "0xceffffff", "0x43b40000", "0xcf000000"],
|
||||
[1, "0x43b40000", "0x439425f8"],
|
||||
[1, "0x43a0dee5", "0x43962d2c"],
|
||||
[1, "0x42000000", "0x41800000"],
|
||||
[1, "0x424da04e", "0x4297477e"],
|
||||
[1, "0x43031abc", "0x43a0484d"],
|
||||
[1, "0x4460205e", "0x428f689e"],
|
||||
[1, "0x44627d00", "0x437ffff2"],
|
||||
[4, "0x4e0d6292", "0xc307820e", "0x4e800002", "0xcde53aee", "0x4e800002", "0xce7ffffc"],
|
||||
[5]],
|
||||
"fillTypeOut": "kEvenOdd_FillType"
|
||||
},
|
||||
"bug8228": {
|
||||
"p1": [[0, "0x41fd5557", "0x4292aaab"],
|
||||
[1, "0x41fd5557", "0x41555556"],
|
||||
@ -96,12 +132,9 @@
|
||||
"expectSuccess": "flaky",
|
||||
"expectMatch": "flaky",
|
||||
"succeeded": true,
|
||||
"out": [[0, "0xeee3ef57", "0xef6300f8"],
|
||||
[2, "0xeeee9c6e", "0xef609993", "0x00000000", "0x6e5a5a1b"],
|
||||
"out": [[0, "0x00000000", "0x00000000"],
|
||||
[2, "0xef646464", "0xefefefef", "0x00000000", "0x6e5a5a1b"],
|
||||
[1, "0x00000000", "0x00000000"],
|
||||
[2, "0xe56c206c", "0x646c5f40", "0x6c80885e", "0x00000000"],
|
||||
[1, "0x00000000", "0x00000000"],
|
||||
[2, "0xeeda2c5a", "0xef6533a7", "0xeee3ef57", "0xef6300f8"],
|
||||
[5]],
|
||||
"fillTypeOut": "kEvenOdd_FillType"
|
||||
},
|
||||
@ -122,7 +155,7 @@
|
||||
"expectMatch": "flaky",
|
||||
"succeeded": true,
|
||||
"out": [[0, "0x00000000", "0x6e5a5a1b"],
|
||||
[2, "0xeeee9c6e", "0xef609993", "0xeee3ef57", "0xef6300f8"],
|
||||
[1, "0xeee3ef57", "0xef6300f8"],
|
||||
[2, "0xeeda2c5a", "0xef6533a7", "0x00000000", "0x00000000"],
|
||||
[1, "0x00000000", "0x6e5a5a1b"],
|
||||
[5],
|
||||
@ -155,7 +188,7 @@
|
||||
[1, "0x00000000", "0x00000000"],
|
||||
[2, "0xe56c206c", "0x646c5f40", "0x6c80885e", "0x00000000"],
|
||||
[1, "0x00000000", "0x00000000"],
|
||||
[2, "0xeeda2c5a", "0xef6533a7", "0xeee3ef57", "0xef6300f8"],
|
||||
[1, "0xeee3ef57", "0xef6300f8"],
|
||||
[5]],
|
||||
"fillTypeOut": "kEvenOdd_FillType"
|
||||
},
|
||||
@ -1258,36 +1291,6 @@
|
||||
[5]],
|
||||
"fillTypeOut": "kEvenOdd_FillType"
|
||||
},
|
||||
"crbug_526025": {
|
||||
"p1": [[0, "0x43b40000", "0xcf000000"],
|
||||
[4, "0x4e0d628f", "0xceffffff", "0x4e800003", "0xcec6b143", "0x4e800002", "0xce7ffffc"],
|
||||
[4, "0x4e800002", "0xcde53aee", "0x4e0d6292", "0xc307820e", "0x44627d00", "0x437ffff2"],
|
||||
[1, "0x444bf3bc", "0x4460537e"],
|
||||
[1, "0x43553abd", "0x440f3cbd"],
|
||||
[1, "0x42000000", "0x41800000"],
|
||||
[1, "0x42c80000", "0x44000000"],
|
||||
[1, "0x43553abd", "0x440f3cbd"],
|
||||
[1, "0x43b40000", "0x44800000"],
|
||||
[1, "0x43b40000", "0x45816000"]],
|
||||
"fillType1": "kEvenOdd_FillType",
|
||||
"p2": [[0, "0x42fe0000", "0x43a08000"],
|
||||
[1, "0x45d5c000", "0x43870000"],
|
||||
[1, "0xd0a00000", "0x4cbebc20"],
|
||||
[1, "0x451f7000", "0x42800000"],
|
||||
[1, "0x42fe0000", "0x43a08000"],
|
||||
[5]],
|
||||
"fillType2": "kWinding_FillType",
|
||||
"op": "kUnion_SkPathOp",
|
||||
"expectSuccess": "yes",
|
||||
"expectMatch": "yes",
|
||||
"succeeded": true,
|
||||
"out": [[0, "0x4e800002", "0xce7ffffc"],
|
||||
[4, "0x4e800003", "0xcec6b143", "0x4e0d628f", "0xceffffff", "0x00000000", "0xcf000000"],
|
||||
[1, "0x00000000", "0x45816000"],
|
||||
[4, "0x4e0d6292", "0x00000000", "0x4e800002", "0xcde53aee", "0x4e800002", "0xce7ffffc"],
|
||||
[5]],
|
||||
"fillTypeOut": "kEvenOdd_FillType"
|
||||
},
|
||||
"fuzz38": {
|
||||
"p1": [[0, "0x42c8ae14", "0x4397a7f0"],
|
||||
[1, "0xccbebc20", "0x4397a7f0"],
|
||||
|
@ -1,4 +1,107 @@
|
||||
{
|
||||
"bug8290": {
|
||||
"path": [[0, "0xcf1c7651", "0xcf1c7650"],
|
||||
[1, "0x4f1c7653", "0xcf1c7650"],
|
||||
[1, "0x4f1c7653", "0x4f1c7654"],
|
||||
[1, "0xcf1c7651", "0x4f1c7654"],
|
||||
[1, "0xcf1c7651", "0xcf1c7650"],
|
||||
[5],
|
||||
[0, "0x433a0000", "0x44388800"],
|
||||
[1, "0x445fb000", "0x44388800"],
|
||||
[1, "0x445fb000", "0x4438c802"],
|
||||
[1, "0x433a0000", "0x4438c802"],
|
||||
[1, "0x433a0000", "0x44388800"],
|
||||
[5],
|
||||
[0, "0x433a0000", "0x44565002"],
|
||||
[1, "0x445fb000", "0x44565002"],
|
||||
[1, "0x445fb000", "0x44569000"],
|
||||
[1, "0x433a0000", "0x44569000"],
|
||||
[1, "0x433a0000", "0x44565002"],
|
||||
[5],
|
||||
[0, "0x433a0000", "0x44741804"],
|
||||
[1, "0x445fb000", "0x44741804"],
|
||||
[1, "0x445fb000", "0x44745806"],
|
||||
[1, "0x433a0000", "0x44745806"],
|
||||
[1, "0x433a0000", "0x44741804"],
|
||||
[5],
|
||||
[0, "0x433a0000", "0x4488f003"],
|
||||
[1, "0x445fb000", "0x4488f003"],
|
||||
[1, "0x445fb000", "0x44891004"],
|
||||
[1, "0x433a0000", "0x44891004"],
|
||||
[1, "0x433a0000", "0x4488f003"],
|
||||
[5],
|
||||
[0, "0x433a0000", "0x4497d404"],
|
||||
[1, "0x445fb000", "0x4497d404"],
|
||||
[1, "0x445fb000", "0x4497f405"],
|
||||
[1, "0x433a0000", "0x4497f405"],
|
||||
[1, "0x433a0000", "0x4497d404"],
|
||||
[5],
|
||||
[0, "0x433a0000", "0x44a6b805"],
|
||||
[1, "0x445fb000", "0x44a6b805"],
|
||||
[1, "0x445fb000", "0x44a6d806"],
|
||||
[1, "0x433a0000", "0x44a6d806"],
|
||||
[1, "0x433a0000", "0x44a6b805"],
|
||||
[5],
|
||||
[0, "0x433a0000", "0x44b59c06"],
|
||||
[1, "0x445fb000", "0x44b59c06"],
|
||||
[1, "0x445fb000", "0x44b5bc07"],
|
||||
[1, "0x433a0000", "0x44b5bc07"],
|
||||
[1, "0x433a0000", "0x44b59c06"],
|
||||
[5]],
|
||||
"fillType": "kEvenOdd_FillType",
|
||||
"expectSuccess": "yes",
|
||||
"expectMatch": "yes",
|
||||
"succeeded": true,
|
||||
"out": [[0, "0x4f1c7653", "0xcf1c7650"],
|
||||
[1, "0xcf1c7651", "0xcf1c7650"],
|
||||
[1, "0xcf1c7651", "0x4f1c7654"],
|
||||
[1, "0x4f1c7653", "0x4f1c7654"],
|
||||
[1, "0x4f1c7653", "0xcf1c7650"],
|
||||
[5],
|
||||
[0, "0x445fb000", "0x44388800"],
|
||||
[1, "0x433a0000", "0x44388800"],
|
||||
[1, "0x433a0000", "0x4438c802"],
|
||||
[1, "0x445fb000", "0x4438c802"],
|
||||
[1, "0x445fb000", "0x44388800"],
|
||||
[5],
|
||||
[0, "0x445fb000", "0x44565002"],
|
||||
[1, "0x433a0000", "0x44565002"],
|
||||
[1, "0x433a0000", "0x44569000"],
|
||||
[1, "0x445fb000", "0x44569000"],
|
||||
[1, "0x445fb000", "0x44565002"],
|
||||
[5],
|
||||
[0, "0x445fb000", "0x44741804"],
|
||||
[1, "0x433a0000", "0x44741804"],
|
||||
[1, "0x433a0000", "0x44745806"],
|
||||
[1, "0x445fb000", "0x44745806"],
|
||||
[1, "0x445fb000", "0x44741804"],
|
||||
[5],
|
||||
[0, "0x445fb000", "0x4488f003"],
|
||||
[1, "0x433a0000", "0x4488f003"],
|
||||
[1, "0x433a0000", "0x44891004"],
|
||||
[1, "0x445fb000", "0x44891004"],
|
||||
[1, "0x445fb000", "0x4488f003"],
|
||||
[5],
|
||||
[0, "0x445fb000", "0x4497d404"],
|
||||
[1, "0x433a0000", "0x4497d404"],
|
||||
[1, "0x433a0000", "0x4497f405"],
|
||||
[1, "0x445fb000", "0x4497f405"],
|
||||
[1, "0x445fb000", "0x4497d404"],
|
||||
[5],
|
||||
[0, "0x445fb000", "0x44a6b805"],
|
||||
[1, "0x433a0000", "0x44a6b805"],
|
||||
[1, "0x433a0000", "0x44a6d806"],
|
||||
[1, "0x445fb000", "0x44a6d806"],
|
||||
[1, "0x445fb000", "0x44a6b805"],
|
||||
[5],
|
||||
[0, "0x445fb000", "0x44b59c06"],
|
||||
[1, "0x433a0000", "0x44b59c06"],
|
||||
[1, "0x433a0000", "0x44b5bc07"],
|
||||
[1, "0x445fb000", "0x44b5bc07"],
|
||||
[1, "0x445fb000", "0x44b59c06"],
|
||||
[5]],
|
||||
"fillTypeOut": "kEvenOdd_FillType"
|
||||
},
|
||||
"bug8249": {
|
||||
"path": [[0, "0x43310000", "0x43810000"],
|
||||
[1, "0x43480000", "0x43868000"],
|
||||
@ -5869,11 +5972,9 @@
|
||||
"out": [[0, "0x42f60000", "0x44160000"],
|
||||
[1, "0x00000000", "0x44160000"],
|
||||
[1, "0x00000000", "0x00000000"],
|
||||
[1, "0x42f60000", "0x00000000"],
|
||||
[1, "0x4c00002a", "0x00000000"],
|
||||
[1, "0x4c00002a", "0x44160000"],
|
||||
[1, "0x4bfffff0", "0x44160000"],
|
||||
[1, "0x42f60000", "0x44160000"],
|
||||
[5]],
|
||||
"fillTypeOut": "kEvenOdd_FillType"
|
||||
},
|
||||
|
@ -896,7 +896,11 @@ bool SkOpSegment::markAndChaseWinding(SkOpSpanBase* start, SkOpSpanBase* end, in
|
||||
bool success = markWinding(spanStart, winding);
|
||||
SkOpSpanBase* last = nullptr;
|
||||
SkOpSegment* other = this;
|
||||
int safetyNet = 100000;
|
||||
while ((other = other->nextChase(&start, &step, &spanStart, &last))) {
|
||||
if (!--safetyNet) {
|
||||
return false;
|
||||
}
|
||||
if (spanStart->windSum() != SK_MinS32) {
|
||||
// SkASSERT(spanStart->windSum() == winding); // FIXME: is this assert too aggressive?
|
||||
SkASSERT(!last);
|
||||
|
@ -13,28 +13,6 @@
|
||||
#include "SkPathWriter.h"
|
||||
#include "SkTSort.h"
|
||||
|
||||
SkScalar ScaleFactor(const SkPath& path) {
|
||||
static const SkScalar twoTo10 = 1024.f;
|
||||
SkScalar largest = 0;
|
||||
const SkScalar* oneBounds = &path.getBounds().fLeft;
|
||||
for (int index = 0; index < 4; ++index) {
|
||||
largest = SkTMax(largest, SkScalarAbs(oneBounds[index]));
|
||||
}
|
||||
SkScalar scale = twoTo10;
|
||||
SkScalar next;
|
||||
while ((next = scale * twoTo10) < largest) {
|
||||
scale = next;
|
||||
}
|
||||
return scale == twoTo10 ? SK_Scalar1 : scale;
|
||||
}
|
||||
|
||||
void ScalePath(const SkPath& path, SkScalar scale, SkPath* scaled) {
|
||||
SkMatrix matrix;
|
||||
matrix.setScale(scale, scale);
|
||||
*scaled = path;
|
||||
scaled->transform(matrix);
|
||||
}
|
||||
|
||||
const SkOpAngle* AngleWinding(SkOpSpanBase* start, SkOpSpanBase* end, int* windingPtr,
|
||||
bool* sortablePtr) {
|
||||
// find first angle, initialize winding to computed fWindSum
|
||||
|
@ -26,7 +26,5 @@ bool HandleCoincidence(SkOpContourHead* , SkOpCoincidence* );
|
||||
bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result
|
||||
SkDEBUGPARAMS(bool skipAssert)
|
||||
SkDEBUGPARAMS(const char* testName));
|
||||
SkScalar ScaleFactor(const SkPath& path);
|
||||
void ScalePath(const SkPath& path, SkScalar scale, SkPath* scaled);
|
||||
|
||||
#endif
|
||||
|
@ -294,18 +294,8 @@ bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result
|
||||
SkOpGlobalState globalState(contourList, &allocator
|
||||
SkDEBUGPARAMS(skipAssert) SkDEBUGPARAMS(testName));
|
||||
SkOpCoincidence coincidence(&globalState);
|
||||
SkScalar scaleFactor = SkTMax(ScaleFactor(one), ScaleFactor(two));
|
||||
SkPath scaledOne, scaledTwo;
|
||||
const SkPath* minuend, * subtrahend;
|
||||
if (scaleFactor > SK_Scalar1) {
|
||||
ScalePath(one, 1.f / scaleFactor, &scaledOne);
|
||||
minuend = &scaledOne;
|
||||
ScalePath(two, 1.f / scaleFactor, &scaledTwo);
|
||||
subtrahend = &scaledTwo;
|
||||
} else {
|
||||
minuend = &one;
|
||||
subtrahend = &two;
|
||||
}
|
||||
const SkPath* minuend = &one;
|
||||
const SkPath* subtrahend = &two;
|
||||
if (op == kReverseDifference_SkPathOp) {
|
||||
using std::swap;
|
||||
swap(minuend, subtrahend);
|
||||
@ -375,9 +365,6 @@ bool OpDebug(const SkPath& one, const SkPath& two, SkPathOp op, SkPath* result
|
||||
debugWorstState.debugDoYourWorst(&globalState);
|
||||
}
|
||||
#endif
|
||||
if (scaleFactor > 1) {
|
||||
ScalePath(*result, scaleFactor, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -167,19 +167,10 @@ bool SimplifyDebug(const SkPath& path, SkPath* result
|
||||
SkPathOpsDebug::DumpSimplify(path, testName);
|
||||
}
|
||||
#endif
|
||||
SkScalar scaleFactor = ScaleFactor(path);
|
||||
SkPath scaledPath;
|
||||
const SkPath* workingPath;
|
||||
if (scaleFactor > SK_Scalar1) {
|
||||
ScalePath(path, 1.f / scaleFactor, &scaledPath);
|
||||
workingPath = &scaledPath;
|
||||
} else {
|
||||
workingPath = &path;
|
||||
}
|
||||
#if DEBUG_SORT
|
||||
SkPathOpsDebug::gSortCount = SkPathOpsDebug::gSortCountDefault;
|
||||
#endif
|
||||
SkOpEdgeBuilder builder(*workingPath, contourList, &globalState);
|
||||
SkOpEdgeBuilder builder(path, contourList, &globalState);
|
||||
if (!builder.finish()) {
|
||||
return false;
|
||||
}
|
||||
@ -220,9 +211,6 @@ bool SimplifyDebug(const SkPath& path, SkPath* result
|
||||
return false;
|
||||
}
|
||||
wrapper.assemble(); // if some edges could not be resolved, assemble remaining
|
||||
if (scaleFactor > 1) {
|
||||
ScalePath(*result, scaleFactor, result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -279,7 +279,7 @@ private:
|
||||
|
||||
bool binarySearchCoin(SkTSect<OppCurve, TCurve>* , double tStart, double tStep, double* t,
|
||||
double* oppT, SkTSpan<OppCurve, TCurve>** oppFirst);
|
||||
SkTSpan<TCurve, OppCurve>* boundsMax() const;
|
||||
SkTSpan<TCurve, OppCurve>* boundsMax();
|
||||
bool coincidentCheck(SkTSect<OppCurve, TCurve>* sect2);
|
||||
void coincidentForce(SkTSect<OppCurve, TCurve>* sect2, double start1s, double start1e);
|
||||
bool coincidentHasT(double t);
|
||||
@ -344,6 +344,7 @@ private:
|
||||
int fActiveCount;
|
||||
bool fRemovedStartT;
|
||||
bool fRemovedEndT;
|
||||
bool fHung;
|
||||
SkDEBUGCODE(SkOpGlobalState* fDebugGlobalState);
|
||||
SkDEBUGCODE(SkTSect<OppCurve, TCurve>* fOppSect);
|
||||
PATH_OPS_DEBUG_T_SECT_CODE(int fID);
|
||||
@ -875,6 +876,7 @@ SkTSect<TCurve, OppCurve>::SkTSect(const TCurve& c
|
||||
, fCoincident(nullptr)
|
||||
, fDeleted(nullptr)
|
||||
, fActiveCount(0)
|
||||
, fHung(false)
|
||||
SkDEBUGPARAMS(fDebugGlobalState(debugGlobalState))
|
||||
PATH_OPS_DEBUG_T_SECT_PARAMS(fID(id))
|
||||
PATH_OPS_DEBUG_T_SECT_PARAMS(fDebugCount(0))
|
||||
@ -985,11 +987,16 @@ bool SkTSect<TCurve, OppCurve>::binarySearchCoin(SkTSect<OppCurve, TCurve>* sect
|
||||
// so that each quad sect has a pointer to the largest, and can update it as spans
|
||||
// are split
|
||||
template<typename TCurve, typename OppCurve>
|
||||
SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() const {
|
||||
SkTSpan<TCurve, OppCurve>* SkTSect<TCurve, OppCurve>::boundsMax() {
|
||||
SkTSpan<TCurve, OppCurve>* test = fHead;
|
||||
SkTSpan<TCurve, OppCurve>* largest = fHead;
|
||||
bool lCollapsed = largest->fCollapsed;
|
||||
int safetyNet = 10000;
|
||||
while ((test = test->fNext)) {
|
||||
if (!--safetyNet) {
|
||||
fHung = true;
|
||||
return nullptr;
|
||||
}
|
||||
bool tCollapsed = test->fCollapsed;
|
||||
if ((lCollapsed && !tCollapsed) || (lCollapsed == tCollapsed &&
|
||||
largest->fBoundsMax < test->fBoundsMax)) {
|
||||
@ -2197,12 +2204,18 @@ void SkTSect<TCurve, OppCurve>::BinarySearch(SkTSect<TCurve, OppCurve>* sect1,
|
||||
// find the largest bounds
|
||||
SkTSpan<TCurve, OppCurve>* largest1 = sect1->boundsMax();
|
||||
if (!largest1) {
|
||||
if (sect1->fHung) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
SkTSpan<OppCurve, TCurve>* largest2 = sect2->boundsMax();
|
||||
// split it
|
||||
if (!largest2 || (largest1 && (largest1->fBoundsMax > largest2->fBoundsMax
|
||||
|| (!largest1->fCollapsed && largest2->fCollapsed)))) {
|
||||
if (sect2->fHung) {
|
||||
return;
|
||||
}
|
||||
if (largest1->fCollapsed) {
|
||||
break;
|
||||
}
|
||||
|
@ -53,16 +53,7 @@ bool TightBounds(const SkPath& path, SkRect* result) {
|
||||
SkOpGlobalState globalState(contourList, &allocator SkDEBUGPARAMS(false)
|
||||
SkDEBUGPARAMS(nullptr));
|
||||
// turn path into list of segments
|
||||
SkScalar scaleFactor = ScaleFactor(path);
|
||||
SkPath scaledPath;
|
||||
const SkPath* workingPath;
|
||||
if (scaleFactor > SK_Scalar1) {
|
||||
ScalePath(path, 1.f / scaleFactor, &scaledPath);
|
||||
workingPath = &scaledPath;
|
||||
} else {
|
||||
workingPath = &path;
|
||||
}
|
||||
SkOpEdgeBuilder builder(*workingPath, contourList, &globalState);
|
||||
SkOpEdgeBuilder builder(path, contourList, &globalState);
|
||||
if (!builder.finish()) {
|
||||
return false;
|
||||
}
|
||||
@ -75,10 +66,6 @@ bool TightBounds(const SkPath& path, SkRect* result) {
|
||||
while ((current = current->next())) {
|
||||
bounds.add(current->bounds());
|
||||
}
|
||||
if (scaleFactor > SK_Scalar1) {
|
||||
bounds.set(bounds.left() * scaleFactor, bounds.top() * scaleFactor,
|
||||
bounds.right() * scaleFactor, bounds.bottom() * scaleFactor);
|
||||
}
|
||||
*result = bounds;
|
||||
if (!moveBounds.isEmpty()) {
|
||||
result->join(moveBounds);
|
||||
|
@ -5170,6 +5170,9 @@ static void fuzz38(skiatest::Reporter* reporter, const char* filename) {
|
||||
testPathOpCheck(reporter, path, pathB, kUnion_SkPathOp, filename, true);
|
||||
}
|
||||
|
||||
// we currently don't produce meaningful intersections when a path has extremely large segments
|
||||
// intersecting relatively small ones. This bug was reported as a fuzzer bug and wasn't expected
|
||||
// to produce meaningful results
|
||||
static void crbug_526025(skiatest::Reporter* reporter, const char* filename) {
|
||||
SkPath path;
|
||||
path.setFillType((SkPath::FillType) 1);
|
||||
@ -5195,7 +5198,7 @@ path.lineTo(SkBits2Float(0x42fe0000), SkBits2Float(0x43a08000)); // 127, 321
|
||||
path.close();
|
||||
|
||||
SkPath path2(path);
|
||||
testPathOp(reporter, path1, path2, (SkPathOp) 2, filename);
|
||||
testPathOpFuzz(reporter, path1, path2, (SkPathOp) 2, filename);
|
||||
}
|
||||
|
||||
static void fuzzX_392(skiatest::Reporter* reporter, const char* filename) {
|
||||
@ -9083,6 +9086,7 @@ static void (*stopTest)(skiatest::Reporter* , const char* filename) = 0;
|
||||
#define TEST(name) { name, #name }
|
||||
|
||||
static struct TestDesc tests[] = {
|
||||
TEST(crbug_526025),
|
||||
TEST(bug8228),
|
||||
TEST(op_4),
|
||||
TEST(op_1),
|
||||
@ -9110,7 +9114,6 @@ static struct TestDesc tests[] = {
|
||||
TEST(cubics_d),
|
||||
TEST(dean2),
|
||||
TEST(fuzzX_392),
|
||||
TEST(crbug_526025),
|
||||
TEST(fuzz38),
|
||||
TEST(cubics44d),
|
||||
TEST(cubics45u),
|
||||
|
@ -9298,11 +9298,71 @@ path.close();
|
||||
testSimplify(reporter, path, filename);
|
||||
}
|
||||
|
||||
static void bug8290(skiatest::Reporter* reporter, const char* filename) {
|
||||
SkPath path;
|
||||
path.setFillType(SkPath::kEvenOdd_FillType);
|
||||
path.moveTo(-1e+09, -1e+09);
|
||||
path.lineTo(1e+09, -1e+09);
|
||||
path.lineTo(1e+09, 1e+09);
|
||||
path.lineTo(-1e+09, 1e+09);
|
||||
path.lineTo(-1e+09, -1e+09);
|
||||
path.close();
|
||||
path.moveTo(0, 45);
|
||||
path.lineTo(270, 45);
|
||||
path.lineTo(270, 45.381f);
|
||||
path.lineTo(0, 45.381f);
|
||||
path.lineTo(0, 45);
|
||||
path.close();
|
||||
path.moveTo(0, 90.381f);
|
||||
path.lineTo(270, 90.381f);
|
||||
path.lineTo(270, 90.7619f);
|
||||
path.lineTo(0, 90.7619f);
|
||||
path.lineTo(0, 90.381f);
|
||||
path.close();
|
||||
path.moveTo(0, 135.762f);
|
||||
path.lineTo(270, 135.762f);
|
||||
path.lineTo(270, 136.143f);
|
||||
path.lineTo(0, 136.143f);
|
||||
path.lineTo(0, 135.762f);
|
||||
path.close();
|
||||
path.moveTo(0, 181.143f);
|
||||
path.lineTo(270, 181.143f);
|
||||
path.lineTo(270, 181.524f);
|
||||
path.lineTo(0, 181.524f);
|
||||
path.lineTo(0, 181.143f);
|
||||
path.close();
|
||||
path.moveTo(0, 226.524f);
|
||||
path.lineTo(270, 226.524f);
|
||||
path.lineTo(270, 226.905f);
|
||||
path.lineTo(0, 226.905f);
|
||||
path.lineTo(0, 226.524f);
|
||||
path.close();
|
||||
path.moveTo(0, 271.905f);
|
||||
path.lineTo(270, 271.905f);
|
||||
path.lineTo(270, 272.286f);
|
||||
path.lineTo(0, 272.286f);
|
||||
path.lineTo(0, 271.905f);
|
||||
path.close();
|
||||
path.moveTo(0, 317.286f);
|
||||
path.lineTo(270, 317.286f);
|
||||
path.lineTo(270, 317.667f);
|
||||
path.lineTo(0, 317.667f);
|
||||
path.lineTo(0, 317.286f);
|
||||
path.close();
|
||||
SkMatrix matrix = SkMatrix::MakeAll(
|
||||
2.625, 0, 186,
|
||||
0, 2.625, 620,
|
||||
0, 0, 1);
|
||||
path.transform(matrix);
|
||||
testSimplify(reporter, path, filename);
|
||||
}
|
||||
|
||||
static void (*skipTest)(skiatest::Reporter* , const char* filename) = nullptr;
|
||||
static void (*firstTest)(skiatest::Reporter* , const char* filename) = nullptr;
|
||||
static void (*stopTest)(skiatest::Reporter* , const char* filename) = nullptr;
|
||||
|
||||
static TestDesc tests[] = {
|
||||
TEST(bug8290),
|
||||
TEST(bug8249),
|
||||
TEST(grshapearc),
|
||||
TEST(coincubics),
|
||||
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue
Block a user