allow conic chop to fail
Fuzzy values may cause the conic chop to fail. Check to see if the values are all finite, and require the caller to do the same. R=reed@google.com BUG=650178 GOLD_TRYBOT_URL= https://gold.skia.org/search?issue=2368993002 Review-Url: https://codereview.chromium.org/2368993002
This commit is contained in:
parent
849f5027e9
commit
414c4295f9
@ -353,7 +353,10 @@ private:
|
||||
if (dst) {
|
||||
SkConic conic;
|
||||
conic.set(src, weight);
|
||||
conic.chopAt(t, dst);
|
||||
if (!conic.chopAt(t, dst)) {
|
||||
dst[0].set(src, weight);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
@ -220,7 +220,9 @@ static void add_path_segment(int index, SkPath* path) {
|
||||
SkConic chop[2];
|
||||
SkConic conic;
|
||||
conic.set(pts, iter.conicWeight());
|
||||
conic.chopAt(0.5f, chop);
|
||||
if (!conic.chopAt(0.5f, chop)) {
|
||||
return;
|
||||
}
|
||||
result.conicTo(chop[0].fPts[1], chop[0].fPts[2], chop[0].fW);
|
||||
pts[1] = chop[1].fPts[1];
|
||||
weight = chop[1].fW;
|
||||
@ -1360,9 +1362,10 @@ public:
|
||||
SkConic split[2];
|
||||
SkConic conic;
|
||||
conic.set(pts, weight);
|
||||
conic.chopAt(0.5f, split);
|
||||
conic_coverage(split[0].fPts, split[0].fW, distanceMap, w, h);
|
||||
conic_coverage(split[1].fPts, split[1].fW, distanceMap, w, h);
|
||||
if (conic.chopAt(0.5f, split)) {
|
||||
conic_coverage(split[0].fPts, split[0].fW, distanceMap, w, h);
|
||||
conic_coverage(split[1].fPts, split[1].fW, distanceMap, w, h);
|
||||
}
|
||||
}
|
||||
|
||||
void cubic_coverage(SkPoint pts[4], uint8_t* distanceMap, int w, int h) {
|
||||
|
@ -975,7 +975,8 @@ static void ratquad_mapTo3D(const SkPoint src[3], SkScalar w, SkP3D dst[]) {
|
||||
dst[2].set(src[2].fX * 1, src[2].fY * 1, 1);
|
||||
}
|
||||
|
||||
void SkConic::chopAt(SkScalar t, SkConic dst[2]) const {
|
||||
// return false if infinity or NaN is generated; caller must check
|
||||
bool SkConic::chopAt(SkScalar t, SkConic dst[2]) const {
|
||||
SkP3D tmp[3], tmp2[3];
|
||||
|
||||
ratquad_mapTo3D(fPts, fW, tmp);
|
||||
@ -1001,18 +1002,23 @@ void SkConic::chopAt(SkScalar t, SkConic dst[2]) const {
|
||||
SkScalar root = SkScalarSqrt(tmp2[1].fZ);
|
||||
dst[0].fW = tmp2[0].fZ / root;
|
||||
dst[1].fW = tmp2[2].fZ / root;
|
||||
SkASSERT(sizeof(dst[0]) == sizeof(SkScalar) * 7);
|
||||
SkASSERT(0 == offsetof(SkConic, fPts[0].fX));
|
||||
return SkScalarsAreFinite(&dst[0].fPts[0].fX, 7 * 2);
|
||||
}
|
||||
|
||||
void SkConic::chopAt(SkScalar t1, SkScalar t2, SkConic* dst) const {
|
||||
if (0 == t1 || 1 == t2) {
|
||||
if (0 == t1 && 1 == t2) {
|
||||
*dst = *this;
|
||||
return;
|
||||
} else {
|
||||
SkConic pair[2];
|
||||
this->chopAt(t1 ? t1 : t2, pair);
|
||||
*dst = pair[SkToBool(t1)];
|
||||
if (this->chopAt(t1 ? t1 : t2, pair)) {
|
||||
*dst = pair[SkToBool(t1)];
|
||||
return;
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
SkConicCoeff coeff(*this);
|
||||
Sk2s tt1(t1);
|
||||
@ -1243,7 +1249,10 @@ bool SkConic::findYExtrema(SkScalar* t) const {
|
||||
bool SkConic::chopAtXExtrema(SkConic dst[2]) const {
|
||||
SkScalar t;
|
||||
if (this->findXExtrema(&t)) {
|
||||
this->chopAt(t, dst);
|
||||
if (!this->chopAt(t, dst)) {
|
||||
// if chop can't return finite values, don't chop
|
||||
return false;
|
||||
}
|
||||
// now clean-up the middle, since we know t was meant to be at
|
||||
// an X-extrema
|
||||
SkScalar value = dst[0].fPts[2].fX;
|
||||
@ -1258,7 +1267,10 @@ bool SkConic::chopAtXExtrema(SkConic dst[2]) const {
|
||||
bool SkConic::chopAtYExtrema(SkConic dst[2]) const {
|
||||
SkScalar t;
|
||||
if (this->findYExtrema(&t)) {
|
||||
this->chopAt(t, dst);
|
||||
if (!this->chopAt(t, dst)) {
|
||||
// if chop can't return finite values, don't chop
|
||||
return false;
|
||||
}
|
||||
// now clean-up the middle, since we know t was meant to be at
|
||||
// an Y-extrema
|
||||
SkScalar value = dst[0].fPts[2].fY;
|
||||
|
@ -215,7 +215,7 @@ struct SkConic {
|
||||
* be used.
|
||||
*/
|
||||
void evalAt(SkScalar t, SkPoint* pos, SkVector* tangent = nullptr) const;
|
||||
void chopAt(SkScalar t, SkConic dst[2]) const;
|
||||
bool SK_WARN_UNUSED_RESULT chopAt(SkScalar t, SkConic dst[2]) const;
|
||||
void chopAt(SkScalar t1, SkScalar t2, SkConic* dst) const;
|
||||
void chop(SkConic dst[2]) const;
|
||||
|
||||
|
@ -85,14 +85,16 @@ void SkPathMeasure_segTo(const SkPoint pts[], unsigned segType,
|
||||
dst->conicTo(conic.fPts[1], conic.fPts[2], conic.fW);
|
||||
} else {
|
||||
SkConic tmp[2];
|
||||
conic.chopAt(stopT, tmp);
|
||||
dst->conicTo(tmp[0].fPts[1], tmp[0].fPts[2], tmp[0].fW);
|
||||
if (conic.chopAt(stopT, tmp)) {
|
||||
dst->conicTo(tmp[0].fPts[1], tmp[0].fPts[2], tmp[0].fW);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (SK_Scalar1 == stopT) {
|
||||
SkConic tmp1[2];
|
||||
conic.chopAt(startT, tmp1);
|
||||
dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW);
|
||||
if (conic.chopAt(startT, tmp1)) {
|
||||
dst->conicTo(tmp1[1].fPts[1], tmp1[1].fPts[2], tmp1[1].fW);
|
||||
}
|
||||
} else {
|
||||
SkConic tmp;
|
||||
conic.chopAt(startT, stopT, &tmp);
|
||||
|
@ -145,7 +145,10 @@ static int split_conic(const SkPoint src[3], SkConic dst[2], const SkScalar weig
|
||||
if (dst) {
|
||||
SkConic conic;
|
||||
conic.set(src, weight);
|
||||
conic.chopAt(t, dst);
|
||||
if (!conic.chopAt(t, dst)) {
|
||||
dst[0].set(src, weight);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 2;
|
||||
}
|
||||
|
@ -231,7 +231,11 @@ bool SkOpEdgeBuilder::walk() {
|
||||
if (maxCurvature > 0) {
|
||||
SkConic conic(pointsPtr, weight);
|
||||
SkConic pair[2];
|
||||
conic.chopAt(maxCurvature, pair);
|
||||
if (!conic.chopAt(maxCurvature, pair)) {
|
||||
// if result can't be computed, use original
|
||||
fCurrentContour->addConic(pointsPtr, weight);
|
||||
break;
|
||||
}
|
||||
SkPoint cStorage[2][3];
|
||||
SkPath::Verb v1 = SkReduceOrder::Conic(pair[0], cStorage[0]);
|
||||
SkPath::Verb v2 = SkReduceOrder::Conic(pair[1], cStorage[1]);
|
||||
|
@ -165,7 +165,9 @@ static void chopBothWays(const SkDConic& dConic, double t, const char* name) {
|
||||
conic.fW = dConic.fWeight;
|
||||
SkConic chopped[2];
|
||||
SkDConic dChopped[2];
|
||||
conic.chopAt(SkDoubleToScalar(t), chopped);
|
||||
if (!conic.chopAt(SkDoubleToScalar(t), chopped)) {
|
||||
return;
|
||||
}
|
||||
dChopped[0] = dConic.subDivide(0, t);
|
||||
dChopped[1] = dConic.subDivide(t, 1);
|
||||
#if DEBUG_VISUALIZE_CONICS
|
||||
|
@ -7915,7 +7915,29 @@ path.cubicTo(SkBits2Float(0x6d06f06a), SkBits2Float(0xe30465cf), SkBits2Float(0x
|
||||
testPathOpFuzz(reporter, path1, path2, (SkPathOp) 4, filename);
|
||||
}
|
||||
|
||||
static void fuzz763_44(skiatest::Reporter* reporter, const char* filename) {
|
||||
SkPath path;
|
||||
path.setFillType((SkPath::FillType) 1);
|
||||
path.moveTo(SkBits2Float(0x7c223bab), SkBits2Float(0x7cf35966)); // 3.36945e+36f, 1.01083e+37f
|
||||
path.quadTo(SkBits2Float(0x00000000), SkBits2Float(0x7ccaca6d), SkBits2Float(0x00000000), SkBits2Float(0x00000000)); // 0, 8.4236e+36f, 0, 0
|
||||
path.lineTo(SkBits2Float(0x7d7d7d7d), SkBits2Float(0x00000000)); // 2.10591e+37f, 0
|
||||
path.quadTo(SkBits2Float(0x7ccacab0), SkBits2Float(0x7d1817f4), SkBits2Float(0x7c223bab), SkBits2Float(0x7cf35966)); // 8.42364e+36f, 1.26354e+37f, 3.36945e+36f, 1.01083e+37f
|
||||
path.close();
|
||||
|
||||
SkPath path1(path);
|
||||
path.reset();
|
||||
path.setFillType((SkPath::FillType) 0);
|
||||
path.moveTo(SkBits2Float(0x109d0000), SkBits2Float(0xff7bc000)); // 6.19256e-29f, -3.34633e+38f
|
||||
path.conicTo(SkBits2Float(0x979797ed), SkBits2Float(0x3a214797), SkBits2Float(0x28aa217a), SkBits2Float(0x01007272), SkBits2Float(0x00000072)); // -9.7965e-25f, 0.000615233f, 1.88883e-14f, 2.3592e-38f, 1.59748e-43f
|
||||
path.quadTo(SkBits2Float(0x72728302), SkBits2Float(0x8b727272), SkBits2Float(0x72727272), SkBits2Float(0xc00308f6)); // 4.80344e+30f, -4.66936e-32f, 4.80216e+30f, -2.04742f
|
||||
path.conicTo(SkBits2Float(0x7f52753a), SkBits2Float(0x8072ffff), SkBits2Float(0x67af2103), SkBits2Float(0x7d2a6847), SkBits2Float(0x7d7d7d7d)); // 2.79747e+38f, -1.05611e-38f, 1.65405e+24f, 1.41569e+37f, 2.10591e+37f
|
||||
|
||||
SkPath path2(path);
|
||||
testPathOpFuzz(reporter, path1, path2, (SkPathOp) 3, filename);
|
||||
}
|
||||
|
||||
static struct TestDesc failTests[] = {
|
||||
TEST(fuzz763_44),
|
||||
TEST(fuzz763_43),
|
||||
TEST(fuzz763_42),
|
||||
TEST(fuzz763_41),
|
||||
|
Loading…
Reference in New Issue
Block a user