add rect-output parameter to isRect, allowing us to return the correct bounds even if a rectagular path has a trailing moveTo
https://code.google.com/p/chromium/issues/detail?id=247770 R=caryclark@google.com Review URL: https://codereview.chromium.org/16950021 git-svn-id: http://skia.googlecode.com/svn/trunk@9724 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
parent
56a57aeb3c
commit
da2b21fa9b
@ -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
|
||||
|
@ -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 {
|
||||
|
@ -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());
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user