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