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 |