hide complex versions of isOval and isRRect

Bug: skia:
Change-Id: I9fa899d409470f424fdfbef5b0c3bb528bcce40e
Reviewed-on: https://skia-review.googlesource.com/108660
Commit-Queue: Mike Reed <reed@google.com>
Reviewed-by: Brian Salomon <bsalomon@google.com>
This commit is contained in:
Mike Reed 2018-02-20 13:57:05 -05:00 committed by Skia Commit-Bot
parent c320b15768
commit 0c3137c4f4
7 changed files with 112 additions and 131 deletions

View File

@ -1137,54 +1137,32 @@ Use setConvexity.
# ------------------------------------------------------------------------------
#Method bool isOval(SkRect* rect, Direction* dir = nullptr,
unsigned* start = nullptr) const
#Method bool isOval(SkRect* bounds) const
#In Property
#Line # returns if describes Oval ##
Returns true if constructed by addCircle, addOval; and in some cases,
addRoundRect, addRRect. Path constructed with conicTo or rConicTo will not
return true though Path draws Oval.
Returns true if this path is recognized as an oval or circle.
rect receives bounds of Oval.
dir receives Direction of Oval: kCW_Direction if clockwise, kCCW_Direction if
counterclockwise.
start receives start of Oval: 0 for top, 1 for right, 2 for bottom, 3 for left.
bounds receives bounds of Oval.
rect, dir, and start are unmodified if Oval is not found.
bounds is unmodified if Oval is not found.
Triggers performance optimizations on some GPU_Surface implementations.
#Param bounds storage for bounding Rect of Oval; may be nullptr ##
#Param rect storage for bounding Rect of Oval; may be nullptr ##
#Param dir storage for Direction; may be nullptr ##
#Param start storage for start of Oval; may be nullptr ##
#Return true if Path was constructed by method that reduces to Oval ##
#Return true if Path is recognized as an oval or circle ##
#Example
void draw(SkCanvas* canvas) {
SkPaint paint;
SkPath path;
path.addOval({20, 20, 220, 220}, SkPath::kCW_Direction, 1);
path.addOval({20, 20, 220, 220});
SkRect bounds;
SkPath::Direction direction;
unsigned start;
path.isOval(&bounds, &direction, &start);
paint.setColor(0xFF9FBFFF);
canvas->drawRect(bounds, paint);
if (path.isOval(&bounds)) {
paint.setColor(0xFF9FBFFF);
canvas->drawRect(bounds, paint);
}
paint.setColor(0x3f000000);
canvas->drawPath(path, paint);
paint.setColor(SK_ColorBLACK);
canvas->rotate(start * 90, bounds.centerX(), bounds.centerY());
char startText = '0' + start;
paint.setTextSize(20);
canvas->drawText(&startText, 1, bounds.centerX(), bounds.fTop + 20, paint);
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(4);
path.reset();
path.addArc(bounds, -90, SkPath::kCW_Direction == direction ? 90 : -90);
path.rLineTo(20, -20);
canvas->drawPath(path, paint);
}
##
@ -1194,59 +1172,36 @@ void draw(SkCanvas* canvas) {
# ------------------------------------------------------------------------------
#Method bool isRRect(SkRRect* rrect, Direction* dir = nullptr,
unsigned* start = nullptr) const
#Method bool isRRect(SkRRect* rrect) const
#In Property
#Line # returns if describes Round_Rect ##
Returns true if constructed by addRoundRect, addRRect; and if construction
is not empty, not Rect, and not Oval. Path constructed with other calls
will not return true though Path draws Round_Rect.
Returns true if this path is recognized as a SkRRect (but not an oval/circle or rect).
rrect receives bounds of Round_Rect.
dir receives Direction of Oval: kCW_Direction if clockwise, kCCW_Direction if
counterclockwise.
start receives start of Round_Rect: 0 for top, 1 for right, 2 for bottom, 3 for left.
rrect, dir, and start are unmodified if Round_Rect is not found.
Triggers performance optimizations on some GPU_Surface implementations.
rrect is unmodified if Round_Rect is not found.
#Param rrect storage for bounding Rect of Round_Rect; may be nullptr ##
#Param dir storage for Direction; may be nullptr ##
#Param start storage for start of Round_Rect; may be nullptr ##
#Return true if Path contains only Round_Rect ##
#Example
#Description
Draw rounded rectangle and its bounds. Draw an arc indicating where the rounded
rectangle starts and its direction.
Draw rounded rectangle and its bounds.
##
void draw(SkCanvas* canvas) {
SkPaint paint;
SkPath path;
path.addRRect(SkRRect::MakeRectXY({20, 20, 220, 220}, 30, 50), SkPath::kCCW_Direction, 3);
path.addRRect(SkRRect::MakeRectXY({20, 20, 220, 220}, 30, 50));
SkRRect rrect;
SkPath::Direction direction;
unsigned start;
path.isRRect(&rrect, &direction, &start);
const SkRect& bounds = rrect.rect();
paint.setColor(0xFF9FBFFF);
canvas->drawRect(bounds, paint);
if (path.isRRect(&rrect)) {
const SkRect& bounds = rrect.rect();
paint.setColor(0xFF9FBFFF);
canvas->drawRect(bounds, paint);
}
paint.setColor(0x3f000000);
canvas->drawPath(path, paint);
paint.setColor(SK_ColorBLACK);
canvas->rotate(start * 90, bounds.centerX(), bounds.centerY());
char startText = '0' + start;
paint.setTextSize(20);
canvas->drawText(&startText, 1, bounds.centerX(), bounds.fTop + 20, paint);
paint.setStyle(SkPaint::kStroke_Style);
paint.setStrokeWidth(4);
path.reset();
path.addArc(bounds, -90, SkPath::kCW_Direction == direction ? 90 : -90);
path.rLineTo(20, -20);
canvas->drawPath(path, paint);
}
##

