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 */ 22 typedef 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 #define SkFixedToFloat(x) ((x) * 1.5258789e-5f) 34 #if 1 35 #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1)) 36 #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 43 44 #ifdef SK_DEBUG 45 static inline SkFixed SkFloatToFixed_Check(float x) { 46 int64_t n64 = (int64_t)(x * SK_Fixed1); 47 SkFixed n32 = (SkFixed)n64; 48 SkASSERT(n64 == n32); 49 return n32; 50 } 51 #else 52 #define SkFloatToFixed_Check(x) SkFloatToFixed(x) 53 #endif 54 55 #define SkFixedToDouble(x) ((x) * 1.5258789e-5) 56 #define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1)) 57 58 /** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point 59 */ 60 typedef int32_t SkFract; 61 #define SK_Fract1 (1 << 30) 62 #define Sk_FracHalf (1 << 29) 63 #define SK_FractPIOver180 (0x11DF46A) 64 65 #define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f) 66 #define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1)) 67 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 */ 97 inline 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) 106 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 120 #define SkFixedAbs(x) SkAbs32(x) 121 #define SkFixedAve(a, b) (((a) + (b)) >> 1) 122 123 SkFixed SkFixedMul_portable(SkFixed, SkFixed); 124 SkFract SkFractMul_portable(SkFract, SkFract); 125 inline 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 137 #define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16) 138 SkFixed SkFixedDivInt(int32_t numer, int32_t denom); 139 SkFixed SkFixedMod(SkFixed numer, SkFixed denom); 140 #define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16) 141 SkFixed SkFixedFastInvert(SkFixed n); 142 #define SkFixedSqrt(n) SkSqrtBits(n, 23) 143 SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y) 144 int 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 149 SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull); 150 #define SkFixedSin(radians) SkFixedSinCos(radians, NULL) 151 inline SkFixed SkFixedCos(SkFixed radians) 152 { 153 SkFixed cosValue; 154 (void)SkFixedSinCos(radians, &cosValue); 155 return cosValue; 156 } 157 SkFixed SkFixedTan(SkFixed radians); 158 SkFixed SkFixedASin(SkFixed); 159 SkFixed SkFixedACos(SkFixed); 160 SkFixed SkFixedATan2(SkFixed y, SkFixed x); 161 SkFixed SkFixedExp(SkFixed); 162 SkFixed SkFixedLog(SkFixed); 163 164 #define SK_FixedNearlyZero (SK_Fixed1 >> 12) 165 166 inline 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 175 #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 (SkFixed)((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 193 #if defined(SK_CPU_ARM) && !defined(__thumb__) 194 /* This guy does not handle NaN or other obscurities, but is faster than 195 than (int)(x*65536) when we only have software floats 196 */ 197 inline SkFixed SkFloatToFixed_arm(float x) 198 { 199 register int32_t y, z; 200 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" 206 "rsbcs %1, %1, #0 \n" 207 : "=r"(x), "=&r"(y), "=&r"(z) 208 : "r"(x) 209 : "cc" 210 ); 211 return y; 212 } 213 inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y) 214 { 215 register int32_t t; 216 asm("smull %0, %2, %1, %3 \n" 217 "mov %0, %0, lsr #16 \n" 218 "orr %0, %0, %2, lsl #16 \n" 219 : "=r"(x), "=&r"(y), "=r"(t) 220 : "r"(x), "1"(y) 221 : 222 ); 223 return x; 224 } 225 inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a) 226 { 227 register int32_t t; 228 asm("smull %0, %3, %1, %4 \n" 229 "add %0, %2, %0, lsr #16 \n" 230 "add %0, %0, %3, lsl #16 \n" 231 : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t) 232 : "%r"(x), "1"(y), "2"(a) 233 : 234 ); 235 return x; 236 } 237 inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y) 238 { 239 register int32_t t; 240 asm("smull %0, %2, %1, %3 \n" 241 "mov %0, %0, lsr #30 \n" 242 "orr %0, %0, %2, lsl #2 \n" 243 : "=r"(x), "=&r"(y), "=r"(t) 244 : "r"(x), "1"(y) 245 : 246 ); 247 return x; 248 } 249 #undef SkFixedMul 250 #undef SkFractMul 251 #define SkFixedMul(x, y) SkFixedMul_arm(x, y) 252 #define SkFractMul(x, y) SkFractMul_arm(x, y) 253 #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a) 254 255 #undef SkFloatToFixed 256 #define SkFloatToFixed(x) SkFloatToFixed_arm(x) 257 #endif 258 259 /////////////////////// Now define our macros to the portable versions if they weren't overridden 260 261 #ifndef SkFixedSquare 262 #define SkFixedSquare(x) SkFixedSquare_portable(x) 263 #endif 264 #ifndef SkFixedMul 265 #define SkFixedMul(x, y) SkFixedMul_portable(x, y) 266 #endif 267 #ifndef SkFractMul 268 #define SkFractMul(x, y) SkFractMul_portable(x, y) 269 #endif 270 #ifndef SkFixedMulAdd 271 #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a)) 272 #endif 273 274 /////////////////////////////////////////////////////////////////////////////// 275 276 typedef int64_t SkFixed48; 277 278 #define SkIntToFixed48(x) ((SkFixed48)(x) << 48) 279 #define SkFixed48ToInt(x) ((int)((x) >> 48)) 280 #define SkFixedToFixed48(x) ((SkFixed48)(x) << 32) 281 #define SkFixed48ToFixed(x) ((SkFixed)((x) >> 32)) 282 #define SkFloatToFixed48(x) ((SkFixed48)((x) * (65536.0f * 65536.0f * 65536.0f))) 283 284 #ifdef SK_SCALAR_IS_FLOAT 285 #define SkScalarToFixed48(x) SkFloatToFixed48(x) 286 #else 287 #define SkScalarToFixed48(x) SkFixedToFixed48(x) 288 #endif 289 290 #endif 291