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 |