Flutter Engine
The Flutter Engine
PathOpsLineIntersectionTest.cpp
Go to the documentation of this file.
1/*
2 * Copyright 2012 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 */
13#include "tests/Test.h"
14
15#include <algorithm>
16#include <array>
17#include <cstddef>
18
19// FIXME: add tests for intersecting, non-intersecting, degenerate, coincident
20static const SkDLine tests[][2] = {
21{{{{0.00010360032320022583, 1.0172703415155411}, {0.00014114845544099808, 1.0200891587883234}}},
22 {{{0.00010259449481964111, 1.017270140349865}, {0.00018215179443359375, 1.022890567779541}}}},
23
24#if 0
25 // these do intersect at a pair of points, but not close enough for check results liking
26 {{{{365.848175,5081.15186}, {368,5103}}}, {{{367.967712,5102.61084}, {368.278717,5105.71045}}}},
27#endif
28 {{{{30,20}, {30,50}}}, {{{24,30}, {36,30}}}},
29 {{{{323,193}, {-317,193}}}, {{{0,994}, {0,0}}}},
30 {{{{90,230}, {160,60}}}, {{{60,120}, {260,120}}}},
31 {{{{90,230}, {160,60}}}, {{{181.176468,120}, {135.294128,120}}}},
32 {{{{181.1764678955078125f, 120}, {186.3661956787109375f, 134.7042236328125f}}},
33 {{{175.8309783935546875f, 141.5211334228515625f}, {187.8782806396484375f, 133.7258148193359375f}}}},
34#if 0 // FIXME: these fail because one line is too short and appears quasi-coincident
35 {{{{158.000000, 926.000000}, {1108.00000, 926.000000}}},
36 {{{1108.00000, 926.000000}, {1108.00000, 925.999634}}}},
37 {{{{1108,926}, {1108,925.9996337890625}}}, {{{158,926}, {1108,926}}}},
38#endif
39 {{{{192, 4}, {243, 4}}}, {{{246, 4}, {189, 4}}}},
40 {{{{246, 4}, {189, 4}}}, {{{192, 4}, {243, 4}}}},
41 {{{{5, 0}, {0, 5}}}, {{{5, 4}, {1, 4}}}},
42 {{{{0, 0}, {1, 0}}}, {{{1, 0}, {0, 0}}}},
43 {{{{0, 0}, {0, 0}}}, {{{0, 0}, {1, 0}}}},
44 {{{{0, 1}, {0, 1}}}, {{{0, 0}, {0, 2}}}},
45 {{{{0, 0}, {1, 0}}}, {{{0, 0}, {2, 0}}}},
46 {{{{1, 1}, {2, 2}}}, {{{0, 0}, {3, 3}}}},
47 {{{{166.86950047022856, 112.69654129527828}, {166.86948801592692, 112.69655741235339}}},
48 {{{166.86960700313026, 112.6965477747386}, {166.86925794355412, 112.69656471103423}}}}
49};
50
51static const size_t tests_count = std::size(tests);
52
53static const SkDLine noIntersect[][2] = {
54 {{{{(double) (2 - 1e-6f),2}, {(double) (2 - 1e-6f),4}}},
55 {{{2,1}, {2,3}}}},
56
57 {{{{0, 0}, {1, 0}}}, {{{3, 0}, {2, 0}}}},
58 {{{{0, 0}, {0, 0}}}, {{{1, 0}, {2, 0}}}},
59 {{{{0, 1}, {0, 1}}}, {{{0, 3}, {0, 2}}}},
60 {{{{0, 0}, {1, 0}}}, {{{2, 0}, {3, 0}}}},
61 {{{{1, 1}, {2, 2}}}, {{{4, 4}, {3, 3}}}},
62};
63
65
66static const SkDLine coincidentTests[][2] = {
67 {{{ {-1.48383003e-006,-83}, {4.2268899e-014,-60} }},
68 {{ {9.5359502e-007,-60}, {5.08227985e-015,-83} }}},
69
70 {{{ { 10105, 2510 }, { 10123, 2509.98999f } }},
71 {{{10105, 2509.98999f}, { 10123, 2510 } }}},
72
73 {{ { { 0, 482.5 }, { -4.4408921e-016, 682.5 } } },
74 {{{0,683}, {0,482}}}},
75
76 {{{{1.77635684e-015,312}, {-1.24344979e-014,348}}},
77 {{{0,348}, {0,312}}}},
78
79 {{{{979.304871, 561}, {1036.69507, 291}}},
80 {{{985.681519, 531}, {982.159790, 547.568542}}}},
81
82 {{{{232.159805, 547.568542}, {235.681549, 531}}},
83 {{{286.695129,291}, {229.304855,561}}}},
84
85 {{{{186.3661956787109375f, 134.7042236328125f}, {187.8782806396484375f, 133.7258148193359375f}}},
86 {{{175.8309783935546875f, 141.5211334228515625f}, {187.8782806396484375f, 133.7258148193359375f}}}},
87
88 {{{{235.681549, 531.000000}, {280.318420, 321.000000}}},
89 {{{286.695129, 291.000000}, {229.304855, 561.000000}}}},
90};
91
93
94static void check_results(skiatest::Reporter* reporter, const SkDLine& line1, const SkDLine& line2,
95 const SkIntersections& ts, bool nearAllowed) {
96 for (int i = 0; i < ts.used(); ++i) {
97 SkDPoint result1 = line1.ptAtT(ts[0][i]);
98 SkDPoint result2 = line2.ptAtT(ts[1][i]);
99 if (nearAllowed && result1.roughlyEqual(result2)) {
100 continue;
101 }
102 if (!result1.approximatelyEqual(result2) && !ts.nearlySame(i)) {
103 REPORTER_ASSERT(reporter, ts.used() != 1);
104 result2 = line2.ptAtT(ts[1][i ^ 1]);
105 if (!result1.approximatelyEqual(result2)) {
106 SkDebugf(".");
107 }
110 }
111 }
112}
113
114static void testOne(skiatest::Reporter* reporter, const SkDLine& line1, const SkDLine& line2,
115 bool nearAllowed) {
116 SkASSERT(ValidLine(line1));
117 SkASSERT(ValidLine(line2));
119 i.allowNear(nearAllowed);
120 int pts = i.intersect(line1, line2);
122 REPORTER_ASSERT(reporter, pts == i.used());
123 check_results(reporter, line1, line2, i, nearAllowed);
124 if (line1[0] == line1[1] || line2[0] == line2[1]) {
125 return;
126 }
127 if (line1[0].fY == line1[1].fY) {
128 double left = std::min(line1[0].fX, line1[1].fX);
129 double right = std::max(line1[0].fX, line1[1].fX);
131 ts.horizontal(line2, left, right, line1[0].fY, line1[0].fX != left);
132 check_results(reporter, line2, line1, ts, nearAllowed);
133 }
134 if (line2[0].fY == line2[1].fY) {
135 double left = std::min(line2[0].fX, line2[1].fX);
136 double right = std::max(line2[0].fX, line2[1].fX);
138 ts.horizontal(line1, left, right, line2[0].fY, line2[0].fX != left);
139 check_results(reporter, line1, line2, ts, nearAllowed);
140 }
141 if (line1[0].fX == line1[1].fX) {
142 double top = std::min(line1[0].fY, line1[1].fY);
143 double bottom = std::max(line1[0].fY, line1[1].fY);
145 ts.vertical(line2, top, bottom, line1[0].fX, line1[0].fY != top);
146 check_results(reporter, line2, line1, ts, nearAllowed);
147 }
148 if (line2[0].fX == line2[1].fX) {
149 double top = std::min(line2[0].fY, line2[1].fY);
150 double bottom = std::max(line2[0].fY, line2[1].fY);
152 ts.vertical(line1, top, bottom, line2[0].fX, line2[0].fY != top);
153 check_results(reporter, line1, line2, ts, nearAllowed);
154 }
155 reporter->bumpTestCount();
156}
157
159 const SkDLine& line2) {
160 SkASSERT(ValidLine(line1));
161 SkASSERT(ValidLine(line2));
163 int pts = i.intersect(line1, line2);
164 REPORTER_ASSERT(reporter, pts == 2);
165 REPORTER_ASSERT(reporter, pts == i.used());
166 check_results(reporter, line1, line2, i, false);
167 if (line1[0] == line1[1] || line2[0] == line2[1]) {
168 return;
169 }
170 if (line1[0].fY == line1[1].fY) {
171 double left = std::min(line1[0].fX, line1[1].fX);
172 double right = std::max(line1[0].fX, line1[1].fX);
174 ts.horizontal(line2, left, right, line1[0].fY, line1[0].fX != left);
175 REPORTER_ASSERT(reporter, pts == 2);
176 REPORTER_ASSERT(reporter, pts == ts.used());
177 check_results(reporter, line2, line1, ts, false);
178 }
179 if (line2[0].fY == line2[1].fY) {
180 double left = std::min(line2[0].fX, line2[1].fX);
181 double right = std::max(line2[0].fX, line2[1].fX);
183 ts.horizontal(line1, left, right, line2[0].fY, line2[0].fX != left);
184 REPORTER_ASSERT(reporter, pts == 2);
185 REPORTER_ASSERT(reporter, pts == ts.used());
186 check_results(reporter, line1, line2, ts, false);
187 }
188 if (line1[0].fX == line1[1].fX) {
189 double top = std::min(line1[0].fY, line1[1].fY);
190 double bottom = std::max(line1[0].fY, line1[1].fY);
192 ts.vertical(line2, top, bottom, line1[0].fX, line1[0].fY != top);
193 REPORTER_ASSERT(reporter, pts == 2);
194 REPORTER_ASSERT(reporter, pts == ts.used());
195 check_results(reporter, line2, line1, ts, false);
196 }
197 if (line2[0].fX == line2[1].fX) {
198 double top = std::min(line2[0].fY, line2[1].fY);
199 double bottom = std::max(line2[0].fY, line2[1].fY);
201 ts.vertical(line1, top, bottom, line2[0].fX, line2[0].fY != top);
202 REPORTER_ASSERT(reporter, pts == 2);
203 REPORTER_ASSERT(reporter, pts == ts.used());
204 check_results(reporter, line1, line2, ts, false);
205 }
206 reporter->bumpTestCount();
207}
208
209DEF_TEST(PathOpsLineIntersection, reporter) {
210 size_t index;
211 for (index = 0; index < coincidentTests_count; ++index) {
212 const SkDLine& line1 = coincidentTests[index][0];
213 const SkDLine& line2 = coincidentTests[index][1];
214 testOneCoincident(reporter, line1, line2);
215 }
216 for (index = 0; index < tests_count; ++index) {
217 const SkDLine& line1 = tests[index][0];
218 const SkDLine& line2 = tests[index][1];
219 testOne(reporter, line1, line2, true);
220 }
221 for (index = 0; index < noIntersect_count; ++index) {
222 const SkDLine& line1 = noIntersect[index][0];
223 const SkDLine& line2 = noIntersect[index][1];
225 int pts = ts.intersect(line1, line2);
227 REPORTER_ASSERT(reporter, pts == ts.used());
228 reporter->bumpTestCount();
229 }
230}
231
232DEF_TEST(PathOpsLineIntersectionOneOff, reporter) {
233 int index = 0;
234 SkASSERT(index < (int) tests_count);
235 testOne(reporter, tests[index][0], tests[index][1], true);
236}
237
238DEF_TEST(PathOpsLineIntersectionExactOneOff, reporter) {
239 int index = 0;
240 SkASSERT(index < (int) tests_count);
241 testOne(reporter, tests[index][0], tests[index][1], false);
242}
243
244DEF_TEST(PathOpsLineIntersectionOneCoincident, reporter) {
245 int index = 0;
246 SkASSERT(index < (int) coincidentTests_count);
247 const SkDLine& line1 = coincidentTests[index][0];
248 const SkDLine& line2 = coincidentTests[index][1];
249 testOneCoincident(reporter, line1, line2);
250}
reporter
Definition: FontMgrTest.cpp:39
static void check_results(skiatest::Reporter *reporter, const SkDLine &line1, const SkDLine &line2, const SkIntersections &ts, bool nearAllowed)
DEF_TEST(PathOpsLineIntersection, reporter)
static const size_t noIntersect_count
static const size_t tests_count
static void testOne(skiatest::Reporter *reporter, const SkDLine &line1, const SkDLine &line2, bool nearAllowed)
static void testOneCoincident(skiatest::Reporter *reporter, const SkDLine &line1, const SkDLine &line2)
static const SkDLine coincidentTests[][2]
static const size_t coincidentTests_count
static const SkDLine noIntersect[][2]
static const SkDLine tests[][2]
bool ValidLine(const SkDLine &line)
#define SkASSERT(cond)
Definition: SkAssert.h:116
void SK_SPI SkDebugf(const char format[],...) SK_PRINTF_LIKE(1
static bool left(const SkPoint &p0, const SkPoint &p1)
static bool right(const SkPoint &p0, const SkPoint &p1)
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
bool nearlySame(int index) const
int intersect(const SkDLine &, const SkDLine &)
const SkDPoint & pt(int index) const
int vertical(const SkDLine &, double top, double bottom, double x, bool flipped)
int used() const
int horizontal(const SkDLine &, double left, double right, double y, bool flipped)
static float max(float r, float g, float b)
Definition: hsl.cpp:49
static float min(float r, float g, float b)
Definition: hsl.cpp:48
it will be possible to load the file into Perfetto s trace viewer disable asset Prevents usage of any non test fonts unless they were explicitly Loaded via prefetched default font Indicates whether the embedding started a prefetch of the default font manager before creating the engine run In non interactive keep the shell running after the Dart script has completed enable serial On low power devices with low core running concurrent GC tasks on threads can cause them to contend with the UI thread which could potentially lead to jank This option turns off all concurrent GC activities domain network JSON encoded network policy per domain This overrides the DisallowInsecureConnections switch Embedder can specify whether to allow or disallow insecure connections at a domain level old gen heap size
Definition: switches.h:259
SkDPoint ptAtT(double t) const
bool approximatelyEqual(const SkDPoint &a) const
SkPoint asSkPoint() const
bool roughlyEqual(const SkDPoint &a) const