1cb93a386Sopenharmony_ci/* 2cb93a386Sopenharmony_ci * Copyright 2006 The Android Open Source Project 3cb93a386Sopenharmony_ci * 4cb93a386Sopenharmony_ci * Use of this source code is governed by a BSD-style license that can be 5cb93a386Sopenharmony_ci * found in the LICENSE file. 6cb93a386Sopenharmony_ci */ 7cb93a386Sopenharmony_ci 8cb93a386Sopenharmony_ci#ifndef SkScalar_DEFINED 9cb93a386Sopenharmony_ci#define SkScalar_DEFINED 10cb93a386Sopenharmony_ci 11cb93a386Sopenharmony_ci#include "include/private/SkFloatingPoint.h" 12cb93a386Sopenharmony_ci 13cb93a386Sopenharmony_ci#undef SK_SCALAR_IS_FLOAT 14cb93a386Sopenharmony_ci#define SK_SCALAR_IS_FLOAT 1 15cb93a386Sopenharmony_ci 16cb93a386Sopenharmony_citypedef float SkScalar; 17cb93a386Sopenharmony_ci 18cb93a386Sopenharmony_ci#define SK_Scalar1 1.0f 19cb93a386Sopenharmony_ci#define SK_ScalarHalf 0.5f 20cb93a386Sopenharmony_ci#define SK_ScalarSqrt2 SK_FloatSqrt2 21cb93a386Sopenharmony_ci#define SK_ScalarPI SK_FloatPI 22cb93a386Sopenharmony_ci#define SK_ScalarTanPIOver8 0.414213562f 23cb93a386Sopenharmony_ci#define SK_ScalarRoot2Over2 0.707106781f 24cb93a386Sopenharmony_ci#define SK_ScalarMax 3.402823466e+38f 25cb93a386Sopenharmony_ci#define SK_ScalarInfinity SK_FloatInfinity 26cb93a386Sopenharmony_ci#define SK_ScalarNegativeInfinity SK_FloatNegativeInfinity 27cb93a386Sopenharmony_ci#define SK_ScalarNaN SK_FloatNaN 28cb93a386Sopenharmony_ci 29cb93a386Sopenharmony_ci#define SkScalarFloorToScalar(x) sk_float_floor(x) 30cb93a386Sopenharmony_ci#define SkScalarCeilToScalar(x) sk_float_ceil(x) 31cb93a386Sopenharmony_ci#define SkScalarRoundToScalar(x) sk_float_floor((x) + 0.5f) 32cb93a386Sopenharmony_ci#define SkScalarTruncToScalar(x) sk_float_trunc(x) 33cb93a386Sopenharmony_ci 34cb93a386Sopenharmony_ci#define SkScalarFloorToInt(x) sk_float_floor2int(x) 35cb93a386Sopenharmony_ci#define SkScalarCeilToInt(x) sk_float_ceil2int(x) 36cb93a386Sopenharmony_ci#define SkScalarRoundToInt(x) sk_float_round2int(x) 37cb93a386Sopenharmony_ci 38cb93a386Sopenharmony_ci#define SkScalarAbs(x) sk_float_abs(x) 39cb93a386Sopenharmony_ci#define SkScalarCopySign(x, y) sk_float_copysign(x, y) 40cb93a386Sopenharmony_ci#define SkScalarMod(x, y) sk_float_mod(x,y) 41cb93a386Sopenharmony_ci#define SkScalarSqrt(x) sk_float_sqrt(x) 42cb93a386Sopenharmony_ci#define SkScalarPow(b, e) sk_float_pow(b, e) 43cb93a386Sopenharmony_ci 44cb93a386Sopenharmony_ci#define SkScalarSin(radians) (float)sk_float_sin(radians) 45cb93a386Sopenharmony_ci#define SkScalarCos(radians) (float)sk_float_cos(radians) 46cb93a386Sopenharmony_ci#define SkScalarTan(radians) (float)sk_float_tan(radians) 47cb93a386Sopenharmony_ci#define SkScalarASin(val) (float)sk_float_asin(val) 48cb93a386Sopenharmony_ci#define SkScalarACos(val) (float)sk_float_acos(val) 49cb93a386Sopenharmony_ci#define SkScalarATan2(y, x) (float)sk_float_atan2(y,x) 50cb93a386Sopenharmony_ci#define SkScalarExp(x) (float)sk_float_exp(x) 51cb93a386Sopenharmony_ci#define SkScalarLog(x) (float)sk_float_log(x) 52cb93a386Sopenharmony_ci#define SkScalarLog2(x) (float)sk_float_log2(x) 53cb93a386Sopenharmony_ci 54cb93a386Sopenharmony_ci////////////////////////////////////////////////////////////////////////////////////////////////// 55cb93a386Sopenharmony_ci 56cb93a386Sopenharmony_ci#define SkIntToScalar(x) static_cast<SkScalar>(x) 57cb93a386Sopenharmony_ci#define SkIntToFloat(x) static_cast<float>(x) 58cb93a386Sopenharmony_ci#define SkScalarTruncToInt(x) sk_float_saturate2int(x) 59cb93a386Sopenharmony_ci 60cb93a386Sopenharmony_ci#define SkScalarToFloat(x) static_cast<float>(x) 61cb93a386Sopenharmony_ci#define SkFloatToScalar(x) static_cast<SkScalar>(x) 62cb93a386Sopenharmony_ci#define SkScalarToDouble(x) static_cast<double>(x) 63cb93a386Sopenharmony_ci#define SkDoubleToScalar(x) sk_double_to_float(x) 64cb93a386Sopenharmony_ci 65cb93a386Sopenharmony_ci#define SK_ScalarMin (-SK_ScalarMax) 66cb93a386Sopenharmony_ci 67cb93a386Sopenharmony_cistatic inline bool SkScalarIsNaN(SkScalar x) { return x != x; } 68cb93a386Sopenharmony_ci 69cb93a386Sopenharmony_ci/** Returns true if x is not NaN and not infinite 70cb93a386Sopenharmony_ci */ 71cb93a386Sopenharmony_cistatic inline bool SkScalarIsFinite(SkScalar x) { return sk_float_isfinite(x); } 72cb93a386Sopenharmony_ci 73cb93a386Sopenharmony_cistatic inline bool SkScalarsAreFinite(SkScalar a, SkScalar b) { 74cb93a386Sopenharmony_ci return sk_floats_are_finite(a, b); 75cb93a386Sopenharmony_ci} 76cb93a386Sopenharmony_ci 77cb93a386Sopenharmony_cistatic inline bool SkScalarsAreFinite(const SkScalar array[], int count) { 78cb93a386Sopenharmony_ci return sk_floats_are_finite(array, count); 79cb93a386Sopenharmony_ci} 80cb93a386Sopenharmony_ci 81cb93a386Sopenharmony_ci/** 82cb93a386Sopenharmony_ci * Variant of SkScalarRoundToInt, that performs the rounding step (adding 0.5) explicitly using 83cb93a386Sopenharmony_ci * double, to avoid possibly losing the low bit(s) of the answer before calling floor(). 84cb93a386Sopenharmony_ci * 85cb93a386Sopenharmony_ci * This routine will likely be slower than SkScalarRoundToInt(), and should only be used when the 86cb93a386Sopenharmony_ci * extra precision is known to be valuable. 87cb93a386Sopenharmony_ci * 88cb93a386Sopenharmony_ci * In particular, this catches the following case: 89cb93a386Sopenharmony_ci * SkScalar x = 0.49999997; 90cb93a386Sopenharmony_ci * int ix = SkScalarRoundToInt(x); 91cb93a386Sopenharmony_ci * SkASSERT(0 == ix); // <--- fails 92cb93a386Sopenharmony_ci * ix = SkDScalarRoundToInt(x); 93cb93a386Sopenharmony_ci * SkASSERT(0 == ix); // <--- succeeds 94cb93a386Sopenharmony_ci */ 95cb93a386Sopenharmony_cistatic inline int SkDScalarRoundToInt(SkScalar x) { 96cb93a386Sopenharmony_ci double xx = x; 97cb93a386Sopenharmony_ci xx += 0.5; 98cb93a386Sopenharmony_ci return (int)floor(xx); 99cb93a386Sopenharmony_ci} 100cb93a386Sopenharmony_ci 101cb93a386Sopenharmony_ci/** Returns the fractional part of the scalar. */ 102cb93a386Sopenharmony_cistatic inline SkScalar SkScalarFraction(SkScalar x) { 103cb93a386Sopenharmony_ci return x - SkScalarTruncToScalar(x); 104cb93a386Sopenharmony_ci} 105cb93a386Sopenharmony_ci 106cb93a386Sopenharmony_cistatic inline SkScalar SkScalarSquare(SkScalar x) { return x * x; } 107cb93a386Sopenharmony_ci 108cb93a386Sopenharmony_ci#define SkScalarInvert(x) sk_ieee_float_divide_TODO_IS_DIVIDE_BY_ZERO_SAFE_HERE(SK_Scalar1, (x)) 109cb93a386Sopenharmony_ci#define SkScalarAve(a, b) (((a) + (b)) * SK_ScalarHalf) 110cb93a386Sopenharmony_ci#define SkScalarHalf(a) ((a) * SK_ScalarHalf) 111cb93a386Sopenharmony_ci 112cb93a386Sopenharmony_ci#define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180)) 113cb93a386Sopenharmony_ci#define SkRadiansToDegrees(radians) ((radians) * (180 / SK_ScalarPI)) 114cb93a386Sopenharmony_ci 115cb93a386Sopenharmony_cistatic inline bool SkScalarIsInt(SkScalar x) { 116cb93a386Sopenharmony_ci return x == SkScalarFloorToScalar(x); 117cb93a386Sopenharmony_ci} 118cb93a386Sopenharmony_ci 119cb93a386Sopenharmony_ci/** 120cb93a386Sopenharmony_ci * Returns -1 || 0 || 1 depending on the sign of value: 121cb93a386Sopenharmony_ci * -1 if x < 0 122cb93a386Sopenharmony_ci * 0 if x == 0 123cb93a386Sopenharmony_ci * 1 if x > 0 124cb93a386Sopenharmony_ci */ 125cb93a386Sopenharmony_cistatic inline int SkScalarSignAsInt(SkScalar x) { 126cb93a386Sopenharmony_ci return x < 0 ? -1 : (x > 0); 127cb93a386Sopenharmony_ci} 128cb93a386Sopenharmony_ci 129cb93a386Sopenharmony_ci// Scalar result version of above 130cb93a386Sopenharmony_cistatic inline SkScalar SkScalarSignAsScalar(SkScalar x) { 131cb93a386Sopenharmony_ci return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0); 132cb93a386Sopenharmony_ci} 133cb93a386Sopenharmony_ci 134cb93a386Sopenharmony_ci#define SK_ScalarNearlyZero (SK_Scalar1 / (1 << 12)) 135cb93a386Sopenharmony_ci 136cb93a386Sopenharmony_cistatic inline bool SkScalarNearlyZero(SkScalar x, 137cb93a386Sopenharmony_ci SkScalar tolerance = SK_ScalarNearlyZero) { 138cb93a386Sopenharmony_ci SkASSERT(tolerance >= 0); 139cb93a386Sopenharmony_ci return SkScalarAbs(x) <= tolerance; 140cb93a386Sopenharmony_ci} 141cb93a386Sopenharmony_ci 142cb93a386Sopenharmony_cistatic inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y, 143cb93a386Sopenharmony_ci SkScalar tolerance = SK_ScalarNearlyZero) { 144cb93a386Sopenharmony_ci SkASSERT(tolerance >= 0); 145cb93a386Sopenharmony_ci return SkScalarAbs(x-y) <= tolerance; 146cb93a386Sopenharmony_ci} 147cb93a386Sopenharmony_ci 148cb93a386Sopenharmony_cistatic inline float SkScalarSinSnapToZero(SkScalar radians) { 149cb93a386Sopenharmony_ci float v = SkScalarSin(radians); 150cb93a386Sopenharmony_ci return SkScalarNearlyZero(v) ? 0.0f : v; 151cb93a386Sopenharmony_ci} 152cb93a386Sopenharmony_ci 153cb93a386Sopenharmony_cistatic inline float SkScalarCosSnapToZero(SkScalar radians) { 154cb93a386Sopenharmony_ci float v = SkScalarCos(radians); 155cb93a386Sopenharmony_ci return SkScalarNearlyZero(v) ? 0.0f : v; 156cb93a386Sopenharmony_ci} 157cb93a386Sopenharmony_ci 158cb93a386Sopenharmony_ci/** Linearly interpolate between A and B, based on t. 159cb93a386Sopenharmony_ci If t is 0, return A 160cb93a386Sopenharmony_ci If t is 1, return B 161cb93a386Sopenharmony_ci else interpolate. 162cb93a386Sopenharmony_ci t must be [0..SK_Scalar1] 163cb93a386Sopenharmony_ci*/ 164cb93a386Sopenharmony_cistatic inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) { 165cb93a386Sopenharmony_ci SkASSERT(t >= 0 && t <= SK_Scalar1); 166cb93a386Sopenharmony_ci return A + (B - A) * t; 167cb93a386Sopenharmony_ci} 168cb93a386Sopenharmony_ci 169cb93a386Sopenharmony_ci/** Interpolate along the function described by (keys[length], values[length]) 170cb93a386Sopenharmony_ci for the passed searchKey. SearchKeys outside the range keys[0]-keys[Length] 171cb93a386Sopenharmony_ci clamp to the min or max value. This function assumes the number of pairs 172cb93a386Sopenharmony_ci (length) will be small and a linear search is used. 173cb93a386Sopenharmony_ci 174cb93a386Sopenharmony_ci Repeated keys are allowed for discontinuous functions (so long as keys is 175cb93a386Sopenharmony_ci monotonically increasing). If key is the value of a repeated scalar in 176cb93a386Sopenharmony_ci keys the first one will be used. 177cb93a386Sopenharmony_ci*/ 178cb93a386Sopenharmony_ciSkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[], 179cb93a386Sopenharmony_ci const SkScalar values[], int length); 180cb93a386Sopenharmony_ci 181cb93a386Sopenharmony_ci// warning: comparing floating point with == or != is unsafe 182cb93a386Sopenharmony_ci// storing and comparing against same constants ok. 183cb93a386Sopenharmony_ci#if defined(__clang__) 184cb93a386Sopenharmony_ci#pragma clang diagnostic ignored "-Wfloat-equal" 185cb93a386Sopenharmony_ci#elif defined(__GNUC__) 186cb93a386Sopenharmony_ci#pragma GCC diagnostic ignored "-Wfloat-equal" 187cb93a386Sopenharmony_ci#endif 188cb93a386Sopenharmony_ci/* 189cb93a386Sopenharmony_ci * Helper to compare an array of scalars. 190cb93a386Sopenharmony_ci */ 191cb93a386Sopenharmony_cistatic inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) { 192cb93a386Sopenharmony_ci SkASSERT(n >= 0); 193cb93a386Sopenharmony_ci for (int i = 0; i < n; ++i) { 194cb93a386Sopenharmony_ci if (a[i] != b[i]) { 195cb93a386Sopenharmony_ci return false; 196cb93a386Sopenharmony_ci } 197cb93a386Sopenharmony_ci } 198cb93a386Sopenharmony_ci return true; 199cb93a386Sopenharmony_ci} 200cb93a386Sopenharmony_ci 201cb93a386Sopenharmony_ci#endif 202