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 "SkSafe_math.h"
     12 #include "SkScalar.h"
     13 #include "SkTo.h"
     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_FixedQuarter     (1 << 14)
     27 #define SK_FixedMax         (0x7FFFFFFF)
     28 #define SK_FixedMin         (-SK_FixedMax)
     29 #define SK_FixedPI          (0x3243F)
     30 #define SK_FixedSqrt2       (92682)
     31 #define SK_FixedTanPIOver8  (0x6A0A)
     32 #define SK_FixedRoot2Over2  (0xB505)
     33 
     34 // NOTE: SkFixedToFloat is exact. SkFloatToFixed seems to lack a rounding step. For all fixed-point
     35 // values, this version is as accurate as possible for (fixed -> float -> fixed). Rounding reduces
     36 // accuracy if the intermediate floats are in the range that only holds integers (adding 0.5f to an
     37 // odd integer then snaps to nearest even). Using double for the rounding math gives maximum
     38 // accuracy for (float -> fixed -> float), but that's usually overkill.
     39 #define SkFixedToFloat(x)   ((x) * 1.52587890625e-5f)
     40 #define SkFloatToFixed(x)   sk_float_saturate2int((x) * SK_Fixed1)
     41 
     42 #ifdef SK_DEBUG
     43     static inline SkFixed SkFloatToFixed_Check(float x) {
     44         int64_t n64 = (int64_t)(x * SK_Fixed1);
     45         SkFixed n32 = (SkFixed)n64;
     46         SkASSERT(n64 == n32);
     47         return n32;
     48     }
     49 #else
     50     #define SkFloatToFixed_Check(x) SkFloatToFixed(x)
     51 #endif
     52 
     53 #define SkFixedToDouble(x)  ((x) * 1.52587890625e-5)
     54 #define SkDoubleToFixed(x)  ((SkFixed)((x) * SK_Fixed1))
     55 
     56 /** Converts an integer to a SkFixed, asserting that the result does not overflow
     57     a 32 bit signed integer
     58 */
     59 #ifdef SK_DEBUG
     60     inline SkFixed SkIntToFixed(int n)
     61     {
     62         SkASSERT(n >= -32768 && n <= 32767);
     63         // Left shifting a negative value has undefined behavior in C, so we cast to unsigned before
     64         // shifting.
     65         return (unsigned)n << 16;
     66     }
     67 #else
     68     // Left shifting a negative value has undefined behavior in C, so we cast to unsigned before
     69     // shifting. Then we force the cast to SkFixed to ensure that the answer is signed (like the
     70     // debug version).
     71     #define SkIntToFixed(n)     (SkFixed)((unsigned)(n) << 16)
     72 #endif
     73 
     74 #define SkFixedRoundToInt(x)    (((x) + SK_FixedHalf) >> 16)
     75 #define SkFixedCeilToInt(x)     (((x) + SK_Fixed1 - 1) >> 16)
     76 #define SkFixedFloorToInt(x)    ((x) >> 16)
     77 
     78 static inline SkFixed SkFixedRoundToFixed(SkFixed x) {
     79     return (x + SK_FixedHalf) & 0xFFFF0000;
     80 }
     81 static inline SkFixed SkFixedCeilToFixed(SkFixed x) {
     82     return (x + SK_Fixed1 - 1) & 0xFFFF0000;
     83 }
     84 static inline SkFixed SkFixedFloorToFixed(SkFixed x) {
     85     return x & 0xFFFF0000;
     86 }
     87 
     88 #define SkFixedAbs(x)       SkAbs32(x)
     89 #define SkFixedAve(a, b)    (((a) + (b)) >> 1)
     90 
     91 // The divide may exceed 32 bits. Clamp to a signed 32 bit result.
     92 #define SkFixedDiv(numer, denom) \
     93     SkToS32(SkTPin<int64_t>((SkLeftShift((int64_t)(numer), 16) / (denom)), SK_MinS32, SK_MaxS32))
     94 
     95 static inline SkFixed SkFixedMul(SkFixed a, SkFixed b) {
     96     return (SkFixed)((int64_t)a * b >> 16);
     97 }
     98 
     99 ///////////////////////////////////////////////////////////////////////////////
    100 // Platform-specific alternatives to our portable versions.
    101 
    102 // The VCVT float-to-fixed instruction is part of the VFPv3 instruction set.
    103 #if defined(__ARM_VFPV3__)
    104     /* This guy does not handle NaN or other obscurities, but is faster than
    105        than (int)(x*65536).  When built on Android with -Os, needs forcing
    106        to inline or we lose the speed benefit.
    107     */
    108     SK_ALWAYS_INLINE SkFixed SkFloatToFixed_arm(float x)
    109     {
    110         int32_t y;
    111         asm("vcvt.s32.f32 %0, %0, #16": "+w"(x));
    112         memcpy(&y, &x, sizeof(y));
    113         return y;
    114     }
    115     #undef SkFloatToFixed
    116     #define SkFloatToFixed(x)  SkFloatToFixed_arm(x)
    117 #endif
    118 
    119 ///////////////////////////////////////////////////////////////////////////////
    120 
    121 #define SkFixedToScalar(x)          SkFixedToFloat(x)
    122 #define SkScalarToFixed(x)          SkFloatToFixed(x)
    123 
    124 ///////////////////////////////////////////////////////////////////////////////
    125 
    126 typedef int64_t SkFixed3232;   // 32.32
    127 
    128 #define SkFixed3232Max            SK_MaxS64
    129 #define SkFixed3232Min            (-SkFixed3232Max)
    130 
    131 #define SkIntToFixed3232(x)       (SkLeftShift((SkFixed3232)(x), 32))
    132 #define SkFixed3232ToInt(x)       ((int)((x) >> 32))
    133 #define SkFixedToFixed3232(x)     (SkLeftShift((SkFixed3232)(x), 16))
    134 #define SkFixed3232ToFixed(x)     ((SkFixed)((x) >> 16))
    135 #define SkFloatToFixed3232(x)     sk_float_saturate2int64((x) * (65536.0f * 65536.0f))
    136 #define SkFixed3232ToFloat(x)     (x * (1 / (65536.0f * 65536.0f)))
    137 
    138 #define SkScalarToFixed3232(x)    SkFloatToFixed3232(x)
    139 
    140 #endif
    141