| 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 |