aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--include/core/SkPath.h14
-rw-r--r--src/core/SkPath.cpp26
-rw-r--r--tests/PathTest.cpp22
3 files changed, 55 insertions, 7 deletions
diff --git a/include/core/SkPath.h b/include/core/SkPath.h
index b2a034f2a4..cea964c177 100644
--- a/include/core/SkPath.h
+++ b/include/core/SkPath.h
@@ -535,6 +535,17 @@ public:
return this->cheapComputeDirection(&computedDir) && 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;
+
/** Add a closed rectangle contour to the path
@param rect The rectangle to add as a closed contour to the path
@param dir The direction to wind the rectangle's contour
@@ -917,7 +928,8 @@ private:
Convexity internalGetConvexity() const;
- bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts) const;
+ bool isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts,
+ bool* isClosed, Direction* direction) const;
friend class SkAutoPathBoundsUpdate;
friend class SkAutoDisableOvalCheck;
diff --git a/src/core/SkPath.cpp b/src/core/SkPath.cpp
index 307f7fddd0..c3aa44e117 100644
--- a/src/core/SkPath.cpp
+++ b/src/core/SkPath.cpp
@@ -459,9 +459,9 @@ bool SkPath::isLine(SkPoint line[2]) const {
The direction is computed such that:
0: vertical up
- 1: horizontal right
+ 1: horizontal left
2: vertical down
- 3: horizontal left
+ 3: horizontal right
A rectangle cycles up/right/down/left or up/left/down/right.
@@ -488,7 +488,8 @@ FIXME: Allow colinear quads and cubics to be treated like lines.
FIXME: If the API passes fill-only, return true if the filled stroke
is a rectangle, though the caller failed to close the path.
*/
-bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** ptsPtr) const {
+bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** ptsPtr,
+ bool* isClosed, Direction* direction) const {
int corners = 0;
SkPoint first, last;
const SkPoint* pts = *ptsPtr;
@@ -571,6 +572,12 @@ bool SkPath::isRectContour(bool allowPartial, int* currVerb, const SkPoint** pts
if (savePts) {
*ptsPtr = savePts;
}
+ if (result && isClosed) {
+ *isClosed = autoClose;
+ }
+ if (result && direction) {
+ *direction = firstDirection == (lastDirection + 1 & 3) ? kCCW_Direction : kCW_Direction;
+ }
return result;
}
@@ -578,24 +585,31 @@ bool SkPath::isRect(SkRect* rect) const {
SkDEBUGCODE(this->validate();)
int currVerb = 0;
const SkPoint* pts = fPathRef->points();
- bool result = isRectContour(false, &currVerb, &pts);
+ bool result = isRectContour(false, &currVerb, &pts, NULL, NULL);
if (result && rect) {
*rect = getBounds();
}
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);
+}
+
bool SkPath::isNestedRects(SkRect rects[2]) const {
SkDEBUGCODE(this->validate();)
int currVerb = 0;
const SkPoint* pts = fPathRef->points();
const SkPoint* first = pts;
- if (!isRectContour(true, &currVerb, &pts)) {
+ if (!isRectContour(true, &currVerb, &pts, NULL, NULL)) {
return false;
}
const SkPoint* last = pts;
SkRect testRects[2];
- if (isRectContour(false, &currVerb, &pts)) {
+ if (isRectContour(false, &currVerb, &pts, NULL, NULL)) {
testRects[0].set(first, last - first);
testRects[1].set(last, pts - last);
if (testRects[0].contains(testRects[1])) {
diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
index bd41e19ac7..58f864d1e5 100644
--- a/tests/PathTest.cpp
+++ b/tests/PathTest.cpp
@@ -1052,12 +1052,34 @@ static void test_isRect(skiatest::Reporter* reporter) {
path.close();
}
REPORTER_ASSERT(reporter, fail ^ path.isRect(0));
+ REPORTER_ASSERT(reporter, fail ^ path.isRect(NULL, NULL));
+
if (!fail) {
SkRect computed, expected;
expected.set(tests[testIndex], testLen[testIndex] / sizeof(SkPoint));
REPORTER_ASSERT(reporter, path.isRect(&computed));
REPORTER_ASSERT(reporter, expected == computed);
+
+ bool isClosed;
+ SkPath::Direction direction, cheapDirection;
+ REPORTER_ASSERT(reporter, path.cheapComputeDirection(&cheapDirection));
+ REPORTER_ASSERT(reporter, path.isRect(&isClosed, &direction));
+ REPORTER_ASSERT(reporter, isClosed == close);
+ REPORTER_ASSERT(reporter, direction == cheapDirection);
+ } else {
+ SkRect computed;
+ computed.set(123, 456, 789, 1011);
+ REPORTER_ASSERT(reporter, !path.isRect(&computed));
+ REPORTER_ASSERT(reporter, computed.fLeft == 123 && computed.fTop == 456);
+ REPORTER_ASSERT(reporter, computed.fRight == 789 && computed.fBottom == 1011);
+
+ bool isClosed = (bool) -1;
+ SkPath::Direction direction = (SkPath::Direction) -1;
+ REPORTER_ASSERT(reporter, !path.isRect(&isClosed, &direction));
+ REPORTER_ASSERT(reporter, isClosed == (bool) -1);
+ REPORTER_ASSERT(reporter, direction == (SkPath::Direction) -1);
}
+
if (tests[testIndex] == lastPass) {
fail = true;
}