blob: ea5e44c39388f1b6b29f972080a9424a253d8a2d [file] [log] [blame]
epoger@google.comec3ed6a2011-07-28 14:26:00 +00001
reed@android.com8a1c16f2008-12-17 15:59:43 +00002/*
epoger@google.comec3ed6a2011-07-28 14:26:00 +00003 * Copyright 2006 The Android Open Source Project
reed@android.com8a1c16f2008-12-17 15:59:43 +00004 *
epoger@google.comec3ed6a2011-07-28 14:26:00 +00005 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
reed@android.com8a1c16f2008-12-17 15:59:43 +00007 */
8
epoger@google.comec3ed6a2011-07-28 14:26:00 +00009
reed@android.com8a1c16f2008-12-17 15:59:43 +000010#ifndef SkFixed_DEFINED
11#define SkFixed_DEFINED
12
tomhudson@google.com889bd8b2011-09-27 17:38:17 +000013#include "SkTypes.h"
reed@android.com8a1c16f2008-12-17 15:59:43 +000014
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)
bsalomon@google.comee9aa302011-05-09 22:32:52 +000026#define SK_FixedMin (-SK_FixedMax)
reed@android.com8a1c16f2008-12-17 15:59:43 +000027#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
reed@google.com7886ad32012-06-11 21:21:26 +000033#define SkFixedToFloat(x) ((x) * 1.5258789e-5f)
reed@google.com4b226022011-01-11 18:32:13 +000034#if 1
reed@android.com8a1c16f2008-12-17 15:59:43 +000035 #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1))
reed@google.com4b226022011-01-11 18:32:13 +000036#else
37 // pins over/under flows to max/min int32 (slower than just a cast)
38 static inline SkFixed SkFloatToFixed(float x) {
39 int64_t n = x * SK_Fixed1;
40 return (SkFixed)n;
41 }
42#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +000043
reed@google.comc9af5d82012-08-03 12:45:14 +000044#ifdef SK_DEBUG
45 static inline SkFixed SkFloatToFixed_Check(float x) {
reed@google.comdea8e252012-08-03 13:55:37 +000046 int64_t n64 = (int64_t)(x * SK_Fixed1);
reed@google.comc9af5d82012-08-03 12:45:14 +000047 SkFixed n32 = (SkFixed)n64;
48 SkASSERT(n64 == n32);
49 return n32;
50 }
51#else
52 #define SkFloatToFixed_Check(x) SkFloatToFixed(x)
53#endif
54
reed@google.com7886ad32012-06-11 21:21:26 +000055#define SkFixedToDouble(x) ((x) * 1.5258789e-5)
56#define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1))
reed@android.com8a1c16f2008-12-17 15:59:43 +000057
58/** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point
59*/
60typedef int32_t SkFract;
61#define SK_Fract1 (1 << 30)
62#define Sk_FracHalf (1 << 29)
63#define SK_FractPIOver180 (0x11DF46A)
64
reed@google.com7886ad32012-06-11 21:21:26 +000065#define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f)
66#define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1))
reed@android.com8a1c16f2008-12-17 15:59:43 +000067
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*/
97inline 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)
reed@google.com1b202802011-08-01 20:49:45 +0000106
107#define SkFixedRoundToInt(x) (((x) + SK_FixedHalf) >> 16)
108#define SkFixedCeilToInt(x) (((x) + SK_Fixed1 - 1) >> 16)
109#define SkFixedFloorToInt(x) ((x) >> 16)
110
111#define SkFixedRoundToFixed(x) (((x) + SK_FixedHalf) & 0xFFFF0000)
112#define SkFixedCeilToFixed(x) (((x) + SK_Fixed1 - 1) & 0xFFFF0000)
113#define SkFixedFloorToFixed(x) ((x) & 0xFFFF0000)
114
115// DEPRECATED
116#define SkFixedFloor(x) SkFixedFloorToInt(x)
117#define SkFixedCeil(x) SkFixedCeilToInt(x)
118#define SkFixedRound(x) SkFixedRoundToInt(x)
119
reed@android.com8a1c16f2008-12-17 15:59:43 +0000120#define SkFixedAbs(x) SkAbs32(x)
121#define SkFixedAve(a, b) (((a) + (b)) >> 1)
122
robertphillips@google.com0e6e8cc2013-08-15 13:43:23 +0000123SkFixed SkFixedMul_portable(SkFixed, SkFixed);
124SkFract SkFractMul_portable(SkFract, SkFract);
125inline SkFixed SkFixedSquare_portable(SkFixed value)
126{
127 uint32_t a = SkAbs32(value);
128 uint32_t ah = a >> 16;
129 uint32_t al = a & 0xFFFF;
130 SkFixed result = ah * a + al * ah + (al * al >> 16);
131 if (result >= 0)
132 return result;
133 else // Overflow.
134 return SK_FixedMax;
135}
136
reed@android.com8a1c16f2008-12-17 15:59:43 +0000137#define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16)
138SkFixed SkFixedDivInt(int32_t numer, int32_t denom);
139SkFixed SkFixedMod(SkFixed numer, SkFixed denom);
140#define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16)
141SkFixed SkFixedFastInvert(SkFixed n);
142#define SkFixedSqrt(n) SkSqrtBits(n, 23)
143SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y)
144int SkFixedMulCommon(SkFixed, int , int bias); // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound
145
146#define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30)
147#define SkFractSqrt(n) SkSqrtBits(n, 30)
148
149SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull);
150#define SkFixedSin(radians) SkFixedSinCos(radians, NULL)
151inline SkFixed SkFixedCos(SkFixed radians)
152{
153 SkFixed cosValue;
154 (void)SkFixedSinCos(radians, &cosValue);
155 return cosValue;
156}
157SkFixed SkFixedTan(SkFixed radians);
158SkFixed SkFixedASin(SkFixed);
159SkFixed SkFixedACos(SkFixed);
160SkFixed SkFixedATan2(SkFixed y, SkFixed x);
161SkFixed SkFixedExp(SkFixed);
162SkFixed SkFixedLog(SkFixed);
163
164#define SK_FixedNearlyZero (SK_Fixed1 >> 12)
165
166inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero)
167{
168 SkASSERT(tolerance > 0);
169 return SkAbs32(x) < tolerance;
170}
171
172//////////////////////////////////////////////////////////////////////////////////////////////////////
173// Now look for ASM overrides for our portable versions (should consider putting this in its own file)
174
robertphillips@google.com0e6e8cc2013-08-15 13:43:23 +0000175#ifdef SkLONGLONG
176 inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b)
177 {
178 return (SkFixed)((SkLONGLONG)a * b >> 16);
179 }
180 inline SkFract SkFractMul_longlong(SkFract a, SkFract b)
181 {
182 return (SkFract)((SkLONGLONG)a * b >> 30);
183 }
184 inline SkFixed SkFixedSquare_longlong(SkFixed value)
185 {
186 return (SkFixed)((SkLONGLONG)value * value >> 16);
187 }
188 #define SkFixedMul(a,b) SkFixedMul_longlong(a,b)
189 #define SkFractMul(a,b) SkFractMul_longlong(a,b)
190 #define SkFixedSquare(a) SkFixedSquare_longlong(a)
191#endif
192
mtklein@google.com069aea72013-07-29 19:30:00 +0000193#if defined(SK_CPU_ARM)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000194 /* This guy does not handle NaN or other obscurities, but is faster than
djsollen@google.com25a11e42013-07-18 19:11:30 +0000195 than (int)(x*65536)
reed@android.com8a1c16f2008-12-17 15:59:43 +0000196 */
197 inline SkFixed SkFloatToFixed_arm(float x)
198 {
commit-bot@chromium.org46ec8152013-12-16 23:51:11 +0000199 int32_t y, z;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000200 asm("movs %1, %3, lsl #1 \n"
201 "mov %2, #0x8E \n"
202 "sub %1, %2, %1, lsr #24 \n"
203 "mov %2, %3, lsl #8 \n"
204 "orr %2, %2, #0x80000000 \n"
205 "mov %1, %2, lsr %1 \n"
mtklein@google.com069aea72013-07-29 19:30:00 +0000206 "it cs \n"
reed@android.com8a1c16f2008-12-17 15:59:43 +0000207 "rsbcs %1, %1, #0 \n"
208 : "=r"(x), "=&r"(y), "=&r"(z)
209 : "r"(x)
210 : "cc"
211 );
212 return y;
213 }
214 inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y)
215 {
commit-bot@chromium.org46ec8152013-12-16 23:51:11 +0000216 int32_t t;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000217 asm("smull %0, %2, %1, %3 \n"
218 "mov %0, %0, lsr #16 \n"
219 "orr %0, %0, %2, lsl #16 \n"
220 : "=r"(x), "=&r"(y), "=r"(t)
221 : "r"(x), "1"(y)
222 :
223 );
224 return x;
225 }
226 inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a)
227 {
commit-bot@chromium.org46ec8152013-12-16 23:51:11 +0000228 int32_t t;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000229 asm("smull %0, %3, %1, %4 \n"
230 "add %0, %2, %0, lsr #16 \n"
231 "add %0, %0, %3, lsl #16 \n"
232 : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t)
233 : "%r"(x), "1"(y), "2"(a)
234 :
235 );
236 return x;
237 }
238 inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y)
239 {
commit-bot@chromium.org46ec8152013-12-16 23:51:11 +0000240 int32_t t;
reed@android.com8a1c16f2008-12-17 15:59:43 +0000241 asm("smull %0, %2, %1, %3 \n"
242 "mov %0, %0, lsr #30 \n"
243 "orr %0, %0, %2, lsl #2 \n"
244 : "=r"(x), "=&r"(y), "=r"(t)
245 : "r"(x), "1"(y)
246 :
247 );
248 return x;
249 }
250 #undef SkFixedMul
251 #undef SkFractMul
252 #define SkFixedMul(x, y) SkFixedMul_arm(x, y)
253 #define SkFractMul(x, y) SkFractMul_arm(x, y)
254 #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a)
255
256 #undef SkFloatToFixed
257 #define SkFloatToFixed(x) SkFloatToFixed_arm(x)
258#endif
259
260/////////////////////// Now define our macros to the portable versions if they weren't overridden
261
262#ifndef SkFixedSquare
263 #define SkFixedSquare(x) SkFixedSquare_portable(x)
264#endif
robertphillips@google.com0e6e8cc2013-08-15 13:43:23 +0000265#ifndef SkFixedMul
266 #define SkFixedMul(x, y) SkFixedMul_portable(x, y)
267#endif
268#ifndef SkFractMul
269 #define SkFractMul(x, y) SkFractMul_portable(x, y)
270#endif
reed@android.com8a1c16f2008-12-17 15:59:43 +0000271#ifndef SkFixedMulAdd
272 #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a))
273#endif
274
reed@google.com4bc0a9d2012-03-07 21:47:41 +0000275///////////////////////////////////////////////////////////////////////////////
276
277typedef int64_t SkFixed48;
278
279#define SkIntToFixed48(x) ((SkFixed48)(x) << 48)
280#define SkFixed48ToInt(x) ((int)((x) >> 48))
281#define SkFixedToFixed48(x) ((SkFixed48)(x) << 32)
282#define SkFixed48ToFixed(x) ((SkFixed)((x) >> 32))
283#define SkFloatToFixed48(x) ((SkFixed48)((x) * (65536.0f * 65536.0f * 65536.0f)))
284
reed@google.com8f4d2302013-12-17 16:44:46 +0000285#define SkScalarToFixed48(x) SkFloatToFixed48(x)
reed@google.com4bc0a9d2012-03-07 21:47:41 +0000286
reed@android.com8a1c16f2008-12-17 15:59:43 +0000287#endif