| Index: src/core/SkPath.cpp
|
| diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
|
| index 9df62850fd2eb5bc9cf442dc4675b7091cded8c1..3442884dcaecb3428b1dbace247956bd745ca51e 100644
|
| --- a/src/core/SkPath.cpp
|
| +++ b/src/core/SkPath.cpp
|
| @@ -2283,8 +2283,17 @@ void SkPath::validate() const {
|
| static int sign(SkScalar x) { return x < 0; }
|
| #define kValueNeverReturnedBySign 2
|
|
|
| -static int CrossProductSign(const SkVector& a, const SkVector& b) {
|
| - return SkScalarSignAsInt(SkPoint::CrossProduct(a, b));
|
| +static bool AlmostEqual(SkScalar compA, SkScalar compB) {
|
| + const int epsilon = 16;
|
| + if (!SkScalarIsFinite(compA) || !SkScalarIsFinite(compB)) {
|
| + return false;
|
| + }
|
| + if (sk_float_abs(compA) <= FLT_EPSILON && sk_float_abs(compB) <= FLT_EPSILON) {
|
| + return true;
|
| + }
|
| + int aBits = SkFloatAs2sCompliment(compA);
|
| + int bBits = SkFloatAs2sCompliment(compB);
|
| + return aBits < bBits + epsilon && bBits < aBits + epsilon;
|
| }
|
|
|
| // only valid for a single contour
|
| @@ -2320,6 +2329,7 @@ struct Convexicator {
|
| } else {
|
| SkVector vec = pt - fCurrPt;
|
| if (vec.fX || vec.fY) {
|
| + fLastPt = fCurrPt;
|
| fCurrPt = pt;
|
| if (++fPtCount == 2) {
|
| fFirstVec = fVec1 = vec;
|
| @@ -2353,7 +2363,11 @@ private:
|
| SkASSERT(vec.fX || vec.fY);
|
| fVec0 = fVec1;
|
| fVec1 = vec;
|
| - int sign = CrossProductSign(fVec0, fVec1);
|
| + SkScalar cross = SkPoint::CrossProduct(fVec0, fVec1);
|
| + SkScalar smallest = SkTMin(fCurrPt.fX, SkTMin(fCurrPt.fY, SkTMin(fLastPt.fX, fLastPt.fY)));
|
| + SkScalar largest = SkTMax(fCurrPt.fX, SkTMax(fCurrPt.fY, SkTMax(fLastPt.fX, fLastPt.fY)));
|
| + largest = SkTMax(largest, -smallest);
|
| + int sign = AlmostEqual(largest, largest + cross) ? 0 : SkScalarSignAsInt(cross);
|
| if (0 == fSign) {
|
| fSign = sign;
|
| if (1 == sign) {
|
| @@ -2369,6 +2383,7 @@ private:
|
| }
|
| }
|
|
|
| + SkPoint fLastPt;
|
| SkPoint fCurrPt;
|
| SkVector fVec0, fVec1, fFirstVec;
|
| int fPtCount; // non-degenerate points
|
|
|