diff options
author | Mike Reed <reed@google.com> | 2018-01-10 14:31:18 -0500 |
---|---|---|
committer | Mike Reed <reed@google.com> | 2018-01-10 20:39:33 +0000 |
commit | d284949b595e2d7c6c6901c5b49e822a02a4d79f (patch) | |
tree | 7aebd5fb935638ba85f34112ccb3f9b39fd039a8 | |
parent | 5366e59e8826a235d25f34f50ae1b93ee9675663 (diff) |
restore intersect methods to use old-style empty-checks on their inputs
Bug introduced when we made isEmpty check for int32_t width/height
Bug:800804
Change-Id: I59799c88fb02f176c1545dd0edae050b510df079
Reviewed-on: https://skia-review.googlesource.com/93302
Reviewed-by: Florin Malita <fmalita@chromium.org>
Commit-Queue: Mike Reed <reed@google.com>
-rw-r--r-- | docs/SkIRect_Reference.bmh | 38 | ||||
-rw-r--r-- | gm/hugepath.cpp | 28 | ||||
-rw-r--r-- | gn/gm.gni | 1 | ||||
-rw-r--r-- | include/core/SkRect.h | 81 |
4 files changed, 98 insertions, 50 deletions
diff --git a/docs/SkIRect_Reference.bmh b/docs/SkIRect_Reference.bmh index 48dcbd57d7..a1b62b046a 100644 --- a/docs/SkIRect_Reference.bmh +++ b/docs/SkIRect_Reference.bmh @@ -54,7 +54,8 @@ its top, it is considered empty. # intersect # Sets to shared area; returns true if not empty. ## # intersectNoEmptyCheck # Sets to shared area; returns true if not empty. Skips empty check. ## # is16Bit # Returns true if members fit in 16-bit word. ## -# isEmpty # Returns true if width or height are zero or negative. ## +# isEmpty # Returns true if width or height are zero or negative or they exceed int32_t. ## +# isEmpty64 # Returns true if width or height are zero or negative. ## # join() # Sets to union of bounds. ## # left() # Returns smaller bounds in x, if sorted. ## # makeInset # Constructs from sides moved symmetrically about the center. ## @@ -584,9 +585,7 @@ left: 1073741824 right: 1073741826 centerX: -1073741823 safe mid x: 1073741825 #Method bool isEmpty() const -Returns true if fLeft is equal to or greater than fRight, or if fTop is equal -to or greater than fBottom. Call sort() to reverse rectangles with negative -width() or height(). +Returns true if width() or height() . #Return true if width() or height() are zero or negative ## @@ -613,6 +612,37 @@ sorted: {20, 40, 20, 50} is empty # ------------------------------------------------------------------------------ +#Method bool isEmpty64() const + +Returns true if fLeft is equal to or greater than fRight, or if fTop is equal +to or greater than fBottom. Call sort() to reverse rectangles with negative +width64() or height64(). + +#Return true if width64() or height64() are zero or negative ## + +#Example +SkIRect tests[] = {{20, 40, 10, 50}, {20, 40, 20, 50}}; +for (auto rect : tests) { +SkDebugf("rect: {%d, %d, %d, %d} is" "%s empty\n", rect.left(), rect.top(), rect.right(), +rect.bottom(), isEmpty64() ? "" : " not"); +rect.sort(); +SkDebugf("sorted: {%d, %d, %d, %d} is" "%s empty\n", rect.left(), rect.top(), rect.right(), +rect.bottom(), isEmpty64() ? "" : " not"); +} +#StdOut +rect: {20, 40, 10, 50} is empty +sorted: {10, 40, 20, 50} is not empty +rect: {20, 40, 20, 50} is empty +sorted: {20, 40, 20, 50} is empty +## +## + +#SeeAlso EmptyIRect MakeEmpty sort SkRect::isEmpty + +## + +# ------------------------------------------------------------------------------ + #Method bool operator==(const SkIRect& a, const SkIRect& b) Returns true if all members in a: fLeft, fTop, fRight, and fBottom; are diff --git a/gm/hugepath.cpp b/gm/hugepath.cpp new file mode 100644 index 0000000000..dbca413093 --- /dev/null +++ b/gm/hugepath.cpp @@ -0,0 +1,28 @@ +/* + * Copyright 2018 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "gm.h" +#include "SkCanvas.h" +#include "SkPath.h" + +DEF_SIMPLE_GM(path_huge_crbug_800804, canvas, 30, 600) { + SkPaint paint; + paint.setAntiAlias(true); + + paint.setStyle(SkPaint::kStroke_Style); + paint.setStrokeWidth(1); + SkPath path; + path.moveTo(-1000,12345678901234567890.f); + path.lineTo(10.5f,200); + canvas->drawPath(path, paint); + + path.reset(); + path.moveTo(20.5f,400); + path.lineTo(1000,-9.8765432109876543210e+19f); + canvas->drawPath(path, paint); +} + @@ -162,6 +162,7 @@ gm_sources = [ "$_gm/hardstop_gradients.cpp", "$_gm/highcontrastfilter.cpp", "$_gm/hittestpath.cpp", + "$_gm/hugepath.cpp", "$_gm/hsl.cpp", "$_gm/image.cpp", "$_gm/image_pict.cpp", diff --git a/include/core/SkRect.h b/include/core/SkRect.h index eae2e49e4b..b09e53997b 100644 --- a/include/core/SkRect.h +++ b/include/core/SkRect.h @@ -197,6 +197,12 @@ struct SK_API SkIRect { int64_t width64() const { return (int64_t)fRight - (int64_t)fLeft; } int64_t height64() const { return (int64_t)fBottom - (int64_t)fTop; } + /** Returns true if the rectangle's dimensions are non-positive. + * Unlike isEmpty(), this does not worry about the size of the width or height, which could + * exceed int32_t but still be logically non-empty. + */ + bool isEmpty64() const { return fRight <= fLeft || fBottom <= fTop; } + /** Returns true if the rectangle's dimensions are non-positive or if either its width or hieght * exceeds int32_t. */ @@ -529,53 +535,47 @@ struct SK_API SkIRect { @return true if r and SkRect have area in common */ bool intersect(const SkIRect& r) { - return this->intersect(r.fLeft, r.fTop, r.fRight, r.fBottom); + return this->intersect(*this, r); } /** Returns true if a intersects b, and sets SkIRect to intersection. Returns false if a does not intersect b, and leaves SkIRect unchanged. - Returns false if either a or b is empty, leaving SkIRect unchanged. + Asserts if either a or b is empty, and if SK_DEBUG is defined. @param a SkIRect to intersect @param b SkIRect to intersect @return true if a and b have area in common */ - bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) { - - if (!a.isEmpty() && !b.isEmpty() && - a.fLeft < b.fRight && b.fLeft < a.fRight && - a.fTop < b.fBottom && b.fTop < a.fBottom) { - fLeft = SkMax32(a.fLeft, b.fLeft); - fTop = SkMax32(a.fTop, b.fTop); - fRight = SkMin32(a.fRight, b.fRight); - fBottom = SkMin32(a.fBottom, b.fBottom); - return true; + bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) { + SkASSERT(!a.isEmpty64() && !b.isEmpty64()); + SkIRect r = { + SkMax32(a.fLeft, b.fLeft), + SkMax32(a.fTop, b.fTop), + SkMin32(a.fRight, b.fRight), + SkMin32(a.fBottom, b.fBottom) + }; + if (r.isEmpty()) { + return false; } - return false; + *this = r; + return true; } /** Returns true if a intersects b, and sets SkIRect to intersection. - Returns false if a does not intersect b, and leaves SkIRect unchanged. + Returns false if a does not intersect b, and leaves SkIRect unchanged. - Asserts if either a or b is empty, and if SK_DEBUG is defined. + Returns false if either a or b is empty, leaving SkIRect unchanged. - @param a SkIRect to intersect - @param b SkIRect to intersect - @return true if a and b have area in common - */ - bool SK_WARN_UNUSED_RESULT intersectNoEmptyCheck(const SkIRect& a, const SkIRect& b) { - SkASSERT(!a.isEmpty() && !b.isEmpty()); - - if (a.fLeft < b.fRight && b.fLeft < a.fRight && - a.fTop < b.fBottom && b.fTop < a.fBottom) { - fLeft = SkMax32(a.fLeft, b.fLeft); - fTop = SkMax32(a.fTop, b.fTop); - fRight = SkMin32(a.fRight, b.fRight); - fBottom = SkMin32(a.fBottom, b.fBottom); - return true; + @param a SkIRect to intersect + @param b SkIRect to intersect + @return true if a and b have area in common + */ + bool SK_WARN_UNUSED_RESULT intersect(const SkIRect& a, const SkIRect& b) { + if (a.isEmpty64() || b.isEmpty64()) { + return false; } - return false; + return this->intersectNoEmptyCheck(a, b); } /** Constructs SkIRect to intersect from (left, top, right, bottom). Does not sort @@ -593,15 +593,7 @@ struct SK_API SkIRect { @return true if construction and SkIRect have area in common */ bool intersect(int32_t left, int32_t top, int32_t right, int32_t bottom) { - if (left < right && top < bottom && !this->isEmpty() && - fLeft < right && left < fRight && fTop < bottom && top < fBottom) { - if (fLeft < left) fLeft = left; - if (fTop < top) fTop = top; - if (fRight > right) fRight = right; - if (fBottom > bottom) fBottom = bottom; - return true; - } - return false; + return this->intersect(*this, {left, top, right, bottom}); } /** Returns true if a intersects b. @@ -612,9 +604,8 @@ struct SK_API SkIRect { @return true if a and b have area in common */ static bool Intersects(const SkIRect& a, const SkIRect& b) { - return !a.isEmpty() && !b.isEmpty() && // check for empties - a.fLeft < b.fRight && b.fLeft < a.fRight && - a.fTop < b.fBottom && b.fTop < a.fBottom; + SkIRect dummy; + return dummy.intersect(a, b); } /** Returns true if a intersects b. @@ -625,10 +616,8 @@ struct SK_API SkIRect { @return true if a and b have area in common */ static bool IntersectsNoEmptyCheck(const SkIRect& a, const SkIRect& b) { - SkASSERT(!a.isEmpty()); - SkASSERT(!b.isEmpty()); - return a.fLeft < b.fRight && b.fLeft < a.fRight && - a.fTop < b.fBottom && b.fTop < a.fBottom; + SkIRect dummy; + return dummy.intersectNoEmptyCheck(a, b); } /** Constructs SkRect to intersect from (left, top, right, bottom). Does not sort |