/* * Copyright (C) 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef MATHUTILS_H #define MATHUTILS_H #include #include namespace android { namespace uirenderer { class MathUtils { public: static constexpr float NON_ZERO_EPSILON = 0.001f; static constexpr float ALPHA_EPSILON = 0.001f; /** * Check for floats that are close enough to zero. */ inline static bool isZero(float value) { // Using fabsf is more performant as ARM computes // fabsf in a single instruction. return fabsf(value) <= NON_ZERO_EPSILON; } inline static bool isOne(float value) { return areEqual(value, 1.0f); } inline static bool isPositive(float value) { return value >= NON_ZERO_EPSILON; } /** * Clamps alpha value, and snaps when very near 0 or 1 */ inline static float clampAlpha(float alpha) { if (alpha <= ALPHA_EPSILON) { return 0; } else if (alpha >= (1 - ALPHA_EPSILON)) { return 1; } else { return alpha; } } /* * Clamps positive tessellation scale values */ inline static float clampTessellationScale(float scale) { const float MIN_SCALE = 0.0001; const float MAX_SCALE = 1e10; if (scale < MIN_SCALE) { return MIN_SCALE; } else if (scale > MAX_SCALE) { return MAX_SCALE; } return scale; } /** * Returns the number of points (beyond two, the start and end) needed to form a polygonal * approximation of an arc, with a given threshold value. */ inline static int divisionsNeededToApproximateArc(float radius, float angleInRads, float threshold) { const float errConst = (-threshold / radius + 1); const float targetCosVal = 2 * errConst * errConst - 1; // needed divisions are rounded up from approximation return (int)(ceilf(angleInRads / acos(targetCosVal) / 2)) * 2; } inline static bool areEqual(float valueA, float valueB) { return isZero(valueA - valueB); } template static inline T clamp(T a, T minValue, T maxValue) { return std::min(std::max(a, minValue), maxValue); } inline static float lerp(float v1, float v2, float t) { return v1 + ((v2 - v1) * t); } }; // class MathUtils } /* namespace uirenderer */ } /* namespace android */ #endif /* MATHUTILS_H */