1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #ifndef MATHUTILS_H
17 #define MATHUTILS_H
18 
19 #include <math.h>
20 
21 namespace android {
22 namespace uirenderer {
23 
24 #define NON_ZERO_EPSILON (0.001f)
25 #define ALPHA_EPSILON (0.001f)
26 
27 class MathUtils {
28 public:
29     /**
30      * Check for floats that are close enough to zero.
31      */
isZero(float value)32     inline static bool isZero(float value) {
33         return (value >= -NON_ZERO_EPSILON) && (value <= NON_ZERO_EPSILON);
34     }
35 
isPositive(float value)36     inline static bool isPositive(float value) {
37         return value >= NON_ZERO_EPSILON;
38     }
39 
40     /**
41      * Clamps alpha value, and snaps when very near 0 or 1
42      */
clampAlpha(float alpha)43     inline static float clampAlpha(float alpha) {
44         if (alpha <= ALPHA_EPSILON) {
45             return 0;
46         } else if (alpha >= (1 - ALPHA_EPSILON)) {
47             return 1;
48         } else {
49             return alpha;
50         }
51     }
52 
53     /*
54      * Clamps positive tessellation scale values
55      */
clampTessellationScale(float scale)56     inline static float clampTessellationScale(float scale) {
57         const float MIN_SCALE = 0.0001;
58         const float MAX_SCALE = 1e10;
59         if (scale < MIN_SCALE) {
60             return MIN_SCALE;
61         } else if (scale > MAX_SCALE) {
62             return MAX_SCALE;
63         }
64         return scale;
65     }
66 
67     /**
68      * Returns the number of points (beyond two, the start and end) needed to form a polygonal
69      * approximation of an arc, with a given threshold value.
70      */
divisionsNeededToApproximateArc(float radius,float angleInRads,float threshold)71     inline static int divisionsNeededToApproximateArc(float radius,
72             float angleInRads, float threshold) {
73         const float errConst = (-threshold / radius + 1);
74         const float targetCosVal = 2 * errConst * errConst - 1;
75 
76         // needed divisions are rounded up from approximation
77         return (int)(ceilf(angleInRads / acos(targetCosVal)/2)) * 2;
78     }
79 
areEqual(float valueA,float valueB)80     inline static bool areEqual(float valueA, float valueB) {
81         return isZero(valueA - valueB);
82     }
83 
84     template<typename T>
max(T a,T b)85     static inline T max(T a, T b) {
86         return a > b ? a : b;
87     }
88 
89     template<typename T>
min(T a,T b)90     static inline T min(T a, T b) {
91         return a < b ? a : b;
92     }
93 
94     template<typename T>
clamp(T a,T minValue,T maxValue)95     static inline T clamp(T a, T minValue, T maxValue) {
96         return min(max(a, minValue), maxValue);
97     }
98 
lerp(float v1,float v2,float t)99     inline static float lerp(float v1, float v2, float t) {
100         return v1 + ((v2 - v1) * t);
101     }
102 }; // class MathUtils
103 
104 } /* namespace uirenderer */
105 } /* namespace android */
106 
107 #endif /* MATHUTILS_H */
108