aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar Mike Reed <reed@google.com>2018-01-10 14:31:18 -0500
committerGravatar Mike Reed <reed@google.com>2018-01-10 20:39:33 +0000
commitd284949b595e2d7c6c6901c5b49e822a02a4d79f (patch)
tree7aebd5fb935638ba85f34112ccb3f9b39fd039a8
parent5366e59e8826a235d25f34f50ae1b93ee9675663 (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.bmh38
-rw-r--r--gm/hugepath.cpp28
-rw-r--r--gn/gm.gni1
-rw-r--r--include/core/SkRect.h81
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);
+}
+
diff --git a/gn/gm.gni b/gn/gm.gni
index cdbe829a8c..25c80bf886 100644
--- a/gn/gm.gni
+++ b/gn/gm.gni
@@ -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