1 /* 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 */ 7 8 #include "Test.h" 9 #include "TestClassDef.h" 10 #include "SkPathMeasure.h" 11 12 static void test_small_segment3() { 13 #ifdef SK_SCALAR_IS_FLOAT 14 SkPath path; 15 const SkPoint pts[] = { 16 { 0, 0 }, 17 { 100000000000.0f, 100000000000.0f }, { 0, 0 }, { 10, 10 }, 18 { 10, 10 }, { 0, 0 }, { 10, 10 } 19 }; 20 21 path.moveTo(pts[0]); 22 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 3) { 23 path.cubicTo(pts[i], pts[i + 1], pts[i + 2]); 24 } 25 26 SkPathMeasure meas(path, false); 27 meas.getLength(); 28 #endif 29 } 30 31 static void test_small_segment2() { 32 #ifdef SK_SCALAR_IS_FLOAT 33 SkPath path; 34 const SkPoint pts[] = { 35 { 0, 0 }, 36 { 100000000000.0f, 100000000000.0f }, { 0, 0 }, 37 { 10, 10 }, { 0, 0 }, 38 }; 39 40 path.moveTo(pts[0]); 41 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); i += 2) { 42 path.quadTo(pts[i], pts[i + 1]); 43 } 44 SkPathMeasure meas(path, false); 45 meas.getLength(); 46 #endif 47 } 48 49 static void test_small_segment() { 50 #ifdef SK_SCALAR_IS_FLOAT 51 SkPath path; 52 const SkPoint pts[] = { 53 { 100000, 100000}, 54 // big jump between these points, makes a big segment 55 { 1.0005f, 0.9999f }, 56 // tiny (non-zero) jump between these points 57 { SK_Scalar1, SK_Scalar1 }, 58 }; 59 60 path.moveTo(pts[0]); 61 for (size_t i = 1; i < SK_ARRAY_COUNT(pts); ++i) { 62 path.lineTo(pts[i]); 63 } 64 SkPathMeasure meas(path, false); 65 66 /* this would assert (before a fix) because we added a segment with 67 the same length as the prev segment, due to the follow (bad) pattern 68 69 d = distance(pts[0], pts[1]); 70 distance += d; 71 seg->fDistance = distance; 72 73 SkASSERT(d > 0); // TRUE 74 SkASSERT(seg->fDistance > prevSeg->fDistance); // FALSE 75 76 This 2nd assert failes because (distance += d) didn't affect distance 77 because distance >>> d. 78 */ 79 meas.getLength(); 80 #endif 81 } 82 83 DEF_TEST(PathMeasure, reporter) { 84 SkPath path; 85 86 path.moveTo(0, 0); 87 path.lineTo(SK_Scalar1, 0); 88 path.lineTo(SK_Scalar1, SK_Scalar1); 89 path.lineTo(0, SK_Scalar1); 90 91 SkPathMeasure meas(path, true); 92 SkScalar length = meas.getLength(); 93 SkASSERT(length == SK_Scalar1*4); 94 95 path.reset(); 96 path.moveTo(0, 0); 97 path.lineTo(SK_Scalar1*3, SK_Scalar1*4); 98 meas.setPath(&path, false); 99 length = meas.getLength(); 100 REPORTER_ASSERT(reporter, length == SK_Scalar1*5); 101 102 path.reset(); 103 path.addCircle(0, 0, SK_Scalar1); 104 meas.setPath(&path, true); 105 length = meas.getLength(); 106 // SkDebugf("circle arc-length = %g\n", length); 107 108 // Test the behavior following a close not followed by a move. 109 path.reset(); 110 path.lineTo(SK_Scalar1, 0); 111 path.lineTo(SK_Scalar1, SK_Scalar1); 112 path.lineTo(0, SK_Scalar1); 113 path.close(); 114 path.lineTo(-SK_Scalar1, 0); 115 meas.setPath(&path, false); 116 length = meas.getLength(); 117 REPORTER_ASSERT(reporter, length == SK_Scalar1 * 4); 118 meas.nextContour(); 119 length = meas.getLength(); 120 REPORTER_ASSERT(reporter, length == SK_Scalar1); 121 SkPoint position; 122 SkVector tangent; 123 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); 124 REPORTER_ASSERT(reporter, 125 SkScalarNearlyEqual(position.fX, 126 -SK_ScalarHalf, 127 0.0001f)); 128 REPORTER_ASSERT(reporter, position.fY == 0); 129 REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1); 130 REPORTER_ASSERT(reporter, tangent.fY == 0); 131 132 // Test degenerate paths 133 path.reset(); 134 path.moveTo(0, 0); 135 path.lineTo(0, 0); 136 path.lineTo(SK_Scalar1, 0); 137 path.quadTo(SK_Scalar1, 0, SK_Scalar1, 0); 138 path.quadTo(SK_Scalar1, SK_Scalar1, SK_Scalar1, SK_Scalar1 * 2); 139 path.cubicTo(SK_Scalar1, SK_Scalar1 * 2, 140 SK_Scalar1, SK_Scalar1 * 2, 141 SK_Scalar1, SK_Scalar1 * 2); 142 path.cubicTo(SK_Scalar1*2, SK_Scalar1 * 2, 143 SK_Scalar1*3, SK_Scalar1 * 2, 144 SK_Scalar1*4, SK_Scalar1 * 2); 145 meas.setPath(&path, false); 146 length = meas.getLength(); 147 REPORTER_ASSERT(reporter, length == SK_Scalar1 * 6); 148 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); 149 REPORTER_ASSERT(reporter, 150 SkScalarNearlyEqual(position.fX, 151 SK_ScalarHalf, 152 0.0001f)); 153 REPORTER_ASSERT(reporter, position.fY == 0); 154 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); 155 REPORTER_ASSERT(reporter, tangent.fY == 0); 156 REPORTER_ASSERT(reporter, meas.getPosTan(2.5f, &position, &tangent)); 157 REPORTER_ASSERT(reporter, 158 SkScalarNearlyEqual(position.fX, SK_Scalar1, 0.0001f)); 159 REPORTER_ASSERT(reporter, 160 SkScalarNearlyEqual(position.fY, 1.5f)); 161 REPORTER_ASSERT(reporter, tangent.fX == 0); 162 REPORTER_ASSERT(reporter, tangent.fY == SK_Scalar1); 163 REPORTER_ASSERT(reporter, meas.getPosTan(4.5f, &position, &tangent)); 164 REPORTER_ASSERT(reporter, 165 SkScalarNearlyEqual(position.fX, 166 2.5f, 167 0.0001f)); 168 REPORTER_ASSERT(reporter, 169 SkScalarNearlyEqual(position.fY, 170 2.0f, 171 0.0001f)); 172 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); 173 REPORTER_ASSERT(reporter, tangent.fY == 0); 174 175 path.reset(); 176 path.moveTo(0, 0); 177 path.lineTo(SK_Scalar1, 0); 178 path.moveTo(SK_Scalar1, SK_Scalar1); 179 path.moveTo(SK_Scalar1 * 2, SK_Scalar1 * 2); 180 path.lineTo(SK_Scalar1, SK_Scalar1 * 2); 181 meas.setPath(&path, false); 182 length = meas.getLength(); 183 REPORTER_ASSERT(reporter, length == SK_Scalar1); 184 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); 185 REPORTER_ASSERT(reporter, 186 SkScalarNearlyEqual(position.fX, 187 SK_ScalarHalf, 188 0.0001f)); 189 REPORTER_ASSERT(reporter, position.fY == 0); 190 REPORTER_ASSERT(reporter, tangent.fX == SK_Scalar1); 191 REPORTER_ASSERT(reporter, tangent.fY == 0); 192 meas.nextContour(); 193 length = meas.getLength(); 194 REPORTER_ASSERT(reporter, length == SK_Scalar1); 195 REPORTER_ASSERT(reporter, meas.getPosTan(SK_ScalarHalf, &position, &tangent)); 196 REPORTER_ASSERT(reporter, 197 SkScalarNearlyEqual(position.fX, 198 1.5f, 199 0.0001f)); 200 REPORTER_ASSERT(reporter, 201 SkScalarNearlyEqual(position.fY, 202 2.0f, 203 0.0001f)); 204 REPORTER_ASSERT(reporter, tangent.fX == -SK_Scalar1); 205 REPORTER_ASSERT(reporter, tangent.fY == 0); 206 207 test_small_segment(); 208 test_small_segment2(); 209 test_small_segment3(); 210 } 211