Flutter Engine
The Flutter Engine
SkPathOpsTypes.h
Go to the documentation of this file.
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 "include/core/SkPath.h"
14
15#include <cfloat>
16#include <cmath>
17
22};
23
24class SkArenaAlloc;
25class SkOpCoincidence;
26class SkOpContour;
27class SkOpContourHead;
28
29enum class SkOpPhase : char {
34};
35
37public:
39 SkArenaAlloc* allocator SkDEBUGPARAMS(bool debugSkipAssert)
40 SkDEBUGPARAMS(const char* testName));
41
42 enum {
44 };
45
46 bool allocatedOpSpan() const {
47 return fAllocatedOpSpan;
48 }
49
51 return fAllocator;
52 }
53
54 void bumpNested() {
55 ++fNested;
56 }
57
58 void clearNested() {
59 fNested = 0;
60 }
61
63 return fCoincidence;
64 }
65
67 return fContourHead;
68 }
69
70#ifdef SK_DEBUG
71 const class SkOpAngle* debugAngle(int id) const;
72 const SkOpCoincidence* debugCoincidence() const;
73 SkOpContour* debugContour(int id) const;
74 const class SkOpPtT* debugPtT(int id) const;
75#endif
76
77 static bool DebugRunFail();
78
79#ifdef SK_DEBUG
80 const class SkOpSegment* debugSegment(int id) const;
81 bool debugSkipAssert() const { return fDebugSkipAssert; }
82 const class SkOpSpanBase* debugSpan(int id) const;
83 const char* debugTestName() const { return fDebugTestName; }
84#endif
85
86#if DEBUG_T_SECT_LOOP_COUNT
87 void debugAddLoopCount(SkIntersections* , const SkIntersectionHelper& ,
88 const SkIntersectionHelper& );
89 void debugDoYourWorst(SkOpGlobalState* );
90 void debugLoopReport();
91 void debugResetLoopCounts();
92#endif
93
94#if DEBUG_COINCIDENCE
95 void debugSetCheckHealth(bool check) { fDebugCheckHealth = check; }
96 bool debugCheckHealth() const { return fDebugCheckHealth; }
97#endif
98
99#if DEBUG_VALIDATE || DEBUG_COIN
100 void debugSetPhase(const char* funcName DEBUG_COIN_DECLARE_PARAMS()) const;
101#endif
102
103#if DEBUG_COIN
104 void debugAddToCoinChangedDict();
105 void debugAddToGlobalCoinDicts();
106 SkPathOpsDebug::CoinDict* debugCoinChangedDict() { return &fCoinChangedDict; }
107 const SkPathOpsDebug::CoinDictEntry& debugCoinDictEntry() const { return fCoinDictEntry; }
108
109 static void DumpCoinDict();
110#endif
111
112
113 int nested() const {
114 return fNested;
115 }
116
117#ifdef SK_DEBUG
118 int nextAngleID() {
119 return ++fAngleID;
120 }
121
122 int nextCoinID() {
123 return ++fCoinID;
124 }
125
126 int nextContourID() {
127 return ++fContourID;
128 }
129
130 int nextPtTID() {
131 return ++fPtTID;
132 }
133
134 int nextSegmentID() {
135 return ++fSegmentID;
136 }
137
138 int nextSpanID() {
139 return ++fSpanID;
140 }
141#endif
142
143 SkOpPhase phase() const {
144 return fPhase;
145 }
146
148 fAllocatedOpSpan = false;
149 }
150
152 fAllocatedOpSpan = true;
153 }
154
156 fCoincidence = coincidence;
157 }
158
160 fContourHead = contourHead;
161 }
162
165 return;
166 }
168 fPhase = phase;
169 }
170
171 // called in very rare cases where angles are sorted incorrectly -- signfies op will fail
173 fWindingFailed = true;
174 }
175
176 bool windingFailed() const {
177 return fWindingFailed;
178 }
179
180private:
181 SkArenaAlloc* fAllocator;
182 SkOpCoincidence* fCoincidence;
183 SkOpContourHead* fContourHead;
184 int fNested;
185 bool fAllocatedOpSpan;
186 bool fWindingFailed;
188#ifdef SK_DEBUG
189 const char* fDebugTestName;
190 void* fDebugReporter;
191 int fAngleID;
192 int fCoinID;
193 int fContourID;
194 int fPtTID;
195 int fSegmentID;
196 int fSpanID;
197 bool fDebugSkipAssert;
198#endif
199#if DEBUG_T_SECT_LOOP_COUNT
200 int fDebugLoopCount[3];
201 SkPath::Verb fDebugWorstVerb[6];
202 SkPoint fDebugWorstPts[24];
203 float fDebugWorstWeight[6];
204#endif
205#if DEBUG_COIN
206 SkPathOpsDebug::CoinDict fCoinChangedDict;
207 SkPathOpsDebug::CoinDict fCoinVisitedDict;
208 SkPathOpsDebug::CoinDictEntry fCoinDictEntry;
209 const char* fPreviousFuncName;
210#endif
211#if DEBUG_COINCIDENCE
212 bool fDebugCheckHealth;
213#endif
214};
215
216#ifdef SK_DEBUG
217#if DEBUG_COINCIDENCE
218#define SkOPASSERT(cond) SkASSERT((this->globalState() && \
219 (this->globalState()->debugCheckHealth() || \
220 this->globalState()->debugSkipAssert())) || (cond))
221#else
222#define SkOPASSERT(cond) SkASSERT((this->globalState() && \
223 this->globalState()->debugSkipAssert()) || (cond))
224#endif
225#define SkOPOBJASSERT(obj, cond) SkASSERT((obj->globalState() && \
226 obj->globalState()->debugSkipAssert()) || (cond))
227#else
228#define SkOPASSERT(cond)
229#define SkOPOBJASSERT(obj, cond)
230#endif
231
232// Use Almost Equal when comparing coordinates. Use epsilon to compare T values.
233bool AlmostEqualUlps(float a, float b);
234inline bool AlmostEqualUlps(double a, double b) {
236}
237
238bool AlmostEqualUlpsNoNormalCheck(float a, float b);
239inline bool AlmostEqualUlpsNoNormalCheck(double a, double b) {
241}
242
243bool AlmostEqualUlps_Pin(float a, float b);
244inline bool AlmostEqualUlps_Pin(double a, double b) {
246}
247
248// Use Almost Dequal when comparing should not special case denormalized values.
249bool AlmostDequalUlps(float a, float b);
250bool AlmostDequalUlps(double a, double b);
251
252bool NotAlmostEqualUlps(float a, float b);
253inline bool NotAlmostEqualUlps(double a, double b) {
255}
256
257bool NotAlmostEqualUlps_Pin(float a, float b);
258inline bool NotAlmostEqualUlps_Pin(double a, double b) {
260}
261
262bool NotAlmostDequalUlps(float a, float b);
263inline bool NotAlmostDequalUlps(double a, double b) {
265}
266
267// Use Almost Bequal when comparing coordinates in conjunction with between.
268bool AlmostBequalUlps(float a, float b);
269inline bool AlmostBequalUlps(double a, double b) {
271}
272
273bool AlmostPequalUlps(float a, float b);
274inline bool AlmostPequalUlps(double a, double b) {
276}
277
278bool RoughlyEqualUlps(float a, float b);
279inline bool RoughlyEqualUlps(double a, double b) {
281}
282
283bool AlmostLessUlps(float a, float b);
284inline bool AlmostLessUlps(double a, double b) {
286}
287
288bool AlmostLessOrEqualUlps(float a, float b);
289inline bool AlmostLessOrEqualUlps(double a, double b) {
291}
292
293bool AlmostBetweenUlps(float a, float b, float c);
294inline bool AlmostBetweenUlps(double a, double b, double c) {
296}
297
298int UlpsDistance(float a, float b);
299inline int UlpsDistance(double a, double b) {
301}
302
303// FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23)
304// DBL_EPSILON == 2.22045e-16
305const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
306const double FLT_EPSILON_HALF = FLT_EPSILON / 2;
307const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2;
308const double FLT_EPSILON_ORDERABLE_ERR = FLT_EPSILON * 16;
309const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
310// Use a compile-time constant for FLT_EPSILON_SQRT to avoid initializers.
311// A 17 digit constant guarantees exact results.
312const double FLT_EPSILON_SQRT = 0.00034526697709225118; // sqrt(FLT_EPSILON);
313const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
314const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // FIXME: tune -- allow a few bits of error
315const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16;
316const double ROUGH_EPSILON = FLT_EPSILON * 64;
317const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256;
318const double WAY_ROUGH_EPSILON = FLT_EPSILON * 2048;
319const double BUMP_EPSILON = FLT_EPSILON * 4096;
320
322
323inline bool zero_or_one(double x) {
324 return x == 0 || x == 1;
325}
326
327inline bool approximately_zero(double x) {
328 return fabs(x) < FLT_EPSILON;
329}
330
331inline bool precisely_zero(double x) {
332 return fabs(x) < DBL_EPSILON_ERR;
333}
334
335inline bool precisely_subdivide_zero(double x) {
336 return fabs(x) < DBL_EPSILON_SUBDIVIDE_ERR;
337}
338
339inline bool approximately_zero(float x) {
340 return fabs(x) < FLT_EPSILON;
341}
342
343inline bool approximately_zero_half(double x) {
344 return fabs(x) < FLT_EPSILON_HALF;
345}
346
347inline bool approximately_zero_double(double x) {
348 return fabs(x) < FLT_EPSILON_DOUBLE;
349}
350
351inline bool approximately_zero_orderable(double x) {
352 return fabs(x) < FLT_EPSILON_ORDERABLE_ERR;
353}
354
355inline bool approximately_zero_squared(double x) {
356 return fabs(x) < FLT_EPSILON_SQUARED;
357}
358
359inline bool approximately_zero_sqrt(double x) {
360 return fabs(x) < FLT_EPSILON_SQRT;
361}
362
363inline bool roughly_zero(double x) {
364 return fabs(x) < ROUGH_EPSILON;
365}
366
367inline bool approximately_zero_inverse(double x) {
368 return fabs(x) > FLT_EPSILON_INVERSE;
369}
370
371inline bool approximately_zero_when_compared_to(double x, double y) {
372 return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
373}
374
375inline bool precisely_zero_when_compared_to(double x, double y) {
376 return x == 0 || fabs(x) < fabs(y * DBL_EPSILON);
377}
378
379inline bool roughly_zero_when_compared_to(double x, double y) {
380 return x == 0 || fabs(x) < fabs(y * ROUGH_EPSILON);
381}
382
383// Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
384// AlmostEqualUlps instead.
385inline bool approximately_equal(double x, double y) {
386 return approximately_zero(x - y);
387}
388
389inline bool precisely_equal(double x, double y) {
390 return precisely_zero(x - y);
391}
392
393inline bool precisely_subdivide_equal(double x, double y) {
394 return precisely_subdivide_zero(x - y);
395}
396
397inline bool approximately_equal_half(double x, double y) {
398 return approximately_zero_half(x - y);
399}
400
401inline bool approximately_equal_double(double x, double y) {
402 return approximately_zero_double(x - y);
403}
404
405inline bool approximately_equal_orderable(double x, double y) {
407}
408
409inline bool approximately_equal_squared(double x, double y) {
410 return approximately_equal(x, y);
411}
412
413inline bool approximately_greater(double x, double y) {
414 return x - FLT_EPSILON >= y;
415}
416
417inline bool approximately_greater_double(double x, double y) {
418 return x - FLT_EPSILON_DOUBLE >= y;
419}
420
421inline bool approximately_greater_orderable(double x, double y) {
422 return x - FLT_EPSILON_ORDERABLE_ERR >= y;
423}
424
425inline bool approximately_greater_or_equal(double x, double y) {
426 return x + FLT_EPSILON > y;
427}
428
429inline bool approximately_greater_or_equal_double(double x, double y) {
430 return x + FLT_EPSILON_DOUBLE > y;
431}
432
433inline bool approximately_greater_or_equal_orderable(double x, double y) {
434 return x + FLT_EPSILON_ORDERABLE_ERR > y;
435}
436
437inline bool approximately_lesser(double x, double y) {
438 return x + FLT_EPSILON <= y;
439}
440
441inline bool approximately_lesser_double(double x, double y) {
442 return x + FLT_EPSILON_DOUBLE <= y;
443}
444
445inline bool approximately_lesser_orderable(double x, double y) {
446 return x + FLT_EPSILON_ORDERABLE_ERR <= y;
447}
448
449inline bool approximately_lesser_or_equal(double x, double y) {
450 return x - FLT_EPSILON < y;
451}
452
453inline bool approximately_lesser_or_equal_double(double x, double y) {
454 return x - FLT_EPSILON_DOUBLE < y;
455}
456
457inline bool approximately_lesser_or_equal_orderable(double x, double y) {
458 return x - FLT_EPSILON_ORDERABLE_ERR < y;
459}
460
462 return x > 1 - FLT_EPSILON;
463}
464
465inline bool precisely_greater_than_one(double x) {
466 return x > 1 - DBL_EPSILON_ERR;
467}
468
469inline bool approximately_less_than_zero(double x) {
470 return x < FLT_EPSILON;
471}
472
473inline bool precisely_less_than_zero(double x) {
474 return x < DBL_EPSILON_ERR;
475}
476
477inline bool approximately_negative(double x) {
478 return x < FLT_EPSILON;
479}
480
483}
484
485inline bool precisely_negative(double x) {
486 return x < DBL_EPSILON_ERR;
487}
488
489inline bool approximately_one_or_less(double x) {
490 return x < 1 + FLT_EPSILON;
491}
492
494 return x < 1 + FLT_EPSILON_DOUBLE;
495}
496
497inline bool approximately_positive(double x) {
498 return x > -FLT_EPSILON;
499}
500
502 return x > -(FLT_EPSILON_SQUARED);
503}
504
505inline bool approximately_zero_or_more(double x) {
506 return x > -FLT_EPSILON;
507}
508
510 return x > -FLT_EPSILON_DOUBLE;
511}
512
513inline bool approximately_between_orderable(double a, double b, double c) {
514 return a <= c
517}
518
519inline bool approximately_between(double a, double b, double c) {
520 return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
522}
523
524inline bool precisely_between(double a, double b, double c) {
525 return a <= c ? precisely_negative(a - b) && precisely_negative(b - c)
527}
528
529// returns true if (a <= b <= c) || (a >= b >= c)
530inline bool between(double a, double b, double c) {
531 SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0)
533 return (a - b) * (c - b) <= 0;
534}
535
536inline bool roughly_equal(double x, double y) {
537 return fabs(x - y) < ROUGH_EPSILON;
538}
539
540inline bool roughly_negative(double x) {
541 return x < ROUGH_EPSILON;
542}
543
544inline bool roughly_between(double a, double b, double c) {
545 return a <= c ? roughly_negative(a - b) && roughly_negative(b - c)
547}
548
549inline bool more_roughly_equal(double x, double y) {
550 return fabs(x - y) < MORE_ROUGH_EPSILON;
551}
552
554 int verb = (1 << points) >> 1;
555#ifdef SK_DEBUG
556 switch (points) {
557 case 0: SkASSERT(SkPath::kMove_Verb == verb); break;
558 case 1: SkASSERT(SkPath::kLine_Verb == verb); break;
559 case 2: SkASSERT(SkPath::kQuad_Verb == verb); break;
560 case 3: SkASSERT(SkPath::kCubic_Verb == verb); break;
561 default: SkDEBUGFAIL("should not be here");
562 }
563#endif
564 return (SkPath::Verb)verb;
565}
566
568 int points = (int) verb - (((int) verb + 1) >> 2);
569#ifdef SK_DEBUG
570 switch (verb) {
571 case SkPath::kLine_Verb: SkASSERT(1 == points); break;
572 case SkPath::kQuad_Verb: SkASSERT(2 == points); break;
573 case SkPath::kConic_Verb: SkASSERT(2 == points); break;
574 case SkPath::kCubic_Verb: SkASSERT(3 == points); break;
575 default: SkDEBUGFAIL("should not get here");
576 }
577#endif
578 return points;
579}
580
581inline double SkDInterp(double A, double B, double t) {
582 return A + (B - A) * t;
583}
584
585/* Returns -1 if negative, 0 if zero, 1 if positive
586*/
587inline int SkDSign(double x) {
588 return (x > 0) - (x < 0);
589}
590
591/* Returns 0 if negative, 1 if zero, 2 if positive
592*/
593inline int SKDSide(double x) {
594 return (x > 0) + (x >= 0);
595}
596
597/* Returns 1 if negative, 2 if zero, 4 if positive
598*/
599inline int SkDSideBit(double x) {
600 return 1 << SKDSide(x);
601}
602
603inline double SkPinT(double t) {
605}
606
607#endif
SkScalar fPhase
Definition: DashOp.cpp:189
static const int points[]
#define check(reporter, ref, unref, make, kill)
Definition: RefCntTest.cpp:85
#define SkDEBUGFAIL(message)
Definition: SkAssert.h:118
#define SkASSERT(cond)
Definition: SkAssert.h:116
#define DEBUG_COIN_DECLARE_PARAMS()
#define SkDEBUGPARAMS(...)
const double FLT_EPSILON_CUBED
bool RoughlyEqualUlps(float a, float b)
bool approximately_negative_orderable(double x)
bool roughly_zero_when_compared_to(double x, double y)
bool approximately_less_than_zero(double x)
const double ROUGH_EPSILON
bool approximately_greater(double x, double y)
bool approximately_equal(double x, double y)
const double FLT_EPSILON_INVERSE
bool approximately_one_or_less_double(double x)
int SkDSideBit(double x)
bool approximately_greater_or_equal_orderable(double x, double y)
const double FLT_EPSILON_SQRT
bool precisely_zero(double x)
bool approximately_lesser_orderable(double x, double y)
double SkPinT(double t)
bool AlmostPequalUlps(float a, float b)
bool approximately_lesser_or_equal_double(double x, double y)
const double FLT_EPSILON_DOUBLE
bool approximately_zero_orderable(double x)
bool approximately_one_or_less(double x)
bool approximately_zero_or_more_double(double x)
bool roughly_between(double a, double b, double c)
bool precisely_subdivide_equal(double x, double y)
bool approximately_zero(double x)
const double FLT_EPSILON_SQUARED
bool approximately_zero_squared(double x)
bool precisely_negative(double x)
bool approximately_zero_or_more(double x)
const double BUMP_EPSILON
bool approximately_greater_than_one(double x)
const double FLT_EPSILON_HALF
bool roughly_negative(double x)
const double FLT_EPSILON_ORDERABLE_ERR
bool AlmostEqualUlps_Pin(float a, float b)
bool approximately_lesser_or_equal_orderable(double x, double y)
const SkScalar INVERSE_NUMBER_RANGE
bool approximately_between_orderable(double a, double b, double c)
bool between(double a, double b, double c)
bool precisely_less_than_zero(double x)
bool approximately_negative(double x)
bool AlmostEqualUlps(float a, float b)
bool precisely_between(double a, double b, double c)
bool approximately_equal_double(double x, double y)
const double DBL_EPSILON_ERR
bool roughly_equal(double x, double y)
const double MORE_ROUGH_EPSILON
bool approximately_positive_squared(double x)
bool approximately_equal_half(double x, double y)
SkOpPhase
bool AlmostBequalUlps(float a, float b)
bool approximately_zero_sqrt(double x)
bool precisely_equal(double x, double y)
double SkDInterp(double A, double B, double t)
int SkDSign(double x)
int UlpsDistance(float a, float b)
bool approximately_zero_inverse(double x)
bool precisely_greater_than_one(double x)
const double WAY_ROUGH_EPSILON
bool NotAlmostEqualUlps_Pin(float a, float b)
bool precisely_zero_when_compared_to(double x, double y)
bool approximately_zero_when_compared_to(double x, double y)
bool approximately_positive(double x)
bool approximately_greater_or_equal_double(double x, double y)
bool approximately_equal_orderable(double x, double y)
bool NotAlmostDequalUlps(float a, float b)
bool NotAlmostEqualUlps(float a, float b)
bool AlmostDequalUlps(float a, float b)
bool AlmostLessOrEqualUlps(float a, float b)
bool AlmostBetweenUlps(float a, float b, float c)
bool AlmostEqualUlpsNoNormalCheck(float a, float b)
bool approximately_lesser(double x, double y)
bool approximately_zero_half(double x)
bool approximately_equal_squared(double x, double y)
SkPathOpsMask
@ kNo_PathOpsMask
@ kWinding_PathOpsMask
@ kEvenOdd_PathOpsMask
bool approximately_lesser_or_equal(double x, double y)
bool approximately_greater_double(double x, double y)
bool precisely_subdivide_zero(double x)
bool AlmostLessUlps(float a, float b)
bool approximately_greater_orderable(double x, double y)
bool zero_or_one(double x)
SkPath::Verb SkPathOpsPointsToVerb(int points)
bool approximately_lesser_double(double x, double y)
bool approximately_zero_double(double x)
bool more_roughly_equal(double x, double y)
const double DBL_EPSILON_SUBDIVIDE_ERR
int SKDSide(double x)
bool approximately_between(double a, double b, double c)
bool roughly_zero(double x)
int SkPathOpsVerbToPoints(SkPath::Verb verb)
bool approximately_greater_or_equal(double x, double y)
#define SkDoubleToScalar(x)
Definition: SkScalar.h:64
const SkOpAngle * debugAngle(int id) const
SkOpContour * debugContour(int id) const
const SkOpCoincidence * debugCoincidence() const
bool allocatedOpSpan() const
void setPhase(SkOpPhase phase)
SkArenaAlloc * allocator()
bool windingFailed() const
SkOpContourHead * contourHead()
SkOpCoincidence * coincidence()
void setContourHead(SkOpContourHead *contourHead)
void resetAllocatedOpSpan()
SkOpGlobalState(SkOpContourHead *head, SkArenaAlloc *allocator SkDEBUGPARAMS(bool debugSkipAssert) SkDEBUGPARAMS(const char *testName))
void setCoincidence(SkOpCoincidence *coincidence)
SkOpPhase phase() const
static bool DebugRunFail()
void setAllocatedOpSpan()
int nested() const
const SkOpPtT * debugPtT(int id) const
const SkOpSegment * debugSegment(int id) const
const SkOpSpanBase * debugSpan(int id) const
double t() const
Definition: SkOpSpan.h:375
@ kMove_Verb
Definition: SkPath.h:1466
@ kConic_Verb
Definition: SkPath.h:1469
@ kCubic_Verb
Definition: SkPath.h:1470
@ kQuad_Verb
Definition: SkPath.h:1468
@ kLine_Verb
Definition: SkPath.h:1467
float SkScalar
Definition: extension.cpp:12
static bool b
struct MyStruct a[10]
double y
double x