SkPathOpsTypes.h revision fa2f2a48f6822b88ab895fece1998af549c16ebe
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 "SkPathOps.h"
15#include "SkPathOpsDebug.h"
16#include "SkScalar.h"
17
18enum SkPathOpsMask {
19    kWinding_PathOpsMask = -1,
20    kNo_PathOpsMask = 0,
21    kEvenOdd_PathOpsMask = 1
22};
23
24// Use Almost Equal when comparing coordinates. Use epsilon to compare T values.
25extern bool AlmostEqualUlps(float A, float B);
26inline bool AlmostEqualUlps(double A, double B) {
27    return AlmostEqualUlps(SkDoubleToScalar(A), SkDoubleToScalar(B));
28}
29
30// FLT_EPSILON == 1.19209290E-07 == 1 / (2 ^ 23)
31// DBL_EPSILON == 2.22045e-16
32const double FLT_EPSILON_CUBED = FLT_EPSILON * FLT_EPSILON * FLT_EPSILON;
33const double FLT_EPSILON_HALF = FLT_EPSILON / 2;
34const double FLT_EPSILON_SQUARED = FLT_EPSILON * FLT_EPSILON;
35const double FLT_EPSILON_SQRT = sqrt(FLT_EPSILON);
36const double FLT_EPSILON_INVERSE = 1 / FLT_EPSILON;
37const double DBL_EPSILON_ERR = DBL_EPSILON * 4;  // FIXME: tune -- allow a few bits of error
38const double ROUGH_EPSILON = FLT_EPSILON * 64;
39const double MORE_ROUGH_EPSILON = FLT_EPSILON * 256;
40
41inline bool approximately_zero(double x) {
42    return fabs(x) < FLT_EPSILON;
43}
44
45inline bool precisely_zero(double x) {
46    return fabs(x) < DBL_EPSILON_ERR;
47}
48
49inline bool approximately_zero(float x) {
50    return fabs(x) < FLT_EPSILON;
51}
52
53inline bool approximately_zero_cubed(double x) {
54    return fabs(x) < FLT_EPSILON_CUBED;
55}
56
57inline bool approximately_zero_half(double x) {
58    return fabs(x) < FLT_EPSILON_HALF;
59}
60
61inline bool approximately_zero_squared(double x) {
62    return fabs(x) < FLT_EPSILON_SQUARED;
63}
64
65inline bool approximately_zero_sqrt(double x) {
66    return fabs(x) < FLT_EPSILON_SQRT;
67}
68
69inline bool approximately_zero_inverse(double x) {
70    return fabs(x) > FLT_EPSILON_INVERSE;
71}
72
73// OPTIMIZATION: if called multiple times with the same denom, we want to pass 1/y instead
74inline bool approximately_zero_when_compared_to(double x, double y) {
75    return x == 0 || fabs(x / y) < FLT_EPSILON;
76}
77
78// Use this for comparing Ts in the range of 0 to 1. For general numbers (larger and smaller) use
79// AlmostEqualUlps instead.
80inline bool approximately_equal(double x, double y) {
81    return approximately_zero(x - y);
82}
83
84inline bool precisely_equal(double x, double y) {
85    return precisely_zero(x - y);
86}
87
88inline bool approximately_equal_half(double x, double y) {
89    return approximately_zero_half(x - y);
90}
91
92inline bool approximately_equal_squared(double x, double y) {
93    return approximately_equal(x, y);
94}
95
96inline bool approximately_greater(double x, double y) {
97    return x - FLT_EPSILON >= y;
98}
99
100inline bool approximately_greater_or_equal(double x, double y) {
101    return x + FLT_EPSILON > y;
102}
103
104inline bool approximately_lesser(double x, double y) {
105    return x + FLT_EPSILON <= y;
106}
107
108inline bool approximately_lesser_or_equal(double x, double y) {
109    return x - FLT_EPSILON < y;
110}
111
112inline double approximately_pin(double x) {
113    return approximately_zero(x) ? 0 : x;
114}
115
116inline float approximately_pin(float x) {
117    return approximately_zero(x) ? 0 : x;
118}
119
120inline bool approximately_greater_than_one(double x) {
121    return x > 1 - FLT_EPSILON;
122}
123
124inline bool precisely_greater_than_one(double x) {
125    return x > 1 - DBL_EPSILON_ERR;
126}
127
128inline bool approximately_less_than_zero(double x) {
129    return x < FLT_EPSILON;
130}
131
132inline bool precisely_less_than_zero(double x) {
133    return x < DBL_EPSILON_ERR;
134}
135
136inline bool approximately_negative(double x) {
137    return x < FLT_EPSILON;
138}
139
140inline bool precisely_negative(double x) {
141    return x < DBL_EPSILON_ERR;
142}
143
144inline bool approximately_one_or_less(double x) {
145    return x < 1 + FLT_EPSILON;
146}
147
148inline bool approximately_positive(double x) {
149    return x > -FLT_EPSILON;
150}
151
152inline bool approximately_positive_squared(double x) {
153    return x > -(FLT_EPSILON_SQUARED);
154}
155
156inline bool approximately_zero_or_more(double x) {
157    return x > -FLT_EPSILON;
158}
159
160inline bool approximately_between(double a, double b, double c) {
161    return a <= c ? approximately_negative(a - b) && approximately_negative(b - c)
162            : approximately_negative(b - a) && approximately_negative(c - b);
163}
164
165inline bool precisely_between(double a, double b, double c) {
166    return a <= c ? precisely_negative(a - b) && precisely_negative(b - c)
167            : precisely_negative(b - a) && precisely_negative(c - b);
168}
169
170// returns true if (a <= b <= c) || (a >= b >= c)
171inline bool between(double a, double b, double c) {
172    SkASSERT(((a <= b && b <= c) || (a >= b && b >= c)) == ((a - b) * (c - b) <= 0));
173    return (a - b) * (c - b) <= 0;
174}
175
176inline bool more_roughly_equal(double x, double y) {
177    return fabs(x - y) < MORE_ROUGH_EPSILON;
178}
179
180inline bool roughly_equal(double x, double y) {
181    return fabs(x - y) < ROUGH_EPSILON;
182}
183
184struct SkDPoint;
185struct SkDVector;
186struct SkDLine;
187struct SkDQuad;
188struct SkDTriangle;
189struct SkDCubic;
190struct SkDRect;
191
192inline double SkDInterp(double A, double B, double t) {
193    return A + (B - A) * t;
194}
195
196double SkDCubeRoot(double x);
197
198/* Returns -1 if negative, 0 if zero, 1 if positive
199*/
200inline int SkDSign(double x) {
201    return (x > 0) - (x < 0);
202}
203
204/* Returns 0 if negative, 1 if zero, 2 if positive
205*/
206inline int SKDSide(double x) {
207    return (x > 0) + (x >= 0);
208}
209
210/* Returns 1 if negative, 2 if zero, 4 if positive
211*/
212inline int SkDSideBit(double x) {
213    return 1 << SKDSide(x);
214}
215
216#endif
217