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 |