Home | History | Annotate | Download | only in private
      1 /*
      2  * Copyright 2006 The Android Open Source Project
      3  *
      4  * Use of this source code is governed by a BSD-style license that can be
      5  * found in the LICENSE file.
      6  */
      7 
      8 #ifndef SkFixed_DEFINED
      9 #define SkFixed_DEFINED
     10 
     11 #include "SkScalar.h"
     12 #include "SkSafe_math.h"
     13 
     14 #include "SkTypes.h"
     15 
     16 /** \file SkFixed.h
     17 
     18     Types and macros for 16.16 fixed point
     19 */
     20 
     21 /** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point
     22 */
     23 typedef int32_t             SkFixed;
     24 #define SK_Fixed1           (1 << 16)
     25 #define SK_FixedHalf        (1 << 15)
     26 #define SK_FixedMax         (0x7FFFFFFF)
     27 #define SK_FixedMin         (-SK_FixedMax)
     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.52587890625e-5f)
     34 #define SkFloatToFixed(x)   ((SkFixed)((x) * SK_Fixed1))
     35 
     36 #ifdef SK_DEBUG
     37     static inline SkFixed SkFloatToFixed_Check(float x) {
     38         int64_t n64 = (int64_t)(x * SK_Fixed1);
     39         SkFixed n32 = (SkFixed)n64;
     40         SkASSERT(n64 == n32);
     41         return n32;
     42     }
     43 #else
     44     #define SkFloatToFixed_Check(x) SkFloatToFixed(x)
     45 #endif
     46 
     47 #define SkFixedToDouble(x)  ((x) * 1.52587890625e-5)
     48 #define SkDoubleToFixed(x)  ((SkFixed)((x) * SK_Fixed1))
     49 
     50 /** Converts an integer to a SkFixed, asserting that the result does not overflow
     51     a 32 bit signed integer
     52 */
     53 #ifdef SK_DEBUG
     54     inline SkFixed SkIntToFixed(int n)
     55     {
     56         SkASSERT(n >= -32768 && n <= 32767);
     57         // Left shifting a negative value has undefined behavior in C, so we cast to unsigned before
     58         // shifting.
     59         return (unsigned)n << 16;
     60     }
     61 #else
     62     // Left shifting a negative value has undefined behavior in C, so we cast to unsigned before
     63     // shifting. Then we force the cast to SkFixed to ensure that the answer is signed (like the
     64     // debug version).
     65     #define SkIntToFixed(n)     (SkFixed)((unsigned)(n) << 16)
     66 #endif
     67 
     68 #define SkFixedRoundToInt(x)    (((x) + SK_FixedHalf) >> 16)
     69 #define SkFixedCeilToInt(x)     (((x) + SK_Fixed1 - 1) >> 16)
     70 #define SkFixedFloorToInt(x)    ((x) >> 16)
     71 
     72 static inline SkFixed SkFixedRoundToFixed(SkFixed x) {
     73     return (x + SK_FixedHalf) & 0xFFFF0000;
     74 }
     75 static inline SkFixed SkFixedCeilToFixed(SkFixed x) {
     76     return (x + SK_Fixed1 - 1) & 0xFFFF0000;
     77 }
     78 static inline SkFixed SkFixedFloorToFixed(SkFixed x) {
     79     return x & 0xFFFF0000;
     80 }
     81 
     82 #define SkFixedAbs(x)       SkAbs32(x)
     83 #define SkFixedAve(a, b)    (((a) + (b)) >> 1)
     84 
     85 // The divide may exceed 32 bits. Clamp to a signed 32 bit result.
     86 #define SkFixedDiv(numer, denom) \
     87     SkToS32(SkTPin<int64_t>((SkLeftShift((int64_t)(numer), 16) / (denom)), SK_MinS32, SK_MaxS32))
     88 
     89 //////////////////////////////////////////////////////////////////////////////////////////////////////
     90 // Now look for ASM overrides for our portable versions (should consider putting this in its own file)
     91 
     92 inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) {
     93     return (SkFixed)((int64_t)a * b >> 16);
     94 }
     95 #define SkFixedMul(a,b)     SkFixedMul_longlong(a,b)
     96 
     97 
     98 #if defined(SK_CPU_ARM32)
     99     /* This guy does not handle NaN or other obscurities, but is faster than
    100        than (int)(x*65536).  When built on Android with -Os, needs forcing
    101        to inline or we lose the speed benefit.
    102     */
    103     SK_ALWAYS_INLINE SkFixed SkFloatToFixed_arm(float x)
    104     {
    105         int32_t y, z;
    106         asm("movs    %1, %3, lsl #1         \n"
    107             "mov     %2, #0x8E              \n"
    108             "sub     %1, %2, %1, lsr #24    \n"
    109             "mov     %2, %3, lsl #8         \n"
    110             "orr     %2, %2, #0x80000000    \n"
    111             "mov     %1, %2, lsr %1         \n"
    112             "it cs                          \n"
    113             "rsbcs   %1, %1, #0             \n"
    114             : "=r"(x), "=&r"(y), "=&r"(z)
    115             : "r"(x)
    116             : "cc"
    117             );
    118         return y;
    119     }
    120     inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
    121     {
    122         int32_t t;
    123         asm("smull  %0, %2, %1, %3          \n"
    124             "mov    %0, %0, lsr #16         \n"
    125             "orr    %0, %0, %2, lsl #16     \n"
    126             : "=r"(x), "=&r"(y), "=r"(t)
    127             : "r"(x), "1"(y)
    128             :
    129             );
    130         return x;
    131     }
    132     #undef SkFixedMul
    133     #define SkFixedMul(x, y)        SkFixedMul_arm(x, y)
    134 
    135     #undef SkFloatToFixed
    136     #define SkFloatToFixed(x)  SkFloatToFixed_arm(x)
    137 #endif
    138 
    139 ///////////////////////////////////////////////////////////////////////////////
    140 
    141 #define SkFixedToScalar(x)          SkFixedToFloat(x)
    142 #define SkScalarToFixed(x)          SkFloatToFixed(x)
    143 
    144 ///////////////////////////////////////////////////////////////////////////////
    145 
    146 typedef int64_t SkFixed3232;   // 32.32
    147 
    148 #define SkFixed3232Max            (0x7FFFFFFFFFFFFFFFLL)
    149 #define SkFixed3232Min            (-SkFixed3232Max)
    150 
    151 #define SkIntToFixed3232(x)       (SkLeftShift((SkFixed3232)(x), 32))
    152 #define SkFixed3232ToInt(x)       ((int)((x) >> 32))
    153 #define SkFixedToFixed3232(x)     (SkLeftShift((SkFixed3232)(x), 16))
    154 #define SkFixed3232ToFixed(x)     ((SkFixed)((x) >> 16))
    155 #define SkFloatToFixed3232(x)     ((SkFixed3232)((x) * (65536.0f * 65536.0f)))
    156 #define SkFixed3232ToFloat(x)     (x * (1 / (65536.0f * 65536.0f)))
    157 
    158 #define SkScalarToFixed3232(x)    SkFloatToFixed3232(x)
    159 
    160 #endif
    161