| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2012 Google Inc. | 2 * Copyright 2012 Google Inc. |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 #ifndef SkPathOpsTypes_DEFINED | 7 #ifndef SkPathOpsTypes_DEFINED |
| 8 #define SkPathOpsTypes_DEFINED | 8 #define SkPathOpsTypes_DEFINED |
| 9 | 9 |
| 10 #define SK_CONIC_SUPPORT_ENABLED 1 | |
| 11 | |
| 12 #include <float.h> // for FLT_EPSILON | 10 #include <float.h> // for FLT_EPSILON |
| 13 #include <math.h> // for fabs, sqrt | 11 #include <math.h> // for fabs, sqrt |
| 14 | 12 |
| 15 #include "SkFloatingPoint.h" | 13 #include "SkFloatingPoint.h" |
| 16 #include "SkPath.h" | 14 #include "SkPath.h" |
| 17 #include "SkPathOps.h" | 15 #include "SkPathOps.h" |
| 18 #include "SkPathOpsDebug.h" | 16 #include "SkPathOpsDebug.h" |
| 19 #include "SkScalar.h" | 17 #include "SkScalar.h" |
| 20 | 18 |
| 21 enum SkPathOpsMask { | 19 enum SkPathOpsMask { |
| 22 kWinding_PathOpsMask = -1, | 20 kWinding_PathOpsMask = -1, |
| 23 kNo_PathOpsMask = 0, | 21 kNo_PathOpsMask = 0, |
| 24 kEvenOdd_PathOpsMask = 1 | 22 kEvenOdd_PathOpsMask = 1 |
| 25 }; | 23 }; |
| 26 | 24 |
| 27 // Use Almost Equal when comparing coordinates. Use epsilon to compare T values. | 25 // Use Almost Equal when comparing coordinates. Use epsilon to compare T values. |
| 28 extern bool AlmostEqualUlps(float A, float B); | 26 bool AlmostEqualUlps(float A, float B); |
| 29 inline bool AlmostEqualUlps(double A, double B) { | 27 inline bool AlmostEqualUlps(double A, double B) { |
| 30 return AlmostEqualUlps(SkDoubleToScalar(A), SkDoubleToScalar(B)); | 28 return AlmostEqualUlps(SkDoubleToScalar(A), SkDoubleToScalar(B)); |
| 31 } | 29 } |
| 32 | 30 |
| 33 // FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23) | 31 // FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23) |
| 34 // DBL_EPSILON == 2.22045e-16 | 32 // DBL_EPSILON == 2.22045e-16 |
| 35 const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON; | 33 const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON; |
| 36 const double FLT_EPSILON_HALF = FLT_EPSILON / 2; | 34 const double FLT_EPSILON_HALF = FLT_EPSILON / 2; |
| 35 const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2; |
| 37 const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON; | 36 const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON; |
| 38 const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON); | 37 const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON); |
| 39 const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON; | 38 const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON; |
| 40 const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // FIXME: tune -- allow a few b
its of error | 39 const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // FIXME: tune -- allow a few b
its of error |
| 40 const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16; |
| 41 const double ROUGH_EPSILON = FLT_EPSILON * 64; | 41 const double ROUGH_EPSILON = FLT_EPSILON * 64; |
| 42 const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256; | 42 const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256; |
| 43 | 43 |
| 44 inline bool approximately_zero(double x) { | 44 inline bool approximately_zero(double x) { |
| 45 return fabs(x) < FLT_EPSILON; | 45 return fabs(x) < FLT_EPSILON; |
| 46 } | 46 } |
| 47 | 47 |
| 48 inline bool precisely_zero(double x) { | 48 inline bool precisely_zero(double x) { |
| 49 return fabs(x) < DBL_EPSILON_ERR; | 49 return fabs(x) < DBL_EPSILON_ERR; |
| 50 } | 50 } |
| 51 | 51 |
| 52 inline bool precisely_subdivide_zero(double x) { |
| 53 return fabs(x) < DBL_EPSILON_SUBDIVIDE_ERR; |
| 54 } |
| 55 |
| 52 inline bool approximately_zero(float x) { | 56 inline bool approximately_zero(float x) { |
| 53 return fabs(x) < FLT_EPSILON; | 57 return fabs(x) < FLT_EPSILON; |
| 54 } | 58 } |
| 55 | 59 |
| 56 inline bool approximately_zero_cubed(double x) { | 60 inline bool approximately_zero_cubed(double x) { |
| 57 return fabs(x) < FLT_EPSILON_CUBED; | 61 return fabs(x) < FLT_EPSILON_CUBED; |
| 58 } | 62 } |
| 59 | 63 |
| 60 inline bool approximately_zero_half(double x) { | 64 inline bool approximately_zero_half(double x) { |
| 61 return fabs(x) < FLT_EPSILON_HALF; | 65 return fabs(x) < FLT_EPSILON_HALF; |
| 62 } | 66 } |
| 63 | 67 |
| 68 inline bool approximately_zero_double(double x) { |
| 69 return fabs(x) < FLT_EPSILON_DOUBLE; |
| 70 } |
| 71 |
| 64 inline bool approximately_zero_squared(double x) { | 72 inline bool approximately_zero_squared(double x) { |
| 65 return fabs(x) < FLT_EPSILON_SQUARED; | 73 return fabs(x) < FLT_EPSILON_SQUARED; |
| 66 } | 74 } |
| 67 | 75 |
| 68 inline bool approximately_zero_sqrt(double x) { | 76 inline bool approximately_zero_sqrt(double x) { |
| 69 return fabs(x) < FLT_EPSILON_SQRT; | 77 return fabs(x) < FLT_EPSILON_SQRT; |
| 70 } | 78 } |
| 71 | 79 |
| 80 inline bool roughly_zero(double x) { |
| 81 return fabs(x) < ROUGH_EPSILON; |
| 82 } |
| 83 |
| 72 inline bool approximately_zero_inverse(double x) { | 84 inline bool approximately_zero_inverse(double x) { |
| 73 return fabs(x) > FLT_EPSILON_INVERSE; | 85 return fabs(x) > FLT_EPSILON_INVERSE; |
| 74 } | 86 } |
| 75 | 87 |
| 76 // OPTIMIZATION: if called multiple times with the same denom, we want to pass 1
/y instead | 88 // OPTIMIZATION: if called multiple times with the same denom, we want to pass 1
/y instead |
| 77 inline bool approximately_zero_when_compared_to(double x, double y) { | 89 inline bool approximately_zero_when_compared_to(double x, double y) { |
| 78 return x == 0 || fabs(x / y) < FLT_EPSILON; | 90 return x == 0 || fabs(x / y) < FLT_EPSILON; |
| 79 } | 91 } |
| 80 | 92 |
| 81 // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger
and smaller) use | 93 // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger
and smaller) use |
| 82 // AlmostEqualUlps instead. | 94 // AlmostEqualUlps instead. |
| 83 inline bool approximately_equal(double x, double y) { | 95 inline bool approximately_equal(double x, double y) { |
| 84 return approximately_zero(x - y); | 96 return approximately_zero(x - y); |
| 85 } | 97 } |
| 86 | 98 |
| 87 inline bool precisely_equal(double x, double y) { | 99 inline bool precisely_equal(double x, double y) { |
| 88 return precisely_zero(x - y); | 100 return precisely_zero(x - y); |
| 89 } | 101 } |
| 90 | 102 |
| 103 inline bool precisely_subdivide_equal(double x, double y) { |
| 104 return precisely_subdivide_zero(x - y); |
| 105 } |
| 106 |
| 91 inline bool approximately_equal_half(double x, double y) { | 107 inline bool approximately_equal_half(double x, double y) { |
| 92 return approximately_zero_half(x - y); | 108 return approximately_zero_half(x - y); |
| 93 } | 109 } |
| 94 | 110 |
| 111 inline bool approximately_equal_double(double x, double y) { |
| 112 return approximately_zero_double(x - y); |
| 113 } |
| 114 |
| 95 inline bool approximately_equal_squared(double x, double y) { | 115 inline bool approximately_equal_squared(double x, double y) { |
| 96 return approximately_equal(x, y); | 116 return approximately_equal(x, y); |
| 97 } | 117 } |
| 98 | 118 |
| 99 inline bool approximately_greater(double x, double y) { | 119 inline bool approximately_greater(double x, double y) { |
| 100 return x - FLT_EPSILON >= y; | 120 return x - FLT_EPSILON >= y; |
| 101 } | 121 } |
| 102 | 122 |
| 103 inline bool approximately_greater_or_equal(double x, double y) { | 123 inline bool approximately_greater_or_equal(double x, double y) { |
| 104 return x + FLT_EPSILON > y; | 124 return x + FLT_EPSILON > y; |
| 105 } | 125 } |
| 106 | 126 |
| 107 inline bool approximately_lesser(double x, double y) { | 127 inline bool approximately_lesser(double x, double y) { |
| 108 return x + FLT_EPSILON <= y; | 128 return x + FLT_EPSILON <= y; |
| 109 } | 129 } |
| 110 | 130 |
| 111 inline bool approximately_lesser_or_equal(double x, double y) { | 131 inline bool approximately_lesser_or_equal(double x, double y) { |
| 112 return x - FLT_EPSILON < y; | 132 return x - FLT_EPSILON < y; |
| 113 } | 133 } |
| 114 | 134 |
| 115 inline double approximately_pin(double x) { | |
| 116 return approximately_zero(x) ? 0 : x; | |
| 117 } | |
| 118 | |
| 119 inline float approximately_pin(float x) { | |
| 120 return approximately_zero(x) ? 0 : x; | |
| 121 } | |
| 122 | |
| 123 inline bool approximately_greater_than_one(double x) { | 135 inline bool approximately_greater_than_one(double x) { |
| 124 return x > 1 - FLT_EPSILON; | 136 return x > 1 - FLT_EPSILON; |
| 125 } | 137 } |
| 126 | 138 |
| 127 inline bool precisely_greater_than_one(double x) { | 139 inline bool precisely_greater_than_one(double x) { |
| 128 return x > 1 - DBL_EPSILON_ERR; | 140 return x > 1 - DBL_EPSILON_ERR; |
| 129 } | 141 } |
| 130 | 142 |
| 131 inline bool approximately_less_than_zero(double x) { | 143 inline bool approximately_less_than_zero(double x) { |
| 132 return x < FLT_EPSILON; | 144 return x < FLT_EPSILON; |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 185 } | 197 } |
| 186 | 198 |
| 187 struct SkDPoint; | 199 struct SkDPoint; |
| 188 struct SkDVector; | 200 struct SkDVector; |
| 189 struct SkDLine; | 201 struct SkDLine; |
| 190 struct SkDQuad; | 202 struct SkDQuad; |
| 191 struct SkDTriangle; | 203 struct SkDTriangle; |
| 192 struct SkDCubic; | 204 struct SkDCubic; |
| 193 struct SkDRect; | 205 struct SkDRect; |
| 194 | 206 |
| 195 #if SK_CONIC_SUPPORT_ENABLED | |
| 196 | |
| 197 inline SkPath::Verb SkPathOpsPointsToVerb(int points) { | 207 inline SkPath::Verb SkPathOpsPointsToVerb(int points) { |
| 198 int verb = (1 << points) >> 1; | 208 int verb = (1 << points) >> 1; |
| 199 #ifdef SK_DEBUG | 209 #ifdef SK_DEBUG |
| 200 switch (points) { | 210 switch (points) { |
| 201 case 0: SkASSERT(SkPath::kMove_Verb == verb); break; | 211 case 0: SkASSERT(SkPath::kMove_Verb == verb); break; |
| 202 case 1: SkASSERT(SkPath::kLine_Verb == verb); break; | 212 case 1: SkASSERT(SkPath::kLine_Verb == verb); break; |
| 203 case 2: SkASSERT(SkPath::kQuad_Verb == verb); break; | 213 case 2: SkASSERT(SkPath::kQuad_Verb == verb); break; |
| 204 case 3: SkASSERT(SkPath::kCubic_Verb == verb); break; | 214 case 3: SkASSERT(SkPath::kCubic_Verb == verb); break; |
| 205 default: SkASSERT(!"should not be here"); | 215 default: SkASSERT(!"should not be here"); |
| 206 } | 216 } |
| 207 #endif | 217 #endif |
| 208 return (SkPath::Verb)verb; | 218 return (SkPath::Verb)verb; |
| 209 } | 219 } |
| 210 | 220 |
| 211 inline int SkPathOpsVerbToPoints(SkPath::Verb verb) { | 221 inline int SkPathOpsVerbToPoints(SkPath::Verb verb) { |
| 212 int points = (int) verb - ((int) verb >> 2); | 222 int points = (int) verb - ((int) verb >> 2); |
| 213 #ifdef SK_DEBUG | 223 #ifdef SK_DEBUG |
| 214 switch (verb) { | 224 switch (verb) { |
| 215 case SkPath::kLine_Verb: SkASSERT(1 == points); break; | 225 case SkPath::kLine_Verb: SkASSERT(1 == points); break; |
| 216 case SkPath::kQuad_Verb: SkASSERT(2 == points); break; | 226 case SkPath::kQuad_Verb: SkASSERT(2 == points); break; |
| 217 case SkPath::kCubic_Verb: SkASSERT(3 == points); break; | 227 case SkPath::kCubic_Verb: SkASSERT(3 == points); break; |
| 218 default: SkASSERT(!"should not get here"); | 228 default: SkASSERT(!"should not get here"); |
| 219 } | 229 } |
| 220 #endif | 230 #endif |
| 221 return points; | 231 return points; |
| 222 } | 232 } |
| 223 | 233 |
| 224 #else | |
| 225 | |
| 226 inline SkPath::Verb SkOpPointsToVerb(int points) { | |
| 227 return (SkPath::Verb) (points); | |
| 228 } | |
| 229 | |
| 230 inline SkPath::Verb SkOpVerbToPoints(SkPath::Verb verb) { | |
| 231 return (int) verb ; | |
| 232 } | |
| 233 | |
| 234 #endif | |
| 235 | |
| 236 inline double SkDInterp(double A, double B, double t) { | 234 inline double SkDInterp(double A, double B, double t) { |
| 237 return A + (B - A) * t; | 235 return A + (B - A) * t; |
| 238 } | 236 } |
| 239 | 237 |
| 240 double SkDCubeRoot(double x); | 238 double SkDCubeRoot(double x); |
| 241 | 239 |
| 242 /* Returns -1 if negative, 0 if zero, 1 if positive | 240 /* Returns -1 if negative, 0 if zero, 1 if positive |
| 243 */ | 241 */ |
| 244 inline int SkDSign(double x) { | 242 inline int SkDSign(double x) { |
| 245 return (x > 0) - (x < 0); | 243 return (x > 0) - (x < 0); |
| 246 } | 244 } |
| 247 | 245 |
| 248 /* Returns 0 if negative, 1 if zero, 2 if positive | 246 /* Returns 0 if negative, 1 if zero, 2 if positive |
| 249 */ | 247 */ |
| 250 inline int SKDSide(double x) { | 248 inline int SKDSide(double x) { |
| 251 return (x > 0) + (x >= 0); | 249 return (x > 0) + (x >= 0); |
| 252 } | 250 } |
| 253 | 251 |
| 254 /* Returns 1 if negative, 2 if zero, 4 if positive | 252 /* Returns 1 if negative, 2 if zero, 4 if positive |
| 255 */ | 253 */ |
| 256 inline int SkDSideBit(double x) { | 254 inline int SkDSideBit(double x) { |
| 257 return 1 << SKDSide(x); | 255 return 1 << SKDSide(x); |
| 258 } | 256 } |
| 259 | 257 |
| 260 #endif | 258 #endif |
| OLD | NEW |