diff options
author | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-07-26 15:20:36 +0000 |
---|---|---|
committer | reed@google.com <reed@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81> | 2012-07-26 15:20:36 +0000 |
commit | 0bb18bb264b26afca45452910437c09445e23a3c (patch) | |
tree | de94a02e74a789b5a80ad9e6a3b8fdcda9573215 /include/core | |
parent | 904160772ed097cd481d6fcd8a3f4bf0a1af8b52 (diff) |
explicitly track if a path is finite or not
we need this (it appears) so we can definitively reject non-finite paths
in canvas, before passing them down into the guts.
Review URL: https://codereview.appspot.com/6453047
git-svn-id: http://skia.googlecode.com/svn/trunk@4784 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'include/core')
-rw-r--r-- | include/core/SkPath.h | 13 | ||||
-rw-r--r-- | include/core/SkPoint.h | 23 | ||||
-rw-r--r-- | include/core/SkRect.h | 18 |
3 files changed, 50 insertions, 4 deletions
diff --git a/include/core/SkPath.h b/include/core/SkPath.h index 8f03de1e86..fcb3cb5f86 100644 --- a/include/core/SkPath.h +++ b/include/core/SkPath.h @@ -192,6 +192,17 @@ public: */ bool isEmpty() const; + /** + * Returns true if all of the points in this path are finite, meaning there + * are no infinities and no NaNs. + */ + bool isFinite() const { + if (fBoundsIsDirty) { + this->computeBounds(); + } + return fIsFinite; + } + /** Test a line for zero length @return true if the line is of zero length; otherwise false. @@ -818,7 +829,7 @@ private: uint8_t fSegmentMask; mutable uint8_t fBoundsIsDirty; mutable uint8_t fConvexity; - + mutable SkBool8 fIsFinite; // only meaningful if bounds are valid mutable SkBool8 fIsOval; #ifdef SK_BUILD_FOR_ANDROID uint32_t fGenerationID; diff --git a/include/core/SkPoint.h b/include/core/SkPoint.h index ffe11595f1..5e20f530c4 100644 --- a/include/core/SkPoint.h +++ b/include/core/SkPoint.h @@ -314,6 +314,29 @@ struct SK_API SkPoint { fY -= v.fY; } + /** + * Returns true if both X and Y are finite (not infinity or NaN) + */ + bool isFinite() const { +#ifdef SK_SCALAR_IS_FLOAT + SkScalar accum = 0; + accum *= fX; + accum *= fY; + + // accum is either NaN or it is finite (zero). + SkASSERT(0 == accum || !(accum == accum)); + + // value==value will be true iff value is not NaN + // TODO: is it faster to say !accum or accum==accum? + return accum == accum; +#else + // use bit-or for speed, since we don't care about short-circuting the + // tests, and we expect the common case will be that we need to check all. + int isNaN = (SK_FixedNaN == fX) | (SK_FixedNaN == fX)); + return !isNaN; +#endif + } + /** Returns true if the point's coordinates equal (x,y) */ bool equals(SkScalar x, SkScalar y) const { return fX == x && fY == y; } diff --git a/include/core/SkRect.h b/include/core/SkRect.h index 83ef2df35c..723f5f6e2b 100644 --- a/include/core/SkRect.h +++ b/include/core/SkRect.h @@ -448,13 +448,25 @@ struct SK_API SkRect { If the array is empty (count == 0), then set this rectangle to the empty rectangle (0,0,0,0) */ - void set(const SkPoint pts[], int count); + void set(const SkPoint pts[], int count) { + // set() had been checking for non-finite values, so keep that behavior + // for now. Now that we have setBoundsCheck(), we may decide to make + // set() be simpler/faster, and not check for those. + (void)this->setBoundsCheck(pts, count); + } // alias for set(pts, count) void setBounds(const SkPoint pts[], int count) { - this->set(pts, count); + (void)this->setBoundsCheck(pts, count); } - + + /** + * Compute the bounds of the array of points, and set this rect to that + * bounds and return true... unless a non-finite value is encountered, + * in which case this rect is set to empty and false is returned. + */ + bool setBoundsCheck(const SkPoint pts[], int count); + void set(const SkPoint& p0, const SkPoint& p1) { fLeft = SkMinScalar(p0.fX, p1.fX); fRight = SkMaxScalar(p0.fX, p1.fX); |