blob: df66578f1bf56927675fb12c8c71dc04a7934d49 [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001/*
2 * Copyright 2011 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 */
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +00007
reed@android.com5e5adfd2009-03-07 03:39:23 +00008#include "SkPathMeasure.h"
tfarina@chromium.org8f6884a2014-01-24 20:56:26 +00009#include "Test.h"
reed@android.com5e5adfd2009-03-07 03:39:23 +000010
sugoi@google.com54f0d1b2013-02-27 19:17:41 +000011static void test_small_segment3() {
reed@google.comded44142012-04-27 20:22:07 +000012 SkPath path;
13 const SkPoint pts[] = {
14 { 0, 0 },
15 { 100000000000.0f, 100000000000.0f }, { 0, 0 }, { 10, 10 },
16 { 10, 10 }, { 0, 0 }, { 10, 10 }
17 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000018
reed@google.comded44142012-04-27 20:22:07 +000019 path.moveTo(pts[0]);
bsalomon@google.com2fc23592012-10-03 19:10:31 +000020 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 3) {
reed@google.comded44142012-04-27 20:22:07 +000021 path.cubicTo(pts[i], pts[i + 1], pts[i + 2]);
22 }
rmistry@google.comd6176b02012-08-23 18:14:13 +000023
reed@google.comded44142012-04-27 20:22:07 +000024 SkPathMeasure meas(path, false);
25 meas.getLength();
reed@google.comded44142012-04-27 20:22:07 +000026}
27
sugoi@google.com54f0d1b2013-02-27 19:17:41 +000028static void test_small_segment2() {
reed@google.comded44142012-04-27 20:22:07 +000029 SkPath path;
30 const SkPoint pts[] = {
31 { 0, 0 },
rmistry@google.comd6176b02012-08-23 18:14:13 +000032 { 100000000000.0f, 100000000000.0f }, { 0, 0 },
33 { 10, 10 }, { 0, 0 },
reed@google.comded44142012-04-27 20:22:07 +000034 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000035
reed@google.comded44142012-04-27 20:22:07 +000036 path.moveTo(pts[0]);
37 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 2) {
38 path.quadTo(pts[i], pts[i + 1]);
39 }
40 SkPathMeasure meas(path, false);
41 meas.getLength();
reed@google.comded44142012-04-27 20:22:07 +000042}
43
sugoi@google.com54f0d1b2013-02-27 19:17:41 +000044static void test_small_segment() {
reed@google.comfab1ddd2012-04-20 15:10:32 +000045 SkPath path;
46 const SkPoint pts[] = {
47 { 100000, 100000},
48 // big jump between these points, makes a big segment
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +000049 { 1.0005f, 0.9999f },
reed@google.comfab1ddd2012-04-20 15:10:32 +000050 // tiny (non-zero) jump between these points
robertphillips@google.comc6ce7502012-05-08 13:15:37 +000051 { SK_Scalar1, SK_Scalar1 },
reed@google.comfab1ddd2012-04-20 15:10:32 +000052 };
rmistry@google.comd6176b02012-08-23 18:14:13 +000053
reed@google.comfab1ddd2012-04-20 15:10:32 +000054 path.moveTo(pts[0]);
55 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); ++i) {
56 path.lineTo(pts[i]);
57 }
58 SkPathMeasure meas(path, false);
59
60 /* this would assert (before a fix) because we added a segment with
61 the same length as the prev segment, due to the follow (bad) pattern
62
63 d = distance(pts[0], pts[1]);
64 distance += d;
65 seg->fDistance = distance;
reed@google.comded44142012-04-27 20:22:07 +000066
reed@google.comfab1ddd2012-04-20 15:10:32 +000067 SkASSERT(d > 0); // TRUE
68 SkASSERT(seg->fDistance > prevSeg->fDistance); // FALSE
69
70 This 2nd assert failes because (distance += d) didn't affect distance
71 because distance >>> d.
72 */
73 meas.getLength();
reed@google.comfab1ddd2012-04-20 15:10:32 +000074}
75
tfarina@chromium.orge4fafb12013-12-12 21:11:12 +000076DEF_TEST(PathMeasure, reporter) {
reed@android.com5e5adfd2009-03-07 03:39:23 +000077 SkPath path;
78
79 path.moveTo(0, 0);
80 path.lineTo(SK_Scalar1, 0);
81 path.lineTo(SK_Scalar1, SK_Scalar1);
82 path.lineTo(0, SK_Scalar1);
83
84 SkPathMeasure meas(path, true);
85 SkScalar length = meas.getLength();
86 SkASSERT(length == SK_Scalar1*4);
87
88 path.reset();
89 path.moveTo(0, 0);
90 path.lineTo(SK_Scalar1*3, SK_Scalar1*4);
91 meas.setPath(&path, false);
92 length = meas.getLength();
93 REPORTER_ASSERT(reporter, length == SK_Scalar1*5);
94
95 path.reset();
96 path.addCircle(0, 0, SK_Scalar1);
97 meas.setPath(&path, true);
98 length = meas.getLength();
99// SkDebugf("circle arc-length = %g\n", length);
100
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000101 // Test the behavior following a close not followed by a move.
102 path.reset();
103 path.lineTo(SK_Scalar1, 0);
104 path.lineTo(SK_Scalar1, SK_Scalar1);
105 path.lineTo(0, SK_Scalar1);
106 path.close();
107 path.lineTo(-SK_Scalar1, 0);
108 meas.setPath(&path, false);
109 length = meas.getLength();
110 REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4);
111 meas.nextContour();
112 length = meas.getLength();
113 REPORTER_ASSERT(reporter, length == SK_Scalar1);
114 SkPoint position;
115 SkVector tangent;
116 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
117 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000118 SkScalarNearlyEqual(position.fX,
119 -SK_ScalarHalf,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000120 0.0001f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000121 REPORTER_ASSERT(reporter, position.fY == 0);
122 REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
123 REPORTER_ASSERT(reporter, tangent.fY == 0);
124
125 // Test degenerate paths
126 path.reset();
127 path.moveTo(0, 0);
128 path.lineTo(0, 0);
129 path.lineTo(SK_Scalar1, 0);
130 path.quadTo(SK_Scalar1, 0, SK_Scalar1, 0);
131 path.quadTo(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1 * 2);
132 path.cubicTo(SK_Scalar1, SK_Scalar1 * 2,
133 SK_Scalar1, SK_Scalar1 * 2,
134 SK_Scalar1, SK_Scalar1 * 2);
135 path.cubicTo(SK_Scalar1*2, SK_Scalar1 * 2,
136 SK_Scalar1*3, SK_Scalar1 * 2,
137 SK_Scalar1*4, SK_Scalar1 * 2);
138 meas.setPath(&path, false);
139 length = meas.getLength();
140 REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6);
141 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
142 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000143 SkScalarNearlyEqual(position.fX,
144 SK_ScalarHalf,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000145 0.0001f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000146 REPORTER_ASSERT(reporter, position.fY == 0);
147 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
148 REPORTER_ASSERT(reporter, tangent.fY == 0);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000149 REPORTER_ASSERT(reporter, meas.getPosTan(2.5f, &position, &tangent));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000150 REPORTER_ASSERT(reporter,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000151 SkScalarNearlyEqual(position.fX, SK_Scalar1, 0.0001f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000152 REPORTER_ASSERT(reporter,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000153 SkScalarNearlyEqual(position.fY, 1.5f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000154 REPORTER_ASSERT(reporter, tangent.fX == 0);
155 REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1);
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000156 REPORTER_ASSERT(reporter, meas.getPosTan(4.5f, &position, &tangent));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000157 REPORTER_ASSERT(reporter,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000158 SkScalarNearlyEqual(position.fX,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000159 2.5f,
160 0.0001f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000161 REPORTER_ASSERT(reporter,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000162 SkScalarNearlyEqual(position.fY,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000163 2.0f,
164 0.0001f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000165 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
166 REPORTER_ASSERT(reporter, tangent.fY == 0);
167
168 path.reset();
169 path.moveTo(0, 0);
170 path.lineTo(SK_Scalar1, 0);
171 path.moveTo(SK_Scalar1, SK_Scalar1);
172 path.moveTo(SK_Scalar1 * 2, SK_Scalar1 * 2);
173 path.lineTo(SK_Scalar1, SK_Scalar1 * 2);
174 meas.setPath(&path, false);
175 length = meas.getLength();
176 REPORTER_ASSERT(reporter, length == SK_Scalar1);
177 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
178 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000179 SkScalarNearlyEqual(position.fX,
180 SK_ScalarHalf,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000181 0.0001f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000182 REPORTER_ASSERT(reporter, position.fY == 0);
183 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
184 REPORTER_ASSERT(reporter, tangent.fY == 0);
185 meas.nextContour();
186 length = meas.getLength();
187 REPORTER_ASSERT(reporter, length == SK_Scalar1);
188 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
189 REPORTER_ASSERT(reporter,
rmistry@google.comd6176b02012-08-23 18:14:13 +0000190 SkScalarNearlyEqual(position.fX,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000191 1.5f,
192 0.0001f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000193 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000194 SkScalarNearlyEqual(position.fY,
commit-bot@chromium.org4b413c82013-11-25 19:44:07 +0000195 2.0f,
196 0.0001f));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000197 REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
198 REPORTER_ASSERT(reporter, tangent.fY == 0);
reed@google.comfab1ddd2012-04-20 15:10:32 +0000199
sugoi@google.com54f0d1b2013-02-27 19:17:41 +0000200 test_small_segment();
201 test_small_segment2();
202 test_small_segment3();
reed@android.com5e5adfd2009-03-07 03:39:23 +0000203}
caryclarkb6474dd2016-01-19 08:07:49 -0800204
205DEF_TEST(PathMeasureConic, reporter) {
206 SkPoint stdP, hiP, pts[] = {{0,0}, {100,0}, {100,0}};
207 SkPath p;
208 p.moveTo(0, 0);
209 p.conicTo(pts[1], pts[2], 1);
210 SkPathMeasure stdm(p, false);
211 REPORTER_ASSERT(reporter, stdm.getPosTan(20, &stdP, nullptr));
212 p.reset();
213 p.moveTo(0, 0);
214 p.conicTo(pts[1], pts[2], 10);
215 stdm.setPath(&p, false);
216 REPORTER_ASSERT(reporter, stdm.getPosTan(20, &hiP, nullptr));
217 REPORTER_ASSERT(reporter, 19.5f < stdP.fX && stdP.fX < 20.5f);
218 REPORTER_ASSERT(reporter, 19.5f < hiP.fX && hiP.fX < 20.5f);
219}