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