| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 #ifndef SkPathOpsTypes_DEFINED | 7 #ifndef SkPathOpsTypes_DEFINED |
| 8 #define SkPathOpsTypes_DEFINED | 8 #define SkPathOpsTypes_DEFINED |
| 9 | 9 |
| 10 #include <float.h> // for FLT_EPSILON | 10 #include <float.h> // for FLT_EPSILON |
| 11 #include <math.h> // for fabs, sqrt | 11 #include <math.h> // for fabs, sqrt |
| 12 | 12 |
| 13 #include "SkFloatingPoint.h" | 13 #include "SkFloatingPoint.h" |
| 14 #include "SkPath.h" | 14 #include "SkPath.h" |
| 15 #include "SkPathOps.h" | 15 #include "SkPathOps.h" |
| 16 #include "SkPathOpsDebug.h" | 16 #include "SkPathOpsDebug.h" |
| 17 #include "SkScalar.h" | 17 #include "SkScalar.h" |
| 18 | 18 |
| 19 enum SkPathOpsMask { | 19 enum SkPathOpsMask { |
| 20 kWinding_PathOpsMask = -1, | 20 kWinding_PathOpsMask = -1, |
| 21 kNo_PathOpsMask = 0, | 21 kNo_PathOpsMask = 0, |
| 22 kEvenOdd_PathOpsMask = 1 | 22 kEvenOdd_PathOpsMask = 1 |
| 23 }; | 23 }; |
| 24 | 24 |
| 25 class SkOpCoincidence; |
| 26 class SkOpContour; |
| 27 |
| 28 class SkOpGlobalState { |
| 29 public: |
| 30 SkOpGlobalState(SkOpCoincidence* coincidence PATH_OPS_DEBUG_PARAMS(SkOpCont
our* head)) |
| 31 : fCoincidence(coincidence) |
| 32 , fWindingFailed(false) |
| 33 , fAngleCoincidence(false) |
| 34 #if DEBUG_VALIDATE |
| 35 , fPhase(kIntersecting) |
| 36 #endif |
| 37 PATH_OPS_DEBUG_PARAMS(fHead(head)) |
| 38 PATH_OPS_DEBUG_PARAMS(fAngleID(0)) |
| 39 PATH_OPS_DEBUG_PARAMS(fContourID(0)) |
| 40 PATH_OPS_DEBUG_PARAMS(fPtTID(0)) |
| 41 PATH_OPS_DEBUG_PARAMS(fSegmentID(0)) |
| 42 PATH_OPS_DEBUG_PARAMS(fSpanID(0)) { |
| 43 } |
| 44 |
| 45 #if DEBUG_VALIDATE |
| 46 enum Phase { |
| 47 kIntersecting, |
| 48 kWalking |
| 49 }; |
| 50 #endif |
| 51 |
| 52 bool angleCoincidence() { |
| 53 return fAngleCoincidence; |
| 54 } |
| 55 |
| 56 SkOpCoincidence* coincidence() { |
| 57 return fCoincidence; |
| 58 } |
| 59 |
| 60 #ifdef SK_DEBUG |
| 61 const struct SkOpAngle* debugAngle(int id) const; |
| 62 SkOpContour* debugContour(int id); |
| 63 const class SkOpPtT* debugPtT(int id) const; |
| 64 const class SkOpSegment* debugSegment(int id) const; |
| 65 const class SkOpSpanBase* debugSpan(int id) const; |
| 66 |
| 67 int nextAngleID() { |
| 68 return ++fAngleID; |
| 69 } |
| 70 |
| 71 int nextContourID() { |
| 72 return ++fContourID; |
| 73 } |
| 74 int nextPtTID() { |
| 75 return ++fPtTID; |
| 76 } |
| 77 |
| 78 int nextSegmentID() { |
| 79 return ++fSegmentID; |
| 80 } |
| 81 |
| 82 int nextSpanID() { |
| 83 return ++fSpanID; |
| 84 } |
| 85 #endif |
| 86 |
| 87 #if DEBUG_VALIDATE |
| 88 Phase phase() const { |
| 89 return fPhase; |
| 90 } |
| 91 #endif |
| 92 |
| 93 void setAngleCoincidence() { |
| 94 fAngleCoincidence = true; |
| 95 } |
| 96 |
| 97 #if DEBUG_VALIDATE |
| 98 void setPhase(Phase phase) { |
| 99 SkASSERT(fPhase != phase); |
| 100 fPhase = phase; |
| 101 } |
| 102 #endif |
| 103 |
| 104 // called in very rare cases where angles are sorted incorrectly -- signfies
op will fail |
| 105 void setWindingFailed() { |
| 106 fWindingFailed = true; |
| 107 } |
| 108 |
| 109 bool windingFailed() const { |
| 110 return fWindingFailed; |
| 111 } |
| 112 |
| 113 private: |
| 114 SkOpCoincidence* fCoincidence; |
| 115 bool fWindingFailed; |
| 116 bool fAngleCoincidence; |
| 117 #if DEBUG_VALIDATE |
| 118 Phase fPhase; |
| 119 #endif |
| 120 #ifdef SK_DEBUG |
| 121 SkOpContour* fHead; |
| 122 int fAngleID; |
| 123 int fContourID; |
| 124 int fPtTID; |
| 125 int fSegmentID; |
| 126 int fSpanID; |
| 127 #endif |
| 128 }; |
| 129 |
| 25 // Use Almost Equal when comparing coordinates. Use epsilon to compare T values. | 130 // Use Almost Equal when comparing coordinates. Use epsilon to compare T values. |
| 26 bool AlmostEqualUlps(float a, float b); | 131 bool AlmostEqualUlps(float a, float b); |
| 27 inline bool AlmostEqualUlps(double a, double b) { | 132 inline bool AlmostEqualUlps(double a, double b) { |
| 28 return AlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); | 133 return AlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); |
| 29 } | 134 } |
| 30 | 135 |
| 31 // Use Almost Dequal when comparing should not special case denormalized values. | 136 // Use Almost Dequal when comparing should not special case denormalized values. |
| 32 bool AlmostDequalUlps(float a, float b); | 137 bool AlmostDequalUlps(float a, float b); |
| 33 bool AlmostDequalUlps(double a, double b); | 138 bool AlmostDequalUlps(double a, double b); |
| 34 | 139 |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 85 const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2; | 190 const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2; |
| 86 const double FLT_EPSILON_ORDERABLE_ERR = FLT_EPSILON * 16; | 191 const double FLT_EPSILON_ORDERABLE_ERR = FLT_EPSILON * 16; |
| 87 const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON; | 192 const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON; |
| 88 const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON); | 193 const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON); |
| 89 const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON; | 194 const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON; |
| 90 const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // FIXME: tune -- allow a few b
its of error | 195 const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // FIXME: tune -- allow a few b
its of error |
| 91 const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16; | 196 const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16; |
| 92 const double ROUGH_EPSILON = FLT_EPSILON * 64; | 197 const double ROUGH_EPSILON = FLT_EPSILON * 64; |
| 93 const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256; | 198 const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256; |
| 94 const double WAY_ROUGH_EPSILON = FLT_EPSILON * 2048; | 199 const double WAY_ROUGH_EPSILON = FLT_EPSILON * 2048; |
| 200 const double BUMP_EPSILON = FLT_EPSILON * 4096; |
| 95 | 201 |
| 96 inline bool zero_or_one(double x) { | 202 inline bool zero_or_one(double x) { |
| 97 return x == 0 || x == 1; | 203 return x == 0 || x == 1; |
| 98 } | 204 } |
| 99 | 205 |
| 100 inline bool approximately_zero(double x) { | 206 inline bool approximately_zero(double x) { |
| 101 return fabs(x) < FLT_EPSILON; | 207 return fabs(x) < FLT_EPSILON; |
| 102 } | 208 } |
| 103 | 209 |
| 104 inline bool precisely_zero(double x) { | 210 inline bool precisely_zero(double x) { |
| (...skipping 29 matching lines...) Expand all Loading... |
| 134 } | 240 } |
| 135 | 241 |
| 136 inline bool approximately_zero_sqrt(double x) { | 242 inline bool approximately_zero_sqrt(double x) { |
| 137 return fabs(x) < FLT_EPSILON_SQRT; | 243 return fabs(x) < FLT_EPSILON_SQRT; |
| 138 } | 244 } |
| 139 | 245 |
| 140 inline bool roughly_zero(double x) { | 246 inline bool roughly_zero(double x) { |
| 141 return fabs(x) < ROUGH_EPSILON; | 247 return fabs(x) < ROUGH_EPSILON; |
| 142 } | 248 } |
| 143 | 249 |
| 144 #if 0 // unused for now | |
| 145 inline bool way_roughly_zero(double x) { | |
| 146 return fabs(x) < WAY_ROUGH_EPSILON; | |
| 147 } | |
| 148 #endif | |
| 149 | |
| 150 inline bool approximately_zero_inverse(double x) { | 250 inline bool approximately_zero_inverse(double x) { |
| 151 return fabs(x) > FLT_EPSILON_INVERSE; | 251 return fabs(x) > FLT_EPSILON_INVERSE; |
| 152 } | 252 } |
| 153 | 253 |
| 154 // OPTIMIZATION: if called multiple times with the same denom, we want to pass 1
/y instead | 254 // OPTIMIZATION: if called multiple times with the same denom, we want to pass 1
/y instead |
| 155 inline bool approximately_zero_when_compared_to(double x, double y) { | 255 inline bool approximately_zero_when_compared_to(double x, double y) { |
| 156 return x == 0 || fabs(x) < fabs(y * FLT_EPSILON); | 256 return x == 0 || fabs(x) < fabs(y * FLT_EPSILON); |
| 157 } | 257 } |
| 158 | 258 |
| 259 inline bool precisely_zero_when_compared_to(double x, double y) { |
| 260 return x == 0 || fabs(x) < fabs(y * DBL_EPSILON); |
| 261 } |
| 262 |
| 159 // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger
and smaller) use | 263 // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger
and smaller) use |
| 160 // AlmostEqualUlps instead. | 264 // AlmostEqualUlps instead. |
| 161 inline bool approximately_equal(double x, double y) { | 265 inline bool approximately_equal(double x, double y) { |
| 162 return approximately_zero(x - y); | 266 return approximately_zero(x - y); |
| 163 } | 267 } |
| 164 | 268 |
| 165 inline bool precisely_equal(double x, double y) { | 269 inline bool precisely_equal(double x, double y) { |
| 166 return precisely_zero(x - y); | 270 return precisely_zero(x - y); |
| 167 } | 271 } |
| 168 | 272 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 297 : approximately_negative(b - a) && approximately_negative(c - b); | 401 : approximately_negative(b - a) && approximately_negative(c - b); |
| 298 } | 402 } |
| 299 | 403 |
| 300 inline bool precisely_between(double a, double b, double c) { | 404 inline bool precisely_between(double a, double b, double c) { |
| 301 return a <= c ? precisely_negative(a - b) && precisely_negative(b - c) | 405 return a <= c ? precisely_negative(a - b) && precisely_negative(b - c) |
| 302 : precisely_negative(b - a) && precisely_negative(c - b); | 406 : precisely_negative(b - a) && precisely_negative(c - b); |
| 303 } | 407 } |
| 304 | 408 |
| 305 // returns true if (a <= b <= c) || (a >= b >= c) | 409 // returns true if (a <= b <= c) || (a >= b >= c) |
| 306 inline bool between(double a, double b, double c) { | 410 inline bool between(double a, double b, double c) { |
| 307 SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <=
0)); | 411 SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <=
0) |
| 412 || (precisely_zero(a) && precisely_zero(b) && precisely_zero(c))); |
| 308 return (a - b) * (c - b) <= 0; | 413 return (a - b) * (c - b) <= 0; |
| 309 } | 414 } |
| 310 | 415 |
| 311 inline bool roughly_equal(double x, double y) { | 416 inline bool roughly_equal(double x, double y) { |
| 312 return fabs(x - y) < ROUGH_EPSILON; | 417 return fabs(x - y) < ROUGH_EPSILON; |
| 313 } | 418 } |
| 314 | 419 |
| 420 inline bool roughly_negative(double x) { |
| 421 return x < ROUGH_EPSILON; |
| 422 } |
| 423 |
| 424 inline bool roughly_between(double a, double b, double c) { |
| 425 return a <= c ? roughly_negative(a - b) && roughly_negative(b - c) |
| 426 : roughly_negative(b - a) && roughly_negative(c - b); |
| 427 } |
| 428 |
| 315 inline bool more_roughly_equal(double x, double y) { | 429 inline bool more_roughly_equal(double x, double y) { |
| 316 return fabs(x - y) < MORE_ROUGH_EPSILON; | 430 return fabs(x - y) < MORE_ROUGH_EPSILON; |
| 317 } | 431 } |
| 318 | 432 |
| 319 inline bool way_roughly_equal(double x, double y) { | 433 inline bool way_roughly_equal(double x, double y) { |
| 320 return fabs(x - y) < WAY_ROUGH_EPSILON; | 434 return fabs(x - y) < WAY_ROUGH_EPSILON; |
| 321 } | 435 } |
| 322 | 436 |
| 323 struct SkDPoint; | 437 struct SkDPoint; |
| 324 struct SkDVector; | 438 struct SkDVector; |
| 325 struct SkDLine; | 439 struct SkDLine; |
| 326 struct SkDQuad; | 440 struct SkDQuad; |
| 327 struct SkDTriangle; | |
| 328 struct SkDCubic; | 441 struct SkDCubic; |
| 329 struct SkDRect; | 442 struct SkDRect; |
| 330 | 443 |
| 331 inline SkPath::Verb SkPathOpsPointsToVerb(int points) { | 444 inline SkPath::Verb SkPathOpsPointsToVerb(int points) { |
| 332 int verb = (1 << points) >> 1; | 445 int verb = (1 << points) >> 1; |
| 333 #ifdef SK_DEBUG | 446 #ifdef SK_DEBUG |
| 334 switch (points) { | 447 switch (points) { |
| 335 case 0: SkASSERT(SkPath::kMove_Verb == verb); break; | 448 case 0: SkASSERT(SkPath::kMove_Verb == verb); break; |
| 336 case 1: SkASSERT(SkPath::kLine_Verb == verb); break; | 449 case 1: SkASSERT(SkPath::kLine_Verb == verb); break; |
| 337 case 2: SkASSERT(SkPath::kQuad_Verb == verb); break; | 450 case 2: SkASSERT(SkPath::kQuad_Verb == verb); break; |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 377 */ | 490 */ |
| 378 inline int SkDSideBit(double x) { | 491 inline int SkDSideBit(double x) { |
| 379 return 1 << SKDSide(x); | 492 return 1 << SKDSide(x); |
| 380 } | 493 } |
| 381 | 494 |
| 382 inline double SkPinT(double t) { | 495 inline double SkPinT(double t) { |
| 383 return precisely_less_than_zero(t) ? 0 : precisely_greater_than_one(t) ? 1 :
t; | 496 return precisely_less_than_zero(t) ? 0 : precisely_greater_than_one(t) ? 1 :
t; |
| 384 } | 497 } |
| 385 | 498 |
| 386 #endif | 499 #endif |
| OLD | NEW |