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 // Use Almost Equal when comparing coordinates. Use epsilon to compare T values. 26 bool AlmostEqualUlps(float a, float b); 27 inline bool AlmostEqualUlps(double a, double b) { 28 return AlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 29 } 30 31 // Use Almost Dequal when comparing should not special case denormalized values. 32 bool AlmostDequalUlps(float a, float b); 33 bool AlmostDequalUlps(double a, double b); 34 35 bool NotAlmostEqualUlps(float a, float b); 36 inline bool NotAlmostEqualUlps(double a, double b) { 37 return NotAlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 38 } 39 40 bool NotAlmostDequalUlps(float a, float b); 41 inline bool NotAlmostDequalUlps(double a, double b) { 42 return NotAlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 43 } 44 45 // Use Almost Bequal when comparing coordinates in conjunction with between. 46 bool AlmostBequalUlps(float a, float b); 47 inline bool AlmostBequalUlps(double a, double b) { 48 return AlmostBequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 49 } 50 51 bool AlmostPequalUlps(float a, float b); 52 inline bool AlmostPequalUlps(double a, double b) { 53 return AlmostPequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 54 } 55 56 bool RoughlyEqualUlps(float a, float b); 57 inline bool RoughlyEqualUlps(double a, double b) { 58 return RoughlyEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 59 } 60 61 bool AlmostLessUlps(float a, float b); 62 inline bool AlmostLessUlps(double a, double b) { 63 return AlmostLessUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 64 } 65 66 bool AlmostLessOrEqualUlps(float a, float b); 67 inline bool AlmostLessOrEqualUlps(double a, double b) { 68 return AlmostLessOrEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b)); 69 } 70 71 bool AlmostBetweenUlps(float a, float b, float c); 72 inline bool AlmostBetweenUlps(double a, double b, double c) { 73 return AlmostBetweenUlps(SkDoubleToScalar(a), SkDoubleToScalar(b), SkDoubleToScalar(c)); 74 } 75 76 int UlpsDistance(float a, float b); 77 inline int UlpsDistance(double a, double b) { 78 return UlpsDistance(SkDoubleToScalar(a), SkDoubleToScalar(b)); 79 } 80 81 // FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23) 82 // DBL_EPSILON == 2.22045e-16 83 const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON; 84 const double FLT_EPSILON_HALF = FLT_EPSILON / 2; 85 const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2; 86 const double FLT_EPSILON_ORDERABLE_ERR = FLT_EPSILON * 16; 87 const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON; 88 const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON); 89 const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON; 90 const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // FIXME: tune -- allow a few bits of error 91 const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16; 92 const double ROUGH_EPSILON = FLT_EPSILON * 64; 93 const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256; 94 const double WAY_ROUGH_EPSILON = FLT_EPSILON * 2048; 95 96 inline bool zero_or_one(double x) { 97 return x == 0 || x == 1; 98 } 99 100 inline bool approximately_zero(double x) { 101 return fabs(x) < FLT_EPSILON; 102 } 103 104 inline bool precisely_zero(double x) { 105 return fabs(x) < DBL_EPSILON_ERR; 106 } 107 108 inline bool precisely_subdivide_zero(double x) { 109 return fabs(x) < DBL_EPSILON_SUBDIVIDE_ERR; 110 } 111 112 inline bool approximately_zero(float x) { 113 return fabs(x) < FLT_EPSILON; 114 } 115 116 inline bool approximately_zero_cubed(double x) { 117 return fabs(x) < FLT_EPSILON_CUBED; 118 } 119 120 inline bool approximately_zero_half(double x) { 121 return fabs(x) < FLT_EPSILON_HALF; 122 } 123 124 inline bool approximately_zero_double(double x) { 125 return fabs(x) < FLT_EPSILON_DOUBLE; 126 } 127 128 inline bool approximately_zero_orderable(double x) { 129 return fabs(x) < FLT_EPSILON_ORDERABLE_ERR; 130 } 131 132 inline bool approximately_zero_squared(double x) { 133 return fabs(x) < FLT_EPSILON_SQUARED; 134 } 135 136 inline bool approximately_zero_sqrt(double x) { 137 return fabs(x) < FLT_EPSILON_SQRT; 138 } 139 140 inline bool roughly_zero(double x) { 141 return fabs(x) < ROUGH_EPSILON; 142 } 143 144 inline bool approximately_zero_inverse(double x) { 145 return fabs(x) > FLT_EPSILON_INVERSE; 146 } 147 148 // OPTIMIZATION: if called multiple times with the same denom, we want to pass 1/y instead 149 inline bool approximately_zero_when_compared_to(double x, double y) { 150 return x == 0 || fabs(x) < fabs(y * FLT_EPSILON); 151 } 152 153 // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use 154 // AlmostEqualUlps instead. 155 inline bool approximately_equal(double x, double y) { 156 return approximately_zero(x - y); 157 } 158 159 inline bool precisely_equal(double x, double y) { 160 return precisely_zero(x - y); 161 } 162 163 inline bool precisely_subdivide_equal(double x, double y) { 164 return precisely_subdivide_zero(x - y); 165 } 166 167 inline bool approximately_equal_half(double x, double y) { 168 return approximately_zero_half(x - y); 169 } 170 171 inline bool approximately_equal_double(double x, double y) { 172 return approximately_zero_double(x - y); 173 } 174 175 inline bool approximately_equal_orderable(double x, double y) { 176 return approximately_zero_orderable(x - y); 177 } 178 179 inline bool approximately_equal_squared(double x, double y) { 180 return approximately_equal(x, y); 181 } 182 183 inline bool approximately_greater(double x, double y) { 184 return x - FLT_EPSILON >= y; 185 } 186 187 inline bool approximately_greater_double(double x, double y) { 188 return x - FLT_EPSILON_DOUBLE >= y; 189 } 190 191 inline bool approximately_greater_orderable(double x, double y) { 192 return x - FLT_EPSILON_ORDERABLE_ERR >= y; 193 } 194 195 inline bool approximately_greater_or_equal(double x, double y) { 196 return x + FLT_EPSILON > y; 197 } 198 199 inline bool approximately_greater_or_equal_double(double x, double y) { 200 return x + FLT_EPSILON_DOUBLE > y; 201 } 202 203 inline bool approximately_greater_or_equal_orderable(double x, double y) { 204 return x + FLT_EPSILON_ORDERABLE_ERR > y; 205 } 206 207 inline bool approximately_lesser(double x, double y) { 208 return x + FLT_EPSILON <= y; 209 } 210 211 inline bool approximately_lesser_double(double x, double y) { 212 return x + FLT_EPSILON_DOUBLE <= y; 213 } 214 215 inline bool approximately_lesser_orderable(double x, double y) { 216 return x + FLT_EPSILON_ORDERABLE_ERR <= y; 217 } 218 219 inline bool approximately_lesser_or_equal(double x, double y) { 220 return x - FLT_EPSILON < y; 221 } 222 223 inline bool approximately_lesser_or_equal_double(double x, double y) { 224 return x - FLT_EPSILON_DOUBLE < y; 225 } 226 227 inline bool approximately_lesser_or_equal_orderable(double x, double y) { 228 return x - FLT_EPSILON_ORDERABLE_ERR < y; 229 } 230 231 inline bool approximately_greater_than_one(double x) { 232 return x > 1 - FLT_EPSILON; 233 } 234 235 inline bool precisely_greater_than_one(double x) { 236 return x > 1 - DBL_EPSILON_ERR; 237 } 238 239 inline bool approximately_less_than_zero(double x) { 240 return x < FLT_EPSILON; 241 } 242 243 inline bool precisely_less_than_zero(double x) { 244 return x < DBL_EPSILON_ERR; 245 } 246 247 inline bool approximately_negative(double x) { 248 return x < FLT_EPSILON; 249 } 250 251 inline bool approximately_negative_orderable(double x) { 252 return x < FLT_EPSILON_ORDERABLE_ERR; 253 } 254 255 inline bool precisely_negative(double x) { 256 return x < DBL_EPSILON_ERR; 257 } 258 259 inline bool approximately_one_or_less(double x) { 260 return x < 1 + FLT_EPSILON; 261 } 262 263 inline bool approximately_one_or_less_double(double x) { 264 return x < 1 + FLT_EPSILON_DOUBLE; 265 } 266 267 inline bool approximately_positive(double x) { 268 return x > -FLT_EPSILON; 269 } 270 271 inline bool approximately_positive_squared(double x) { 272 return x > -(FLT_EPSILON_SQUARED); 273 } 274 275 inline bool approximately_zero_or_more(double x) { 276 return x > -FLT_EPSILON; 277 } 278 279 inline bool approximately_zero_or_more_double(double x) { 280 return x > -FLT_EPSILON_DOUBLE; 281 } 282 283 inline bool approximately_between_orderable(double a, double b, double c) { 284 return a <= c 285 ? approximately_negative_orderable(a - b) && approximately_negative_orderable(b - c) 286 : approximately_negative_orderable(b - a) && approximately_negative_orderable(c - b); 287 } 288 289 inline bool approximately_between(double a, double b, double c) { 290 return a <= c ? approximately_negative(a - b) && approximately_negative(b - c) 291 : approximately_negative(b - a) && approximately_negative(c - b); 292 } 293 294 inline bool precisely_between(double a, double b, double c) { 295 return a <= c ? precisely_negative(a - b) && precisely_negative(b - c) 296 : precisely_negative(b - a) && precisely_negative(c - b); 297 } 298 299 // returns true if (a <= b <= c) || (a >= b >= c) 300 inline bool between(double a, double b, double c) { 301 SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0)); 302 return (a - b) * (c - b) <= 0; 303 } 304 305 inline bool roughly_equal(double x, double y) { 306 return fabs(x - y) < ROUGH_EPSILON; 307 } 308 309 inline bool more_roughly_equal(double x, double y) { 310 return fabs(x - y) < MORE_ROUGH_EPSILON; 311 } 312 313 inline bool way_roughly_equal(double x, double y) { 314 return fabs(x - y) < WAY_ROUGH_EPSILON; 315 } 316 317 struct SkDPoint; 318 struct SkDVector; 319 struct SkDLine; 320 struct SkDQuad; 321 struct SkDTriangle; 322 struct SkDCubic; 323 struct SkDRect; 324 325 inline SkPath::Verb SkPathOpsPointsToVerb(int points) { 326 int verb = (1 << points) >> 1; 327 #ifdef SK_DEBUG 328 switch (points) { 329 case 0: SkASSERT(SkPath::kMove_Verb == verb); break; 330 case 1: SkASSERT(SkPath::kLine_Verb == verb); break; 331 case 2: SkASSERT(SkPath::kQuad_Verb == verb); break; 332 case 3: SkASSERT(SkPath::kCubic_Verb == verb); break; 333 default: SkDEBUGFAIL("should not be here"); 334 } 335 #endif 336 return (SkPath::Verb)verb; 337 } 338 339 inline int SkPathOpsVerbToPoints(SkPath::Verb verb) { 340 int points = (int) verb - ((int) verb >> 2); 341 #ifdef SK_DEBUG 342 switch (verb) { 343 case SkPath::kLine_Verb: SkASSERT(1 == points); break; 344 case SkPath::kQuad_Verb: SkASSERT(2 == points); break; 345 case SkPath::kCubic_Verb: SkASSERT(3 == points); break; 346 default: SkDEBUGFAIL("should not get here"); 347 } 348 #endif 349 return points; 350 } 351 352 inline double SkDInterp(double A, double B, double t) { 353 return A + (B - A) * t; 354 } 355 356 double SkDCubeRoot(double x); 357 358 /* Returns -1 if negative, 0 if zero, 1 if positive 359 */ 360 inline int SkDSign(double x) { 361 return (x > 0) - (x < 0); 362 } 363 364 /* Returns 0 if negative, 1 if zero, 2 if positive 365 */ 366 inline int SKDSide(double x) { 367 return (x > 0) + (x >= 0); 368 } 369 370 /* Returns 1 if negative, 2 if zero, 4 if positive 371 */ 372 inline int SkDSideBit(double x) { 373 return 1 << SKDSide(x); 374 } 375 376 inline double SkPinT(double t) { 377 return precisely_less_than_zero(t) ? 0 : precisely_greater_than_one(t) ? 1 : t; 378 } 379 380 #endif 381