| Index: tests/PathTest.cpp
|
| diff --git a/tests/PathTest.cpp b/tests/PathTest.cpp
|
| index 2dbf5c695e99039d9ef9d05619011afa9d0a7549..18d50d005d4ff1edd0dd5f76b764391e58c2d23b 100644
|
| --- a/tests/PathTest.cpp
|
| +++ b/tests/PathTest.cpp
|
| @@ -357,6 +357,33 @@ static void test_crbug_170666() {
|
| surface->getCanvas()->drawPath(path, paint);
|
| }
|
|
|
| +static void test_addrect(skiatest::Reporter* reporter) {
|
| + SkPath path;
|
| + path.lineTo(0, 0);
|
| + path.addRect(SkRect::MakeWH(50, 100));
|
| + REPORTER_ASSERT(reporter, path.isRect(NULL));
|
| +
|
| + path.reset();
|
| + path.lineTo(FLT_EPSILON, FLT_EPSILON);
|
| + path.addRect(SkRect::MakeWH(50, 100));
|
| + REPORTER_ASSERT(reporter, !path.isRect(NULL));
|
| +
|
| + path.reset();
|
| + path.quadTo(0, 0, 0, 0);
|
| + path.addRect(SkRect::MakeWH(50, 100));
|
| + REPORTER_ASSERT(reporter, !path.isRect(NULL));
|
| +
|
| + path.reset();
|
| + path.conicTo(0, 0, 0, 0, 0.5f);
|
| + path.addRect(SkRect::MakeWH(50, 100));
|
| + REPORTER_ASSERT(reporter, !path.isRect(NULL));
|
| +
|
| + path.reset();
|
| + path.cubicTo(0, 0, 0, 0, 0, 0);
|
| + path.addRect(SkRect::MakeWH(50, 100));
|
| + REPORTER_ASSERT(reporter, !path.isRect(NULL));
|
| +}
|
| +
|
| // Make sure we stay non-finite once we get there (unless we reset or rewind).
|
| static void test_addrect_isfinite(skiatest::Reporter* reporter) {
|
| SkPath path;
|
| @@ -811,6 +838,18 @@ static void test_direction(skiatest::Reporter* reporter) {
|
| path.lineTo(-10 * SK_Scalar1, 60 * SK_Scalar1);
|
| check_direction(reporter, path, SkPath::kCCW_Direction);
|
| #endif
|
| +
|
| + path.reset();
|
| + path.conicTo(20, 0, 20, 20, 0.5f);
|
| + path.close();
|
| + check_direction(reporter, path, SkPath::kCW_Direction);
|
| +
|
| + path.reset();
|
| + path.lineTo(1, 1e7f);
|
| + path.lineTo(1e7f, 2e7f);
|
| + path.close();
|
| + REPORTER_ASSERT(reporter, SkPath::kConvex_Convexity == path.getConvexity());
|
| + check_direction(reporter, path, SkPath::kCCW_Direction);
|
| }
|
|
|
| static void add_rect(SkPath* path, const SkRect& r) {
|
| @@ -1146,6 +1185,18 @@ static void test_convexity(skiatest::Reporter* reporter) {
|
| setFromString(&path, gRec[i].fPathStr);
|
| check_convexity(reporter, path, gRec[i].fExpectedConvexity);
|
| check_direction(reporter, path, gRec[i].fExpectedDirection);
|
| + // check after setting the initial convex and direction
|
| + if (kDontCheckDir != gRec[i].fExpectedDirection) {
|
| + SkPath copy(path);
|
| + SkPath::Direction dir;
|
| + bool foundDir = copy.cheapComputeDirection(&dir);
|
| + REPORTER_ASSERT(reporter, (gRec[i].fExpectedDirection == SkPath::kUnknown_Direction)
|
| + ^ foundDir);
|
| + REPORTER_ASSERT(reporter, !foundDir || gRec[i].fExpectedDirection == dir);
|
| + check_convexity(reporter, copy, gRec[i].fExpectedConvexity);
|
| + }
|
| + REPORTER_ASSERT(reporter, gRec[i].fExpectedConvexity == path.getConvexity());
|
| + check_direction(reporter, path, gRec[i].fExpectedDirection);
|
| }
|
| }
|
|
|
| @@ -1166,7 +1217,7 @@ static void test_isLine(skiatest::Reporter* reporter) {
|
|
|
| const SkScalar moveX = SkIntToScalar(1);
|
| const SkScalar moveY = SkIntToScalar(2);
|
| - SkASSERT(value != moveX && value != moveY);
|
| + REPORTER_ASSERT(reporter, value != moveX && value != moveY);
|
|
|
| path.moveTo(moveX, moveY);
|
| REPORTER_ASSERT(reporter, !path.isLine(NULL));
|
| @@ -1177,7 +1228,7 @@ static void test_isLine(skiatest::Reporter* reporter) {
|
|
|
| const SkScalar lineX = SkIntToScalar(2);
|
| const SkScalar lineY = SkIntToScalar(2);
|
| - SkASSERT(value != lineX && value != lineY);
|
| + REPORTER_ASSERT(reporter, value != lineX && value != lineY);
|
|
|
| path.lineTo(lineX, lineY);
|
| REPORTER_ASSERT(reporter, path.isLine(NULL));
|
| @@ -1193,6 +1244,10 @@ static void test_isLine(skiatest::Reporter* reporter) {
|
| REPORTER_ASSERT(reporter, !path.isLine(pts));
|
| REPORTER_ASSERT(reporter, pts[0].equals(moveX, moveY));
|
| REPORTER_ASSERT(reporter, pts[1].equals(lineX, lineY));
|
| +
|
| + path.reset();
|
| + path.quadTo(1, 1, 2, 2);
|
| + REPORTER_ASSERT(reporter, !path.isLine(NULL));
|
| }
|
|
|
| static void test_conservativelyContains(skiatest::Reporter* reporter) {
|
| @@ -1203,7 +1258,7 @@ static void test_conservativelyContains(skiatest::Reporter* reporter) {
|
|
|
| // A circle that bounds kBaseRect (with a significant amount of slop)
|
| SkScalar circleR = SkMaxScalar(kBaseRect.width(), kBaseRect.height());
|
| - circleR = SkScalarMul(circleR, SkFloatToScalar(1.75f)) / 2;
|
| + circleR = SkScalarMul(circleR, 1.75f) / 2;
|
| static const SkPoint kCircleC = {kBaseRect.centerX(), kBaseRect.centerY()};
|
|
|
| // round-rect radii
|
| @@ -1214,74 +1269,75 @@ static void test_conservativelyContains(skiatest::Reporter* reporter) {
|
| bool fInRect;
|
| bool fInCircle;
|
| bool fInRR;
|
| + bool fInCubicRR;
|
| } kQueries[] = {
|
| - {kBaseRect, true, true, false},
|
| + {kBaseRect, true, true, false, false},
|
|
|
| // rect well inside of kBaseRect
|
| {SkRect::MakeLTRB(kBaseRect.fLeft + SkFloatToScalar(0.25f)*kBaseRect.width(),
|
| kBaseRect.fTop + SkFloatToScalar(0.25f)*kBaseRect.height(),
|
| kBaseRect.fRight - SkFloatToScalar(0.25f)*kBaseRect.width(),
|
| kBaseRect.fBottom - SkFloatToScalar(0.25f)*kBaseRect.height()),
|
| - true, true, true},
|
| + true, true, true, true},
|
|
|
| // rects with edges off by one from kBaseRect's edges
|
| {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop,
|
| kBaseRect.width(), kBaseRect.height() + 1),
|
| - false, true, false},
|
| + false, true, false, false},
|
| {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop,
|
| kBaseRect.width() + 1, kBaseRect.height()),
|
| - false, true, false},
|
| + false, true, false, false},
|
| {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop,
|
| kBaseRect.width() + 1, kBaseRect.height() + 1),
|
| - false, true, false},
|
| + false, true, false, false},
|
| {SkRect::MakeXYWH(kBaseRect.fLeft - 1, kBaseRect.fTop,
|
| kBaseRect.width(), kBaseRect.height()),
|
| - false, true, false},
|
| + false, true, false, false},
|
| {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop - 1,
|
| kBaseRect.width(), kBaseRect.height()),
|
| - false, true, false},
|
| + false, true, false, false},
|
| {SkRect::MakeXYWH(kBaseRect.fLeft - 1, kBaseRect.fTop,
|
| kBaseRect.width() + 2, kBaseRect.height()),
|
| - false, true, false},
|
| + false, true, false, false},
|
| {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop - 1,
|
| kBaseRect.width() + 2, kBaseRect.height()),
|
| - false, true, false},
|
| + false, true, false, false},
|
|
|
| // zero-w/h rects at each corner of kBaseRect
|
| - {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop, 0, 0), true, true, false},
|
| - {SkRect::MakeXYWH(kBaseRect.fRight, kBaseRect.fTop, 0, 0), true, true, false},
|
| - {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fBottom, 0, 0), true, true, false},
|
| - {SkRect::MakeXYWH(kBaseRect.fRight, kBaseRect.fBottom, 0, 0), true, true, false},
|
| + {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fTop, 0, 0), true, true, false, false},
|
| + {SkRect::MakeXYWH(kBaseRect.fRight, kBaseRect.fTop, 0, 0), true, true, false, true},
|
| + {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.fBottom, 0, 0), true, true, false, true},
|
| + {SkRect::MakeXYWH(kBaseRect.fRight, kBaseRect.fBottom, 0, 0), true, true, false, true},
|
|
|
| // far away rect
|
| {SkRect::MakeXYWH(10 * kBaseRect.fRight, 10 * kBaseRect.fBottom,
|
| SkIntToScalar(10), SkIntToScalar(10)),
|
| - false, false, false},
|
| + false, false, false, false},
|
|
|
| // very large rect containing kBaseRect
|
| {SkRect::MakeXYWH(kBaseRect.fLeft - 5 * kBaseRect.width(),
|
| kBaseRect.fTop - 5 * kBaseRect.height(),
|
| 11 * kBaseRect.width(), 11 * kBaseRect.height()),
|
| - false, false, false},
|
| + false, false, false, false},
|
|
|
| // skinny rect that spans same y-range as kBaseRect
|
| {SkRect::MakeXYWH(kBaseRect.centerX(), kBaseRect.fTop,
|
| SkIntToScalar(1), kBaseRect.height()),
|
| - true, true, true},
|
| + true, true, true, true},
|
|
|
| // short rect that spans same x-range as kBaseRect
|
| {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.centerY(), kBaseRect.width(), SkScalar(1)),
|
| - true, true, true},
|
| + true, true, true, true},
|
|
|
| // skinny rect that spans slightly larger y-range than kBaseRect
|
| {SkRect::MakeXYWH(kBaseRect.centerX(), kBaseRect.fTop,
|
| SkIntToScalar(1), kBaseRect.height() + 1),
|
| - false, true, false},
|
| + false, true, false, false},
|
|
|
| // short rect that spans slightly larger x-range than kBaseRect
|
| {SkRect::MakeXYWH(kBaseRect.fLeft, kBaseRect.centerY(),
|
| kBaseRect.width() + 1, SkScalar(1)),
|
| - false, true, false},
|
| + false, true, false, false},
|
| };
|
|
|
| for (int inv = 0; inv < 4; ++inv) {
|
| @@ -1309,6 +1365,19 @@ static void test_conservativelyContains(skiatest::Reporter* reporter) {
|
| path.addRoundRect(kBaseRect, kRRRadii[0], kRRRadii[1], dir);
|
| REPORTER_ASSERT(reporter, kQueries[q].fInRR ==
|
| path.conservativelyContainsRect(qRect));
|
| +
|
| + path.reset();
|
| + path.moveTo(kBaseRect.fLeft + kRRRadii[0], kBaseRect.fTop);
|
| + path.cubicTo(kBaseRect.fLeft + kRRRadii[0] / 2, kBaseRect.fTop,
|
| + kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1] / 2,
|
| + kBaseRect.fLeft, kBaseRect.fTop + kRRRadii[1]);
|
| + path.lineTo(kBaseRect.fLeft, kBaseRect.fBottom);
|
| + path.lineTo(kBaseRect.fRight, kBaseRect.fBottom);
|
| + path.lineTo(kBaseRect.fRight, kBaseRect.fTop);
|
| + path.close();
|
| + REPORTER_ASSERT(reporter, kQueries[q].fInCubicRR ==
|
| + path.conservativelyContainsRect(qRect));
|
| +
|
| }
|
| // Slightly non-convex shape, shouldn't contain any rects.
|
| path.reset();
|
| @@ -1361,6 +1430,9 @@ static void test_conservativelyContains(skiatest::Reporter* reporter) {
|
| SkIntToScalar(10),
|
| SkIntToScalar(10))));
|
|
|
| + path.reset();
|
| + path.lineTo(100, 100);
|
| + REPORTER_ASSERT(reporter, !path.conservativelyContainsRect(SkRect::MakeXYWH(0, 0, 1, 1)));
|
| }
|
|
|
| static void test_isRect_open_close(skiatest::Reporter* reporter) {
|
| @@ -1818,6 +1890,13 @@ static void test_flattening(skiatest::Reporter* reporter) {
|
| REPORTER_ASSERT(reporter, size1 == size3);
|
| REPORTER_ASSERT(reporter, p == p2);
|
|
|
| + size3 = p2.readFromMemory(buffer, 0);
|
| + REPORTER_ASSERT(reporter, !size3);
|
| +
|
| + SkPath tooShort;
|
| + size3 = tooShort.readFromMemory(buffer, size1 - 1);
|
| + REPORTER_ASSERT(reporter, tooShort.isEmpty());
|
| +
|
| char buffer2[1024];
|
| size3 = p2.writeToMemory(buffer2);
|
| REPORTER_ASSERT(reporter, size1 == size3);
|
| @@ -1836,17 +1915,25 @@ static void test_flattening(skiatest::Reporter* reporter) {
|
| static void test_transform(skiatest::Reporter* reporter) {
|
| SkPath p, p1;
|
|
|
| +#define CONIC_PERSPECTIVE_BUG_FIXED 0
|
| static const SkPoint pts[] = {
|
| - { 0, 0 },
|
| - { SkIntToScalar(10), SkIntToScalar(10) },
|
| - { SkIntToScalar(20), SkIntToScalar(10) }, { SkIntToScalar(20), 0 },
|
| - { 0, 0 }, { 0, SkIntToScalar(10) }, { SkIntToScalar(1), SkIntToScalar(10) }
|
| + { 0, 0 }, // move
|
| + { SkIntToScalar(10), SkIntToScalar(10) }, // line
|
| + { SkIntToScalar(20), SkIntToScalar(10) }, { SkIntToScalar(20), 0 }, // quad
|
| + { 0, 0 }, { 0, SkIntToScalar(10) }, { SkIntToScalar(1), SkIntToScalar(10) }, // cubic
|
| +#if CONIC_PERSPECTIVE_BUG_FIXED
|
| + { 0, 0 }, { SkIntToScalar(20), SkIntToScalar(10) }, // conic
|
| +#endif
|
| };
|
| + const int kPtCount = SK_ARRAY_COUNT(pts);
|
| p.moveTo(pts[0]);
|
| p.lineTo(pts[1]);
|
| p.quadTo(pts[2], pts[3]);
|
| p.cubicTo(pts[4], pts[5], pts[6]);
|
| -
|
| +#if CONIC_PERSPECTIVE_BUG_FIXED
|
| + p.conicTo(pts[4], pts[5], 0.5f);
|
| +#endif
|
| + p.close();
|
| SkMatrix matrix;
|
| matrix.reset();
|
| p.transform(matrix, &p1);
|
| @@ -1854,13 +1941,36 @@ static void test_transform(skiatest::Reporter* reporter) {
|
|
|
| matrix.setScale(SK_Scalar1 * 2, SK_Scalar1 * 3);
|
| p.transform(matrix, &p1);
|
| - SkPoint pts1[7];
|
| - int count = p1.getPoints(pts1, 7);
|
| - REPORTER_ASSERT(reporter, 7 == count);
|
| + SkPoint pts1[kPtCount];
|
| + int count = p1.getPoints(pts1, kPtCount);
|
| + REPORTER_ASSERT(reporter, kPtCount == count);
|
| for (int i = 0; i < count; ++i) {
|
| SkPoint newPt = SkPoint::Make(pts[i].fX * 2, pts[i].fY * 3);
|
| REPORTER_ASSERT(reporter, newPt == pts1[i]);
|
| }
|
| + matrix.reset();
|
| + matrix.setPerspX(SkScalarToPersp(4));
|
| + p.transform(matrix, &p1);
|
| + REPORTER_ASSERT(reporter, matrix.invert(&matrix));
|
| + p1.transform(matrix, NULL);
|
| + SkRect pBounds = p.getBounds();
|
| + SkRect p1Bounds = p1.getBounds();
|
| + REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pBounds.fLeft, p1Bounds.fLeft));
|
| + REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pBounds.fTop, p1Bounds.fTop));
|
| + REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pBounds.fRight, p1Bounds.fRight));
|
| + REPORTER_ASSERT(reporter, SkScalarNearlyEqual(pBounds.fBottom, p1Bounds.fBottom));
|
| +
|
| + matrix.reset();
|
| + p.reset();
|
| + p.addCircle(0, 0, 1, SkPath::kCW_Direction);
|
| + p.transform(matrix, &p1);
|
| + REPORTER_ASSERT(reporter, p1.cheapIsDirection(SkPath::kCW_Direction));
|
| + matrix.setScaleX(-1);
|
| + p.transform(matrix, &p1);
|
| + REPORTER_ASSERT(reporter, p1.cheapIsDirection(SkPath::kCCW_Direction));
|
| + matrix.setAll(1, 1, 0, 1, 1, 0, 0, 0, 1);
|
| + p.transform(matrix, &p1);
|
| + REPORTER_ASSERT(reporter, p1.cheapIsDirection(SkPath::kUnknown_Direction));
|
| }
|
|
|
| static void test_zero_length_paths(skiatest::Reporter* reporter) {
|
| @@ -2064,6 +2174,71 @@ static void test_iter(skiatest::Reporter* reporter) {
|
| REPORTER_ASSERT(reporter, j == (int)gIterTests[i].numResultVerbs);
|
| }
|
|
|
| + p.reset();
|
| + iter.setPath(p, false);
|
| + REPORTER_ASSERT(reporter, !iter.isClosedContour());
|
| + p.lineTo(1, 1);
|
| + p.close();
|
| + iter.setPath(p, false);
|
| + REPORTER_ASSERT(reporter, iter.isClosedContour());
|
| + p.reset();
|
| + iter.setPath(p, true);
|
| + REPORTER_ASSERT(reporter, !iter.isClosedContour());
|
| + p.lineTo(1, 1);
|
| + iter.setPath(p, true);
|
| + REPORTER_ASSERT(reporter, iter.isClosedContour());
|
| + p.moveTo(0, 0);
|
| + p.lineTo(2, 2);
|
| + iter.setPath(p, false);
|
| + REPORTER_ASSERT(reporter, !iter.isClosedContour());
|
| +
|
| + // this checks to see if the NaN logic is executed in SkPath::autoClose(), but does not
|
| + // check to see if the result is correct.
|
| + for (int setNaN = 0; setNaN < 4; ++setNaN) {
|
| + p.reset();
|
| + p.moveTo(setNaN == 0 ? SK_ScalarNaN : 0, setNaN == 1 ? SK_ScalarNaN : 0);
|
| + p.lineTo(setNaN == 2 ? SK_ScalarNaN : 1, setNaN == 3 ? SK_ScalarNaN : 1);
|
| + iter.setPath(p, true);
|
| + iter.next(pts, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kClose_Verb == iter.next(pts, false));
|
| + }
|
| +
|
| + p.reset();
|
| + p.quadTo(0, 0, 0, 0);
|
| + iter.setPath(p, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kQuad_Verb == iter.next(pts, false));
|
| + iter.setPath(p, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kDone_Verb == iter.next(pts, true));
|
| +
|
| + p.reset();
|
| + p.conicTo(0, 0, 0, 0, 0.5f);
|
| + iter.setPath(p, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kConic_Verb == iter.next(pts, false));
|
| + iter.setPath(p, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kDone_Verb == iter.next(pts, true));
|
| +
|
| + p.reset();
|
| + p.cubicTo(0, 0, 0, 0, 0, 0);
|
| + iter.setPath(p, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == iter.next(pts, false));
|
| + iter.setPath(p, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kDone_Verb == iter.next(pts, true));
|
| +
|
| + p.moveTo(1, 1); // add a trailing moveto
|
| + iter.setPath(p, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kCubic_Verb == iter.next(pts, false));
|
| + iter.setPath(p, false);
|
| + iter.next(pts, false);
|
| + REPORTER_ASSERT(reporter, SkPath::kDone_Verb == iter.next(pts, true));
|
| +
|
| // The GM degeneratesegments.cpp test is more extensive
|
| }
|
|
|
| @@ -2323,7 +2498,7 @@ static void test_circle_skew(skiatest::Reporter* reporter,
|
| if (SkPath::kCCW_Direction == dir) {
|
| dir = SkPath::kCW_Direction;
|
| } else {
|
| - SkASSERT(SkPath::kCW_Direction == dir);
|
| + REPORTER_ASSERT(reporter, SkPath::kCW_Direction == dir);
|
| dir = SkPath::kCCW_Direction;
|
| }
|
| check_for_circle(reporter, tmp, false, dir);
|
| @@ -2381,7 +2556,7 @@ static void test_circle_mirror_x(skiatest::Reporter* reporter,
|
| if (SkPath::kCW_Direction == dir) {
|
| dir = SkPath::kCCW_Direction;
|
| } else {
|
| - SkASSERT(SkPath::kCCW_Direction == dir);
|
| + REPORTER_ASSERT(reporter, SkPath::kCCW_Direction == dir);
|
| dir = SkPath::kCW_Direction;
|
| }
|
|
|
| @@ -2400,7 +2575,7 @@ static void test_circle_mirror_y(skiatest::Reporter* reporter,
|
| if (SkPath::kCW_Direction == dir) {
|
| dir = SkPath::kCCW_Direction;
|
| } else {
|
| - SkASSERT(SkPath::kCCW_Direction == dir);
|
| + REPORTER_ASSERT(reporter, SkPath::kCCW_Direction == dir);
|
| dir = SkPath::kCW_Direction;
|
| }
|
|
|
| @@ -2502,6 +2677,11 @@ static void test_circle(skiatest::Reporter* reporter) {
|
| check_for_circle(reporter, path, false, SkPath::kCW_Direction);
|
|
|
| test_circle_with_add_paths(reporter);
|
| +
|
| + // test negative radius
|
| + path.reset();
|
| + path.addCircle(0, 0, -1, SkPath::kCW_Direction);
|
| + REPORTER_ASSERT(reporter, path.isEmpty());
|
| }
|
|
|
| static void test_oval(skiatest::Reporter* reporter) {
|
| @@ -2573,8 +2753,10 @@ static void test_empty(skiatest::Reporter* reporter, const SkPath& p) {
|
| REPORTER_ASSERT(reporter, !(p != empty));
|
| }
|
|
|
| -static void test_rrect_is_convex(skiatest::Reporter* reporter, SkPath* path) {
|
| +static void test_rrect_is_convex(skiatest::Reporter* reporter, SkPath* path,
|
| + SkPath::Direction dir) {
|
| REPORTER_ASSERT(reporter, path->isConvex());
|
| + REPORTER_ASSERT(reporter, path->cheapIsDirection(dir));
|
| path->setConvexity(SkPath::kUnknown_Convexity);
|
| REPORTER_ASSERT(reporter, path->isConvex());
|
| path->reset();
|
| @@ -2587,19 +2769,373 @@ static void test_rrect(skiatest::Reporter* reporter) {
|
| SkRect r = {10, 20, 30, 40};
|
| rr.setRectRadii(r, radii);
|
| p.addRRect(rr);
|
| - test_rrect_is_convex(reporter, &p);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| p.addRRect(rr, SkPath::kCCW_Direction);
|
| - test_rrect_is_convex(reporter, &p);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCCW_Direction);
|
| p.addRoundRect(r, &radii[0].fX);
|
| - test_rrect_is_convex(reporter, &p);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| p.addRoundRect(r, &radii[0].fX, SkPath::kCCW_Direction);
|
| - test_rrect_is_convex(reporter, &p);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCCW_Direction);
|
| p.addRoundRect(r, radii[1].fX, radii[1].fY);
|
| - test_rrect_is_convex(reporter, &p);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| p.addRoundRect(r, radii[1].fX, radii[1].fY, SkPath::kCCW_Direction);
|
| - test_rrect_is_convex(reporter, &p);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCCW_Direction);
|
| + for (size_t i = 0; i < SK_ARRAY_COUNT(radii); ++i) {
|
| + SkVector save = radii[i];
|
| + radii[i].set(0, 0);
|
| + rr.setRectRadii(r, radii);
|
| + p.addRRect(rr);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| + radii[i] = save;
|
| + }
|
| + p.addRoundRect(r, 0, 0);
|
| + SkRect returnedRect;
|
| + REPORTER_ASSERT(reporter, p.isRect(&returnedRect));
|
| + REPORTER_ASSERT(reporter, returnedRect == r);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| + SkVector zeroRadii[] = {{0, 0}, {0, 0}, {0, 0}, {0, 0}};
|
| + rr.setRectRadii(r, zeroRadii);
|
| + p.addRRect(rr);
|
| + bool closed;
|
| + SkPath::Direction dir;
|
| + REPORTER_ASSERT(reporter, p.isRect(&closed, &dir));
|
| + REPORTER_ASSERT(reporter, closed);
|
| + REPORTER_ASSERT(reporter, SkPath::kCW_Direction == dir);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| + p.addRRect(rr, SkPath::kCW_Direction);
|
| + p.addRRect(rr, SkPath::kCW_Direction);
|
| + REPORTER_ASSERT(reporter, !p.isConvex());
|
| + p.reset();
|
| + p.addRRect(rr, SkPath::kCCW_Direction);
|
| + p.addRRect(rr, SkPath::kCCW_Direction);
|
| + REPORTER_ASSERT(reporter, !p.isConvex());
|
| + p.reset();
|
| + SkRect emptyR = {10, 20, 10, 30};
|
| + rr.setRectRadii(emptyR, radii);
|
| + p.addRRect(rr);
|
| + REPORTER_ASSERT(reporter, p.isEmpty());
|
| + SkRect largeR = {0, 0, SK_ScalarMax, SK_ScalarMax};
|
| + rr.setRectRadii(largeR, radii);
|
| + p.addRRect(rr);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| + SkRect infR = {0, 0, SK_ScalarMax, SK_ScalarInfinity};
|
| + rr.setRectRadii(infR, radii);
|
| + p.addRRect(rr);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| + SkRect tinyR = {0, 0, 1e-9f, 1e-9f};
|
| + p.addRoundRect(tinyR, 5e-11f, 5e-11f);
|
| + test_rrect_is_convex(reporter, &p, SkPath::kCW_Direction);
|
| +}
|
| +
|
| +static void test_arc(skiatest::Reporter* reporter) {
|
| + SkPath p;
|
| + SkRect emptyOval = {10, 20, 30, 20};
|
| + REPORTER_ASSERT(reporter, emptyOval.isEmpty());
|
| + p.addArc(emptyOval, 1, 2);
|
| + REPORTER_ASSERT(reporter, p.isEmpty());
|
| + p.reset();
|
| + SkRect oval = {10, 20, 30, 40};
|
| + p.addArc(oval, 1, 0);
|
| + REPORTER_ASSERT(reporter, p.isEmpty());
|
| + p.reset();
|
| + SkPath cwOval;
|
| + cwOval.addOval(oval);
|
| + p.addArc(oval, 1, 360);
|
| + REPORTER_ASSERT(reporter, p == cwOval);
|
| + p.reset();
|
| + SkPath ccwOval;
|
| + ccwOval.addOval(oval, SkPath::kCCW_Direction);
|
| + p.addArc(oval, 1, -360);
|
| + REPORTER_ASSERT(reporter, p == ccwOval);
|
| + p.reset();
|
| + p.addArc(oval, 1, 180);
|
| + REPORTER_ASSERT(reporter, p.isConvex());
|
| + REPORTER_ASSERT(reporter, p.cheapIsDirection(SkPath::kCW_Direction));
|
| + p.setConvexity(SkPath::kUnknown_Convexity);
|
| + REPORTER_ASSERT(reporter, p.isConvex());
|
| +}
|
| +
|
| +static void check_move(skiatest::Reporter* reporter, SkPath::RawIter* iter,
|
| + SkScalar x0, SkScalar y0) {
|
| + SkPoint pts[4];
|
| + SkPath::Verb v = iter->next(pts);
|
| + REPORTER_ASSERT(reporter, v == SkPath::kMove_Verb);
|
| + REPORTER_ASSERT(reporter, pts[0].fX == x0);
|
| + REPORTER_ASSERT(reporter, pts[0].fY == y0);
|
| +}
|
| +
|
| +static void check_line(skiatest::Reporter* reporter, SkPath::RawIter* iter,
|
| + SkScalar x1, SkScalar y1) {
|
| + SkPoint pts[4];
|
| + SkPath::Verb v = iter->next(pts);
|
| + REPORTER_ASSERT(reporter, v == SkPath::kLine_Verb);
|
| + REPORTER_ASSERT(reporter, pts[1].fX == x1);
|
| + REPORTER_ASSERT(reporter, pts[1].fY == y1);
|
| +}
|
| +
|
| +static void check_quad(skiatest::Reporter* reporter, SkPath::RawIter* iter,
|
| + SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
|
| + SkPoint pts[4];
|
| + SkPath::Verb v = iter->next(pts);
|
| + REPORTER_ASSERT(reporter, v == SkPath::kQuad_Verb);
|
| + REPORTER_ASSERT(reporter, pts[1].fX == x1);
|
| + REPORTER_ASSERT(reporter, pts[1].fY == y1);
|
| + REPORTER_ASSERT(reporter, pts[2].fX == x2);
|
| + REPORTER_ASSERT(reporter, pts[2].fY == y2);
|
| +}
|
| +
|
| +static void check_done(skiatest::Reporter* reporter, SkPath* p, SkPath::RawIter* iter) {
|
| + SkPoint pts[4];
|
| + SkPath::Verb v = iter->next(pts);
|
| + REPORTER_ASSERT(reporter, v == SkPath::kDone_Verb);
|
| +}
|
| +
|
| +static void check_done_and_reset(skiatest::Reporter* reporter, SkPath* p, SkPath::RawIter* iter) {
|
| + check_done(reporter, p, iter);
|
| + p->reset();
|
| +}
|
| +
|
| +static void check_path_is_move_and_reset(skiatest::Reporter* reporter, SkPath* p,
|
| + SkScalar x0, SkScalar y0) {
|
| + SkPath::RawIter iter(*p);
|
| + check_move(reporter, &iter, x0, y0);
|
| + check_done_and_reset(reporter, p, &iter);
|
| +}
|
| +
|
| +static void check_path_is_line_and_reset(skiatest::Reporter* reporter, SkPath* p,
|
| + SkScalar x1, SkScalar y1) {
|
| + SkPath::RawIter iter(*p);
|
| + check_move(reporter, &iter, 0, 0);
|
| + check_line(reporter, &iter, x1, y1);
|
| + check_done_and_reset(reporter, p, &iter);
|
| +}
|
| +
|
| +static void check_path_is_line(skiatest::Reporter* reporter, SkPath* p,
|
| + SkScalar x1, SkScalar y1) {
|
| + SkPath::RawIter iter(*p);
|
| + check_move(reporter, &iter, 0, 0);
|
| + check_line(reporter, &iter, x1, y1);
|
| + check_done(reporter, p, &iter);
|
| +}
|
| +
|
| +static void check_path_is_line_pair_and_reset(skiatest::Reporter* reporter, SkPath* p,
|
| + SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
|
| + SkPath::RawIter iter(*p);
|
| + check_move(reporter, &iter, 0, 0);
|
| + check_line(reporter, &iter, x1, y1);
|
| + check_line(reporter, &iter, x2, y2);
|
| + check_done_and_reset(reporter, p, &iter);
|
| +}
|
| +
|
| +static void check_path_is_quad_and_reset(skiatest::Reporter* reporter, SkPath* p,
|
| + SkScalar x1, SkScalar y1, SkScalar x2, SkScalar y2) {
|
| + SkPath::RawIter iter(*p);
|
| + check_move(reporter, &iter, 0, 0);
|
| + check_quad(reporter, &iter, x1, y1, x2, y2);
|
| + check_done_and_reset(reporter, p, &iter);
|
| }
|
|
|
| +static void test_arcTo(skiatest::Reporter* reporter) {
|
| + SkPath p;
|
| + p.arcTo(0, 0, 1, 2, 1);
|
| + check_path_is_line_and_reset(reporter, &p, 0, 0);
|
| + p.arcTo(1, 2, 1, 2, 1);
|
| + check_path_is_line_and_reset(reporter, &p, 1, 2);
|
| + p.arcTo(1, 2, 3, 4, 0);
|
| + check_path_is_line_and_reset(reporter, &p, 1, 2);
|
| + p.arcTo(1, 2, 0, 0, 1);
|
| + check_path_is_line_and_reset(reporter, &p, 1, 2);
|
| + p.arcTo(1, 0, 1, 1, 1);
|
| + SkPoint pt;
|
| + REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt.fX == 1 && pt.fY == 1);
|
| + p.reset();
|
| + p.arcTo(1, 0, 1, -1, 1);
|
| + REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt.fX == 1 && pt.fY == -1);
|
| + p.reset();
|
| + SkRect oval = {1, 2, 3, 4};
|
| + p.arcTo(oval, 0, 0, true);
|
| + check_path_is_move_and_reset(reporter, &p, oval.fRight, oval.centerY());
|
| + p.arcTo(oval, 0, 0, false);
|
| + check_path_is_move_and_reset(reporter, &p, oval.fRight, oval.centerY());
|
| + p.arcTo(oval, 360, 0, true);
|
| + check_path_is_move_and_reset(reporter, &p, oval.fRight, oval.centerY());
|
| + p.arcTo(oval, 360, 0, false);
|
| + check_path_is_move_and_reset(reporter, &p, oval.fRight, oval.centerY());
|
| + for (float sweep = 359, delta = 0.5f; sweep != (float) (sweep + delta); ) {
|
| + p.arcTo(oval, 0, SkFloatToScalar(sweep), false);
|
| + REPORTER_ASSERT(reporter, p.getBounds() == oval);
|
| + sweep += delta;
|
| + delta /= 2;
|
| + }
|
| + for (float sweep = 361, delta = 0.5f; sweep != (float) (sweep - delta);) {
|
| + p.arcTo(oval, 0, SkFloatToScalar(sweep), false);
|
| + REPORTER_ASSERT(reporter, p.getBounds() == oval);
|
| + sweep -= delta;
|
| + delta /= 2;
|
| + }
|
| + SkRect noOvalWidth = {1, 2, 0, 3};
|
| + p.reset();
|
| + p.arcTo(noOvalWidth, 0, 360, false);
|
| + REPORTER_ASSERT(reporter, p.isEmpty());
|
| +
|
| + SkRect noOvalHeight = {1, 2, 3, 1};
|
| + p.reset();
|
| + p.arcTo(noOvalHeight, 0, 360, false);
|
| + REPORTER_ASSERT(reporter, p.isEmpty());
|
| +}
|
| +
|
| +static void test_addPath(skiatest::Reporter* reporter) {
|
| + SkPath p, q;
|
| + p.lineTo(1, 2);
|
| + q.moveTo(4, 4);
|
| + q.lineTo(7, 8);
|
| + q.conicTo(8, 7, 6, 5, 0.5f);
|
| + q.quadTo(6, 7, 8, 6);
|
| + q.cubicTo(5, 6, 7, 8, 7, 5);
|
| + q.close();
|
| + p.addPath(q, -4, -4);
|
| + SkRect expected = {0, 0, 4, 4};
|
| + REPORTER_ASSERT(reporter, p.getBounds() == expected);
|
| + p.reset();
|
| + p.reverseAddPath(q);
|
| + SkRect reverseExpected = {4, 4, 8, 8};
|
| + REPORTER_ASSERT(reporter, p.getBounds() == reverseExpected);
|
| +}
|
| +
|
| +static void test_conicTo_special_case(skiatest::Reporter* reporter) {
|
| + SkPath p;
|
| + p.conicTo(1, 2, 3, 4, -1);
|
| + check_path_is_line_and_reset(reporter, &p, 3, 4);
|
| + p.conicTo(1, 2, 3, 4, SK_ScalarInfinity);
|
| + check_path_is_line_pair_and_reset(reporter, &p, 1, 2, 3, 4);
|
| + p.conicTo(1, 2, 3, 4, 1);
|
| + check_path_is_quad_and_reset(reporter, &p, 1, 2, 3, 4);
|
| +}
|
| +
|
| +static void test_get_point(skiatest::Reporter* reporter) {
|
| + SkPath p;
|
| + SkPoint pt = p.getPoint(0);
|
| + REPORTER_ASSERT(reporter, pt == SkPoint::Make(0, 0));
|
| + REPORTER_ASSERT(reporter, !p.getLastPt(NULL));
|
| + REPORTER_ASSERT(reporter, !p.getLastPt(&pt) && pt == SkPoint::Make(0, 0));
|
| + p.setLastPt(10, 10);
|
| + pt = p.getPoint(0);
|
| + REPORTER_ASSERT(reporter, pt == SkPoint::Make(10, 10));
|
| + REPORTER_ASSERT(reporter, p.getLastPt(NULL));
|
| + p.rMoveTo(10, 10);
|
| + REPORTER_ASSERT(reporter, p.getLastPt(&pt) && pt == SkPoint::Make(20, 20));
|
| +}
|
| +
|
| +static void test_contains(skiatest::Reporter* reporter) {
|
| + SkPath p;
|
| + p.setFillType(SkPath::kInverseWinding_FillType);
|
| + REPORTER_ASSERT(reporter, p.contains(0, 0));
|
| + p.setFillType(SkPath::kWinding_FillType);
|
| + REPORTER_ASSERT(reporter, !p.contains(0, 0));
|
| + p.moveTo(4, 4);
|
| + p.lineTo(6, 8);
|
| + p.lineTo(8, 4);
|
| + // test quick reject
|
| + REPORTER_ASSERT(reporter, !p.contains(4, 0));
|
| + REPORTER_ASSERT(reporter, !p.contains(0, 4));
|
| + REPORTER_ASSERT(reporter, !p.contains(4, 10));
|
| + REPORTER_ASSERT(reporter, !p.contains(10, 4));
|
| + // test various crossings in x
|
| + REPORTER_ASSERT(reporter, !p.contains(5, 7));
|
| + REPORTER_ASSERT(reporter, p.contains(6, 7));
|
| + REPORTER_ASSERT(reporter, !p.contains(7, 7));
|
| + p.reset();
|
| + p.moveTo(4, 4);
|
| + p.lineTo(8, 6);
|
| + p.lineTo(4, 8);
|
| + // test various crossings in y
|
| + REPORTER_ASSERT(reporter, !p.contains(7, 5));
|
| + REPORTER_ASSERT(reporter, p.contains(7, 6));
|
| + REPORTER_ASSERT(reporter, !p.contains(7, 7));
|
| + // test quads
|
| + p.reset();
|
| + p.moveTo(4, 4);
|
| + p.quadTo(6, 6, 8, 8);
|
| + p.quadTo(6, 8, 4, 8);
|
| + p.quadTo(4, 6, 4, 4);
|
| + REPORTER_ASSERT(reporter, p.contains(5, 6));
|
| + REPORTER_ASSERT(reporter, !p.contains(6, 5));
|
| +
|
| + p.reset();
|
| + p.moveTo(6, 6);
|
| + p.quadTo(8, 8, 6, 8);
|
| + p.quadTo(4, 8, 4, 6);
|
| + p.quadTo(4, 4, 6, 6);
|
| + REPORTER_ASSERT(reporter, p.contains(5, 6));
|
| + REPORTER_ASSERT(reporter, !p.contains(6, 5));
|
| +
|
| +#define CONIC_CONTAINS_BUG_FIXED 0
|
| +#if CONIC_CONTAINS_BUG_FIXED
|
| + p.reset();
|
| + p.moveTo(4, 4);
|
| + p.conicTo(6, 6, 8, 8, 0.5f);
|
| + p.conicTo(6, 8, 4, 8, 0.5f);
|
| + p.conicTo(4, 6, 4, 4, 0.5f);
|
| + REPORTER_ASSERT(reporter, p.contains(5, 6));
|
| + REPORTER_ASSERT(reporter, !p.contains(6, 5));
|
| +#endif
|
| +
|
| + // test cubics
|
| + SkPoint pts[] = {{5, 4}, {6, 5}, {7, 6}, {6, 6}, {4, 6}, {5, 7}, {5, 5}, {5, 4}, {6, 5}, {7, 6}};
|
| + for (int i = 0; i < 3; ++i) {
|
| + p.reset();
|
| + p.setFillType(SkPath::kEvenOdd_FillType);
|
| + p.moveTo(pts[i].fX, pts[i].fY);
|
| + p.cubicTo(pts[i + 1].fX, pts[i + 1].fY, pts[i + 2].fX, pts[i + 2].fY, pts[i + 3].fX, pts[i + 3].fY);
|
| + p.cubicTo(pts[i + 4].fX, pts[i + 4].fY, pts[i + 5].fX, pts[i + 5].fY, pts[i + 6].fX, pts[i + 6].fY);
|
| + p.close();
|
| + REPORTER_ASSERT(reporter, p.contains(5.5f, 5.5f));
|
| + REPORTER_ASSERT(reporter, !p.contains(4.5f, 5.5f));
|
| + }
|
| +}
|
| +
|
| +static void test_operatorEqual(skiatest::Reporter* reporter) {
|
| + SkPath a;
|
| + SkPath b;
|
| + REPORTER_ASSERT(reporter, a == a);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| + a.setFillType(SkPath::kInverseWinding_FillType);
|
| + REPORTER_ASSERT(reporter, a != b);
|
| + a.reset();
|
| + REPORTER_ASSERT(reporter, a == b);
|
| + a.lineTo(1, 1);
|
| + REPORTER_ASSERT(reporter, a != b);
|
| + a.reset();
|
| + REPORTER_ASSERT(reporter, a == b);
|
| + a.lineTo(1, 1);
|
| + b.lineTo(1, 2);
|
| + REPORTER_ASSERT(reporter, a != b);
|
| + a.reset();
|
| + a.lineTo(1, 2);
|
| + REPORTER_ASSERT(reporter, a == b);
|
| +}
|
| +
|
| +class PathTest_Private {
|
| +public:
|
| + static void TestPathTo(skiatest::Reporter* reporter) {
|
| + SkPath p, q;
|
| + p.lineTo(4, 4);
|
| + p.reversePathTo(q);
|
| + check_path_is_line(reporter, &p, 4, 4);
|
| + q.moveTo(-4, -4);
|
| + p.reversePathTo(q);
|
| + check_path_is_line(reporter, &p, 4, 4);
|
| + q.lineTo(7, 8);
|
| + q.conicTo(8, 7, 6, 5, 0.5f);
|
| + q.quadTo(6, 7, 8, 6);
|
| + q.cubicTo(5, 6, 7, 8, 7, 5);
|
| + q.close();
|
| + p.reversePathTo(q);
|
| + SkRect reverseExpected = {-4, -4, 8, 8};
|
| + REPORTER_ASSERT(reporter, p.getBounds() == reverseExpected);
|
| + }
|
| +};
|
| +
|
| static void TestPath(skiatest::Reporter* reporter) {
|
| SkTSize<SkScalar>::Make(3,4);
|
|
|
| @@ -2609,6 +3145,13 @@ static void TestPath(skiatest::Reporter* reporter) {
|
|
|
| REPORTER_ASSERT(reporter, p.getBounds().isEmpty());
|
|
|
| + // this triggers a code path in SkPath::operator= which is otherwise unexercised
|
| + SkPath& self = p;
|
| + p = self;
|
| +
|
| + // this triggers a code path in SkPath::swap which is otherwise unexercised
|
| + p.swap(self);
|
| +
|
| bounds.set(0, 0, SK_Scalar1, SK_Scalar1);
|
|
|
| p.addRoundRect(bounds, SK_Scalar1, SK_Scalar1);
|
| @@ -2668,6 +3211,7 @@ static void TestPath(skiatest::Reporter* reporter) {
|
| p.addRect(bounds);
|
| REPORTER_ASSERT(reporter, !p.isRect(NULL));
|
|
|
| + test_operatorEqual(reporter);
|
| test_isLine(reporter);
|
| test_isRect(reporter);
|
| test_isNestedRects(reporter);
|
| @@ -2691,6 +3235,7 @@ static void TestPath(skiatest::Reporter* reporter) {
|
| test_isfinite_after_transform(reporter);
|
| test_arb_round_rect_is_convex(reporter);
|
| test_arb_zero_rad_round_rect_is_rect(reporter);
|
| + test_addrect(reporter);
|
| test_addrect_isfinite(reporter);
|
| test_tricky_cubic();
|
| test_clipped_cubic();
|
| @@ -2702,6 +3247,13 @@ static void TestPath(skiatest::Reporter* reporter) {
|
| test_path_close_issue1474(reporter);
|
| test_path_to_region(reporter);
|
| test_rrect(reporter);
|
| + test_arc(reporter);
|
| + test_arcTo(reporter);
|
| + test_addPath(reporter);
|
| + test_conicTo_special_case(reporter);
|
| + test_get_point(reporter);
|
| + test_contains(reporter);
|
| + PathTest_Private::TestPathTo(reporter);
|
| }
|
|
|
| #include "TestClassDef.h"
|
|
|