Home | History | Annotate | Download | only in core
      1 /*
      2  * Copyright (C) 2006 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 
     17 #ifndef SkScalar_DEFINED
     18 #define SkScalar_DEFINED
     19 
     20 #include "SkFixed.h"
     21 #include "SkFloatingPoint.h"
     22 
     23 /** \file SkScalar.h
     24 
     25     Types and macros for the data type SkScalar. This is the fractional numeric type
     26     that, depending on the compile-time flag SK_SCALAR_IS_FLOAT, may be implemented
     27     either as an IEEE float, or as a 16.16 SkFixed. The macros in this file are written
     28     to allow the calling code to manipulate SkScalar values without knowing which representation
     29     is in effect.
     30 */
     31 
     32 #ifdef SK_SCALAR_IS_FLOAT
     33 
     34     /** SkScalar is our type for fractional values and coordinates. Depending on
     35         compile configurations, it is either represented as an IEEE float, or
     36         as a 16.16 fixed point integer.
     37     */
     38     typedef float   SkScalar;
     39     extern const uint32_t gIEEENotANumber;
     40     extern const uint32_t gIEEEInfinity;
     41 
     42     /** SK_Scalar1 is defined to be 1.0 represented as an SkScalar
     43     */
     44     #define SK_Scalar1              (1.0f)
     45     /** SK_Scalar1 is defined to be 1/2 represented as an SkScalar
     46     */
     47     #define SK_ScalarHalf           (0.5f)
     48     /** SK_ScalarInfinity is defined to be infinity as an SkScalar
     49     */
     50     #define SK_ScalarInfinity           (*(const float*)&gIEEEInfinity)
     51     /** SK_ScalarMax is defined to be the largest value representable as an SkScalar
     52     */
     53     #define SK_ScalarMax            (3.402823466e+38f)
     54     /** SK_ScalarMin is defined to be the smallest value representable as an SkScalar
     55     */
     56     #define SK_ScalarMin            (-SK_ScalarMax)
     57     /** SK_ScalarNaN is defined to be 'Not a Number' as an SkScalar
     58     */
     59     #define SK_ScalarNaN      (*(const float*)(const void*)&gIEEENotANumber)
     60     /** SkScalarIsNaN(n) returns true if argument is not a number
     61     */
     62     static inline bool SkScalarIsNaN(float x) { return x != x; }
     63     /** Returns true if x is not NaN and not infinite */
     64     static inline bool SkScalarIsFinite(float x) {
     65         uint32_t bits = SkFloat2Bits(x);    // need unsigned for our shifts
     66         int exponent = bits << 1 >> 24;
     67         return exponent != 0xFF;
     68     }
     69 #ifdef SK_DEBUG
     70     /** SkIntToScalar(n) returns its integer argument as an SkScalar
     71      *
     72      * If we're compiling in DEBUG mode, and can thus afford some extra runtime
     73      * cycles, check to make sure that the parameter passed in has not already
     74      * been converted to SkScalar.  (A double conversion like this is harmless
     75      * for SK_SCALAR_IS_FLOAT, but for SK_SCALAR_IS_FIXED this causes trouble.)
     76      *
     77      * Note that we need all of these method signatures to properly handle the
     78      * various types that we pass into SkIntToScalar() to date:
     79      * int, size_t, U8CPU, etc., even though what we really mean is "anything
     80      * but a float".
     81      */
     82     static inline float SkIntToScalar(signed int param) {
     83         return (float)param;
     84     }
     85     static inline float SkIntToScalar(unsigned int param) {
     86         return (float)param;
     87     }
     88     static inline float SkIntToScalar(signed long param) {
     89         return (float)param;
     90     }
     91     static inline float SkIntToScalar(unsigned long param) {
     92         return (float)param;
     93     }
     94     static inline float SkIntToScalar(float param) {
     95         /* If the parameter passed into SkIntToScalar is a float,
     96          * one of two things has happened:
     97          * 1. the parameter was an SkScalar (which is typedef'd to float)
     98          * 2. the parameter was a float instead of an int
     99          *
    100          * Either way, it's not good.
    101          */
    102         SkASSERT(!"looks like you passed an SkScalar into SkIntToScalar");
    103         return (float)0;
    104     }
    105 #else  // not SK_DEBUG
    106     /** SkIntToScalar(n) returns its integer argument as an SkScalar
    107     */
    108     #define SkIntToScalar(n)        ((float)(n))
    109 #endif // not SK_DEBUG
    110     /** SkFixedToScalar(n) returns its SkFixed argument as an SkScalar
    111     */
    112     #define SkFixedToScalar(x)      SkFixedToFloat(x)
    113     /** SkScalarToFixed(n) returns its SkScalar argument as an SkFixed
    114     */
    115     #define SkScalarToFixed(x)      SkFloatToFixed(x)
    116 
    117     #define SkScalarToFloat(n)      (n)
    118     #define SkFloatToScalar(n)      (n)
    119 
    120     #define SkScalarToDouble(n)      (double)(n)
    121     #define SkDoubleToScalar(n)      (float)(n)
    122 
    123     /** SkScalarFraction(x) returns the signed fractional part of the argument
    124     */
    125     #define SkScalarFraction(x)     sk_float_mod(x, 1.0f)
    126     /** Rounds the SkScalar to the nearest integer value
    127     */
    128     #define SkScalarRound(x)        sk_float_round2int(x)
    129     /** Returns the smallest integer that is >= the specified SkScalar
    130     */
    131     #define SkScalarCeil(x)         sk_float_ceil2int(x)
    132     /** Returns the largest integer that is <= the specified SkScalar
    133     */
    134     #define SkScalarFloor(x)        sk_float_floor2int(x)
    135     /** Returns the absolute value of the specified SkScalar
    136     */
    137     #define SkScalarAbs(x)          sk_float_abs(x)
    138     /** Return x with the sign of y
    139      */
    140     #define SkScalarCopySign(x, y)  sk_float_copysign(x, y)
    141     /** Returns the value pinned between 0 and max inclusive
    142     */
    143     inline SkScalar SkScalarClampMax(SkScalar x, SkScalar max) {
    144         return x < 0 ? 0 : x > max ? max : x;
    145     }
    146     /** Returns the value pinned between min and max inclusive
    147     */
    148     inline SkScalar SkScalarPin(SkScalar x, SkScalar min, SkScalar max) {
    149         return x < min ? min : x > max ? max : x;
    150     }
    151     /** Returns the specified SkScalar squared (x*x)
    152     */
    153     inline SkScalar SkScalarSquare(SkScalar x) { return x * x; }
    154     /** Returns the product of two SkScalars
    155     */
    156     #define SkScalarMul(a, b)       ((float)(a) * (b))
    157     /** Returns the product of two SkScalars plus a third SkScalar
    158     */
    159     #define SkScalarMulAdd(a, b, c) ((float)(a) * (b) + (c))
    160     /** Returns the product of a SkScalar and an int rounded to the nearest integer value
    161     */
    162     #define SkScalarMulRound(a, b) SkScalarRound((float)(a) * (b))
    163     /** Returns the product of a SkScalar and an int promoted to the next larger int
    164     */
    165     #define SkScalarMulCeil(a, b) SkScalarCeil((float)(a) * (b))
    166     /** Returns the product of a SkScalar and an int truncated to the next smaller int
    167     */
    168     #define SkScalarMulFloor(a, b) SkScalarFloor((float)(a) * (b))
    169     /** Returns the quotient of two SkScalars (a/b)
    170     */
    171     #define SkScalarDiv(a, b)       ((float)(a) / (b))
    172     /** Returns the mod of two SkScalars (a mod b)
    173     */
    174     #define SkScalarMod(x,y)        sk_float_mod(x,y)
    175     /** Returns the product of the first two arguments, divided by the third argument
    176     */
    177     #define SkScalarMulDiv(a, b, c) ((float)(a) * (b) / (c))
    178     /** Returns the multiplicative inverse of the SkScalar (1/x)
    179     */
    180     #define SkScalarInvert(x)       (SK_Scalar1 / (x))
    181     #define SkScalarFastInvert(x)   (SK_Scalar1 / (x))
    182     /** Returns the square root of the SkScalar
    183     */
    184     #define SkScalarSqrt(x)         sk_float_sqrt(x)
    185     /** Returns the average of two SkScalars (a+b)/2
    186     */
    187     #define SkScalarAve(a, b)       (((a) + (b)) * 0.5f)
    188     /** Returns the geometric mean of two SkScalars
    189     */
    190     #define SkScalarMean(a, b)      sk_float_sqrt((float)(a) * (b))
    191     /** Returns one half of the specified SkScalar
    192     */
    193     #define SkScalarHalf(a)         ((a) * 0.5f)
    194 
    195     #define SK_ScalarSqrt2          1.41421356f
    196     #define SK_ScalarPI             3.14159265f
    197     #define SK_ScalarTanPIOver8     0.414213562f
    198     #define SK_ScalarRoot2Over2     0.707106781f
    199 
    200     #define SkDegreesToRadians(degrees) ((degrees) * (SK_ScalarPI / 180))
    201     float SkScalarSinCos(SkScalar radians, SkScalar* cosValue);
    202     #define SkScalarSin(radians)    (float)sk_float_sin(radians)
    203     #define SkScalarCos(radians)    (float)sk_float_cos(radians)
    204     #define SkScalarTan(radians)    (float)sk_float_tan(radians)
    205     #define SkScalarASin(val)   (float)sk_float_asin(val)
    206     #define SkScalarACos(val)   (float)sk_float_acos(val)
    207     #define SkScalarATan2(y, x) (float)sk_float_atan2(y,x)
    208     #define SkScalarExp(x)  (float)sk_float_exp(x)
    209     #define SkScalarLog(x)  (float)sk_float_log(x)
    210 
    211     inline SkScalar SkMaxScalar(SkScalar a, SkScalar b) { return a > b ? a : b; }
    212     inline SkScalar SkMinScalar(SkScalar a, SkScalar b) { return a < b ? a : b; }
    213 
    214     static inline bool SkScalarIsInt(SkScalar x) {
    215         return x == (float)(int)x;
    216     }
    217 #else
    218     typedef SkFixed SkScalar;
    219 
    220     #define SK_Scalar1              SK_Fixed1
    221     #define SK_ScalarHalf           SK_FixedHalf
    222     #define SK_ScalarInfinity   SK_FixedMax
    223     #define SK_ScalarMax            SK_FixedMax
    224     #define SK_ScalarMin            SK_FixedMin
    225     #define SK_ScalarNaN            SK_FixedNaN
    226     #define SkScalarIsNaN(x)        ((x) == SK_FixedNaN)
    227     #define SkScalarIsFinite(x)     ((x) != SK_FixedNaN)
    228 
    229     #define SkIntToScalar(n)        SkIntToFixed(n)
    230     #define SkFixedToScalar(x)      (x)
    231     #define SkScalarToFixed(x)      (x)
    232     #ifdef SK_CAN_USE_FLOAT
    233         #define SkScalarToFloat(n)  SkFixedToFloat(n)
    234         #define SkFloatToScalar(n)  SkFloatToFixed(n)
    235 
    236         #define SkScalarToDouble(n) SkFixedToDouble(n)
    237         #define SkDoubleToScalar(n) SkDoubleToFixed(n)
    238     #endif
    239     #define SkScalarFraction(x)     SkFixedFraction(x)
    240     #define SkScalarRound(x)        SkFixedRound(x)
    241     #define SkScalarCeil(x)         SkFixedCeil(x)
    242     #define SkScalarFloor(x)        SkFixedFloor(x)
    243     #define SkScalarAbs(x)          SkFixedAbs(x)
    244     #define SkScalarCopySign(x, y)  SkCopySign32(x, y)
    245     #define SkScalarClampMax(x, max) SkClampMax(x, max)
    246     #define SkScalarPin(x, min, max) SkPin32(x, min, max)
    247     #define SkScalarSquare(x)       SkFixedSquare(x)
    248     #define SkScalarMul(a, b)       SkFixedMul(a, b)
    249     #define SkScalarMulAdd(a, b, c) SkFixedMulAdd(a, b, c)
    250     #define SkScalarMulRound(a, b)  SkFixedMulCommon(a, b, SK_FixedHalf)
    251     #define SkScalarMulCeil(a, b)   SkFixedMulCommon(a, b, SK_Fixed1 - 1)
    252     #define SkScalarMulFloor(a, b)  SkFixedMulCommon(a, b, 0)
    253     #define SkScalarDiv(a, b)       SkFixedDiv(a, b)
    254     #define SkScalarMod(a, b)       SkFixedMod(a, b)
    255     #define SkScalarMulDiv(a, b, c) SkMulDiv(a, b, c)
    256     #define SkScalarInvert(x)       SkFixedInvert(x)
    257     #define SkScalarFastInvert(x)   SkFixedFastInvert(x)
    258     #define SkScalarSqrt(x)         SkFixedSqrt(x)
    259     #define SkScalarAve(a, b)       SkFixedAve(a, b)
    260     #define SkScalarMean(a, b)      SkFixedMean(a, b)
    261     #define SkScalarHalf(a)         ((a) >> 1)
    262 
    263     #define SK_ScalarSqrt2          SK_FixedSqrt2
    264     #define SK_ScalarPI             SK_FixedPI
    265     #define SK_ScalarTanPIOver8     SK_FixedTanPIOver8
    266     #define SK_ScalarRoot2Over2     SK_FixedRoot2Over2
    267 
    268     #define SkDegreesToRadians(degrees)     SkFractMul(degrees, SK_FractPIOver180)
    269     #define SkScalarSinCos(radians, cosPtr) SkFixedSinCos(radians, cosPtr)
    270     #define SkScalarSin(radians)    SkFixedSin(radians)
    271     #define SkScalarCos(radians)    SkFixedCos(radians)
    272     #define SkScalarTan(val)        SkFixedTan(val)
    273     #define SkScalarASin(val)       SkFixedASin(val)
    274     #define SkScalarACos(val)       SkFixedACos(val)
    275     #define SkScalarATan2(y, x)     SkFixedATan2(y,x)
    276     #define SkScalarExp(x)          SkFixedExp(x)
    277     #define SkScalarLog(x)          SkFixedLog(x)
    278 
    279     #define SkMaxScalar(a, b)       SkMax32(a, b)
    280     #define SkMinScalar(a, b)       SkMin32(a, b)
    281 
    282     static inline bool SkScalarIsInt(SkFixed x) {
    283         return 0 == (x & 0xffff);
    284     }
    285 #endif
    286 
    287 #define SK_ScalarNearlyZero         (SK_Scalar1 / (1 << 12))
    288 
    289 /*  <= is slower than < for floats, so we use < for our tolerance test
    290 */
    291 
    292 static inline bool SkScalarNearlyZero(SkScalar x,
    293                                   SkScalar tolerance = SK_ScalarNearlyZero) {
    294     SkASSERT(tolerance > 0);
    295     return SkScalarAbs(x) < tolerance;
    296 }
    297 
    298 /** Linearly interpolate between A and B, based on t.
    299     If t is 0, return A
    300     If t is 1, return B
    301     else interpolate.
    302     t must be [0..SK_Scalar1]
    303 */
    304 static inline SkScalar SkScalarInterp(SkScalar A, SkScalar B, SkScalar t) {
    305     SkASSERT(t >= 0 && t <= SK_Scalar1);
    306     return A + SkScalarMul(B - A, t);
    307 }
    308 
    309 /** Interpolate along the function described by (keys[length], values[length])
    310     for the passed searchKey.  SearchKeys outside the range keys[0]-keys[Length]
    311     clamp to the min or max value.  This function was inspired by a desire
    312     to change the multiplier for thickness in fakeBold; therefore it assumes
    313     the number of pairs (length) will be small, and a linear search is used.
    314     Repeated keys are allowed for discontinuous functions (so long as keys is
    315     monotonically increasing), and if key is the value of a repeated scalar in
    316     keys, the first one will be used.  However, that may change if a binary
    317     search is used.
    318 */
    319 SkScalar SkScalarInterpFunc(SkScalar searchKey, const SkScalar keys[],
    320                             const SkScalar values[], int length);
    321 
    322 #endif
    323