Adding new 'extend' mode to SkPath::addPath

BUG=261727
R=reed@google.com, caryclark@google.com, schenney@chromium.org, robertphillips@google.com

Author: junov@chromium.org

Review URL: https://codereview.chromium.org/151353006

git-svn-id: http://skia.googlecode.com/svn/trunk@13415 2bbb7eff-a529-9590-31e7-b0007b416f81
This commit is contained in:
commit-bot@chromium.org 2014-02-11 21:16:29 +00:00
parent e07dfe54c4
commit 14747e58f8
3 changed files with 100 additions and 9 deletions

View File

@ -702,25 +702,41 @@ public:
*/
void addPoly(const SkPoint pts[], int count, bool close);
enum AddPathMode {
/** Source path contours are added as new contours.
*/
kAppend_AddPathMode,
/** Path is added by extending the last contour of the destination path
with the first contour of the source path. If the last contour of
the destination path is closed, then it will not be extended.
Instead, the start of source path will be extended by a straight
line to the end point of the destination path.
*/
kExtend_AddPathMode
};
/** Add a copy of src to the path, offset by (dx,dy)
@param src The path to add as a new contour
@param dx The amount to translate the path in X as it is added
@param dx The amount to translate the path in Y as it is added
*/
void addPath(const SkPath& src, SkScalar dx, SkScalar dy);
void addPath(const SkPath& src, SkScalar dx, SkScalar dy,
AddPathMode mode = kAppend_AddPathMode);
/** Add a copy of src to the path
*/
void addPath(const SkPath& src) {
void addPath(const SkPath& src, AddPathMode mode = kAppend_AddPathMode) {
SkMatrix m;
m.reset();
this->addPath(src, m);
this->addPath(src, m, mode);
}
/** Add a copy of src to the path, transformed by matrix
@param src The path to add as a new contour
@param matrix Transform applied to src
@param mode Determines how path is added
*/
void addPath(const SkPath& src, const SkMatrix& matrix);
void addPath(const SkPath& src, const SkMatrix& matrix, AddPathMode mode = kAppend_AddPathMode);
/**
* Same as addPath(), but reverses the src input

View File

@ -1403,14 +1403,14 @@ void SkPath::arcTo(SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2,
///////////////////////////////////////////////////////////////////////////////
void SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy) {
void SkPath::addPath(const SkPath& path, SkScalar dx, SkScalar dy, AddPathMode mode) {
SkMatrix matrix;
matrix.setTranslate(dx, dy);
this->addPath(path, matrix);
this->addPath(path, matrix, mode);
}
void SkPath::addPath(const SkPath& path, const SkMatrix& matrix) {
void SkPath::addPath(const SkPath& path, const SkMatrix& matrix, AddPathMode mode) {
SkPathRef::Editor(&fPathRef, path.countVerbs(), path.countPoints());
RawIter iter(path);
@ -1418,12 +1418,17 @@ void SkPath::addPath(const SkPath& path, const SkMatrix& matrix) {
Verb verb;
SkMatrix::MapPtsProc proc = matrix.getMapPtsProc();
bool firstVerb = true;
while ((verb = iter.next(pts)) != kDone_Verb) {
switch (verb) {
case kMove_Verb:
proc(matrix, &pts[0], &pts[0], 1);
this->moveTo(pts[0]);
if (firstVerb && mode == kExtend_AddPathMode && !isEmpty()) {
injectMoveToIfNeeded(); // In case last contour is closed
this->lineTo(pts[0]);
} else {
this->moveTo(pts[0]);
}
break;
case kLine_Verb:
proc(matrix, &pts[1], &pts[1], 1);
@ -1447,6 +1452,7 @@ void SkPath::addPath(const SkPath& path, const SkMatrix& matrix) {
default:
SkDEBUGFAIL("unknown verb");
}
firstVerb = false;
}
}

View File

@ -3060,6 +3060,68 @@ static void test_addPath(skiatest::Reporter* reporter) {
REPORTER_ASSERT(reporter, p.getBounds() == reverseExpected);
}
static void test_addPathMode(skiatest::Reporter* reporter, bool explicitMoveTo, bool extend) {
SkPath p, q;
if (explicitMoveTo) {
p.moveTo(1, 1);
}
p.lineTo(1, 2);
if (explicitMoveTo) {
q.moveTo(2, 1);
}
q.lineTo(2, 2);
p.addPath(q, extend ? SkPath::kExtend_AddPathMode : SkPath::kAppend_AddPathMode);
uint8_t verbs[4];
int verbcount = p.getVerbs(verbs, 4);
REPORTER_ASSERT(reporter, verbcount == 4);
REPORTER_ASSERT(reporter, verbs[0] == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, verbs[1] == SkPath::kLine_Verb);
REPORTER_ASSERT(reporter, verbs[2] == (extend ? SkPath::kLine_Verb : SkPath::kMove_Verb));
REPORTER_ASSERT(reporter, verbs[3] == SkPath::kLine_Verb);
}
static void test_extendClosedPath(skiatest::Reporter* reporter) {
SkPath p, q;
p.moveTo(1, 1);
p.lineTo(1, 2);
p.lineTo(2, 2);
p.close();
q.moveTo(2, 1);
q.lineTo(2, 3);
p.addPath(q, SkPath::kExtend_AddPathMode);
uint8_t verbs[7];
int verbcount = p.getVerbs(verbs, 7);
REPORTER_ASSERT(reporter, verbcount == 7);
REPORTER_ASSERT(reporter, verbs[0] == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, verbs[1] == SkPath::kLine_Verb);
REPORTER_ASSERT(reporter, verbs[2] == SkPath::kLine_Verb);
REPORTER_ASSERT(reporter, verbs[3] == SkPath::kClose_Verb);
REPORTER_ASSERT(reporter, verbs[4] == SkPath::kMove_Verb);
REPORTER_ASSERT(reporter, verbs[5] == SkPath::kLine_Verb);
REPORTER_ASSERT(reporter, verbs[6] == SkPath::kLine_Verb);
SkPoint pt;
REPORTER_ASSERT(reporter, p.getLastPt(&pt));
REPORTER_ASSERT(reporter, pt == SkPoint::Make(2, 3));
REPORTER_ASSERT(reporter, p.getPoint(3) == SkPoint::Make(1, 1));
}
static void test_addEmptyPath(skiatest::Reporter* reporter, SkPath::AddPathMode mode) {
SkPath p, q, r;
// case 1: dst is empty
p.moveTo(2, 1);
p.lineTo(2, 3);
q.addPath(p, mode);
REPORTER_ASSERT(reporter, q == p);
// case 2: src is empty
p.addPath(r, mode);
REPORTER_ASSERT(reporter, q == p);
// case 3: src and dst are empty
q.reset();
q.addPath(r, mode);
REPORTER_ASSERT(reporter, q.isEmpty());
}
static void test_conicTo_special_case(skiatest::Reporter* reporter) {
SkPath p;
p.conicTo(1, 2, 3, 4, -1);
@ -3377,6 +3439,13 @@ DEF_TEST(Paths, reporter) {
test_arc(reporter);
test_arcTo(reporter);
test_addPath(reporter);
test_addPathMode(reporter, false, false);
test_addPathMode(reporter, true, false);
test_addPathMode(reporter, false, true);
test_addPathMode(reporter, true, true);
test_extendClosedPath(reporter);
test_addEmptyPath(reporter, SkPath::kExtend_AddPathMode);
test_addEmptyPath(reporter, SkPath::kAppend_AddPathMode);
test_conicTo_special_case(reporter);
test_get_point(reporter);
test_contains(reporter);