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 SkPathOpsTypes_DEFINED
8 #define SkPathOpsTypes_DEFINED
9 
10 #include <float.h>  // for FLT_EPSILON
11 #include <math.h>   // for fabs, sqrt
12 
13 #include "SkFloatingPoint.h"
14 #include "SkPath.h"
15 #include "SkPathOps.h"
16 #include "SkPathOpsDebug.h"
17 #include "SkScalar.h"
18 
19 enum SkPathOpsMask {
20     kWinding_PathOpsMask = -1,
21     kNo_PathOpsMask = 0,
22     kEvenOdd_PathOpsMask = 1
23 };
24 
25 class SkOpCoincidence;
26 class SkOpContour;
27 class SkOpContourHead;
28 class SkIntersections;
29 class SkIntersectionHelper;
30 
31 class SkOpGlobalState {
32 public:
33     SkOpGlobalState(SkOpCoincidence* coincidence, SkOpContourHead* head
34                     SkDEBUGPARAMS(const char* testName));
35 
36     enum Phase {
37         kIntersecting,
38         kWalking,
39         kFixWinding,
40     };
41 
42     enum {
43         kMaxWindingTries = 10
44     };
45 
angleCoincidence()46     bool angleCoincidence() const {
47         return fAngleCoincidence;
48     }
49 
bumpNested()50     void bumpNested() {
51         ++fNested;
52     }
53 
clearNested()54     void clearNested() {
55         fNested = 0;
56     }
57 
coincidence()58     SkOpCoincidence* coincidence() {
59         return fCoincidence;
60     }
61 
contourHead()62     SkOpContourHead* contourHead() {
63         return fContourHead;
64     }
65 
66 #ifdef SK_DEBUG
67     const struct SkOpAngle* debugAngle(int id) const;
68     SkOpContour* debugContour(int id);
69     const class SkOpPtT* debugPtT(int id) const;
70     bool debugRunFail() const;
71     const class SkOpSegment* debugSegment(int id) const;
72     const class SkOpSpanBase* debugSpan(int id) const;
debugTestName()73     const char* debugTestName() const { return fDebugTestName; }
74 #endif
75 
76 #if DEBUG_T_SECT_LOOP_COUNT
77     void debugAddLoopCount(SkIntersections* , const SkIntersectionHelper& ,
78         const SkIntersectionHelper& );
79     void debugDoYourWorst(SkOpGlobalState* );
80     void debugLoopReport();
81     void debugResetLoopCounts();
82 #endif
83 
nested()84     int nested() const {
85         return fNested;
86     }
87 
88 #ifdef SK_DEBUG
nextAngleID()89     int nextAngleID() {
90         return ++fAngleID;
91     }
92 
nextCoinID()93     int nextCoinID() {
94         return ++fCoinID;
95     }
96 
nextContourID()97     int nextContourID() {
98         return ++fContourID;
99     }
100 
nextPtTID()101     int nextPtTID() {
102         return ++fPtTID;
103     }
104 
nextSegmentID()105     int nextSegmentID() {
106         return ++fSegmentID;
107     }
108 
nextSpanID()109     int nextSpanID() {
110         return ++fSpanID;
111     }
112 #endif
113 
phase()114     Phase phase() const {
115         return fPhase;
116     }
117 
setAngleCoincidence()118     void setAngleCoincidence() {
119         fAngleCoincidence = true;
120     }
121 
setContourHead(SkOpContourHead * contourHead)122     void setContourHead(SkOpContourHead* contourHead) {
123         fContourHead = contourHead;
124     }
125 
setPhase(Phase phase)126     void setPhase(Phase phase) {
127         SkASSERT(fPhase != phase);
128         fPhase = phase;
129     }
130 
131     // called in very rare cases where angles are sorted incorrectly -- signfies op will fail
setWindingFailed()132     void setWindingFailed() {
133         fWindingFailed = true;
134     }
135 
windingFailed()136     bool windingFailed() const {
137         return fWindingFailed;
138     }
139 
140 private:
141     SkOpCoincidence* fCoincidence;
142     SkOpContourHead* fContourHead;
143     int fNested;
144     bool fWindingFailed;
145     bool fAngleCoincidence;
146     Phase fPhase;
147 #ifdef SK_DEBUG
148     const char* fDebugTestName;
149     int fAngleID;
150     int fCoinID;
151     int fContourID;
152     int fPtTID;
153     int fSegmentID;
154     int fSpanID;
155 #endif
156 #if DEBUG_T_SECT_LOOP_COUNT
157     int fDebugLoopCount[3];
158     SkPath::Verb fDebugWorstVerb[6];
159     SkPoint fDebugWorstPts[24];
160     float fDebugWorstWeight[6];
161 #endif
162 };
163 
164 // Use Almost Equal when comparing coordinates. Use epsilon to compare T values.
165 bool AlmostEqualUlps(float a, float b);
AlmostEqualUlps(double a,double b)166 inline bool AlmostEqualUlps(double a, double b) {
167     return AlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
168 }
169 
170 bool AlmostEqualUlps_Pin(float a, float b);
AlmostEqualUlps_Pin(double a,double b)171 inline bool AlmostEqualUlps_Pin(double a, double b) {
172     return AlmostEqualUlps_Pin(SkDoubleToScalar(a), SkDoubleToScalar(b));
173 }
174 
175 // Use Almost Dequal when comparing should not special case denormalized values.
176 bool AlmostDequalUlps(float a, float b);
177 bool AlmostDequalUlps(double a, double b);
178 
179 bool NotAlmostEqualUlps(float a, float b);
NotAlmostEqualUlps(double a,double b)180 inline bool NotAlmostEqualUlps(double a, double b) {
181     return NotAlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
182 }
183 
184 bool NotAlmostEqualUlps_Pin(float a, float b);
NotAlmostEqualUlps_Pin(double a,double b)185 inline bool NotAlmostEqualUlps_Pin(double a, double b) {
186     return NotAlmostEqualUlps_Pin(SkDoubleToScalar(a), SkDoubleToScalar(b));
187 }
188 
189 bool NotAlmostDequalUlps(float a, float b);
NotAlmostDequalUlps(double a,double b)190 inline bool NotAlmostDequalUlps(double a, double b) {
191     return NotAlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
192 }
193 
194 // Use Almost Bequal when comparing coordinates in conjunction with between.
195 bool AlmostBequalUlps(float a, float b);
AlmostBequalUlps(double a,double b)196 inline bool AlmostBequalUlps(double a, double b) {
197     return AlmostBequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
198 }
199 
200 bool AlmostPequalUlps(float a, float b);
AlmostPequalUlps(double a,double b)201 inline bool AlmostPequalUlps(double a, double b) {
202     return AlmostPequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
203 }
204 
205 bool RoughlyEqualUlps(float a, float b);
RoughlyEqualUlps(double a,double b)206 inline bool RoughlyEqualUlps(double a, double b) {
207     return RoughlyEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
208 }
209 
210 bool AlmostLessUlps(float a, float b);
AlmostLessUlps(double a,double b)211 inline bool AlmostLessUlps(double a, double b) {
212     return AlmostLessUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
213 }
214 
215 bool AlmostLessOrEqualUlps(float a, float b);
AlmostLessOrEqualUlps(double a,double b)216 inline bool AlmostLessOrEqualUlps(double a, double b) {
217     return AlmostLessOrEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
218 }
219 
220 bool AlmostBetweenUlps(float a, float b, float c);
AlmostBetweenUlps(double a,double b,double c)221 inline bool AlmostBetweenUlps(double a, double b, double c) {
222     return AlmostBetweenUlps(SkDoubleToScalar(a), SkDoubleToScalar(b), SkDoubleToScalar(c));
223 }
224 
225 int UlpsDistance(float a, float b);
UlpsDistance(double a,double b)226 inline int UlpsDistance(double a, double b) {
227     return UlpsDistance(SkDoubleToScalar(a), SkDoubleToScalar(b));
228 }
229 
230 // FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23)
231 // DBL_EPSILON == 2.22045e-16
232 const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
233 const double FLT_EPSILON_HALF = FLT_EPSILON / 2;
234 const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2;
235 const double FLT_EPSILON_ORDERABLE_ERR = FLT_EPSILON * 16;
236 const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
237 const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON);
238 const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
239 const double DBL_EPSILON_ERR = DBL_EPSILON * 4;  // FIXME: tune -- allow a few bits of error
240 const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16;
241 const double ROUGH_EPSILON = FLT_EPSILON * 64;
242 const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256;
243 const double WAY_ROUGH_EPSILON = FLT_EPSILON * 2048;
244 const double BUMP_EPSILON = FLT_EPSILON * 4096;
245 
zero_or_one(double x)246 inline bool zero_or_one(double x) {
247     return x == 0 || x == 1;
248 }
249 
approximately_zero(double x)250 inline bool approximately_zero(double x) {
251     return fabs(x) < FLT_EPSILON;
252 }
253 
precisely_zero(double x)254 inline bool precisely_zero(double x) {
255     return fabs(x) < DBL_EPSILON_ERR;
256 }
257 
precisely_subdivide_zero(double x)258 inline bool precisely_subdivide_zero(double x) {
259     return fabs(x) < DBL_EPSILON_SUBDIVIDE_ERR;
260 }
261 
approximately_zero(float x)262 inline bool approximately_zero(float x) {
263     return fabs(x) < FLT_EPSILON;
264 }
265 
approximately_zero_cubed(double x)266 inline bool approximately_zero_cubed(double x) {
267     return fabs(x) < FLT_EPSILON_CUBED;
268 }
269 
approximately_zero_half(double x)270 inline bool approximately_zero_half(double x) {
271     return fabs(x) < FLT_EPSILON_HALF;
272 }
273 
approximately_zero_double(double x)274 inline bool approximately_zero_double(double x) {
275     return fabs(x) < FLT_EPSILON_DOUBLE;
276 }
277 
approximately_zero_orderable(double x)278 inline bool approximately_zero_orderable(double x) {
279     return fabs(x) < FLT_EPSILON_ORDERABLE_ERR;
280 }
281 
approximately_zero_squared(double x)282 inline bool approximately_zero_squared(double x) {
283     return fabs(x) < FLT_EPSILON_SQUARED;
284 }
285 
approximately_zero_sqrt(double x)286 inline bool approximately_zero_sqrt(double x) {
287     return fabs(x) < FLT_EPSILON_SQRT;
288 }
289 
roughly_zero(double x)290 inline bool roughly_zero(double x) {
291     return fabs(x) < ROUGH_EPSILON;
292 }
293 
approximately_zero_inverse(double x)294 inline bool approximately_zero_inverse(double x) {
295     return fabs(x) > FLT_EPSILON_INVERSE;
296 }
297 
298 // OPTIMIZATION: if called multiple times with the same denom, we want to pass 1/y instead
approximately_zero_when_compared_to(double x,double y)299 inline bool approximately_zero_when_compared_to(double x, double y) {
300     return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
301 }
302 
precisely_zero_when_compared_to(double x,double y)303 inline bool precisely_zero_when_compared_to(double x, double y) {
304     return x == 0 || fabs(x) < fabs(y * DBL_EPSILON);
305 }
306 
307 // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
308 // AlmostEqualUlps instead.
approximately_equal(double x,double y)309 inline bool approximately_equal(double x, double y) {
310     return approximately_zero(x - y);
311 }
312 
precisely_equal(double x,double y)313 inline bool precisely_equal(double x, double y) {
314     return precisely_zero(x - y);
315 }
316 
precisely_subdivide_equal(double x,double y)317 inline bool precisely_subdivide_equal(double x, double y) {
318     return precisely_subdivide_zero(x - y);
319 }
320 
approximately_equal_half(double x,double y)321 inline bool approximately_equal_half(double x, double y) {
322     return approximately_zero_half(x - y);
323 }
324 
approximately_equal_double(double x,double y)325 inline bool approximately_equal_double(double x, double y) {
326     return approximately_zero_double(x - y);
327 }
328 
approximately_equal_orderable(double x,double y)329 inline bool approximately_equal_orderable(double x, double y) {
330     return approximately_zero_orderable(x - y);
331 }
332 
approximately_equal_squared(double x,double y)333 inline bool approximately_equal_squared(double x, double y) {
334     return approximately_equal(x, y);
335 }
336 
approximately_greater(double x,double y)337 inline bool approximately_greater(double x, double y) {
338     return x - FLT_EPSILON >= y;
339 }
340 
approximately_greater_double(double x,double y)341 inline bool approximately_greater_double(double x, double y) {
342     return x - FLT_EPSILON_DOUBLE >= y;
343 }
344 
approximately_greater_orderable(double x,double y)345 inline bool approximately_greater_orderable(double x, double y) {
346     return x - FLT_EPSILON_ORDERABLE_ERR >= y;
347 }
348 
approximately_greater_or_equal(double x,double y)349 inline bool approximately_greater_or_equal(double x, double y) {
350     return x + FLT_EPSILON > y;
351 }
352 
approximately_greater_or_equal_double(double x,double y)353 inline bool approximately_greater_or_equal_double(double x, double y) {
354     return x + FLT_EPSILON_DOUBLE > y;
355 }
356 
approximately_greater_or_equal_orderable(double x,double y)357 inline bool approximately_greater_or_equal_orderable(double x, double y) {
358     return x + FLT_EPSILON_ORDERABLE_ERR > y;
359 }
360 
approximately_lesser(double x,double y)361 inline bool approximately_lesser(double x, double y) {
362     return x + FLT_EPSILON <= y;
363 }
364 
approximately_lesser_double(double x,double y)365 inline bool approximately_lesser_double(double x, double y) {
366     return x + FLT_EPSILON_DOUBLE <= y;
367 }
368 
approximately_lesser_orderable(double x,double y)369 inline bool approximately_lesser_orderable(double x, double y) {
370     return x + FLT_EPSILON_ORDERABLE_ERR <= y;
371 }
372 
approximately_lesser_or_equal(double x,double y)373 inline bool approximately_lesser_or_equal(double x, double y) {
374     return x - FLT_EPSILON < y;
375 }
376 
approximately_lesser_or_equal_double(double x,double y)377 inline bool approximately_lesser_or_equal_double(double x, double y) {
378     return x - FLT_EPSILON_DOUBLE < y;
379 }
380 
approximately_lesser_or_equal_orderable(double x,double y)381 inline bool approximately_lesser_or_equal_orderable(double x, double y) {
382     return x - FLT_EPSILON_ORDERABLE_ERR < y;
383 }
384 
approximately_greater_than_one(double x)385 inline bool approximately_greater_than_one(double x) {
386     return x > 1 - FLT_EPSILON;
387 }
388 
precisely_greater_than_one(double x)389 inline bool precisely_greater_than_one(double x) {
390     return x > 1 - DBL_EPSILON_ERR;
391 }
392 
approximately_less_than_zero(double x)393 inline bool approximately_less_than_zero(double x) {
394     return x < FLT_EPSILON;
395 }
396 
precisely_less_than_zero(double x)397 inline bool precisely_less_than_zero(double x) {
398     return x < DBL_EPSILON_ERR;
399 }
400 
approximately_negative(double x)401 inline bool approximately_negative(double x) {
402     return x < FLT_EPSILON;
403 }
404 
approximately_negative_orderable(double x)405 inline bool approximately_negative_orderable(double x) {
406     return x < FLT_EPSILON_ORDERABLE_ERR;
407 }
408 
precisely_negative(double x)409 inline bool precisely_negative(double x) {
410     return x < DBL_EPSILON_ERR;
411 }
412 
approximately_one_or_less(double x)413 inline bool approximately_one_or_less(double x) {
414     return x < 1 + FLT_EPSILON;
415 }
416 
approximately_one_or_less_double(double x)417 inline bool approximately_one_or_less_double(double x) {
418     return x < 1 + FLT_EPSILON_DOUBLE;
419 }
420 
approximately_positive(double x)421 inline bool approximately_positive(double x) {
422     return x > -FLT_EPSILON;
423 }
424 
approximately_positive_squared(double x)425 inline bool approximately_positive_squared(double x) {
426     return x > -(FLT_EPSILON_SQUARED);
427 }
428 
approximately_zero_or_more(double x)429 inline bool approximately_zero_or_more(double x) {
430     return x > -FLT_EPSILON;
431 }
432 
approximately_zero_or_more_double(double x)433 inline bool approximately_zero_or_more_double(double x) {
434     return x > -FLT_EPSILON_DOUBLE;
435 }
436 
approximately_between_orderable(double a,double b,double c)437 inline bool approximately_between_orderable(double a, double b, double c) {
438     return a <= c
439             ? approximately_negative_orderable(a - b) && approximately_negative_orderable(b - c)
440             : approximately_negative_orderable(b - a) && approximately_negative_orderable(c - b);
441 }
442 
approximately_between(double a,double b,double c)443 inline bool approximately_between(double a, double b, double c) {
444     return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
445             : approximately_negative(b - a) && approximately_negative(c - b);
446 }
447 
precisely_between(double a,double b,double c)448 inline bool precisely_between(double a, double b, double c) {
449     return a <= c ? precisely_negative(a - b) && precisely_negative(b - c)
450             : precisely_negative(b - a) && precisely_negative(c - b);
451 }
452 
453 // returns true if (a <= b <= c) || (a >= b >= c)
between(double a,double b,double c)454 inline bool between(double a, double b, double c) {
455     SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0)
456             || (precisely_zero(a) && precisely_zero(b) && precisely_zero(c)));
457     return (a - b) * (c - b) <= 0;
458 }
459 
roughly_equal(double x,double y)460 inline bool roughly_equal(double x, double y) {
461     return fabs(x - y) < ROUGH_EPSILON;
462 }
463 
roughly_negative(double x)464 inline bool roughly_negative(double x) {
465     return x < ROUGH_EPSILON;
466 }
467 
roughly_between(double a,double b,double c)468 inline bool roughly_between(double a, double b, double c) {
469     return a <= c ? roughly_negative(a - b) && roughly_negative(b - c)
470             : roughly_negative(b - a) && roughly_negative(c - b);
471 }
472 
more_roughly_equal(double x,double y)473 inline bool more_roughly_equal(double x, double y) {
474     return fabs(x - y) < MORE_ROUGH_EPSILON;
475 }
476 
way_roughly_equal(double x,double y)477 inline bool way_roughly_equal(double x, double y) {
478     return fabs(x - y) < WAY_ROUGH_EPSILON;
479 }
480 
481 struct SkDPoint;
482 struct SkDVector;
483 struct SkDLine;
484 struct SkDQuad;
485 struct SkDConic;
486 struct SkDCubic;
487 struct SkDRect;
488 
SkPathOpsPointsToVerb(int points)489 inline SkPath::Verb SkPathOpsPointsToVerb(int points) {
490     int verb = (1 << points) >> 1;
491 #ifdef SK_DEBUG
492     switch (points) {
493         case 0: SkASSERT(SkPath::kMove_Verb == verb); break;
494         case 1: SkASSERT(SkPath::kLine_Verb == verb); break;
495         case 2: SkASSERT(SkPath::kQuad_Verb == verb); break;
496         case 3: SkASSERT(SkPath::kCubic_Verb == verb); break;
497         default: SkDEBUGFAIL("should not be here");
498     }
499 #endif
500     return (SkPath::Verb)verb;
501 }
502 
SkPathOpsVerbToPoints(SkPath::Verb verb)503 inline int SkPathOpsVerbToPoints(SkPath::Verb verb) {
504     int points = (int) verb - (((int) verb + 1) >> 2);
505 #ifdef SK_DEBUG
506     switch (verb) {
507         case SkPath::kLine_Verb: SkASSERT(1 == points); break;
508         case SkPath::kQuad_Verb: SkASSERT(2 == points); break;
509         case SkPath::kConic_Verb: SkASSERT(2 == points); break;
510         case SkPath::kCubic_Verb: SkASSERT(3 == points); break;
511         default: SkDEBUGFAIL("should not get here");
512     }
513 #endif
514     return points;
515 }
516 
SkDInterp(double A,double B,double t)517 inline double SkDInterp(double A, double B, double t) {
518     return A + (B - A) * t;
519 }
520 
521 double SkDCubeRoot(double x);
522 
523 /* Returns -1 if negative, 0 if zero, 1 if positive
524 */
SkDSign(double x)525 inline int SkDSign(double x) {
526     return (x > 0) - (x < 0);
527 }
528 
529 /* Returns 0 if negative, 1 if zero, 2 if positive
530 */
SKDSide(double x)531 inline int SKDSide(double x) {
532     return (x > 0) + (x >= 0);
533 }
534 
535 /* Returns 1 if negative, 2 if zero, 4 if positive
536 */
SkDSideBit(double x)537 inline int SkDSideBit(double x) {
538     return 1 << SKDSide(x);
539 }
540 
SkPinT(double t)541 inline double SkPinT(double t) {
542     return precisely_less_than_zero(t) ? 0 : precisely_greater_than_one(t) ? 1 : t;
543 }
544 
545 #endif
546