View File

@ -279,61 +279,23 @@ public:
this->setConvexity(isConvex ? kConvex_Convexity : kConcave_Convexity);
}
/** Returns true if constructed by addCircle(), addOval(); and in some cases,
addRoundRect(), addRRect(). SkPath constructed with conicTo() or rConicTo() will not
return true though SkPath draws oval.
/**
* Returns true if this path is recognized as an oval or circle.
*
* @param bounds If this returns true and bounds is not null, then it is set to the
* bounds of the oval that matches this path. If this returns false,
* then this parameter is ignored.
*/
bool isOval(SkRect* bounds) const;
rect receives bounds of oval.
dir receives SkPath::Direction of oval: kCW_Direction if clockwise, kCCW_Direction if
counterclockwise.
start receives start of oval: 0 for top, 1 for right, 2 for bottom, 3 for left.
rect, dir, and start are unmodified if oval is not found.
Triggers performance optimizations on some GPU surface implementations.
@param rect storage for bounding SkRect of oval; may be nullptr
@param dir storage for SkPath::Direction; may be nullptr
@param start storage for start of oval; may be nullptr
@return true if SkPath was constructed by method that reduces to oval
*/
bool isOval(SkRect* rect, Direction* dir = nullptr,
unsigned* start = nullptr) const {
bool isCCW = false;
bool result = fPathRef->isOval(rect, &isCCW, start);
if (dir && result) {
*dir = isCCW ? kCCW_Direction : kCW_Direction;
}
return result;
}
/** Returns true if constructed by addRoundRect(), addRRect(); and if construction
is not empty, not SkRect, and not oval. SkPath constructed with other calls
will not return true though SkPath draws SkRRect.
rrect receives bounds of SkRRect.
dir receives SkPath::Direction of oval: kCW_Direction if clockwise, kCCW_Direction if
counterclockwise.
start receives start of SkRRect: 0 for top, 1 for right, 2 for bottom, 3 for left.
rrect, dir, and start are unmodified if SkRRect is not found.
Triggers performance optimizations on some GPU surface implementations.
@param rrect storage for bounding SkRect of SkRRect; may be nullptr
@param dir storage for SkPath::Direction; may be nullptr
@param start storage for start of SkRRect; may be nullptr
@return true if SkPath contains only SkRRect
*/
bool isRRect(SkRRect* rrect, Direction* dir = nullptr,
unsigned* start = nullptr) const {
bool isCCW = false;
bool result = fPathRef->isRRect(rrect, &isCCW, start);
if (dir && result) {
*dir = isCCW ? kCCW_Direction : kCW_Direction;
}
return result;
}
/**
* Returns true if this path is recognized as a SkRRect (but not an oval/circle or rect).
*
* @param rrect If this returns true and rrect is not null, then it is set to the
* SkRRect that matches this path. If this returns false, then this parameter
* is ignored.
*/
bool isRRect(SkRRect* rrect) const;
/** Sets SkPath to its initial state.
Removes verb array, SkPoint array, and weights, and sets FillType to kWinding_FillType.

View File

@ -632,6 +632,14 @@ bool SkPath::isNestedFillRects(SkRect rects[2], Direction dirs[2]) const {
return false;
}
bool SkPath::isOval(SkRect* bounds) const {
return SkPathPriv::IsOval(*this, bounds, nullptr, nullptr);
}
bool SkPath::isRRect(SkRRect* rrect) const {
return SkPathPriv::IsRRect(*this, rrect, nullptr, nullptr);
}
int SkPath::countPoints() const {
return fPathRef->countPoints();
}

View File

@ -157,6 +157,60 @@ public:
return path.fPathRef->unique();
}
/** Returns true if constructed by addCircle(), addOval(); and in some cases,
addRoundRect(), addRRect(). SkPath constructed with conicTo() or rConicTo() will not
return true though SkPath draws oval.
rect receives bounds of oval.
dir receives SkPath::Direction of oval: kCW_Direction if clockwise, kCCW_Direction if
counterclockwise.
start receives start of oval: 0 for top, 1 for right, 2 for bottom, 3 for left.
rect, dir, and start are unmodified if oval is not found.
Triggers performance optimizations on some GPU surface implementations.
@param rect storage for bounding SkRect of oval; may be nullptr
@param dir storage for SkPath::Direction; may be nullptr
@param start storage for start of oval; may be nullptr
@return true if SkPath was constructed by method that reduces to oval
*/
static bool IsOval(const SkPath& path, SkRect* rect, SkPath::Direction* dir, unsigned* start) {
bool isCCW = false;
bool result = path.fPathRef->isOval(rect, &isCCW, start);
if (dir && result) {
*dir = isCCW ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
}
return result;
}
/** Returns true if constructed by addRoundRect(), addRRect(); and if construction
is not empty, not SkRect, and not oval. SkPath constructed with other calls
will not return true though SkPath draws SkRRect.
rrect receives bounds of SkRRect.
dir receives SkPath::Direction of oval: kCW_Direction if clockwise, kCCW_Direction if
counterclockwise.
start receives start of SkRRect: 0 for top, 1 for right, 2 for bottom, 3 for left.
rrect, dir, and start are unmodified if SkRRect is not found.
Triggers performance optimizations on some GPU surface implementations.
@param rrect storage for bounding SkRect of SkRRect; may be nullptr
@param dir storage for SkPath::Direction; may be nullptr
@param start storage for start of SkRRect; may be nullptr
@return true if SkPath contains only SkRRect
*/
static bool IsRRect(const SkPath& path, SkRRect* rrect, SkPath::Direction* dir,
unsigned* start) {
bool isCCW = false;
bool result = path.fPathRef->isRRect(rrect, &isCCW, start);
if (dir && result) {
*dir = isCCW ? SkPath::kCCW_Direction : SkPath::kCW_Direction;
}
return result;
}
};
#endif

