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