1 /* 2 * Copyright (C) 2006 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 #ifndef SkFixed_DEFINED 18 #define SkFixed_DEFINED 19 20 #include "SkMath.h" 21 22 /** \file SkFixed.h 23 24 Types and macros for 16.16 fixed point 25 */ 26 27 /** 32 bit signed integer used to represent fractions values with 16 bits to the right of the decimal point 28 */ 29 typedef int32_t SkFixed; 30 #define SK_Fixed1 (1 << 16) 31 #define SK_FixedHalf (1 << 15) 32 #define SK_FixedMax (0x7FFFFFFF) 33 #define SK_FixedMin (-SK_FixedMax) 34 #define SK_FixedNaN ((int) 0x80000000) 35 #define SK_FixedPI (0x3243F) 36 #define SK_FixedSqrt2 (92682) 37 #define SK_FixedTanPIOver8 (0x6A0A) 38 #define SK_FixedRoot2Over2 (0xB505) 39 40 #ifdef SK_CAN_USE_FLOAT 41 #define SkFixedToFloat(x) ((x) * 1.5258789e-5f) 42 #if 1 43 #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1)) 44 #else 45 // pins over/under flows to max/min int32 (slower than just a cast) 46 static inline SkFixed SkFloatToFixed(float x) { 47 int64_t n = x * SK_Fixed1; 48 return (SkFixed)n; 49 } 50 #endif 51 52 #define SkFixedToDouble(x) ((x) * 1.5258789e-5) 53 #define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1)) 54 #endif 55 56 /** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point 57 */ 58 typedef int32_t SkFract; 59 #define SK_Fract1 (1 << 30) 60 #define Sk_FracHalf (1 << 29) 61 #define SK_FractPIOver180 (0x11DF46A) 62 63 #ifdef SK_CAN_USE_FLOAT 64 #define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f) 65 #define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1)) 66 #endif 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 /** Round a SkFixed to an integer 107 */ 108 #define SkFixedRound(x) (((x) + SK_FixedHalf) >> 16) 109 #define SkFixedCeil(x) (((x) + SK_Fixed1 - 1) >> 16) 110 #define SkFixedFloor(x) ((x) >> 16) 111 #define SkFixedAbs(x) SkAbs32(x) 112 #define SkFixedAve(a, b) (((a) + (b)) >> 1) 113 114 // The same as SkIntToFixed(SkFixedFloor(x)) 115 #define SkFixedFloorToFixed(x) ((x) & ~0xFFFF) 116 117 SkFixed SkFixedMul_portable(SkFixed, SkFixed); 118 SkFract SkFractMul_portable(SkFract, SkFract); 119 inline SkFixed SkFixedSquare_portable(SkFixed value) 120 { 121 uint32_t a = SkAbs32(value); 122 uint32_t ah = a >> 16; 123 uint32_t al = a & 0xFFFF; 124 SkFixed result = ah * a + al * ah + (al * al >> 16); 125 if (result >= 0) 126 return result; 127 else // Overflow. 128 return SK_FixedMax; 129 } 130 131 #define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16) 132 SkFixed SkFixedDivInt(int32_t numer, int32_t denom); 133 SkFixed SkFixedMod(SkFixed numer, SkFixed denom); 134 #define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16) 135 SkFixed SkFixedFastInvert(SkFixed n); 136 #define SkFixedSqrt(n) SkSqrtBits(n, 23) 137 SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y) 138 int SkFixedMulCommon(SkFixed, int , int bias); // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound 139 140 #define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30) 141 #define SkFractSqrt(n) SkSqrtBits(n, 30) 142 143 SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull); 144 #define SkFixedSin(radians) SkFixedSinCos(radians, NULL) 145 inline SkFixed SkFixedCos(SkFixed radians) 146 { 147 SkFixed cosValue; 148 (void)SkFixedSinCos(radians, &cosValue); 149 return cosValue; 150 } 151 SkFixed SkFixedTan(SkFixed radians); 152 SkFixed SkFixedASin(SkFixed); 153 SkFixed SkFixedACos(SkFixed); 154 SkFixed SkFixedATan2(SkFixed y, SkFixed x); 155 SkFixed SkFixedExp(SkFixed); 156 SkFixed SkFixedLog(SkFixed); 157 158 #define SK_FixedNearlyZero (SK_Fixed1 >> 12) 159 160 inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero) 161 { 162 SkASSERT(tolerance > 0); 163 return SkAbs32(x) < tolerance; 164 } 165 166 ////////////////////////////////////////////////////////////////////////////////////////////////////// 167 // Now look for ASM overrides for our portable versions (should consider putting this in its own file) 168 169 #ifdef SkLONGLONG 170 inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) 171 { 172 return (SkFixed)((SkLONGLONG)a * b >> 16); 173 } 174 inline SkFract SkFractMul_longlong(SkFract a, SkFract b) 175 { 176 return (SkFixed)((SkLONGLONG)a * b >> 30); 177 } 178 inline SkFixed SkFixedSquare_longlong(SkFixed value) 179 { 180 return (SkFixed)((SkLONGLONG)value * value >> 16); 181 } 182 #define SkFixedMul(a,b) SkFixedMul_longlong(a,b) 183 #define SkFractMul(a,b) SkFractMul_longlong(a,b) 184 #define SkFixedSquare(a) SkFixedSquare_longlong(a) 185 #endif 186 187 #if defined(__arm__) && !defined(__thumb__) 188 /* This guy does not handle NaN or other obscurities, but is faster than 189 than (int)(x*65536) when we only have software floats 190 */ 191 inline SkFixed SkFloatToFixed_arm(float x) 192 { 193 register int32_t y, z; 194 asm("movs %1, %3, lsl #1 \n" 195 "mov %2, #0x8E \n" 196 "sub %1, %2, %1, lsr #24 \n" 197 "mov %2, %3, lsl #8 \n" 198 "orr %2, %2, #0x80000000 \n" 199 "mov %1, %2, lsr %1 \n" 200 "rsbcs %1, %1, #0 \n" 201 : "=r"(x), "=&r"(y), "=&r"(z) 202 : "r"(x) 203 : "cc" 204 ); 205 return y; 206 } 207 inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y) 208 { 209 register int32_t t; 210 asm("smull %0, %2, %1, %3 \n" 211 "mov %0, %0, lsr #16 \n" 212 "orr %0, %0, %2, lsl #16 \n" 213 : "=r"(x), "=&r"(y), "=r"(t) 214 : "r"(x), "1"(y) 215 : 216 ); 217 return x; 218 } 219 inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a) 220 { 221 register int32_t t; 222 asm("smull %0, %3, %1, %4 \n" 223 "add %0, %2, %0, lsr #16 \n" 224 "add %0, %0, %3, lsl #16 \n" 225 : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t) 226 : "%r"(x), "1"(y), "2"(a) 227 : 228 ); 229 return x; 230 } 231 inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y) 232 { 233 register int32_t t; 234 asm("smull %0, %2, %1, %3 \n" 235 "mov %0, %0, lsr #30 \n" 236 "orr %0, %0, %2, lsl #2 \n" 237 : "=r"(x), "=&r"(y), "=r"(t) 238 : "r"(x), "1"(y) 239 : 240 ); 241 return x; 242 } 243 #undef SkFixedMul 244 #undef SkFractMul 245 #define SkFixedMul(x, y) SkFixedMul_arm(x, y) 246 #define SkFractMul(x, y) SkFractMul_arm(x, y) 247 #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a) 248 249 #undef SkFloatToFixed 250 #define SkFloatToFixed(x) SkFloatToFixed_arm(x) 251 #endif 252 253 /////////////////////// Now define our macros to the portable versions if they weren't overridden 254 255 #ifndef SkFixedSquare 256 #define SkFixedSquare(x) SkFixedSquare_portable(x) 257 #endif 258 #ifndef SkFixedMul 259 #define SkFixedMul(x, y) SkFixedMul_portable(x, y) 260 #endif 261 #ifndef SkFractMul 262 #define SkFractMul(x, y) SkFractMul_portable(x, y) 263 #endif 264 #ifndef SkFixedMulAdd 265 #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a)) 266 #endif 267 268 #endif 269