2 * Copyright 2012 Google Inc.
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
7 #ifndef SkPathOpsTypes_DEFINED
8 #define SkPathOpsTypes_DEFINED
10 #include <float.h> // for FLT_EPSILON
11 #include <math.h> // for fabs, sqrt
13 #include "SkFloatingPoint.h"
15 #include "SkPathOps.h"
16 #include "SkPathOpsDebug.h"
20 kWinding_PathOpsMask = -1,
22 kEvenOdd_PathOpsMask = 1
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));
31 // Use Almost Dequal when comparing should not special case denormalized values.
32 bool AlmostDequalUlps(float a, float b);
33 inline bool AlmostDequalUlps(double a, double b) {
34 return AlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
37 bool NotAlmostEqualUlps(float a, float b);
38 inline bool NotAlmostEqualUlps(double a, double b) {
39 return NotAlmostEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
42 bool NotAlmostDequalUlps(float a, float b);
43 inline bool NotAlmostDequalUlps(double a, double b) {
44 return NotAlmostDequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
47 // Use Almost Bequal when comparing coordinates in conjunction with between.
48 bool AlmostBequalUlps(float a, float b);
49 inline bool AlmostBequalUlps(double a, double b) {
50 return AlmostBequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
53 bool AlmostPequalUlps(float a, float b);
54 inline bool AlmostPequalUlps(double a, double b) {
55 return AlmostPequalUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
58 bool RoughlyEqualUlps(float a, float b);
59 inline bool RoughlyEqualUlps(double a, double b) {
60 return RoughlyEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
63 bool AlmostLessUlps(float a, float b);
64 inline bool AlmostLessUlps(double a, double b) {
65 return AlmostLessUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
68 bool AlmostLessOrEqualUlps(float a, float b);
69 inline bool AlmostLessOrEqualUlps(double a, double b) {
70 return AlmostLessOrEqualUlps(SkDoubleToScalar(a), SkDoubleToScalar(b));
73 bool AlmostBetweenUlps(float a, float b, float c);
74 inline bool AlmostBetweenUlps(double a, double b, double c) {
75 return AlmostBetweenUlps(SkDoubleToScalar(a), SkDoubleToScalar(b), SkDoubleToScalar(c));
78 int UlpsDistance(float a, float b);
79 inline int UlpsDistance(double a, double b) {
80 return UlpsDistance(SkDoubleToScalar(a), SkDoubleToScalar(b));
83 // FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23)
84 // DBL_EPSILON == 2.22045e-16
85 const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
86 const double FLT_EPSILON_HALF = FLT_EPSILON / 2;
87 const double FLT_EPSILON_DOUBLE = FLT_EPSILON * 2;
88 const double FLT_EPSILON_ORDERABLE_ERR = FLT_EPSILON * 16;
89 const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
90 const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON);
91 const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
92 const double DBL_EPSILON_ERR = DBL_EPSILON * 4; // FIXME: tune -- allow a few bits of error
93 const double DBL_EPSILON_SUBDIVIDE_ERR = DBL_EPSILON * 16;
94 const double ROUGH_EPSILON = FLT_EPSILON * 64;
95 const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256;
97 inline bool approximately_zero(double x) {
98 return fabs(x) < FLT_EPSILON;
101 inline bool precisely_zero(double x) {
102 return fabs(x) < DBL_EPSILON_ERR;
105 inline bool precisely_subdivide_zero(double x) {
106 return fabs(x) < DBL_EPSILON_SUBDIVIDE_ERR;
109 inline bool approximately_zero(float x) {
110 return fabs(x) < FLT_EPSILON;
113 inline bool approximately_zero_cubed(double x) {
114 return fabs(x) < FLT_EPSILON_CUBED;
117 inline bool approximately_zero_half(double x) {
118 return fabs(x) < FLT_EPSILON_HALF;
121 inline bool approximately_zero_double(double x) {
122 return fabs(x) < FLT_EPSILON_DOUBLE;
125 inline bool approximately_zero_orderable(double x) {
126 return fabs(x) < FLT_EPSILON_ORDERABLE_ERR;
129 inline bool approximately_zero_squared(double x) {
130 return fabs(x) < FLT_EPSILON_SQUARED;
133 inline bool approximately_zero_sqrt(double x) {
134 return fabs(x) < FLT_EPSILON_SQRT;
137 inline bool roughly_zero(double x) {
138 return fabs(x) < ROUGH_EPSILON;
141 inline bool approximately_zero_inverse(double x) {
142 return fabs(x) > FLT_EPSILON_INVERSE;
145 // OPTIMIZATION: if called multiple times with the same denom, we want to pass 1/y instead
146 inline bool approximately_zero_when_compared_to(double x, double y) {
147 return x == 0 || fabs(x) < fabs(y * FLT_EPSILON);
150 // Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
151 // AlmostEqualUlps instead.
152 inline bool approximately_equal(double x, double y) {
153 return approximately_zero(x - y);
156 inline bool precisely_equal(double x, double y) {
157 return precisely_zero(x - y);
160 inline bool precisely_subdivide_equal(double x, double y) {
161 return precisely_subdivide_zero(x - y);
164 inline bool approximately_equal_half(double x, double y) {
165 return approximately_zero_half(x - y);
168 inline bool approximately_equal_double(double x, double y) {
169 return approximately_zero_double(x - y);
172 inline bool approximately_equal_orderable(double x, double y) {
173 return approximately_zero_orderable(x - y);
176 inline bool approximately_equal_squared(double x, double y) {
177 return approximately_equal(x, y);
180 inline bool approximately_greater(double x, double y) {
181 return x - FLT_EPSILON >= y;
184 inline bool approximately_greater_double(double x, double y) {
185 return x - FLT_EPSILON_DOUBLE >= y;
188 inline bool approximately_greater_orderable(double x, double y) {
189 return x - FLT_EPSILON_ORDERABLE_ERR >= y;
192 inline bool approximately_greater_or_equal(double x, double y) {
193 return x + FLT_EPSILON > y;
196 inline bool approximately_greater_or_equal_double(double x, double y) {
197 return x + FLT_EPSILON_DOUBLE > y;
200 inline bool approximately_greater_or_equal_orderable(double x, double y) {
201 return x + FLT_EPSILON_ORDERABLE_ERR > y;
204 inline bool approximately_lesser(double x, double y) {
205 return x + FLT_EPSILON <= y;
208 inline bool approximately_lesser_double(double x, double y) {
209 return x + FLT_EPSILON_DOUBLE <= y;
212 inline bool approximately_lesser_orderable(double x, double y) {
213 return x + FLT_EPSILON_ORDERABLE_ERR <= y;
216 inline bool approximately_lesser_or_equal(double x, double y) {
217 return x - FLT_EPSILON < y;
220 inline bool approximately_lesser_or_equal_double(double x, double y) {
221 return x - FLT_EPSILON_DOUBLE < y;
224 inline bool approximately_lesser_or_equal_orderable(double x, double y) {
225 return x - FLT_EPSILON_ORDERABLE_ERR < y;
228 inline bool approximately_greater_than_one(double x) {
229 return x > 1 - FLT_EPSILON;
232 inline bool precisely_greater_than_one(double x) {
233 return x > 1 - DBL_EPSILON_ERR;
236 inline bool approximately_less_than_zero(double x) {
237 return x < FLT_EPSILON;
240 inline bool precisely_less_than_zero(double x) {
241 return x < DBL_EPSILON_ERR;
244 inline bool approximately_negative(double x) {
245 return x < FLT_EPSILON;
248 inline bool approximately_negative_orderable(double x) {
249 return x < FLT_EPSILON_ORDERABLE_ERR;
252 inline bool precisely_negative(double x) {
253 return x < DBL_EPSILON_ERR;
256 inline bool approximately_one_or_less(double x) {
257 return x < 1 + FLT_EPSILON;
260 inline bool approximately_one_or_less_double(double x) {
261 return x < 1 + FLT_EPSILON_DOUBLE;
264 inline bool approximately_positive(double x) {
265 return x > -FLT_EPSILON;
268 inline bool approximately_positive_squared(double x) {
269 return x > -(FLT_EPSILON_SQUARED);
272 inline bool approximately_zero_or_more(double x) {
273 return x > -FLT_EPSILON;
276 inline bool approximately_zero_or_more_double(double x) {
277 return x > -FLT_EPSILON_DOUBLE;
280 inline bool approximately_between_orderable(double a, double b, double c) {
282 ? approximately_negative_orderable(a - b) && approximately_negative_orderable(b - c)
283 : approximately_negative_orderable(b - a) && approximately_negative_orderable(c - b);
286 inline bool approximately_between(double a, double b, double c) {
287 return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
288 : approximately_negative(b - a) && approximately_negative(c - b);
291 inline bool precisely_between(double a, double b, double c) {
292 return a <= c ? precisely_negative(a - b) && precisely_negative(b - c)
293 : precisely_negative(b - a) && precisely_negative(c - b);
296 // returns true if (a <= b <= c) || (a >= b >= c)
297 inline bool between(double a, double b, double c) {
298 SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
299 return (a - b) * (c - b) <= 0;
302 inline bool more_roughly_equal(double x, double y) {
303 return fabs(x - y) < MORE_ROUGH_EPSILON;
306 inline bool roughly_equal(double x, double y) {
307 return fabs(x - y) < ROUGH_EPSILON;
318 inline SkPath::Verb SkPathOpsPointsToVerb(int points) {
319 int verb = (1 << points) >> 1;
322 case 0: SkASSERT(SkPath::kMove_Verb == verb); break;
323 case 1: SkASSERT(SkPath::kLine_Verb == verb); break;
324 case 2: SkASSERT(SkPath::kQuad_Verb == verb); break;
325 case 3: SkASSERT(SkPath::kCubic_Verb == verb); break;
326 default: SkDEBUGFAIL("should not be here");
329 return (SkPath::Verb)verb;
332 inline int SkPathOpsVerbToPoints(SkPath::Verb verb) {
333 int points = (int) verb - ((int) verb >> 2);
336 case SkPath::kLine_Verb: SkASSERT(1 == points); break;
337 case SkPath::kQuad_Verb: SkASSERT(2 == points); break;
338 case SkPath::kCubic_Verb: SkASSERT(3 == points); break;
339 default: SkDEBUGFAIL("should not get here");
345 inline double SkDInterp(double A, double B, double t) {
346 return A + (B - A) * t;
349 double SkDCubeRoot(double x);
351 /* Returns -1 if negative, 0 if zero, 1 if positive
353 inline int SkDSign(double x) {
354 return (x > 0) - (x < 0);
357 /* Returns 0 if negative, 1 if zero, 2 if positive
359 inline int SKDSide(double x) {
360 return (x > 0) + (x >= 0);
363 /* Returns 1 if negative, 2 if zero, 4 if positive
365 inline int SkDSideBit(double x) {
366 return 1 << SKDSide(x);
369 inline double SkPinT(double t) {
370 return precisely_less_than_zero(t) ? 0 : precisely_greater_than_one(t) ? 1 : t;