View File

@ -483,14 +483,14 @@ void GrShape::attemptToSimplifyPath() {
fLineData.fPts[0] = pts[0];
fLineData.fPts[1] = pts[1];
fLineData.fInverted = inverted;
} else if (this->path().isRRect(&rrect, &rrectDir, &rrectStart)) {
} else if (SkPathPriv::IsRRect(this->path(), &rrect, &rrectDir, &rrectStart)) {
this->changeType(Type::kRRect);
fRRectData.fRRect = rrect;
fRRectData.fDir = rrectDir;
fRRectData.fStart = rrectStart;
fRRectData.fInverted = inverted;
SkASSERT(!fRRectData.fRRect.isEmpty());
} else if (this->path().isOval(&rect, &rrectDir, &rrectStart)) {
} else if (SkPathPriv::IsOval(this->path(), &rect, &rrectDir, &rrectStart)) {
this->changeType(Type::kRRect);
fRRectData.fRRect.setOval(rect);
fRRectData.fDir = rrectDir;

View File

@ -2508,14 +2508,16 @@ static void write_and_read_back(skiatest::Reporter* reporter,
SkPath::Direction dir0, dir1;
unsigned start0, start1;
REPORTER_ASSERT(reporter, readBack.isOval(nullptr) == p.isOval(nullptr));
if (p.isOval(&oval0, &dir0, &start0) && readBack.isOval(&oval1, &dir1, &start1)) {
if (SkPathPriv::IsOval(p, &oval0, &dir0, &start0) &&
SkPathPriv::IsOval(readBack, &oval1, &dir1, &start1)) {
REPORTER_ASSERT(reporter, oval0 == oval1);
REPORTER_ASSERT(reporter, dir0 == dir1);
REPORTER_ASSERT(reporter, start0 == start1);
}
REPORTER_ASSERT(reporter, readBack.isRRect(nullptr) == p.isRRect(nullptr));
SkRRect rrect0, rrect1;
if (p.isRRect(&rrect0, &dir0, &start0) && readBack.isRRect(&rrect1, &dir1, &start1)) {
if (SkPathPriv::IsRRect(p, &rrect0, &dir0, &start0) &&
SkPathPriv::IsRRect(readBack, &rrect1, &dir1, &start1)) {
REPORTER_ASSERT(reporter, rrect0 == rrect1);
REPORTER_ASSERT(reporter, dir0 == dir1);
REPORTER_ASSERT(reporter, start0 == start1);
@ -3291,7 +3293,7 @@ static void check_for_circle(skiatest::Reporter* reporter,
REPORTER_ASSERT(reporter, path.isOval(&rect) == expectedCircle);
SkPath::Direction isOvalDir;
unsigned isOvalStart;
if (path.isOval(&rect, &isOvalDir, &isOvalStart)) {
if (SkPathPriv::IsOval(path, &rect, &isOvalDir, &isOvalStart)) {
REPORTER_ASSERT(reporter, rect.height() == rect.width());
REPORTER_ASSERT(reporter, SkPathPriv::AsFirstDirection(isOvalDir) == expectedDir);
SkPath tmpPath;
@ -3534,7 +3536,7 @@ static void test_oval(skiatest::Reporter* reporter) {
path.transform(m, &tmp);
// an oval rotated 90 degrees is still an oval. The start index changes from 1 to 2. Direction
// is unchanged.
REPORTER_ASSERT(reporter, tmp.isOval(nullptr, &dir, &start));
REPORTER_ASSERT(reporter, SkPathPriv::IsOval(tmp, nullptr, &dir, &start));
REPORTER_ASSERT(reporter, 2 == start);
REPORTER_ASSERT(reporter, SkPath::kCW_Direction == dir);
@ -3574,7 +3576,7 @@ static void test_oval(skiatest::Reporter* reporter) {
tmp.reset();
tmp.addOval(rect);
path = tmp;
REPORTER_ASSERT(reporter, path.isOval(nullptr, &dir, &start));
REPORTER_ASSERT(reporter, SkPathPriv::IsOval(path, nullptr, &dir, &start));
REPORTER_ASSERT(reporter, SkPath::kCW_Direction == dir);
REPORTER_ASSERT(reporter, 1 == start);
}
@ -3739,7 +3741,7 @@ static void check_oval_arc(skiatest::Reporter* reporter, SkScalar start, SkScala
SkRect r = SkRect::MakeEmpty();
SkPath::Direction d = SkPath::kCCW_Direction;
unsigned s = ~0U;
bool isOval = path.isOval(&r, &d, &s);
bool isOval = SkPathPriv::IsOval(path, &r, &d, &s);
REPORTER_ASSERT(reporter, isOval);
SkPath recreatedPath;
recreatedPath.addOval(r, d, s);

View File

@ -7,14 +7,14 @@
#include "SkMatrix.h"
#include "SkPath.h"
//#include "SkPathRef.h"
#include "SkPathPriv.h"
#include "SkRRect.h"
#include "Test.h"
static SkRRect path_contains_rrect(skiatest::Reporter* reporter, const SkPath& path,
SkPath::Direction* dir, unsigned* start) {
SkRRect out;
REPORTER_ASSERT(reporter, path.isRRect(&out, dir, start));
REPORTER_ASSERT(reporter, SkPathPriv::IsRRect(path, &out, dir, start));
SkPath recreatedPath;
recreatedPath.addRRect(out, *dir, *start);
REPORTER_ASSERT(reporter, path == recreatedPath);
@ -32,7 +32,7 @@ static SkRRect path_contains_rrect(skiatest::Reporter* reporter, const SkPath& p
SkRRect xrr = SkRRect::MakeRect(SkRect::MakeEmpty());
SkPath::Direction xd = SkPath::kCCW_Direction;
unsigned xs = ~0U;
REPORTER_ASSERT(reporter, xformed.isRRect(&xrr, &xd, &xs));
REPORTER_ASSERT(reporter, SkPathPriv::IsRRect(xformed, &xrr, &xd, &xs));
recreatedPath.reset();
recreatedPath.addRRect(xrr, xd, xs);
REPORTER_ASSERT(reporter, recreatedPath == xformed);