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