1 /*
2 * Copyright 2014 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "Test.h"
9
10 #include "SkDashPathEffect.h"
11 #include "SkWriteBuffer.h"
12 #include "SkStrokeRec.h"
13
14 // crbug.com/348821 was rooted in SkDashPathEffect refusing to flatten and unflatten itself when
15 // fInitialDashLength < 0 (a signal the effect is nonsense). Here we test that it flattens.
16
DEF_TEST(DashPathEffectTest_crbug_348821,r)17 DEF_TEST(DashPathEffectTest_crbug_348821, r) {
18 SkScalar intervals[] = { 1.76934361e+36f, 2.80259693e-45f }; // Values from bug.
19 const int count = 2;
20 SkScalar phase = SK_ScalarInfinity; // Used to force the bad fInitialDashLength = -1 path.
21 SkAutoTUnref<SkPathEffect> dash(SkDashPathEffect::Create(intervals, count, phase));
22
23 // nullptr -> refuses to work with flattening framework.
24 REPORTER_ASSERT(r, dash->getFactory() != nullptr);
25
26 SkWriteBuffer buffer;
27 buffer.writeFlattenable(dash);
28 REPORTER_ASSERT(r, buffer.bytesWritten() > 12); // We'd write 12 if broken, >=40 if not.
29 }
30
31 // Test out the asPoint culling behavior.
DEF_TEST(DashPathEffectTest_asPoints,r)32 DEF_TEST(DashPathEffectTest_asPoints, r) {
33
34 const SkScalar intervals[] = { 1.0f, 1.0f };
35 const int count = 2;
36 SkAutoTUnref<SkPathEffect> dash(SkDashPathEffect::Create(intervals, count, 0.0f));
37
38 SkRect cull = SkRect::MakeWH(1.0f, 1.0f);
39
40 const struct {
41 SkPoint fPts[2];
42 bool fExpectedResult;
43 } testCases[] = {
44 { { { -5.0f, 0.5f }, { -4.0f, 0.5f } }, false }, // off to the left
45 { { { 4.0f, 0.5f }, { 5.0f, 0.5f } }, false }, // off to the right
46 { { { 0.5f, 4.0f }, { 0.5f, 5.0f } }, false }, // off the bottom
47 { { { 0.5f, -5.0f }, { 0.5f, -4.0f } }, false }, // off the top
48 { { { 0.5f, 0.2f }, { 0.5f, 0.8f } }, true }, // entirely inside vertical
49 { { { 0.2f, 0.5f }, { 0.8f, 0.5f } }, true }, // entirely inside horizontal
50 { { { 0.5f, -5.0f }, { 0.5f, 5.0f } }, true }, // straddles both sides vertically
51 { { { -5.0f, 0.5f }, { 5.0f, 0.5f } }, true }, // straddles both sides horizontally
52 { { { 0.5f, -5.0f }, { 0.5f, 0.5f } }, true }, // straddles top
53 { { { 0.5f, 5.0f }, { 0.5f, 0.5f } }, true }, // straddles bottom
54 { { { -5.0f, 0.5f }, { 0.5f, 0.5f } }, true }, // straddles left
55 { { { 5.0f, 0.5f }, { 0.5f, 0.5f } }, true }, // straddles right
56 { { { 0.5f, 0.5f }, { 0.5f, 0.5f } }, false }, // zero length
57 };
58
59 SkPaint paint;
60 paint.setStyle(SkPaint::kStroke_Style);
61 paint.setStrokeWidth(1.0f);
62 SkStrokeRec rec(paint);
63
64 static const int kNumMats = 3;
65 SkMatrix mats[kNumMats];
66 mats[0].reset();
67 mats[1].setRotate(90, 0.5f, 0.5f);
68 mats[2].setTranslate(10.0f, 10.0f);
69
70 for (int i = 0; i < kNumMats; ++i) {
71 for (int j = 0; j < (int)SK_ARRAY_COUNT(testCases); ++j) {
72 for (int k = 0; k < 2; ++k) { // exercise alternating endpoints
73 SkPathEffect::PointData results;
74 SkPath src;
75
76 src.moveTo(testCases[j].fPts[k]);
77 src.lineTo(testCases[j].fPts[(k+1)%2]);
78
79 bool actualResult = dash->asPoints(&results, src, rec, mats[i], &cull);
80 if (i < 2) {
81 REPORTER_ASSERT(r, actualResult == testCases[j].fExpectedResult);
82 } else {
83 // On the third pass all the lines should be outside the translated cull rect
84 REPORTER_ASSERT(r, !actualResult);
85 }
86 }
87 }
88 }
89 }
90
DEF_TEST(DashPath_bug4871,r)91 DEF_TEST(DashPath_bug4871, r) {
92 SkPath path;
93 path.moveTo(30, 24);
94 path.cubicTo(30.002f, 24, 30, 24, 30, 24);
95 path.close();
96
97 SkScalar intervals[2] = { 1, 1 };
98 SkAutoTUnref<SkPathEffect> dash(SkDashPathEffect::Create(intervals, 2, 0));
99
100 SkPaint paint;
101 paint.setStyle(SkPaint::kStroke_Style);
102 paint.setPathEffect(dash);
103
104 SkPath fill;
105 paint.getFillPath(path, &fill);
106 }
107