Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      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 
      8 #ifndef SkScalar_DEFINED
      9 #define SkScalar_DEFINED
     10 
     11 #include "SkFixed.h"
     12 #include "../private/SkFloatingPoint.h"
     13 
     14 // TODO: move this sort of check into SkPostConfig.h
     15 #define SK_SCALAR_IS_DOUBLE 0
     16 #undef SK_SCALAR_IS_FLOAT
     17 #define SK_SCALAR_IS_FLOAT  1
     18 
     19 
     20 #if SK_SCALAR_IS_FLOAT
     21 
     22 typedef float SkScalar;
     23 
     24 #define SK_Scalar1                  1.0f
     25 #define SK_ScalarHalf               0.5f
     26 #define SK_ScalarSqrt2              1.41421356f
     27 #define SK_ScalarPI                 3.14159265f
     28 #define SK_ScalarTanPIOver8         0.414213562f
     29 #define SK_ScalarRoot2Over2         0.707106781f
     30 #define SK_ScalarMax                3.402823466e+38f
     31 #define SK_ScalarInfinity           SK_FloatInfinity
     32 #define SK_ScalarNegativeInfinity   SK_FloatNegativeInfinity
     33 #define SK_ScalarNaN                SK_FloatNaN
     34 
     35 #define SkFixedToScalar(x)          SkFixedToFloat(x)
     36 #define SkScalarToFixed(x)          SkFloatToFixed(x)
     37 
     38 #define SkScalarFloorToScalar(x)    sk_float_floor(x)
     39 #define SkScalarCeilToScalar(x)     sk_float_ceil(x)
     40 #define SkScalarRoundToScalar(x)    sk_float_floor((x) + 0.5f)
     41 
     42 #define SkScalarFloorToInt(x)       sk_float_floor2int(x)
     43 #define SkScalarCeilToInt(x)        sk_float_ceil2int(x)
     44 #define SkScalarRoundToInt(x)       sk_float_round2int(x)
     45 
     46 #define SkScalarAbs(x)              sk_float_abs(x)
     47 #define SkScalarCopySign(x, y)      sk_float_copysign(x, y)
     48 #define SkScalarMod(x, y)           sk_float_mod(x,y)
     49 #define SkScalarFraction(x)         sk_float_mod(x, 1.0f)
     50 #define SkScalarSqrt(x)             sk_float_sqrt(x)
     51 #define SkScalarPow(b, e)           sk_float_pow(b, e)
     52 
     53 #define SkScalarSin(radians)        (float)sk_float_sin(radians)
     54 #define SkScalarCos(radians)        (float)sk_float_cos(radians)
     55 #define SkScalarTan(radians)        (float)sk_float_tan(radians)
     56 #define SkScalarASin(val)           (float)sk_float_asin(val)
     57 #define SkScalarACos(val)           (float)sk_float_acos(val)
     58 #define SkScalarATan2(y, x)         (float)sk_float_atan2(y,x)
     59 #define SkScalarExp(x)              (float)sk_float_exp(x)
     60 #define SkScalarLog(x)              (float)sk_float_log(x)
     61 #define SkScalarLog2(x)             (float)sk_float_log2(x)
     62 
     63 #else   // SK_SCALAR_IS_DOUBLE
     64 
     65 typedef double SkScalar;
     66 
     67 #define SK_Scalar1                  1.0
     68 #define SK_ScalarHalf               0.5
     69 #define SK_ScalarSqrt2              1.414213562373095
     70 #define SK_ScalarPI                 3.141592653589793
     71 #define SK_ScalarTanPIOver8         0.4142135623731
     72 #define SK_ScalarRoot2Over2         0.70710678118655
     73 #define SK_ScalarMax                1.7976931348623157+308
     74 #define SK_ScalarInfinity           SK_DoubleInfinity
     75 #define SK_ScalarNegativeInfinity   SK_DoubleNegativeInfinity
     76 #define SK_ScalarNaN                SK_DoubleNaN
     77 
     78 #define SkFixedToScalar(x)          SkFixedToDouble(x)
     79 #define SkScalarToFixed(x)          SkDoubleToFixed(x)
     80 
     81 #define SkScalarFloorToScalar(x)    floor(x)
     82 #define SkScalarCeilToScalar(x)     ceil(x)
     83 #define SkScalarRoundToScalar(x)    floor((x) + 0.5)
     84 
     85 #define SkScalarFloorToInt(x)       (int)floor(x)
     86 #define SkScalarCeilToInt(x)        (int)ceil(x)
     87 #define SkScalarRoundToInt(x)       (int)floor((x) + 0.5)
     88 
     89 #define SkScalarAbs(x)              abs(x)
     90 #define SkScalarCopySign(x, y)      copysign(x, y)
     91 #define SkScalarMod(x, y)           fmod(x,y)
     92 #define SkScalarFraction(x)         fmod(x, 1.0)
     93 #define SkScalarSqrt(x)             sqrt(x)
     94 #define SkScalarPow(b, e)           pow(b, e)
     95 
     96 #define SkScalarSin(radians)        sin(radians)
     97 #define SkScalarCos(radians)        cos(radians)
     98 #define SkScalarTan(radians)        tan(radians)
     99 #define SkScalarASin(val)           asin(val)
    100 #define SkScalarACos(val)           acos(val)
    101 #define SkScalarATan2(y, x)         atan2(y,x)
    102 #define SkScalarExp(x)              exp(x)
    103 #define SkScalarLog(x)              log(x)
    104 #define SkScalarLog2(x)             log2(x)
    105 
    106 #endif
    107 
    108 //////////////////////////////////////////////////////////////////////////////////////////////////
    109 
    110 #define SkIntToScalar(x)        static_cast<SkScalar>(x)
    111 #define SkScalarTruncToInt(x)   static_cast<int>(x)
    112 
    113 #define SkScalarToFloat(x)      static_cast<float>(x)
    114 #define SkFloatToScalar(x)      static_cast<SkScalar>(x)
    115 #define SkScalarToDouble(x)     static_cast<double>(x)
    116 #define SkDoubleToScalar(x)     static_cast<SkScalar>(x)
    117 
    118 #define SK_ScalarMin            (-SK_ScalarMax)
    119 
    120 static inline bool SkScalarIsNaN(SkScalar x) { return x != x; }
    121 
    122 /** Returns true if x is not NaN and not infinite
    123  */
    124 static inline bool SkScalarIsFinite(SkScalar x) {
    125     // We rely on the following behavior of infinities and nans
    126     // 0 * finite --> 0
    127     // 0 * infinity --> NaN
    128     // 0 * NaN --> NaN
    129     SkScalar prod = x * 0;
    130     // At this point, prod will either be NaN or 0
    131     return !SkScalarIsNaN(prod);
    132 }
    133 
    134 static inline bool SkScalarsAreFinite(SkScalar a, SkScalar b) {
    135     SkScalar prod = 0;
    136     prod *= a;
    137     prod *= b;
    138     // At this point, prod will either be NaN or 0
    139     return !SkScalarIsNaN(prod);
    140 }
    141 
    142 static inline bool SkScalarsAreFinite(const SkScalar array[], int count) {
    143     SkScalar prod = 0;
    144     for (int i = 0; i < count; ++i) {
    145         prod *= array[i];
    146     }
    147     // At this point, prod will either be NaN or 0
    148     return !SkScalarIsNaN(prod);
    149 }
    150 
    151 /**
    152  *  Variant of SkScalarRoundToInt, that performs the rounding step (adding 0.5) explicitly using
    153  *  double, to avoid possibly losing the low bit(s) of the answer before calling floor().
    154  *
    155  *  This routine will likely be slower than SkScalarRoundToInt(), and should only be used when the
    156  *  extra precision is known to be valuable.
    157  *
    158  *  In particular, this catches the following case:
    159  *      SkScalar x = 0.49999997;
    160  *      int ix = SkScalarRoundToInt(x);
    161  *      SkASSERT(0 == ix);    // <--- fails
    162  *      ix = SkDScalarRoundToInt(x);
    163  *      SkASSERT(0 == ix);    // <--- succeeds
    164  */
    165 static inline int SkDScalarRoundToInt(SkScalar x) {
    166     double xx = x;
    167     xx += 0.5;
    168     return (int)floor(xx);
    169 }
    170 
    171 static inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) {
    172     x = SkTMin(x, max);
    173     x = SkTMax<SkScalar>(x, 0);
    174     return x;
    175 }
    176 
    177 static inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) {
    178     return SkTPin(x, min, max);
    179 }
    180 
    181 SkScalar SkScalarSinCos(SkScalar radians, SkScalar* cosValue);
    182 
    183 static inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
    184 
    185 #define SkScalarMul(a, b)       ((SkScalar)(a) * (b))
    186 #define SkScalarMulAdd(a, b, c) ((SkScalar)(a) * (b) + (c))
    187 #define SkScalarMulDiv(a, b, c) ((SkScalar)(a) * (b) / (c))
    188 #define SkScalarInvert(x)       (SK_Scalar1 / (x))
    189 #define SkScalarFastInvert(x)   (SK_Scalar1 / (x))
    190 #define SkScalarAve(a, b)       (((a) + (b)) * SK_ScalarHalf)
    191 #define SkScalarHalf(a)         ((a) * SK_ScalarHalf)
    192 
    193 #define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
    194 #define SkRadiansToDegrees(radians) ((radians) * (180 / SK_ScalarPI))
    195 
    196 static inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; }
    197 static inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; }
    198 
    199 static inline bool SkScalarIsInt(SkScalar x) {
    200     return x == (SkScalar)(int)x;
    201 }
    202 
    203 /**
    204  *  Returns -1 || 0 || 1 depending on the sign of value:
    205  *  -1 if x < 0
    206  *   0 if x == 0
    207  *   1 if x > 0
    208  */
    209 static inline int SkScalarSignAsInt(SkScalar x) {
    210     return x < 0 ? -1 : (x > 0);
    211 }
    212 
    213 // Scalar result version of above
    214 static inline SkScalar SkScalarSignAsScalar(SkScalar x) {
    215     return x < 0 ? -SK_Scalar1 : ((x > 0) ? SK_Scalar1 : 0);
    216 }
    217 
    218 #define SK_ScalarNearlyZero         (SK_Scalar1 / (1 << 12))
    219 
    220 static inline bool SkScalarNearlyZero(SkScalar x,
    221                                       SkScalar tolerance = SK_ScalarNearlyZero) {
    222     SkASSERT(tolerance >= 0);
    223     return SkScalarAbs(x) <= tolerance;
    224 }
    225 
    226 static inline bool SkScalarNearlyEqual(SkScalar x, SkScalar y,
    227                                        SkScalar tolerance = SK_ScalarNearlyZero) {
    228     SkASSERT(tolerance >= 0);
    229     return SkScalarAbs(x-y) <= tolerance;
    230 }
    231 
    232 /** Linearly interpolate between A and B, based on t.
    233     If t is 0, return A
    234     If t is 1, return B
    235     else interpolate.
    236     t must be [0..SK_Scalar1]
    237 */
    238 static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {
    239     SkASSERT(t >= 0 && t <= SK_Scalar1);
    240     return A + (B - A) * t;
    241 }
    242 
    243 /** Interpolate along the function described by (keys[length], values[length])
    244     for the passed searchKey.  SearchKeys outside the range keys[0]-keys[Length]
    245     clamp to the min or max value.  This function was inspired by a desire
    246     to change the multiplier for thickness in fakeBold; therefore it assumes
    247     the number of pairs (length) will be small, and a linear search is used.
    248     Repeated keys are allowed for discontinuous functions (so long as keys is
    249     monotonically increasing), and if key is the value of a repeated scalar in
    250     keys, the first one will be used.  However, that may change if a binary
    251     search is used.
    252 */
    253 SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],
    254                             const SkScalar values[], int length);
    255 
    256 /*
    257  *  Helper to compare an array of scalars.
    258  */
    259 static inline bool SkScalarsEqual(const SkScalar a[], const SkScalar b[], int n) {
    260     SkASSERT(n >= 0);
    261     for (int i = 0; i < n; ++i) {
    262         if (a[i] != b[i]) {
    263             return false;
    264         }
    265     }
    266     return true;
    267 }
    268 
    269 #endif
    270