OLD | NEW |
| (Empty) |
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 __DataTypes_h__ | |
8 #define __DataTypes_h__ | |
9 | |
10 #include <float.h> // for FLT_EPSILON | |
11 #include <math.h> // for fabs, sqrt | |
12 | |
13 #include "SkPoint.h" | |
14 | |
15 #define FORCE_RELEASE 0 // set force release to 1 for multiple thread -- no deb
ugging | |
16 #define ONE_OFF_DEBUG 1 | |
17 #define ONE_OFF_DEBUG_MATHEMATICA 0 | |
18 | |
19 // FIXME: move these into SkTypes.h | |
20 template <typename T> inline T SkTMax(T a, T b) { | |
21 if (a < b) | |
22 a = b; | |
23 return a; | |
24 } | |
25 | |
26 template <typename T> inline T SkTMin(T a, T b) { | |
27 if (a > b) | |
28 a = b; | |
29 return a; | |
30 } | |
31 | |
32 extern bool AlmostEqualUlps(float A, float B); | |
33 inline bool AlmostEqualUlps(double A, double B) { return AlmostEqualUlps((float)
A, (float) B); } | |
34 | |
35 // FIXME: delete | |
36 int UlpsDiff(float A, float B); | |
37 | |
38 // FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23) | |
39 // DBL_EPSILON == 2.22045e-16 | |
40 const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON; | |
41 const double FLT_EPSILON_HALF = FLT_EPSILON / 2; | |
42 const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON; | |
43 const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON); | |
44 const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON; | |
45 const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // tune -- allow a few bits of e
rror | |
46 const double ROUGH_EPSILON = FLT_EPSILON * 64; | |
47 const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256; | |
48 | |
49 inline bool approximately_zero(double x) { | |
50 return fabs(x) < FLT_EPSILON; | |
51 } | |
52 | |
53 inline bool precisely_zero(double x) { | |
54 return fabs(x) < DBL_EPSILON_ERR; | |
55 } | |
56 | |
57 inline bool approximately_zero(float x) { | |
58 return fabs(x) < FLT_EPSILON; | |
59 } | |
60 | |
61 inline bool approximately_zero_cubed(double x) { | |
62 return fabs(x) < FLT_EPSILON_CUBED; | |
63 } | |
64 | |
65 inline bool approximately_zero_half(double x) { | |
66 return fabs(x) < FLT_EPSILON_HALF; | |
67 } | |
68 | |
69 inline bool approximately_zero_squared(double x) { | |
70 return fabs(x) < FLT_EPSILON_SQUARED; | |
71 } | |
72 | |
73 inline bool approximately_zero_sqrt(double x) { | |
74 return fabs(x) < FLT_EPSILON_SQRT; | |
75 } | |
76 | |
77 inline bool approximately_zero_inverse(double x) { | |
78 return fabs(x) > FLT_EPSILON_INVERSE; | |
79 } | |
80 | |
81 // FIXME: if called multiple times with the same denom, we want to pass 1/y inst
ead | |
82 inline bool approximately_zero_when_compared_to(double x, double y) { | |
83 return x == 0 || fabs(x / y) < FLT_EPSILON; | |
84 } | |
85 | |
86 // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger
and smaller) use | |
87 // AlmostEqualUlps instead. | |
88 inline bool approximately_equal(double x, double y) { | |
89 #if 1 | |
90 return approximately_zero(x - y); | |
91 #else | |
92 // see http://visualstudiomagazine.com/blogs/tool-tracker/2011/11/compare-floati
ng-point-numbers.aspx | |
93 // this allows very small (e.g. degenerate) values to compare unequally, but in
this case, | |
94 // AlmostEqualUlps should be used instead. | |
95 if (x == y) { | |
96 return true; | |
97 } | |
98 double absY = fabs(y); | |
99 if (x == 0) { | |
100 return absY < FLT_EPSILON; | |
101 } | |
102 double absX = fabs(x); | |
103 if (y == 0) { | |
104 return absX < FLT_EPSILON; | |
105 } | |
106 return fabs(x - y) < (absX > absY ? absX : absY) * FLT_EPSILON; | |
107 #endif | |
108 } | |
109 | |
110 inline bool precisely_equal(double x, double y) { | |
111 return precisely_zero(x - y); | |
112 } | |
113 | |
114 inline bool approximately_equal_half(double x, double y) { | |
115 return approximately_zero_half(x - y); | |
116 } | |
117 | |
118 inline bool approximately_equal_squared(double x, double y) { | |
119 return approximately_equal(x, y); | |
120 } | |
121 | |
122 inline bool approximately_greater(double x, double y) { | |
123 return x - FLT_EPSILON >= y; | |
124 } | |
125 | |
126 inline bool approximately_greater_or_equal(double x, double y) { | |
127 return x + FLT_EPSILON > y; | |
128 } | |
129 | |
130 inline bool approximately_lesser(double x, double y) { | |
131 return x + FLT_EPSILON <= y; | |
132 } | |
133 | |
134 inline bool approximately_lesser_or_equal(double x, double y) { | |
135 return x - FLT_EPSILON < y; | |
136 } | |
137 | |
138 inline double approximately_pin(double x) { | |
139 return approximately_zero(x) ? 0 : x; | |
140 } | |
141 | |
142 inline float approximately_pin(float x) { | |
143 return approximately_zero(x) ? 0 : x; | |
144 } | |
145 | |
146 inline bool approximately_greater_than_one(double x) { | |
147 return x > 1 - FLT_EPSILON; | |
148 } | |
149 | |
150 inline bool precisely_greater_than_one(double x) { | |
151 return x > 1 - DBL_EPSILON_ERR; | |
152 } | |
153 | |
154 inline bool approximately_less_than_zero(double x) { | |
155 return x < FLT_EPSILON; | |
156 } | |
157 | |
158 inline bool precisely_less_than_zero(double x) { | |
159 return x < DBL_EPSILON_ERR; | |
160 } | |
161 | |
162 inline bool approximately_negative(double x) { | |
163 return x < FLT_EPSILON; | |
164 } | |
165 | |
166 inline bool precisely_negative(double x) { | |
167 return x < DBL_EPSILON_ERR; | |
168 } | |
169 | |
170 inline bool approximately_one_or_less(double x) { | |
171 return x < 1 + FLT_EPSILON; | |
172 } | |
173 | |
174 inline bool approximately_positive(double x) { | |
175 return x > -FLT_EPSILON; | |
176 } | |
177 | |
178 inline bool approximately_positive_squared(double x) { | |
179 return x > -(FLT_EPSILON_SQUARED); | |
180 } | |
181 | |
182 inline bool approximately_zero_or_more(double x) { | |
183 return x > -FLT_EPSILON; | |
184 } | |
185 | |
186 inline bool approximately_between(double a, double b, double c) { | |
187 return a <= c ? approximately_negative(a - b) && approximately_negative(b -
c) | |
188 : approximately_negative(b - a) && approximately_negative(c - b); | |
189 } | |
190 | |
191 // returns true if (a <= b <= c) || (a >= b >= c) | |
192 inline bool between(double a, double b, double c) { | |
193 SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <=
0)); | |
194 return (a - b) * (c - b) <= 0; | |
195 } | |
196 | |
197 inline bool more_roughly_equal(double x, double y) { | |
198 return fabs(x - y) < MORE_ROUGH_EPSILON; | |
199 } | |
200 | |
201 inline bool roughly_equal(double x, double y) { | |
202 return fabs(x - y) < ROUGH_EPSILON; | |
203 } | |
204 | |
205 struct _Point; | |
206 | |
207 struct _Vector { | |
208 double x; | |
209 double y; | |
210 | |
211 friend _Point operator+(const _Point& a, const _Vector& b); | |
212 | |
213 void operator+=(const _Vector& v) { | |
214 x += v.x; | |
215 y += v.y; | |
216 } | |
217 | |
218 void operator-=(const _Vector& v) { | |
219 x -= v.x; | |
220 y -= v.y; | |
221 } | |
222 | |
223 void operator/=(const double s) { | |
224 x /= s; | |
225 y /= s; | |
226 } | |
227 | |
228 void operator*=(const double s) { | |
229 x *= s; | |
230 y *= s; | |
231 } | |
232 | |
233 double cross(const _Vector& a) const { | |
234 return x * a.y - y * a.x; | |
235 } | |
236 | |
237 double dot(const _Vector& a) const { | |
238 return x * a.x + y * a.y; | |
239 } | |
240 | |
241 double length() const { | |
242 return sqrt(lengthSquared()); | |
243 } | |
244 | |
245 double lengthSquared() const { | |
246 return x * x + y * y; | |
247 } | |
248 | |
249 SkVector asSkVector() const { | |
250 SkVector v = {SkDoubleToScalar(x), SkDoubleToScalar(y)}; | |
251 return v; | |
252 } | |
253 }; | |
254 | |
255 struct _Point { | |
256 double x; | |
257 double y; | |
258 | |
259 friend _Vector operator-(const _Point& a, const _Point& b); | |
260 | |
261 void operator+=(const _Vector& v) { | |
262 x += v.x; | |
263 y += v.y; | |
264 } | |
265 | |
266 void operator-=(const _Vector& v) { | |
267 x -= v.x; | |
268 y -= v.y; | |
269 } | |
270 | |
271 friend bool operator==(const _Point& a, const _Point& b) { | |
272 return a.x == b.x && a.y == b.y; | |
273 } | |
274 | |
275 friend bool operator!=(const _Point& a, const _Point& b) { | |
276 return a.x != b.x || a.y != b.y; | |
277 } | |
278 | |
279 // note: this can not be implemented with | |
280 // return approximately_equal(a.y, y) && approximately_equal(a.x, x); | |
281 // because that will not take the magnitude of the values | |
282 bool approximatelyEqual(const _Point& a) const { | |
283 double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.x), fabs(a.
y)))); | |
284 if (denom == 0) { | |
285 return true; | |
286 } | |
287 double inv = 1 / denom; | |
288 return approximately_equal(x * inv, a.x * inv) && approximately_equal(y
* inv, a.y * inv); | |
289 } | |
290 | |
291 bool approximatelyEqual(const SkPoint& a) const { | |
292 double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.fX), fabs(a
.fY)))); | |
293 if (denom == 0) { | |
294 return true; | |
295 } | |
296 double inv = 1 / denom; | |
297 return approximately_equal(x * inv, a.fX * inv) && approximately_equal(y
* inv, a.fY * inv); | |
298 } | |
299 | |
300 bool approximatelyEqualHalf(const _Point& a) const { | |
301 double denom = SkTMax(fabs(x), SkTMax(fabs(y), SkTMax(fabs(a.x), fabs(a.
y)))); | |
302 if (denom == 0) { | |
303 return true; | |
304 } | |
305 double inv = 1 / denom; | |
306 return approximately_equal_half(x * inv, a.x * inv) | |
307 && approximately_equal_half(y * inv, a.y * inv); | |
308 } | |
309 | |
310 bool approximatelyZero() const { | |
311 return approximately_zero(x) && approximately_zero(y); | |
312 } | |
313 | |
314 SkPoint asSkPoint() const { | |
315 SkPoint pt = {SkDoubleToScalar(x), SkDoubleToScalar(y)}; | |
316 return pt; | |
317 } | |
318 | |
319 double distance(const _Point& a) const { | |
320 _Vector temp = *this - a; | |
321 return temp.length(); | |
322 } | |
323 | |
324 double distanceSquared(const _Point& a) const { | |
325 _Vector temp = *this - a; | |
326 return temp.lengthSquared(); | |
327 } | |
328 | |
329 double moreRoughlyEqual(const _Point& a) const { | |
330 return more_roughly_equal(a.y, y) && more_roughly_equal(a.x, x); | |
331 } | |
332 | |
333 double roughlyEqual(const _Point& a) const { | |
334 return roughly_equal(a.y, y) && roughly_equal(a.x, x); | |
335 } | |
336 }; | |
337 | |
338 typedef _Point _Line[2]; | |
339 typedef _Point Quadratic[3]; | |
340 typedef _Point Triangle[3]; | |
341 typedef _Point Cubic[4]; | |
342 | |
343 struct _Rect { | |
344 double left; | |
345 double top; | |
346 double right; | |
347 double bottom; | |
348 | |
349 void add(const _Point& pt) { | |
350 if (left > pt.x) { | |
351 left = pt.x; | |
352 } | |
353 if (top > pt.y) { | |
354 top = pt.y; | |
355 } | |
356 if (right < pt.x) { | |
357 right = pt.x; | |
358 } | |
359 if (bottom < pt.y) { | |
360 bottom = pt.y; | |
361 } | |
362 } | |
363 | |
364 // FIXME: used by debugging only ? | |
365 bool contains(const _Point& pt) const { | |
366 return approximately_between(left, pt.x, right) | |
367 && approximately_between(top, pt.y, bottom); | |
368 } | |
369 | |
370 bool intersects(_Rect& r) const { | |
371 SkASSERT(left <= right); | |
372 SkASSERT(top <= bottom); | |
373 SkASSERT(r.left <= r.right); | |
374 SkASSERT(r.top <= r.bottom); | |
375 return r.left <= right && left <= r.right && r.top <= bottom && top <= r
.bottom; | |
376 } | |
377 | |
378 void set(const _Point& pt) { | |
379 left = right = pt.x; | |
380 top = bottom = pt.y; | |
381 } | |
382 | |
383 void setBounds(const _Line& line) { | |
384 set(line[0]); | |
385 add(line[1]); | |
386 } | |
387 | |
388 void setBounds(const Cubic& ); | |
389 void setBounds(const Quadratic& ); | |
390 void setRawBounds(const Cubic& ); | |
391 void setRawBounds(const Quadratic& ); | |
392 }; | |
393 | |
394 struct CubicPair { | |
395 const Cubic& first() const { return (const Cubic&) pts[0]; } | |
396 const Cubic& second() const { return (const Cubic&) pts[3]; } | |
397 _Point pts[7]; | |
398 }; | |
399 | |
400 struct QuadraticPair { | |
401 const Quadratic& first() const { return (const Quadratic&) pts[0]; } | |
402 const Quadratic& second() const { return (const Quadratic&) pts[2]; } | |
403 _Point pts[5]; | |
404 }; | |
405 | |
406 // FIXME: move these into SkFloatingPoint.h | |
407 #include "SkFloatingPoint.h" | |
408 | |
409 #define sk_double_isnan(a) sk_float_isnan(a) | |
410 | |
411 // FIXME: move these to debugging file | |
412 #ifdef SK_DEBUG | |
413 void mathematica_ize(char* str, size_t bufferSize); | |
414 bool valid_wind(int winding); | |
415 void winding_printf(int winding); | |
416 #endif | |
417 | |
418 #endif // __DataTypes_h__ | |
OLD | NEW |