aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkPath.h73
-rw-r--r--src/core/SkPath.cpp21
-rw-r--r--src/core/SkStroke.cpp5
-rw-r--r--tests/PathTest.cpp30
4 files changed, 72 insertions, 57 deletions
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index 2488dd8bf9..76aad0df0b 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -236,6 +236,15 @@ public:
*/
bool isLine(SkPoint line[2]) const;
+ enum Direction {
+ /** Direction either has not been or could not be computed */
+ kUnknown_Direction,
+ /** clockwise direction for adding closed contours */
+ kCW_Direction,
+ /** counter-clockwise direction for adding closed contours */
+ kCCW_Direction,
+ };
+
/** Returns true if the path specifies a rectangle. If so, and if rect is
not null, set rect to the bounds of the path. If the path does not
specify a rectangle, return false and ignore rect.
@@ -244,7 +253,36 @@ public:
a rectangle
@return true if the path specifies a rectangle
*/
- bool isRect(SkRect* rect) const;
+ bool isRect(SkRect* rect) const {
+ return this->isRect(rect, NULL, NULL);
+ }
+
+ /**
+ * Returns true if the path specifies a rectangle.
+ *
+ * If this returns false, then all output parameters are ignored, and left
+ * unchanged. If this returns true, then each of the output parameters
+ * are checked for NULL. If they are not, they return their value.
+ *
+ * @param rect If not null, set to the bounds of the rectangle
+ * @param isClosed If not null, set to true if the path is closed
+ * @param direction If not null, set to the rectangle's direction
+ * @return true if the path specifies a rectangle
+ */
+ bool isRect(SkRect* rect, bool* isClosed, Direction* direction) const;
+
+ /** Returns true if the path specifies a pair of nested rectangles. If so, and if
+ rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
+ rectangle. If so, and dirs is not null, set dirs[0] to the direction of
+ the outer rectangle and dirs[1] to the direction of the inner rectangle. If
+ the path does not specify a pair of nested rectangles, return
+ false and ignore rect and dirs.
+
+ @param rect If not null, returns the path as a pair of nested rectangles
+ @param dirs If not null, returns the direction of the rects
+ @return true if the path describes a pair of nested rectangles
+ */
+ bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const;
/** Return the number of points in the path
*/
@@ -500,15 +538,6 @@ public:
*/
void close();
- enum Direction {
- /** Direction either has not been or could not be computed */
- kUnknown_Direction,
- /** clockwise direction for adding closed contours */
- kCW_Direction,
- /** counter-clockwise direction for adding closed contours */
- kCCW_Direction,
- };
-
/**
* Return the opposite of the specified direction. kUnknown is its own
* opposite.
@@ -573,30 +602,6 @@ public:
return computedDir == dir;
}
- /** Returns true if the path specifies a rectangle. If so, and if isClosed is
- not null, set isClosed to true if the path is closed. Also, if returning true
- and direction is not null, return the rect direction. If the path does not
- specify a rectangle, return false and ignore isClosed and direction.
-
- @param isClosed If not null, set to true if the path is closed
- @param direction If not null, set to the rectangle's direction
- @return true if the path specifies a rectangle
- */
- bool isRect(bool* isClosed, Direction* direction) const;
-
- /** Returns true if the path specifies a pair of nested rectangles. If so, and if
- rect is not null, set rect[0] to the outer rectangle and rect[1] to the inner
- rectangle. If so, and dirs is not null, set dirs[0] to the direction of
- the outer rectangle and dirs[1] to the direction of the inner rectangle. If
- the path does not specify a pair of nested rectangles, return
- false and ignore rect and dirs.
-
- @param rect If not null, returns the path as a pair of nested rectangles
- @param dirs If not null, returns the direction of the rects
- @return true if the path describes a pair of nested rectangles
- */
- bool isNestedRects(SkRect rect[2], Direction dirs[2] = NULL) const;
-
/**
* Add a closed rectangle contour to the path
* @param rect The rectangle to add as a closed contour to the path
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index e997b80e4f..2d819c168d 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -584,22 +584,19 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
return result;
}
-bool SkPath::isRect(SkRect* rect) const {
+bool SkPath::isRect(SkRect* rect, bool* isClosed, Direction* direction) const {
SkDEBUGCODE(this->validate();)
int currVerb = 0;
const SkPoint* pts = fPathRef->points();
- bool result = isRectContour(false, &currVerb, &pts, NULL, NULL);
- if (result && rect) {
- *rect = getBounds();
+ const SkPoint* first = pts;
+ if (!this->isRectContour(false, &currVerb, &pts, isClosed, direction)) {
+ return false;
}
- return result;
-}
-
-bool SkPath::isRect(bool* isClosed, Direction* direction) const {
- SkDEBUGCODE(this->validate();)
- int currVerb = 0;
- const SkPoint* pts = fPathRef->points();
- return isRectContour(false, &currVerb, &pts, isClosed, direction);
+
+ if (rect) {
+ rect->set(first, SkToS32(pts - first));
+ }
+ return true;
}
bool SkPath::isNestedRects(SkRect rects[2], Direction dirs[2]) const {
diff --git a/src/core/SkStroke.cpp b/src/core/SkStroke.cpp
index d094ef65b7..2fd5a14c2c 100644
--- a/src/core/SkStroke.cpp
+++ b/src/core/SkStroke.cpp
@@ -549,10 +549,11 @@ void SkStroke::strokePath(const SkPath& src, SkPath* dst) const {
// If src is really a rect, call our specialty strokeRect() method
{
+ SkRect rect;
bool isClosed;
SkPath::Direction dir;
- if (src.isRect(&isClosed, &dir) && isClosed) {
- this->strokeRect(src.getBounds(), dst, dir);
+ if (src.isRect(&rect, &isClosed, &dir) && isClosed) {
+ this->strokeRect(rect, dst, dir);
// our answer should preserve the inverseness of the src
if (src.isInverseFillType()) {
SkASSERT(!dst->isInverseFillType());
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index 6c8f83e540..41151a54bc 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -1230,8 +1230,7 @@ static void test_isRect(skiatest::Reporter* reporter) {
if (close) {
path.close();
}
- REPORTER_ASSERT(reporter, fail ^ path.isRect(0));
- REPORTER_ASSERT(reporter, fail ^ path.isRect(NULL, NULL));
+ REPORTER_ASSERT(reporter, fail ^ path.isRect(NULL));
if (!fail) {
SkRect computed, expected;
@@ -1242,7 +1241,7 @@ static void test_isRect(skiatest::Reporter* reporter) {
bool isClosed;
SkPath::Direction direction, cheapDirection;
REPORTER_ASSERT(reporter, path.cheapComputeDirection(&cheapDirection));
- REPORTER_ASSERT(reporter, path.isRect(&isClosed, &direction));
+ REPORTER_ASSERT(reporter, path.isRect(NULL, &isClosed, &direction));
REPORTER_ASSERT(reporter, isClosed == close);
REPORTER_ASSERT(reporter, direction == cheapDirection);
} else {
@@ -1254,7 +1253,7 @@ static void test_isRect(skiatest::Reporter* reporter) {
bool isClosed = (bool) -1;
SkPath::Direction direction = (SkPath::Direction) -1;
- REPORTER_ASSERT(reporter, !path.isRect(&isClosed, &direction));
+ REPORTER_ASSERT(reporter, !path.isRect(NULL, &isClosed, &direction));
REPORTER_ASSERT(reporter, isClosed == (bool) -1);
REPORTER_ASSERT(reporter, direction == (SkPath::Direction) -1);
}
@@ -1275,7 +1274,7 @@ static void test_isRect(skiatest::Reporter* reporter) {
}
path1.close();
path1.lineTo(1, 0);
- REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
+ REPORTER_ASSERT(reporter, fail ^ path1.isRect(NULL));
// fail, move in the middle
path1.reset();
@@ -1287,7 +1286,7 @@ static void test_isRect(skiatest::Reporter* reporter) {
path1.lineTo(r1[index].fX, r1[index].fY);
}
path1.close();
- REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
+ REPORTER_ASSERT(reporter, fail ^ path1.isRect(NULL));
// fail, move on the edge
path1.reset();
@@ -1296,7 +1295,7 @@ static void test_isRect(skiatest::Reporter* reporter) {
path1.lineTo(r1[index].fX, r1[index].fY);
}
path1.close();
- REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
+ REPORTER_ASSERT(reporter, fail ^ path1.isRect(NULL));
// fail, quad
path1.reset();
@@ -1308,7 +1307,7 @@ static void test_isRect(skiatest::Reporter* reporter) {
path1.lineTo(r1[index].fX, r1[index].fY);
}
path1.close();
- REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
+ REPORTER_ASSERT(reporter, fail ^ path1.isRect(NULL));
// fail, cubic
path1.reset();
@@ -1320,7 +1319,7 @@ static void test_isRect(skiatest::Reporter* reporter) {
path1.lineTo(r1[index].fX, r1[index].fY);
}
path1.close();
- REPORTER_ASSERT(reporter, fail ^ path1.isRect(0));
+ REPORTER_ASSERT(reporter, fail ^ path1.isRect(NULL));
}
static void test_isNestedRects(skiatest::Reporter* reporter) {
@@ -2409,6 +2408,19 @@ static void TestPath(skiatest::Reporter* reporter) {
p.addRect(bounds);
REPORTER_ASSERT(reporter, !p.isRect(NULL));
+ // test isRect for a trailing moveTo
+ {
+ SkRect r;
+ p.reset();
+ p.addRect(bounds);
+ REPORTER_ASSERT(reporter, p.isRect(&r));
+ REPORTER_ASSERT(reporter, r == bounds);
+ // add a moveTo outside of our bounds
+ p.moveTo(bounds.fLeft + 10, bounds.fBottom + 10);
+ REPORTER_ASSERT(reporter, p.isRect(&r));
+ REPORTER_ASSERT(reporter, r == bounds);
+ }
+
test_isLine(reporter);
test_isRect(reporter);
test_isNestedRects(reporter);