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