Fix rMoveTo to be relative to the start of a closed path

Other relative PathOps were fixed in
https://chromiumcodereview.appspot.com/22681006/

Fiddle: https://fiddle.skia.org/c/58ab5cfea29432c432ea7b467c1266ac
Bug: skia:1474
Change-Id: I6c3381087c81b2c28030c8158f5fa5662e5bfa7b
Reviewed-on: https://skia-review.googlesource.com/c/skia/+/436477
Reviewed-by: Brian Salomon <bsalomon@google.com>
Commit-Queue: Brian Salomon <bsalomon@google.com>
This commit is contained in:
William Hesse 2021-08-05 18:27:06 +02:00 committed by SkCQ
parent e07c8fc583
commit 3c2461126b
2 changed files with 45 additions and 2 deletions

View File

@ -139,6 +139,8 @@ private:
////////////////////////////////////////////////////////////////////////////
// flag to require a moveTo if we begin with something else, like lineTo etc.
// This will also be the value of lastMoveToIndex for a single contour
// ending with close, so countVerbs needs to be checked against 0.
#define INITIAL_LASTMOVETOINDEX_VALUE ~0
SkPath::SkPath()
@ -626,8 +628,15 @@ SkPath& SkPath::moveTo(SkScalar x, SkScalar y) {
}
SkPath& SkPath::rMoveTo(SkScalar x, SkScalar y) {
SkPoint pt;
this->getLastPt(&pt);
SkPoint pt = {0,0};
int count = fPathRef->countPoints();
if (count > 0) {
if (fLastMoveToIndex >= 0) {
pt = fPathRef->atPoint(count - 1);
} else {
pt = fPathRef->atPoint(~fLastMoveToIndex);
}
}
return this->moveTo(pt.fX + x, pt.fY + y);
}

View File

@ -3806,6 +3806,11 @@ static void check_quad(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter
REPORTER_ASSERT(reporter, pts[2].fY == y2);
}
static void check_close(skiatest::Reporter* reporter, SkPathPriv::RangeIter* iter) {
auto [v, pts, w] = *(*iter)++;
REPORTER_ASSERT(reporter, v == SkPathVerb::kClose);
}
static void check_done(skiatest::Reporter* reporter, SkPath* p, SkPathPriv::RangeIter* iter) {
REPORTER_ASSERT(reporter, *iter == SkPathPriv::Iterate(*p).end());
}
@ -3863,6 +3868,34 @@ static bool nearly_equal(const SkRect& a, const SkRect& b) {
SkScalarNearlyEqual(a.fBottom, b.fBottom);
}
static void test_rMoveTo(skiatest::Reporter* reporter) {
SkPath p;
p.moveTo(10, 11);
p.lineTo(20, 21);
p.close();
p.rMoveTo(30, 31);
SkPathPriv::RangeIter iter = SkPathPriv::Iterate(p).begin();
check_move(reporter, &iter, 10, 11);
check_line(reporter, &iter, 20, 21);
check_close(reporter, &iter);
check_move(reporter, &iter, 10 + 30, 11 + 31);
check_done_and_reset(reporter, &p, &iter);
p.moveTo(10, 11);
p.lineTo(20, 21);
p.rMoveTo(30, 31);
iter = SkPathPriv::Iterate(p).begin();
check_move(reporter, &iter, 10, 11);
check_line(reporter, &iter, 20, 21);
check_move(reporter, &iter, 20 + 30, 21 + 31);
check_done_and_reset(reporter, &p, &iter);
p.rMoveTo(30, 31);
iter = SkPathPriv::Iterate(p).begin();
check_move(reporter, &iter, 30, 31);
check_done_and_reset(reporter, &p, &iter);
}
static void test_arcTo(skiatest::Reporter* reporter) {
SkPath p;
p.arcTo(0, 0, 1, 2, 1);
@ -4927,6 +4960,7 @@ DEF_TEST(Paths, reporter) {
test_path_close_issue1474(reporter);
test_path_to_region(reporter);
test_rrect(reporter);
test_rMoveTo(reporter);
test_arc(reporter);
test_arc_ovals(reporter);
test_arcTo(reporter);