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*/
22typedef 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*/
51typedef 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*/
90inline 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
116SkFixed SkFixedMul_portable(SkFixed, SkFixed);
117SkFract SkFractMul_portable(SkFract, SkFract);
118inline 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)
131SkFixed SkFixedDivInt(int32_t numer, int32_t denom);
132SkFixed SkFixedMod(SkFixed numer, SkFixed denom);
133#define SkFixedInvert(n)            SkDivBits(SK_Fixed1, n, 16)
134SkFixed SkFixedFastInvert(SkFixed n);
135#define SkFixedSqrt(n)              SkSqrtBits(n, 23)
136SkFixed SkFixedMean(SkFixed a, SkFixed b);  //*< returns sqrt(x*y)
137int 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
142SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull);
143#define SkFixedSin(radians)         SkFixedSinCos(radians, NULL)
144inline SkFixed SkFixedCos(SkFixed radians)
145{
146    SkFixed cosValue;
147    (void)SkFixedSinCos(radians, &cosValue);
148    return cosValue;
149}
150SkFixed SkFixedTan(SkFixed radians);
151SkFixed SkFixedASin(SkFixed);
152SkFixed SkFixedACos(SkFixed);
153SkFixed SkFixedATan2(SkFixed y, SkFixed x);
154SkFixed SkFixedExp(SkFixed);
155SkFixed SkFixedLog(SkFixed);
156
157#define SK_FixedNearlyZero          (SK_Fixed1 >> 12)
158
159inline 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