blob: e8477c6fdec5d4b0418654b712b6bf53de4c369f [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
2/*
3 * Copyright 2011 Google Inc.
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
reed@android.com5e5adfd2009-03-07 03:39:23 +00008#include "Test.h"
9#include "SkPathMeasure.h"
10
reed@google.comded44142012-04-27 20:22:07 +000011static void test_small_segment3(skiatest::Reporter* reporter) {
12#ifdef SK_SCALAR_IS_FLOAT
13 SkPath path;
14 const SkPoint pts[] = {
15 { 0, 0 },
16 { 100000000000.0f, 100000000000.0f }, { 0, 0 }, { 10, 10 },
17 { 10, 10 }, { 0, 0 }, { 10, 10 }
18 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000019
reed@google.comded44142012-04-27 20:22:07 +000020 path.moveTo(pts[0]);
bsalomon@google.com2fc23592012-10-03 19:10:31 +000021 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 3) {
reed@google.comded44142012-04-27 20:22:07 +000022 path.cubicTo(pts[i], pts[i + 1], pts[i + 2]);
23 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000024
reed@google.comded44142012-04-27 20:22:07 +000025 SkPathMeasure meas(path, false);
26 meas.getLength();
27#endif
28}
29
30static void test_small_segment2(skiatest::Reporter* reporter) {
31#ifdef SK_SCALAR_IS_FLOAT
32 SkPath path;
33 const SkPoint pts[] = {
34 { 0, 0 },
rmistry@google.comd6176b02012-08-23 18:14:13 +000035 { 100000000000.0f, 100000000000.0f }, { 0, 0 },
36 { 10, 10 }, { 0, 0 },
reed@google.comded44142012-04-27 20:22:07 +000037 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000038
reed@google.comded44142012-04-27 20:22:07 +000039 path.moveTo(pts[0]);
40 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 2) {
41 path.quadTo(pts[i], pts[i + 1]);
42 }
43 SkPathMeasure meas(path, false);
44 meas.getLength();
45#endif
46}
47
reed@google.comfab1ddd2012-04-20 15:10:32 +000048static void test_small_segment(skiatest::Reporter* reporter) {
49#ifdef SK_SCALAR_IS_FLOAT
50 SkPath path;
51 const SkPoint pts[] = {
52 { 100000, 100000},
53 // big jump between these points, makes a big segment
robertphillips@google.comc6ce7502012-05-08 13:15:37 +000054 { SkFloatToScalar(1.0005f), SkFloatToScalar(0.9999f) },
reed@google.comfab1ddd2012-04-20 15:10:32 +000055 // tiny (non-zero) jump between these points
robertphillips@google.comc6ce7502012-05-08 13:15:37 +000056 { SK_Scalar1, SK_Scalar1 },
reed@google.comfab1ddd2012-04-20 15:10:32 +000057 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000058
reed@google.comfab1ddd2012-04-20 15:10:32 +000059 path.moveTo(pts[0]);
60 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); ++i) {
61 path.lineTo(pts[i]);
62 }
63 SkPathMeasure meas(path, false);
64
65 /* this would assert (before a fix) because we added a segment with
66 the same length as the prev segment, due to the follow (bad) pattern
67
68 d = distance(pts[0], pts[1]);
69 distance += d;
70 seg->fDistance = distance;
reed@google.comded44142012-04-27 20:22:07 +000071
reed@google.comfab1ddd2012-04-20 15:10:32 +000072 SkASSERT(d > 0); // TRUE
73 SkASSERT(seg->fDistance > prevSeg->fDistance); // FALSE
74
75 This 2nd assert failes because (distance += d) didn't affect distance
76 because distance >>> d.
77 */
78 meas.getLength();
79#endif
80}
81
reed@android.com5e5adfd2009-03-07 03:39:23 +000082static void TestPathMeasure(skiatest::Reporter* reporter) {
83 SkPath path;
84
85 path.moveTo(0, 0);
86 path.lineTo(SK_Scalar1, 0);
87 path.lineTo(SK_Scalar1, SK_Scalar1);
88 path.lineTo(0, SK_Scalar1);
89
90 SkPathMeasure meas(path, true);
91 SkScalar length = meas.getLength();
92 SkASSERT(length == SK_Scalar1*4);
93
94 path.reset();
95 path.moveTo(0, 0);
96 path.lineTo(SK_Scalar1*3, SK_Scalar1*4);
97 meas.setPath(&path, false);
98 length = meas.getLength();
99 REPORTER_ASSERT(reporter, length == SK_Scalar1*5);
100
101 path.reset();
102 path.addCircle(0, 0, SK_Scalar1);
103 meas.setPath(&path, true);
104 length = meas.getLength();
105// SkDebugf("circle arc-length = %g\n", length);
106
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000107 // Test the behavior following a close not followed by a move.
108 path.reset();
109 path.lineTo(SK_Scalar1, 0);
110 path.lineTo(SK_Scalar1, SK_Scalar1);
111 path.lineTo(0, SK_Scalar1);
112 path.close();
113 path.lineTo(-SK_Scalar1, 0);
114 meas.setPath(&path, false);
115 length = meas.getLength();
116 REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4);
117 meas.nextContour();
118 length = meas.getLength();
119 REPORTER_ASSERT(reporter, length == SK_Scalar1);
120 SkPoint position;
121 SkVector tangent;
122 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
123 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000124 SkScalarNearlyEqual(position.fX,
125 -SK_ScalarHalf,
126 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000127 REPORTER_ASSERT(reporter, position.fY == 0);
128 REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
129 REPORTER_ASSERT(reporter, tangent.fY == 0);
130
131 // Test degenerate paths
132 path.reset();
133 path.moveTo(0, 0);
134 path.lineTo(0, 0);
135 path.lineTo(SK_Scalar1, 0);
136 path.quadTo(SK_Scalar1, 0, SK_Scalar1, 0);
137 path.quadTo(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1 * 2);
138 path.cubicTo(SK_Scalar1, SK_Scalar1 * 2,
139 SK_Scalar1, SK_Scalar1 * 2,
140 SK_Scalar1, SK_Scalar1 * 2);
141 path.cubicTo(SK_Scalar1*2, SK_Scalar1 * 2,
142 SK_Scalar1*3, SK_Scalar1 * 2,
143 SK_Scalar1*4, SK_Scalar1 * 2);
144 meas.setPath(&path, false);
145 length = meas.getLength();
146 REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6);
147 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
148 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000149 SkScalarNearlyEqual(position.fX,
150 SK_ScalarHalf,
151 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000152 REPORTER_ASSERT(reporter, position.fY == 0);
153 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
154 REPORTER_ASSERT(reporter, tangent.fY == 0);
robertphillips@google.com59f46b82012-07-10 17:30:58 +0000155 REPORTER_ASSERT(reporter, meas.getPosTan(SkFloatToScalar(2.5f), &position, &tangent));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000156 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000157 SkScalarNearlyEqual(position.fX, SK_Scalar1, SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000158 REPORTER_ASSERT(reporter,
robertphillips@google.com59f46b82012-07-10 17:30:58 +0000159 SkScalarNearlyEqual(position.fY, SkFloatToScalar(1.5f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000160 REPORTER_ASSERT(reporter, tangent.fX == 0);
161 REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1);
robertphillips@google.com59f46b82012-07-10 17:30:58 +0000162 REPORTER_ASSERT(reporter, meas.getPosTan(SkFloatToScalar(4.5f), &position, &tangent));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000163 REPORTER_ASSERT(reporter,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000164 SkScalarNearlyEqual(position.fX,
165 SkFloatToScalar(2.5f),
robertphillips@google.com6853e802012-04-16 15:50:18 +0000166 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000167 REPORTER_ASSERT(reporter,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000168 SkScalarNearlyEqual(position.fY,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000169 SkFloatToScalar(2.0f),
170 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000171 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
172 REPORTER_ASSERT(reporter, tangent.fY == 0);
173
174 path.reset();
175 path.moveTo(0, 0);
176 path.lineTo(SK_Scalar1, 0);
177 path.moveTo(SK_Scalar1, SK_Scalar1);
178 path.moveTo(SK_Scalar1 * 2, SK_Scalar1 * 2);
179 path.lineTo(SK_Scalar1, SK_Scalar1 * 2);
180 meas.setPath(&path, false);
181 length = meas.getLength();
182 REPORTER_ASSERT(reporter, length == SK_Scalar1);
183 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
184 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000185 SkScalarNearlyEqual(position.fX,
186 SK_ScalarHalf,
187 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000188 REPORTER_ASSERT(reporter, position.fY == 0);
189 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
190 REPORTER_ASSERT(reporter, tangent.fY == 0);
191 meas.nextContour();
192 length = meas.getLength();
193 REPORTER_ASSERT(reporter, length == SK_Scalar1);
194 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
195 REPORTER_ASSERT(reporter,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000196 SkScalarNearlyEqual(position.fX,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000197 SkFloatToScalar(1.5f),
198 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000199 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000200 SkScalarNearlyEqual(position.fY,
201 SkFloatToScalar(2.0f),
202 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000203 REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
204 REPORTER_ASSERT(reporter, tangent.fY == 0);
reed@google.comfab1ddd2012-04-20 15:10:32 +0000205
206 test_small_segment(reporter);
reed@google.comded44142012-04-27 20:22:07 +0000207 test_small_segment2(reporter);
208 test_small_segment3(reporter);
reed@android.com5e5adfd2009-03-07 03:39:23 +0000209}
210
211#include "TestClassDef.h"
212DEFINE_TESTCLASS("PathMeasure", PathMeasureTestClass, TestPathMeasure)