Flutter Engine
The Flutter Engine
Loading...
Searching...
No Matches
SkPathOpsPoint.h
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 */
7#ifndef SkPathOpsPoint_DEFINED
8#define SkPathOpsPoint_DEFINED
9
14
15inline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) {
16 return AlmostEqualUlps(pt1.fX, pt2.fX) && AlmostEqualUlps(pt1.fY, pt2.fY);
17}
18
19struct SkDVector {
20 double fX;
21 double fY;
22
23 SkDVector& set(const SkVector& pt) {
24 fX = pt.fX;
25 fY = pt.fY;
26 return *this;
27 }
28
29 // only used by testing
30 void operator+=(const SkDVector& v) {
31 fX += v.fX;
32 fY += v.fY;
33 }
34
35 // only called by nearestT, which is currently only used by testing
36 void operator-=(const SkDVector& v) {
37 fX -= v.fX;
38 fY -= v.fY;
39 }
40
41 // only used by testing
42 void operator/=(const double s) {
43 fX /= s;
44 fY /= s;
45 }
46
47 // only used by testing
48 void operator*=(const double s) {
49 fX *= s;
50 fY *= s;
51 }
52
55 return v;
56 }
57
58 // only used by testing
59 double cross(const SkDVector& a) const {
60 return fX * a.fY - fY * a.fX;
61 }
62
63 // similar to cross, this bastardization considers nearly coincident to be zero
64 // uses ulps epsilon == 16
65 double crossCheck(const SkDVector& a) const {
66 double xy = fX * a.fY;
67 double yx = fY * a.fX;
68 return AlmostEqualUlps(xy, yx) ? 0 : xy - yx;
69 }
70
71 // allow tinier numbers
72 double crossNoNormalCheck(const SkDVector& a) const {
73 double xy = fX * a.fY;
74 double yx = fY * a.fX;
75 return AlmostEqualUlpsNoNormalCheck(xy, yx) ? 0 : xy - yx;
76 }
77
78 double dot(const SkDVector& a) const {
79 return fX * a.fX + fY * a.fY;
80 }
81
82 double length() const {
83 return sqrt(lengthSquared());
84 }
85
86 double lengthSquared() const {
87 return fX * fX + fY * fY;
88 }
89
91 double inverseLength = sk_ieee_double_divide(1, this->length());
92 fX *= inverseLength;
93 fY *= inverseLength;
94 return *this;
95 }
96
97 bool isFinite() const {
98 return SkIsFinite(fX, fY);
99 }
100};
101
102struct SkDPoint {
103 double fX;
104 double fY;
105
106 void set(const SkPoint& pt) {
107 fX = pt.fX;
108 fY = pt.fY;
109 }
110
111 friend SkDVector operator-(const SkDPoint& a, const SkDPoint& b) {
112 return { a.fX - b.fX, a.fY - b.fY };
113 }
114
115 friend bool operator==(const SkDPoint& a, const SkDPoint& b) {
116 return a.fX == b.fX && a.fY == b.fY;
117 }
118
119 friend bool operator!=(const SkDPoint& a, const SkDPoint& b) {
120 return a.fX != b.fX || a.fY != b.fY;
121 }
122
123 void operator=(const SkPoint& pt) {
124 fX = pt.fX;
125 fY = pt.fY;
126 }
127
128 // only used by testing
129 void operator+=(const SkDVector& v) {
130 fX += v.fX;
131 fY += v.fY;
132 }
133
134 // only used by testing
135 void operator-=(const SkDVector& v) {
136 fX -= v.fX;
137 fY -= v.fY;
138 }
139
140 // only used by testing
142 SkDPoint result = *this;
143 result += v;
144 return result;
145 }
146
147 // only used by testing
149 SkDPoint result = *this;
150 result -= v;
151 return result;
152 }
153
154 // note: this can not be implemented with
155 // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX);
156 // because that will not take the magnitude of the values into account
157 bool approximatelyDEqual(const SkDPoint& a) const {
158 if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
159 return true;
160 }
161 if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
162 return false;
163 }
164 double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
165 double tiniest = std::min(std::min(std::min(fX, a.fX), fY), a.fY);
166 double largest = std::max(std::max(std::max(fX, a.fX), fY), a.fY);
167 largest = std::max(largest, -tiniest);
168 return AlmostDequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
169 }
170
171 bool approximatelyDEqual(const SkPoint& a) const {
172 SkDPoint dA;
173 dA.set(a);
174 return approximatelyDEqual(dA);
175 }
176
177 bool approximatelyEqual(const SkDPoint& a) const {
178 if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
179 return true;
180 }
181 if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
182 return false;
183 }
184 double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
185 double tiniest = std::min(std::min(std::min(fX, a.fX), fY), a.fY);
186 double largest = std::max(std::max(std::max(fX, a.fX), fY), a.fY);
187 largest = std::max(largest, -tiniest);
188 return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
189 }
190
191 bool approximatelyEqual(const SkPoint& a) const {
192 SkDPoint dA;
193 dA.set(a);
194 return approximatelyEqual(dA);
195 }
196
197 static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) {
198 if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
199 return true;
200 }
201 if (!RoughlyEqualUlps(a.fX, b.fX) || !RoughlyEqualUlps(a.fY, b.fY)) {
202 return false;
203 }
204 SkDPoint dA, dB;
205 dA.set(a);
206 dB.set(b);
207 double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ?
208 float tiniest = std::min(std::min(std::min(a.fX, b.fX), a.fY), b.fY);
209 float largest = std::max(std::max(std::max(a.fX, b.fX), a.fY), b.fY);
210 largest = std::max(largest, -tiniest);
211 return AlmostDequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
212 }
213
214 // only used by testing
215 bool approximatelyZero() const {
217 }
218
221 return pt;
222 }
223
224 double distance(const SkDPoint& a) const {
225 SkDVector temp = *this - a;
226 return temp.length();
227 }
228
229 double distanceSquared(const SkDPoint& a) const {
230 SkDVector temp = *this - a;
231 return temp.lengthSquared();
232 }
233
234 static SkDPoint Mid(const SkDPoint& a, const SkDPoint& b) {
236 result.fX = (a.fX + b.fX) / 2;
237 result.fY = (a.fY + b.fY) / 2;
238 return result;
239 }
240
241 bool roughlyEqual(const SkDPoint& a) const {
242 if (roughly_equal(fX, a.fX) && roughly_equal(fY, a.fY)) {
243 return true;
244 }
245 double dist = distance(a); // OPTIMIZATION: can we compare against distSq instead ?
246 double tiniest = std::min(std::min(std::min(fX, a.fX), fY), a.fY);
247 double largest = std::max(std::max(std::max(fX, a.fX), fY), a.fY);
248 largest = std::max(largest, -tiniest);
249 return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance?
250 }
251
252 static bool RoughlyEqual(const SkPoint& a, const SkPoint& b) {
253 if (!RoughlyEqualUlps(a.fX, b.fX) && !RoughlyEqualUlps(a.fY, b.fY)) {
254 return false;
255 }
256 SkDPoint dA, dB;
257 dA.set(a);
258 dB.set(b);
259 double dist = dA.distance(dB); // OPTIMIZATION: can we compare against distSq instead ?
260 float tiniest = std::min(std::min(std::min(a.fX, b.fX), a.fY), b.fY);
261 float largest = std::max(std::max(std::max(a.fX, b.fX), a.fY), b.fY);
262 largest = std::max(largest, -tiniest);
263 return RoughlyEqualUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
264 }
265
266 // very light weight check, should only be used for inequality check
267 static bool WayRoughlyEqual(const SkPoint& a, const SkPoint& b) {
268 float largestNumber = std::max(SkTAbs(a.fX), std::max(SkTAbs(a.fY),
269 std::max(SkTAbs(b.fX), SkTAbs(b.fY))));
270 SkVector diffs = a - b;
271 float largestDiff = std::max(diffs.fX, diffs.fY);
272 return roughly_zero_when_compared_to(largestDiff, largestNumber);
273 }
274
275 // utilities callable by the user from the debugger when the implementation code is linked in
276 void dump() const;
277 static void Dump(const SkPoint& pt);
278 static void DumpHex(const SkPoint& pt);
279};
280
281#endif
static bool approximately_zero(double x)
Definition SkCubics.cpp:153
static bool SkIsFinite(T x, Pack... values)
static constexpr double sk_ieee_double_divide(double numer, double denom)
bool AlmostEqualUlps(const SkPoint &pt1, const SkPoint &pt2)
bool RoughlyEqualUlps(float a, float b)
bool AlmostPequalUlps(float a, float b)
bool AlmostDequalUlps(float a, float b)
bool AlmostEqualUlpsNoNormalCheck(float a, float b)
bool roughly_zero_when_compared_to(double x, double y)
bool approximately_equal(double x, double y)
bool roughly_equal(double x, double y)
#define SkDoubleToScalar(x)
Definition SkScalar.h:64
static T SkTAbs(T value)
Definition SkTemplates.h:43
static bool b
struct MyStruct s
struct MyStruct a[10]
GAsyncResult * result
void set(const SkPoint &pt)
SkDPoint operator+(const SkDVector &v)
bool approximatelyEqual(const SkPoint &a) const
void operator+=(const SkDVector &v)
void operator=(const SkPoint &pt)
void operator-=(const SkDVector &v)
friend bool operator==(const SkDPoint &a, const SkDPoint &b)
double distanceSquared(const SkDPoint &a) const
SkDPoint operator-(const SkDVector &v)
static SkDPoint Mid(const SkDPoint &a, const SkDPoint &b)
bool approximatelyDEqual(const SkPoint &a) const
bool approximatelyEqual(const SkDPoint &a) const
SkPoint asSkPoint() const
static void Dump(const SkPoint &pt)
static bool ApproximatelyEqual(const SkPoint &a, const SkPoint &b)
friend SkDVector operator-(const SkDPoint &a, const SkDPoint &b)
static bool RoughlyEqual(const SkPoint &a, const SkPoint &b)
friend bool operator!=(const SkDPoint &a, const SkDPoint &b)
static void DumpHex(const SkPoint &pt)
bool approximatelyDEqual(const SkDPoint &a) const
void dump() const
static bool WayRoughlyEqual(const SkPoint &a, const SkPoint &b)
bool approximatelyZero() const
bool roughlyEqual(const SkDPoint &a) const
double distance(const SkDPoint &a) const
bool isFinite() const
void operator/=(const double s)
SkDVector & set(const SkVector &pt)
double crossNoNormalCheck(const SkDVector &a) const
double length() const
double cross(const SkDVector &a) const
SkVector asSkVector() const
void operator*=(const double s)
double dot(const SkDVector &a) const
void operator-=(const SkDVector &v)
void operator+=(const SkDVector &v)
SkDVector & normalize()
double crossCheck(const SkDVector &a) const
double lengthSquared() const
float fX
x-axis value
float fY
y-axis value