Home | History | Annotate | Download | only in core
      1 
      2 /*
      3  * Copyright 2006 The Android Open Source Project
      4  *
      5  * Use of this source code is governed by a BSD-style license that can be
      6  * found in the LICENSE file.
      7  */
      8 
      9 
     10 #ifndef SkFixed_DEFINED
     11 #define SkFixed_DEFINED
     12 
     13 #include "SkTypes.h"
     14 
     15 /** \file SkFixed.h
     16 
     17     Types and macros for 16.16 fixed point
     18 */
     19 
     20 /** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point
     21 */
     22 typedef int32_t             SkFixed;
     23 #define SK_Fixed1           (1 << 16)
     24 #define SK_FixedHalf        (1 << 15)
     25 #define SK_FixedMax         (0x7FFFFFFF)
     26 #define SK_FixedMin         (-SK_FixedMax)
     27 #define SK_FixedNaN         ((int) 0x80000000)
     28 #define SK_FixedPI          (0x3243F)
     29 #define SK_FixedSqrt2       (92682)
     30 #define SK_FixedTanPIOver8  (0x6A0A)
     31 #define SK_FixedRoot2Over2  (0xB505)
     32 
     33 #define SkFixedToFloat(x)   ((x) * 1.5258789e-5f)
     34 #if 1
     35     #define SkFloatToFixed(x)   ((SkFixed)((x) * SK_Fixed1))
     36 #else
     37     // pins over/under flows to max/min int32 (slower than just a cast)
     38     static inline SkFixed SkFloatToFixed(float x) {
     39         int64_t n = x * SK_Fixed1;
     40         return (SkFixed)n;
     41     }
     42 #endif
     43 
     44 #ifdef SK_DEBUG
     45     static inline SkFixed SkFloatToFixed_Check(float x) {
     46         int64_t n64 = (int64_t)(x * SK_Fixed1);
     47         SkFixed n32 = (SkFixed)n64;
     48         SkASSERT(n64 == n32);
     49         return n32;
     50     }
     51 #else
     52     #define SkFloatToFixed_Check(x) SkFloatToFixed(x)
     53 #endif
     54 
     55 #define SkFixedToDouble(x)  ((x) * 1.5258789e-5)
     56 #define SkDoubleToFixed(x)  ((SkFixed)((x) * SK_Fixed1))
     57 
     58 /** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point
     59 */
     60 typedef int32_t             SkFract;
     61 #define SK_Fract1           (1 << 30)
     62 #define Sk_FracHalf         (1 << 29)
     63 #define SK_FractPIOver180   (0x11DF46A)
     64 
     65 #define SkFractToFloat(x)   ((float)(x) * 0.00000000093132257f)
     66 #define SkFloatToFract(x)   ((SkFract)((x) * SK_Fract1))
     67 
     68 /** Converts an integer to a SkFixed, asserting that the result does not overflow
     69     a 32 bit signed integer
     70 */
     71 #ifdef SK_DEBUG
     72     inline SkFixed SkIntToFixed(int n)
     73     {
     74         SkASSERT(n >= -32768 && n <= 32767);
     75         return n << 16;
     76     }
     77 #else
     78     //  force the cast to SkFixed to ensure that the answer is signed (like the debug version)
     79     #define SkIntToFixed(n)     (SkFixed)((n) << 16)
     80 #endif
     81 
     82 /** Converts a SkFixed to a SkFract, asserting that the result does not overflow
     83     a 32 bit signed integer
     84 */
     85 #ifdef SK_DEBUG
     86     inline SkFract SkFixedToFract(SkFixed x)
     87     {
     88         SkASSERT(x >= (-2 << 16) && x <= (2 << 16) - 1);
     89         return x << 14;
     90     }
     91 #else
     92     #define SkFixedToFract(x)   ((x) << 14)
     93 #endif
     94 
     95 /** Returns the signed fraction of a SkFixed
     96 */
     97 inline SkFixed SkFixedFraction(SkFixed x)
     98 {
     99     SkFixed mask = x >> 31 << 16;
    100     return (x & 0xFFFF) | mask;
    101 }
    102 
    103 /** Converts a SkFract to a SkFixed
    104 */
    105 #define SkFractToFixed(x)   ((x) >> 14)
    106 
    107 #define SkFixedRoundToInt(x)    (((x) + SK_FixedHalf) >> 16)
    108 #define SkFixedCeilToInt(x)     (((x) + SK_Fixed1 - 1) >> 16)
    109 #define SkFixedFloorToInt(x)    ((x) >> 16)
    110 
    111 #define SkFixedRoundToFixed(x)  (((x) + SK_FixedHalf) & 0xFFFF0000)
    112 #define SkFixedCeilToFixed(x)   (((x) + SK_Fixed1 - 1) & 0xFFFF0000)
    113 #define SkFixedFloorToFixed(x)  ((x) & 0xFFFF0000)
    114 
    115 // DEPRECATED
    116 #define SkFixedFloor(x)     SkFixedFloorToInt(x)
    117 #define SkFixedCeil(x)      SkFixedCeilToInt(x)
    118 #define SkFixedRound(x)     SkFixedRoundToInt(x)
    119 
    120 #define SkFixedAbs(x)       SkAbs32(x)
    121 #define SkFixedAve(a, b)    (((a) + (b)) >> 1)
    122 
    123 SkFixed SkFixedMul_portable(SkFixed, SkFixed);
    124 SkFract SkFractMul_portable(SkFract, SkFract);
    125 inline SkFixed SkFixedSquare_portable(SkFixed value)
    126 {
    127     uint32_t a = SkAbs32(value);
    128     uint32_t ah = a >> 16;
    129     uint32_t al = a & 0xFFFF;
    130     SkFixed result = ah * a + al * ah + (al * al >> 16);
    131     if (result >= 0)
    132         return result;
    133     else // Overflow.
    134         return SK_FixedMax;
    135 }
    136 
    137 #define SkFixedDiv(numer, denom)    SkDivBits(numer, denom, 16)
    138 SkFixed SkFixedDivInt(int32_t numer, int32_t denom);
    139 SkFixed SkFixedMod(SkFixed numer, SkFixed denom);
    140 #define SkFixedInvert(n)            SkDivBits(SK_Fixed1, n, 16)
    141 SkFixed SkFixedFastInvert(SkFixed n);
    142 #define SkFixedSqrt(n)              SkSqrtBits(n, 23)
    143 SkFixed SkFixedMean(SkFixed a, SkFixed b);  //*< returns sqrt(x*y)
    144 int SkFixedMulCommon(SkFixed, int , int bias);  // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound
    145 
    146 #define SkFractDiv(numer, denom)    SkDivBits(numer, denom, 30)
    147 #define SkFractSqrt(n)              SkSqrtBits(n, 30)
    148 
    149 SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull);
    150 #define SkFixedSin(radians)         SkFixedSinCos(radians, NULL)
    151 inline SkFixed SkFixedCos(SkFixed radians)
    152 {
    153     SkFixed cosValue;
    154     (void)SkFixedSinCos(radians, &cosValue);
    155     return cosValue;
    156 }
    157 SkFixed SkFixedTan(SkFixed radians);
    158 SkFixed SkFixedASin(SkFixed);
    159 SkFixed SkFixedACos(SkFixed);
    160 SkFixed SkFixedATan2(SkFixed y, SkFixed x);
    161 SkFixed SkFixedExp(SkFixed);
    162 SkFixed SkFixedLog(SkFixed);
    163 
    164 #define SK_FixedNearlyZero          (SK_Fixed1 >> 12)
    165 
    166 inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero)
    167 {
    168     SkASSERT(tolerance > 0);
    169     return SkAbs32(x) < tolerance;
    170 }
    171 
    172 //////////////////////////////////////////////////////////////////////////////////////////////////////
    173 // Now look for ASM overrides for our portable versions (should consider putting this in its own file)
    174 
    175 #ifdef SkLONGLONG
    176     inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
    177     {
    178         return (SkFixed)((SkLONGLONG)a * b >> 16);
    179     }
    180     inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
    181     {
    182         return (SkFixed)((SkLONGLONG)a * b >> 30);
    183     }
    184     inline SkFixed SkFixedSquare_longlong(SkFixed value)
    185     {
    186         return (SkFixed)((SkLONGLONG)value * value >> 16);
    187     }
    188     #define SkFixedMul(a,b)     SkFixedMul_longlong(a,b)
    189     #define SkFractMul(a,b)     SkFractMul_longlong(a,b)
    190     #define SkFixedSquare(a)    SkFixedSquare_longlong(a)
    191 #endif
    192 
    193 #if defined(SK_CPU_ARM) && !defined(__thumb__)
    194     /* This guy does not handle NaN or other obscurities, but is faster than
    195        than (int)(x*65536) when we only have software floats
    196     */
    197     inline SkFixed SkFloatToFixed_arm(float x)
    198     {
    199         register int32_t y, z;
    200         asm("movs    %1, %3, lsl #1         \n"
    201             "mov     %2, #0x8E              \n"
    202             "sub     %1, %2, %1, lsr #24    \n"
    203             "mov     %2, %3, lsl #8         \n"
    204             "orr     %2, %2, #0x80000000    \n"
    205             "mov     %1, %2, lsr %1         \n"
    206             "rsbcs   %1, %1, #0             \n"
    207             : "=r"(x), "=&r"(y), "=&r"(z)
    208             : "r"(x)
    209             : "cc"
    210             );
    211         return y;
    212     }
    213     inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
    214     {
    215         register int32_t t;
    216         asm("smull  %0, %2, %1, %3          \n"
    217             "mov    %0, %0, lsr #16         \n"
    218             "orr    %0, %0, %2, lsl #16     \n"
    219             : "=r"(x), "=&r"(y), "=r"(t)
    220             : "r"(x), "1"(y)
    221             :
    222             );
    223         return x;
    224     }
    225     inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a)
    226     {
    227         register int32_t t;
    228         asm("smull  %0, %3, %1, %4          \n"
    229             "add    %0, %2, %0, lsr #16     \n"
    230             "add    %0, %0, %3, lsl #16     \n"
    231             : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t)
    232             : "%r"(x), "1"(y), "2"(a)
    233             :
    234             );
    235         return x;
    236     }
    237     inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y)
    238     {
    239         register int32_t t;
    240         asm("smull  %0, %2, %1, %3          \n"
    241             "mov    %0, %0, lsr #30         \n"
    242             "orr    %0, %0, %2, lsl #2      \n"
    243             : "=r"(x), "=&r"(y), "=r"(t)
    244             : "r"(x), "1"(y)
    245             :
    246             );
    247         return x;
    248     }
    249     #undef SkFixedMul
    250     #undef SkFractMul
    251     #define SkFixedMul(x, y)        SkFixedMul_arm(x, y)
    252     #define SkFractMul(x, y)        SkFractMul_arm(x, y)
    253     #define SkFixedMulAdd(x, y, a)  SkFixedMulAdd_arm(x, y, a)
    254 
    255     #undef SkFloatToFixed
    256     #define SkFloatToFixed(x)  SkFloatToFixed_arm(x)
    257 #endif
    258 
    259 /////////////////////// Now define our macros to the portable versions if they weren't overridden
    260 
    261 #ifndef SkFixedSquare
    262     #define SkFixedSquare(x)    SkFixedSquare_portable(x)
    263 #endif
    264 #ifndef SkFixedMul
    265     #define SkFixedMul(x, y)    SkFixedMul_portable(x, y)
    266 #endif
    267 #ifndef SkFractMul
    268     #define SkFractMul(x, y)    SkFractMul_portable(x, y)
    269 #endif
    270 #ifndef SkFixedMulAdd
    271     #define SkFixedMulAdd(x, y, a)  (SkFixedMul(x, y) + (a))
    272 #endif
    273 
    274 ///////////////////////////////////////////////////////////////////////////////
    275 
    276 typedef int64_t SkFixed48;
    277 
    278 #define SkIntToFixed48(x)       ((SkFixed48)(x) << 48)
    279 #define SkFixed48ToInt(x)       ((int)((x) >> 48))
    280 #define SkFixedToFixed48(x)     ((SkFixed48)(x) << 32)
    281 #define SkFixed48ToFixed(x)     ((SkFixed)((x) >> 32))
    282 #define SkFloatToFixed48(x)     ((SkFixed48)((x) * (65536.0f * 65536.0f * 65536.0f)))
    283 
    284 #ifdef SK_SCALAR_IS_FLOAT
    285     #define SkScalarToFixed48(x)    SkFloatToFixed48(x)
    286 #else
    287     #define SkScalarToFixed48(x)    SkFixedToFixed48(x)
    288 #endif
    289 
    290 #endif
    291