• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
10 #include "SkPathOpsTypes.h"
11 #include "SkPoint.h"
12 
AlmostEqualUlps(const SkPoint & pt1,const SkPoint & pt2)13 inline bool AlmostEqualUlps(const SkPoint& pt1, const SkPoint& pt2) {
14     return AlmostEqualUlps(pt1.fX, pt2.fX) && AlmostEqualUlps(pt1.fY, pt2.fY);
15 }
16 
17 struct SkDVector {
18     double fX, fY;
19 
20     friend SkDPoint operator+(const SkDPoint& a, const SkDVector& b);
21 
22     void operator+=(const SkDVector& v) {
23         fX += v.fX;
24         fY += v.fY;
25     }
26 
27     void operator-=(const SkDVector& v) {
28         fX -= v.fX;
29         fY -= v.fY;
30     }
31 
32     void operator/=(const double s) {
33         fX /= s;
34         fY /= s;
35     }
36 
37     void operator*=(const double s) {
38         fX *= s;
39         fY *= s;
40     }
41 
asSkVectorSkDVector42     SkVector asSkVector() const {
43         SkVector v = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
44         return v;
45     }
46 
crossSkDVector47     double cross(const SkDVector& a) const {
48         return fX * a.fY - fY * a.fX;
49     }
50 
dotSkDVector51     double dot(const SkDVector& a) const {
52         return fX * a.fX + fY * a.fY;
53     }
54 
lengthSkDVector55     double length() const {
56         return sqrt(lengthSquared());
57     }
58 
lengthSquaredSkDVector59     double lengthSquared() const {
60         return fX * fX + fY * fY;
61     }
62 };
63 
64 struct SkDPoint {
65     double fX;
66     double fY;
67 
setSkDPoint68     void set(const SkPoint& pt) {
69         fX = pt.fX;
70         fY = pt.fY;
71     }
72 
73     friend SkDVector operator-(const SkDPoint& a, const SkDPoint& b);
74 
75     friend bool operator==(const SkDPoint& a, const SkDPoint& b) {
76         return a.fX == b.fX && a.fY == b.fY;
77     }
78 
79     friend bool operator!=(const SkDPoint& a, const SkDPoint& b) {
80         return a.fX != b.fX || a.fY != b.fY;
81     }
82 
83     void operator=(const SkPoint& pt) {
84         fX = pt.fX;
85         fY = pt.fY;
86     }
87 
88 
89     void operator+=(const SkDVector& v) {
90         fX += v.fX;
91         fY += v.fY;
92     }
93 
94     void operator-=(const SkDVector& v) {
95         fX -= v.fX;
96         fY -= v.fY;
97     }
98 
99     // note: this can not be implemented with
100     // return approximately_equal(a.fY, fY) && approximately_equal(a.fX, fX);
101     // because that will not take the magnitude of the values into account
approximatelyEqualSkDPoint102     bool approximatelyEqual(const SkDPoint& a) const {
103         if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
104             return true;
105         }
106         if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
107             return false;
108         }
109         double dist = distance(a);  // OPTIMIZATION: can we compare against distSq instead ?
110         double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
111         double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
112         largest = SkTMax(largest, -tiniest);
113         return AlmostBequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
114     }
115 
approximatelyEqualSkDPoint116     bool approximatelyEqual(const SkPoint& a) const {
117         SkDPoint dA;
118         dA.set(a);
119         return approximatelyEqual(dA);
120     }
121 
ApproximatelyEqualSkDPoint122     static bool ApproximatelyEqual(const SkPoint& a, const SkPoint& b) {
123         if (approximately_equal(a.fX, b.fX) && approximately_equal(a.fY, b.fY)) {
124             return true;
125         }
126         if (!RoughlyEqualUlps(a.fX, b.fX) || !RoughlyEqualUlps(a.fY, b.fY)) {
127             return false;
128         }
129         SkDPoint dA, dB;
130         dA.set(a);
131         dB.set(b);
132         double dist = dA.distance(dB);  // OPTIMIZATION: can we compare against distSq instead ?
133         float tiniest = SkTMin(SkTMin(SkTMin(a.fX, b.fX), a.fY), b.fY);
134         float largest = SkTMax(SkTMax(SkTMax(a.fX, b.fX), a.fY), b.fY);
135         largest = SkTMax(largest, -tiniest);
136         return AlmostBequalUlps((double) largest, largest + dist); // is dist within ULPS tolerance?
137     }
138 
approximatelyPEqualSkDPoint139     bool approximatelyPEqual(const SkDPoint& a) const {
140         if (approximately_equal(fX, a.fX) && approximately_equal(fY, a.fY)) {
141             return true;
142         }
143         if (!RoughlyEqualUlps(fX, a.fX) || !RoughlyEqualUlps(fY, a.fY)) {
144             return false;
145         }
146         double dist = distance(a);  // OPTIMIZATION: can we compare against distSq instead ?
147         double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
148         double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
149         largest = SkTMax(largest, -tiniest);
150         return AlmostPequalUlps(largest, largest + dist); // is the dist within ULPS tolerance?
151     }
152 
approximatelyZeroSkDPoint153     bool approximatelyZero() const {
154         return approximately_zero(fX) && approximately_zero(fY);
155     }
156 
asSkPointSkDPoint157     SkPoint asSkPoint() const {
158         SkPoint pt = {SkDoubleToScalar(fX), SkDoubleToScalar(fY)};
159         return pt;
160     }
161 
distanceSkDPoint162     double distance(const SkDPoint& a) const {
163         SkDVector temp = *this - a;
164         return temp.length();
165     }
166 
distanceSquaredSkDPoint167     double distanceSquared(const SkDPoint& a) const {
168         SkDVector temp = *this - a;
169         return temp.lengthSquared();
170     }
171 
MidSkDPoint172     static SkDPoint Mid(const SkDPoint& a, const SkDPoint& b) {
173         SkDPoint result;
174         result.fX = (a.fX + b.fX) / 2;
175         result.fY = (a.fY + b.fY) / 2;
176         return result;
177     }
178 
moreRoughlyEqualSkDPoint179     bool moreRoughlyEqual(const SkDPoint& a) const {
180         if (roughly_equal(fX, a.fX) && roughly_equal(fY, a.fY)) {
181             return true;
182         }
183         double dist = distance(a);  // OPTIMIZATION: can we compare against distSq instead ?
184         double tiniest = SkTMin(SkTMin(SkTMin(fX, a.fX), fY), a.fY);
185         double largest = SkTMax(SkTMax(SkTMax(fX, a.fX), fY), a.fY);
186         largest = SkTMax(largest, -tiniest);
187         return RoughlyEqualUlps(largest, largest + dist); // is the dist within ULPS tolerance?
188     }
189 
roughlyEqualSkDPoint190     bool roughlyEqual(const SkDPoint& a) const {
191         return roughly_equal(a.fY, fY) && roughly_equal(a.fX, fX);
192     }
193 
194     #ifdef SK_DEBUG
dumpSkDPoint195     void dump() {
196         SkDebugf("{");
197         DebugDumpDouble(fX);
198         SkDebugf(", ");
199         DebugDumpDouble(fY);
200         SkDebugf("}");
201     }
202 
dumpSkDPoint203     static void dump(const SkPoint& pt) {
204         SkDebugf("{");
205         DebugDumpFloat(pt.fX);
206         SkDebugf(", ");
207         DebugDumpFloat(pt.fY);
208         SkDebugf("}");
209     }
210    #endif
211 };
212 
213 #endif
214