blob: e636ff38fc3bd4276a517b0b31498a956b60761f [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.comfab1ddd2012-04-20 15:10:32 +000011static void test_small_segment(skiatest::Reporter* reporter) {
12#ifdef SK_SCALAR_IS_FLOAT
13 SkPath path;
14 const SkPoint pts[] = {
15 { 100000, 100000},
16 // big jump between these points, makes a big segment
17 { 1.0005, 0.9999 },
18 // tiny (non-zero) jump between these points
19 { 1, 1 },
20 };
21
22 path.moveTo(pts[0]);
23 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); ++i) {
24 path.lineTo(pts[i]);
25 }
26 SkPathMeasure meas(path, false);
27
28 /* this would assert (before a fix) because we added a segment with
29 the same length as the prev segment, due to the follow (bad) pattern
30
31 d = distance(pts[0], pts[1]);
32 distance += d;
33 seg->fDistance = distance;
34
35 SkASSERT(d > 0); // TRUE
36 SkASSERT(seg->fDistance > prevSeg->fDistance); // FALSE
37
38 This 2nd assert failes because (distance += d) didn't affect distance
39 because distance >>> d.
40 */
41 meas.getLength();
42#endif
43}
44
reed@android.com5e5adfd2009-03-07 03:39:23 +000045static void TestPathMeasure(skiatest::Reporter* reporter) {
46 SkPath path;
47
48 path.moveTo(0, 0);
49 path.lineTo(SK_Scalar1, 0);
50 path.lineTo(SK_Scalar1, SK_Scalar1);
51 path.lineTo(0, SK_Scalar1);
52
53 SkPathMeasure meas(path, true);
54 SkScalar length = meas.getLength();
55 SkASSERT(length == SK_Scalar1*4);
56
57 path.reset();
58 path.moveTo(0, 0);
59 path.lineTo(SK_Scalar1*3, SK_Scalar1*4);
60 meas.setPath(&path, false);
61 length = meas.getLength();
62 REPORTER_ASSERT(reporter, length == SK_Scalar1*5);
63
64 path.reset();
65 path.addCircle(0, 0, SK_Scalar1);
66 meas.setPath(&path, true);
67 length = meas.getLength();
68// SkDebugf("circle arc-length = %g\n", length);
69
schenney@chromium.org510c6b12012-01-12 20:04:06 +000070 // Test the behavior following a close not followed by a move.
71 path.reset();
72 path.lineTo(SK_Scalar1, 0);
73 path.lineTo(SK_Scalar1, SK_Scalar1);
74 path.lineTo(0, SK_Scalar1);
75 path.close();
76 path.lineTo(-SK_Scalar1, 0);
77 meas.setPath(&path, false);
78 length = meas.getLength();
79 REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4);
80 meas.nextContour();
81 length = meas.getLength();
82 REPORTER_ASSERT(reporter, length == SK_Scalar1);
83 SkPoint position;
84 SkVector tangent;
85 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
86 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +000087 SkScalarNearlyEqual(position.fX,
88 -SK_ScalarHalf,
89 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +000090 REPORTER_ASSERT(reporter, position.fY == 0);
91 REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
92 REPORTER_ASSERT(reporter, tangent.fY == 0);
93
94 // Test degenerate paths
95 path.reset();
96 path.moveTo(0, 0);
97 path.lineTo(0, 0);
98 path.lineTo(SK_Scalar1, 0);
99 path.quadTo(SK_Scalar1, 0, SK_Scalar1, 0);
100 path.quadTo(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1 * 2);
101 path.cubicTo(SK_Scalar1, SK_Scalar1 * 2,
102 SK_Scalar1, SK_Scalar1 * 2,
103 SK_Scalar1, SK_Scalar1 * 2);
104 path.cubicTo(SK_Scalar1*2, SK_Scalar1 * 2,
105 SK_Scalar1*3, SK_Scalar1 * 2,
106 SK_Scalar1*4, SK_Scalar1 * 2);
107 meas.setPath(&path, false);
108 length = meas.getLength();
109 REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6);
110 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
111 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000112 SkScalarNearlyEqual(position.fX,
113 SK_ScalarHalf,
114 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000115 REPORTER_ASSERT(reporter, position.fY == 0);
116 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
117 REPORTER_ASSERT(reporter, tangent.fY == 0);
118 REPORTER_ASSERT(reporter, meas.getPosTan(SK_Scalar1 * 2.5f, &position, &tangent));
119 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000120 SkScalarNearlyEqual(position.fX, SK_Scalar1, SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000121 REPORTER_ASSERT(reporter,
122 SkScalarNearlyEqual(position.fY, SK_Scalar1 * 1.5f));
123 REPORTER_ASSERT(reporter, tangent.fX == 0);
124 REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1);
125 REPORTER_ASSERT(reporter, meas.getPosTan(SK_Scalar1 * 4.5f, &position, &tangent));
126 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000127 SkScalarNearlyEqual(position.fX,
128 SkFloatToScalar(2.5f),
129 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000130 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000131 SkScalarNearlyEqual(position.fY,
132 SkFloatToScalar(2.0f),
133 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000134 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
135 REPORTER_ASSERT(reporter, tangent.fY == 0);
136
137 path.reset();
138 path.moveTo(0, 0);
139 path.lineTo(SK_Scalar1, 0);
140 path.moveTo(SK_Scalar1, SK_Scalar1);
141 path.moveTo(SK_Scalar1 * 2, SK_Scalar1 * 2);
142 path.lineTo(SK_Scalar1, SK_Scalar1 * 2);
143 meas.setPath(&path, false);
144 length = meas.getLength();
145 REPORTER_ASSERT(reporter, length == SK_Scalar1);
146 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
147 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000148 SkScalarNearlyEqual(position.fX,
149 SK_ScalarHalf,
150 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000151 REPORTER_ASSERT(reporter, position.fY == 0);
152 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1);
153 REPORTER_ASSERT(reporter, tangent.fY == 0);
154 meas.nextContour();
155 length = meas.getLength();
156 REPORTER_ASSERT(reporter, length == SK_Scalar1);
157 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent));
158 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000159 SkScalarNearlyEqual(position.fX,
160 SkFloatToScalar(1.5f),
161 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000162 REPORTER_ASSERT(reporter,
robertphillips@google.com6853e802012-04-16 15:50:18 +0000163 SkScalarNearlyEqual(position.fY,
164 SkFloatToScalar(2.0f),
165 SkFloatToScalar(0.0001f)));
schenney@chromium.org510c6b12012-01-12 20:04:06 +0000166 REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1);
167 REPORTER_ASSERT(reporter, tangent.fY == 0);
reed@google.comfab1ddd2012-04-20 15:10:32 +0000168
169 test_small_segment(reporter);
reed@android.com5e5adfd2009-03-07 03:39:23 +0000170}
171
172#include "TestClassDef.h"
173DEFINE_TESTCLASS("PathMeasure", PathMeasureTestClass, TestPathMeasure)