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