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