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 #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 
     46     bool angleCoincidence() const {
     47         return fAngleCoincidence;
     48     }
     49 
     50     void bumpNested() {
     51         ++fNested;
     52     }
     53 
     54     void clearNested() {
     55         fNested = 0;
     56     }
     57 
     58     SkOpCoincidence* coincidence() {
     59         return fCoincidence;
     60     }
     61 
     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;
     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 
     84     int nested() const {
     85         return fNested;
     86     }
     87 
     88 #ifdef SK_DEBUG
     89     int nextAngleID() {
     90         return ++fAngleID;
     91     }
     92 
     93     int nextCoinID() {
     94         return ++fCoinID;
     95     }
     96 
     97     int nextContourID() {
     98         return ++fContourID;
     99     }
    100 
    101     int nextPtTID() {
    102         return ++fPtTID;
    103     }
    104 
    105     int nextSegmentID() {
    106         return ++fSegmentID;
    107     }
    108 
    109     int nextSpanID() {
    110         return ++fSpanID;
    111     }
    112 #endif
    113 
    114     Phase phase() const {
    115         return fPhase;
    116     }
    117 
    118     void setAngleCoincidence() {
    119         fAngleCoincidence = true;
    120     }
    121 
    122     void setContourHead(SkOpContourHead* contourHead) {
    123         fContourHead = contourHead;
    124     }
    125 
    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
    132     void setWindingFailed() {
    133         fWindingFailed = true;
    134     }
    135 
    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);
    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);
    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);
    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);
    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);
    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);
    196 inline bool AlmostBequalUlps(double a, double b) {
    197     return AlmostBequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
    198 }
    199 
    200 bool AlmostPequalUlps(float a, float 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);
    206 inline bool RoughlyEqualUlps(double a, double b) {
    207     return RoughlyEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
    208 }
    209 
    210 bool AlmostLessUlps(float a, float 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);
    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);
    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);
    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 
    246 inline bool zero_or_one(double x) {
    247     return x == 0 || x == 1;
    248 }
    249 
    250 inline bool approximately_zero(double x) {
    251     return fabs(x) < FLT_EPSILON;
    252 }
    253 
    254 inline bool precisely_zero(double x) {
    255     return fabs(x) < DBL_EPSILON_ERR;
    256 }
    257 
    258 inline bool precisely_subdivide_zero(double x) {
    259     return fabs(x) < DBL_EPSILON_SUBDIVIDE_ERR;
    260 }
    261 
    262 inline bool approximately_zero(float x) {
    263     return fabs(x) < FLT_EPSILON;
    264 }
    265 
    266 inline bool approximately_zero_cubed(double x) {
    267     return fabs(x) < FLT_EPSILON_CUBED;
    268 }
    269 
    270 inline bool approximately_zero_half(double x) {
    271     return fabs(x) < FLT_EPSILON_HALF;
    272 }
    273 
    274 inline bool approximately_zero_double(double x) {
    275     return fabs(x) < FLT_EPSILON_DOUBLE;
    276 }
    277 
    278 inline bool approximately_zero_orderable(double x) {
    279     return fabs(x) < FLT_EPSILON_ORDERABLE_ERR;
    280 }
    281 
    282 inline bool approximately_zero_squared(double x) {
    283     return fabs(x) < FLT_EPSILON_SQUARED;
    284 }
    285 
    286 inline bool approximately_zero_sqrt(double x) {
    287     return fabs(x) < FLT_EPSILON_SQRT;
    288 }
    289 
    290 inline bool roughly_zero(double x) {
    291     return fabs(x) < ROUGH_EPSILON;
    292 }
    293 
    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
    299 inline bool approximately_zero_when_compared_to(double x, double y) {
    300     return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
    301 }
    302 
    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.
    309 inline bool approximately_equal(double x, double y) {
    310     return approximately_zero(x - y);
    311 }
    312 
    313 inline bool precisely_equal(double x, double y) {
    314     return precisely_zero(x - y);
    315 }
    316 
    317 inline bool precisely_subdivide_equal(double x, double y) {
    318     return precisely_subdivide_zero(x - y);
    319 }
    320 
    321 inline bool approximately_equal_half(double x, double y) {
    322     return approximately_zero_half(x - y);
    323 }
    324 
    325 inline bool approximately_equal_double(double x, double y) {
    326     return approximately_zero_double(x - y);
    327 }
    328 
    329 inline bool approximately_equal_orderable(double x, double y) {
    330     return approximately_zero_orderable(x - y);
    331 }
    332 
    333 inline bool approximately_equal_squared(double x, double y) {
    334     return approximately_equal(x, y);
    335 }
    336 
    337 inline bool approximately_greater(double x, double y) {
    338     return x - FLT_EPSILON >= y;
    339 }
    340 
    341 inline bool approximately_greater_double(double x, double y) {
    342     return x - FLT_EPSILON_DOUBLE >= y;
    343 }
    344 
    345 inline bool approximately_greater_orderable(double x, double y) {
    346     return x - FLT_EPSILON_ORDERABLE_ERR >= y;
    347 }
    348 
    349 inline bool approximately_greater_or_equal(double x, double y) {
    350     return x + FLT_EPSILON > y;
    351 }
    352 
    353 inline bool approximately_greater_or_equal_double(double x, double y) {
    354     return x + FLT_EPSILON_DOUBLE > y;
    355 }
    356 
    357 inline bool approximately_greater_or_equal_orderable(double x, double y) {
    358     return x + FLT_EPSILON_ORDERABLE_ERR > y;
    359 }
    360 
    361 inline bool approximately_lesser(double x, double y) {
    362     return x + FLT_EPSILON <= y;
    363 }
    364 
    365 inline bool approximately_lesser_double(double x, double y) {
    366     return x + FLT_EPSILON_DOUBLE <= y;
    367 }
    368 
    369 inline bool approximately_lesser_orderable(double x, double y) {
    370     return x + FLT_EPSILON_ORDERABLE_ERR <= y;
    371 }
    372 
    373 inline bool approximately_lesser_or_equal(double x, double y) {
    374     return x - FLT_EPSILON < y;
    375 }
    376 
    377 inline bool approximately_lesser_or_equal_double(double x, double y) {
    378     return x - FLT_EPSILON_DOUBLE < y;
    379 }
    380 
    381 inline bool approximately_lesser_or_equal_orderable(double x, double y) {
    382     return x - FLT_EPSILON_ORDERABLE_ERR < y;
    383 }
    384 
    385 inline bool approximately_greater_than_one(double x) {
    386     return x > 1 - FLT_EPSILON;
    387 }
    388 
    389 inline bool precisely_greater_than_one(double x) {
    390     return x > 1 - DBL_EPSILON_ERR;
    391 }
    392 
    393 inline bool approximately_less_than_zero(double x) {
    394     return x < FLT_EPSILON;
    395 }
    396 
    397 inline bool precisely_less_than_zero(double x) {
    398     return x < DBL_EPSILON_ERR;
    399 }
    400 
    401 inline bool approximately_negative(double x) {
    402     return x < FLT_EPSILON;
    403 }
    404 
    405 inline bool approximately_negative_orderable(double x) {
    406     return x < FLT_EPSILON_ORDERABLE_ERR;
    407 }
    408 
    409 inline bool precisely_negative(double x) {
    410     return x < DBL_EPSILON_ERR;
    411 }
    412 
    413 inline bool approximately_one_or_less(double x) {
    414     return x < 1 + FLT_EPSILON;
    415 }
    416 
    417 inline bool approximately_one_or_less_double(double x) {
    418     return x < 1 + FLT_EPSILON_DOUBLE;
    419 }
    420 
    421 inline bool approximately_positive(double x) {
    422     return x > -FLT_EPSILON;
    423 }
    424 
    425 inline bool approximately_positive_squared(double x) {
    426     return x > -(FLT_EPSILON_SQUARED);
    427 }
    428 
    429 inline bool approximately_zero_or_more(double x) {
    430     return x > -FLT_EPSILON;
    431 }
    432 
    433 inline bool approximately_zero_or_more_double(double x) {
    434     return x > -FLT_EPSILON_DOUBLE;
    435 }
    436 
    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 
    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 
    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)
    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 
    460 inline bool roughly_equal(double x, double y) {
    461     return fabs(x - y) < ROUGH_EPSILON;
    462 }
    463 
    464 inline bool roughly_negative(double x) {
    465     return x < ROUGH_EPSILON;
    466 }
    467 
    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 
    473 inline bool more_roughly_equal(double x, double y) {
    474     return fabs(x - y) < MORE_ROUGH_EPSILON;
    475 }
    476 
    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 
    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 
    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 
    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 */
    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 */
    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 */
    537 inline int SkDSideBit(double x) {
    538     return 1 << SKDSide(x);
    539 }
    540 
    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