Flutter Engine
The Flutter Engine
All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Modules Pages
PathOpsCubicLineIntersectionTest.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 */
16#include "tests/Test.h"
17
18#include <array>
19#include <cstddef>
20#include <utility>
21
22struct lineCubic {
25};
26
28 {{{{37.5273438,-1.44140625}, {37.8736992,-1.69921875}, {38.1640625,-2.140625},
29 {38.3984375,-2.765625}}},
30 {{{40.625,-5.7890625}, {37.7109375,1.3515625}}}},
31};
32
34
35static void testFail(skiatest::Reporter* reporter, int iIndex) {
36 const CubicPts& cuPts = failLineCubicTests[iIndex].cubic;
38 cubic.debugSet(cuPts.fPts);
40 const SkDLine& line = failLineCubicTests[iIndex].line;
42 SkReduceOrder reduce1;
43 SkReduceOrder reduce2;
44 int order1 = reduce1.reduce(cubic, SkReduceOrder::kNo_Quadratics);
45 int order2 = reduce2.reduce(line);
46 if (order1 < 4) {
47 SkDebugf("[%d] cubic order=%d\n", iIndex, order1);
49 }
50 if (order2 < 2) {
51 SkDebugf("[%d] line order=%d\n", iIndex, order2);
53 }
54 if (order1 == 4 && order2 == 2) {
56 int roots = i.intersect(cubic, line);
58 }
59}
60
62 {{{{0, 6}, {1.0851458311080933, 4.3722810745239258}, {1.5815209150314331, 3.038947582244873}, {1.9683018922805786, 1.9999997615814209}}},
63 {{{3,2}, {1,2}}}},
64
65 {{{{0.468027353,4}, {1.06734705,1.33333337}, {1.36700678,0}, {3,0}}},
66 {{{2,1}, {0,1}}}},
67
68 {{{{-634.60540771484375, -481.262939453125}, {266.2696533203125, -752.70867919921875},
69 {-751.8370361328125, -317.37921142578125}, {-969.7427978515625, 824.7255859375}}},
70 {{{-287.9506133720805678, -557.1376476615772617},
71 {-285.9506133720805678, -557.1376476615772617}}}},
72
73 {{{{36.7184372,0.888650894}, {36.7184372,0.888650894}, {35.1233864,0.554015458},
74 {34.5114098,-0.115255356}}}, {{{35.4531212,0}, {31.9375,0}}}},
75
76 {{{{421, 378}, {421, 380.209137f}, {418.761414f, 382}, {416, 382}}},
77 {{{320, 378}, {421, 378.000031f}}}},
78
79 {{{{416, 383}, {418.761414f, 383}, {421, 380.761414f}, {421, 378}}},
80 {{{320, 378}, {421, 378.000031f}}}},
81
82 {{{{154,715}, {151.238571,715}, {149,712.761414}, {149,710}}},
83 {{{149,675}, {149,710.001465}}}},
84
85 {{{{0,1}, {1,6}, {4,1}, {4,3}}},
86 {{{6,1}, {1,4}}}},
87
88 {{{{0,1}, {2,6}, {4,1}, {5,4}}},
89 {{{6,2}, {1,4}}}},
90
91 {{{{0,4}, {3,4}, {6,2}, {5,2}}},
92 {{{4,3}, {2,6}}}},
93#if 0
94 {{{{258, 122}, {260.761414, 122}, { 263, 124.238579}, {263, 127}}},
95 {{{259.82843, 125.17157}, {261.535522, 123.46447}}}},
96#endif
97 {{{{1006.6951293945312,291}, {1023.263671875,291}, {1033.8402099609375,304.43145751953125},
98 {1030.318359375,321}}},
99 {{{979.30487060546875,561}, {1036.695068359375,291}}}},
100 {{{{259.30487060546875,561}, {242.73631286621094,561}, {232.15980529785156,547.56854248046875},
101 {235.68154907226562,531}}},
102 {{{286.69512939453125,291}, {229.30485534667969,561}}}},
103 {{{{1, 2}, {2, 6}, {2, 0}, {1, 0}}}, {{{1, 0}, {1, 2}}}},
104 {{{{0, 0}, {0, 1}, {0, 1}, {1, 1}}}, {{{0, 1}, {1, 0}}}},
105};
106
108
109static int doIntersect(SkIntersections& intersections, const SkDCubic& cubic, const SkDLine& line) {
110 int result;
111 bool flipped = false;
112 if (line[0].fX == line[1].fX) {
113 double top = line[0].fY;
114 double bottom = line[1].fY;
115 flipped = top > bottom;
116 if (flipped) {
117 using std::swap;
118 swap(top, bottom);
119 }
120 result = intersections.vertical(cubic, top, bottom, line[0].fX, flipped);
121 } else if (line[0].fY == line[1].fY) {
122 double left = line[0].fX;
123 double right = line[1].fX;
124 flipped = left > right;
125 if (flipped) {
126 using std::swap;
127 swap(left, right);
128 }
129 result = intersections.horizontal(cubic, left, right, line[0].fY, flipped);
130 } else {
131 intersections.intersect(cubic, line);
132 result = intersections.used();
133 }
134 return result;
135}
136
137static void testOne(skiatest::Reporter* reporter, int iIndex) {
138 const CubicPts& cuPts = lineCubicTests[iIndex].cubic;
140 cubic.debugSet(cuPts.fPts);
142 const SkDLine& line = lineCubicTests[iIndex].line;
144 SkReduceOrder reduce1;
145 SkReduceOrder reduce2;
146 int order1 = reduce1.reduce(cubic, SkReduceOrder::kNo_Quadratics);
147 int order2 = reduce2.reduce(line);
148 if (order1 < 4) {
149 SkDebugf("[%d] cubic order=%d\n", iIndex, order1);
151 }
152 if (order2 < 2) {
153 SkDebugf("[%d] line order=%d\n", iIndex, order2);
155 }
156 if (order1 == 4 && order2 == 2) {
158 int roots = doIntersect(i, cubic, line);
159 for (int pt = 0; pt < roots; ++pt) {
160 double tt1 = i[0][pt];
161 SkDPoint xy1 = cubic.ptAtT(tt1);
162 double tt2 = i[1][pt];
163 SkDPoint xy2 = line.ptAtT(tt2);
164 if (!xy1.approximatelyEqual(xy2)) {
165 SkDebugf("%s [%d,%d] x!= t1=%g (%g,%g) t2=%g (%g,%g)\n",
166 __FUNCTION__, iIndex, pt, tt1, xy1.fX, xy1.fY, tt2, xy2.fX, xy2.fY);
167 }
169 }
170#if ONE_OFF_DEBUG
171 double cubicT = i[0][0];
172 SkDPoint prev = cubic.ptAtT(cubicT * 2 - 1);
173 SkDPoint sect = cubic.ptAtT(cubicT);
174 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", prev.fX, prev.fY, sect.fX, sect.fY);
175 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", sect.fX, sect.fY, cubic[3].fX, cubic[3].fY);
176 SkDPoint prevL = line.ptAtT(i[1][0] - 0.0000007);
177 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", prevL.fX, prevL.fY, i.pt(0).fX, i.pt(0).fY);
178 SkDPoint nextL = line.ptAtT(i[1][0] + 0.0000007);
179 SkDebugf("{{%1.9g,%1.9g}, {%1.9g,%1.9g}},\n", i.pt(0).fX, i.pt(0).fY, nextL.fX, nextL.fY);
180 SkDebugf("prevD=%1.9g dist=%1.9g nextD=%1.9g\n", prev.distance(nextL),
181 sect.distance(i.pt(0)), cubic[3].distance(prevL));
182#endif
183 }
184}
185
186DEF_TEST(PathOpsFailCubicLineIntersection, reporter) {
187 for (size_t index = 0; index < failLineCubicTests_count; ++index) {
188 int iIndex = static_cast<int>(index);
189 testFail(reporter, iIndex);
190 reporter->bumpTestCount();
191 }
192}
193
194DEF_TEST(PathOpsCubicLineIntersection, reporter) {
195 for (size_t index = 0; index < lineCubicTests_count; ++index) {
196 int iIndex = static_cast<int>(index);
197 testOne(reporter, iIndex);
198 reporter->bumpTestCount();
199 }
200}
201
202DEF_TEST(PathOpsCubicLineIntersectionOneOff, reporter) {
203 int iIndex = 0;
204 testOne(reporter, iIndex);
205 const CubicPts& cuPts = lineCubicTests[iIndex].cubic;
207 cubic.debugSet(cuPts.fPts);
208 const SkDLine& line = lineCubicTests[iIndex].line;
210 i.intersect(cubic, line);
211 SkASSERT(i.used() == 1);
212}
reporter
Definition: FontMgrTest.cpp:39
static float prev(float f)
static lineCubic failLineCubicTests[]
DEF_TEST(PathOpsFailCubicLineIntersection, reporter)
static const size_t lineCubicTests_count
static int doIntersect(SkIntersections &intersections, const SkDCubic &cubic, const SkDLine &line)
static lineCubic lineCubicTests[]
static void testFail(skiatest::Reporter *reporter, int iIndex)
static void testOne(skiatest::Reporter *reporter, int iIndex)
static const size_t failLineCubicTests_count
bool ValidCubic(const SkDCubic &cubic)
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)
void swap(sk_sp< T > &a, sk_sp< T > &b)
Definition: SkRefCnt.h:341
#define REPORTER_ASSERT(r, cond,...)
Definition: Test.h:286
int intersect(const SkDLine &, const SkDLine &)
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)
GAsyncResult * result
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
AI float cubic(float precision, const SkPoint pts[], const VectorXform &vectorXform=VectorXform())
Definition: WangsFormula.h:195
SkDPoint fPts[kPointCount]
bool approximatelyEqual(const SkDPoint &a) const
double distance(const SkDPoint &a) const
int reduce(const SkDCubic &cubic, Quadratics)