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 "SkTypes.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 (0x1) 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 #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1)) 43 44 #define SkFixedToDouble(x) ((x) * 1.5258789e-5) 45 #define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1)) 46 #endif 47 48 /** 32 bit signed integer used to represent fractions values with 30 bits to the right of the decimal point 49 */ 50 typedef int32_t SkFract; 51 #define SK_Fract1 (1 << 30) 52 #define Sk_FracHalf (1 << 29) 53 #define SK_FractPIOver180 (0x11DF46A) 54 55 #ifdef SK_CAN_USE_FLOAT 56 #define SkFractToFloat(x) ((float)(x) * 0.00000000093132257f) 57 #define SkFloatToFract(x) ((SkFract)((x) * SK_Fract1)) 58 #endif 59 60 /** Converts an integer to a SkFixed, asserting that the result does not overflow 61 a 32 bit signed integer 62 */ 63 #ifdef SK_DEBUG 64 inline SkFixed SkIntToFixed(int n) 65 { 66 SkASSERT(n >= -32768 && n <= 32767); 67 return n << 16; 68 } 69 #else 70 // force the cast to SkFixed to ensure that the answer is signed (like the debug version) 71 #define SkIntToFixed(n) (SkFixed)((n) << 16) 72 #endif 73 74 /** Converts a SkFixed to a SkFract, asserting that the result does not overflow 75 a 32 bit signed integer 76 */ 77 #ifdef SK_DEBUG 78 inline SkFract SkFixedToFract(SkFixed x) 79 { 80 SkASSERT(x >= (-2 << 16) && x <= (2 << 16) - 1); 81 return x << 14; 82 } 83 #else 84 #define SkFixedToFract(x) ((x) << 14) 85 #endif 86 87 /** Returns the signed fraction of a SkFixed 88 */ 89 inline SkFixed SkFixedFraction(SkFixed x) 90 { 91 SkFixed mask = x >> 31 << 16; 92 return (x & 0xFFFF) | mask; 93 } 94 95 /** Converts a SkFract to a SkFixed 96 */ 97 #define SkFractToFixed(x) ((x) >> 14) 98 /** Round a SkFixed to an integer 99 */ 100 #define SkFixedRound(x) (((x) + SK_FixedHalf) >> 16) 101 #define SkFixedCeil(x) (((x) + SK_Fixed1 - 1) >> 16) 102 #define SkFixedFloor(x) ((x) >> 16) 103 #define SkFixedAbs(x) SkAbs32(x) 104 #define SkFixedAve(a, b) (((a) + (b)) >> 1) 105 106 SkFixed SkFixedMul_portable(SkFixed, SkFixed); 107 SkFract SkFractMul_portable(SkFract, SkFract); 108 inline SkFixed SkFixedSquare_portable(SkFixed value) 109 { 110 uint32_t a = SkAbs32(value); 111 uint32_t ah = a >> 16; 112 uint32_t al = a & 0xFFFF; 113 return ah * a + al * ah + (al * al >> 16); 114 } 115 116 #define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16) 117 SkFixed SkFixedDivInt(int32_t numer, int32_t denom); 118 SkFixed SkFixedMod(SkFixed numer, SkFixed denom); 119 #define SkFixedInvert(n) SkDivBits(SK_Fixed1, n, 16) 120 SkFixed SkFixedFastInvert(SkFixed n); 121 #define SkFixedSqrt(n) SkSqrtBits(n, 23) 122 SkFixed SkFixedMean(SkFixed a, SkFixed b); //*< returns sqrt(x*y) 123 int SkFixedMulCommon(SkFixed, int , int bias); // internal used by SkFixedMulFloor, SkFixedMulCeil, SkFixedMulRound 124 125 #define SkFractDiv(numer, denom) SkDivBits(numer, denom, 30) 126 #define SkFractSqrt(n) SkSqrtBits(n, 30) 127 128 SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValueOrNull); 129 #define SkFixedSin(radians) SkFixedSinCos(radians, NULL) 130 inline SkFixed SkFixedCos(SkFixed radians) 131 { 132 SkFixed cosValue; 133 (void)SkFixedSinCos(radians, &cosValue); 134 return cosValue; 135 } 136 SkFixed SkFixedTan(SkFixed radians); 137 SkFixed SkFixedASin(SkFixed); 138 SkFixed SkFixedACos(SkFixed); 139 SkFixed SkFixedATan2(SkFixed y, SkFixed x); 140 SkFixed SkFixedExp(SkFixed); 141 SkFixed SkFixedLog(SkFixed); 142 143 #define SK_FixedNearlyZero (SK_Fixed1 >> 12) 144 145 inline bool SkFixedNearlyZero(SkFixed x, SkFixed tolerance = SK_FixedNearlyZero) 146 { 147 SkASSERT(tolerance > 0); 148 return SkAbs32(x) < tolerance; 149 } 150 151 ////////////////////////////////////////////////////////////////////////////////////////////////////// 152 // Now look for ASM overrides for our portable versions (should consider putting this in its own file) 153 154 #ifdef SkLONGLONG 155 inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) 156 { 157 return (SkFixed)((SkLONGLONG)a * b >> 16); 158 } 159 inline SkFract SkFractMul_longlong(SkFract a, SkFract b) 160 { 161 return (SkFixed)((SkLONGLONG)a * b >> 30); 162 } 163 inline SkFixed SkFixedSquare_longlong(SkFixed value) 164 { 165 return (SkFixed)((SkLONGLONG)value * value >> 16); 166 } 167 #define SkFixedMul(a,b) SkFixedMul_longlong(a,b) 168 #define SkFractMul(a,b) SkFractMul_longlong(a,b) 169 #define SkFixedSquare(a) SkFixedSquare_longlong(a) 170 #endif 171 172 #if defined(__arm__) && !defined(__thumb__) 173 /* This guy does not handle NaN or other obscurities, but is faster than 174 than (int)(x*65536) when we only have software floats 175 */ 176 inline SkFixed SkFloatToFixed_arm(float x) 177 { 178 register int32_t y, z; 179 asm("movs %1, %3, lsl #1 \n" 180 "mov %2, #0x8E \n" 181 "sub %1, %2, %1, lsr #24 \n" 182 "mov %2, %3, lsl #8 \n" 183 "orr %2, %2, #0x80000000 \n" 184 "mov %1, %2, lsr %1 \n" 185 "rsbcs %1, %1, #0 \n" 186 : "=r"(x), "=&r"(y), "=&r"(z) 187 : "r"(x) 188 : "cc" 189 ); 190 return y; 191 } 192 inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y) 193 { 194 register int32_t t; 195 asm("smull %0, %2, %1, %3 \n" 196 "mov %0, %0, lsr #16 \n" 197 "orr %0, %0, %2, lsl #16 \n" 198 : "=r"(x), "=&r"(y), "=r"(t) 199 : "r"(x), "1"(y) 200 : 201 ); 202 return x; 203 } 204 inline SkFixed SkFixedMulAdd_arm(SkFixed x, SkFixed y, SkFixed a) 205 { 206 register int32_t t; 207 asm("smull %0, %3, %1, %4 \n" 208 "add %0, %2, %0, lsr #16 \n" 209 "add %0, %0, %3, lsl #16 \n" 210 : "=r"(x), "=&r"(y), "=&r"(a), "=r"(t) 211 : "%r"(x), "1"(y), "2"(a) 212 : 213 ); 214 return x; 215 } 216 inline SkFixed SkFractMul_arm(SkFixed x, SkFixed y) 217 { 218 register int32_t t; 219 asm("smull %0, %2, %1, %3 \n" 220 "mov %0, %0, lsr #30 \n" 221 "orr %0, %0, %2, lsl #2 \n" 222 : "=r"(x), "=&r"(y), "=r"(t) 223 : "r"(x), "1"(y) 224 : 225 ); 226 return x; 227 } 228 #undef SkFixedMul 229 #undef SkFractMul 230 #define SkFixedMul(x, y) SkFixedMul_arm(x, y) 231 #define SkFractMul(x, y) SkFractMul_arm(x, y) 232 #define SkFixedMulAdd(x, y, a) SkFixedMulAdd_arm(x, y, a) 233 234 #undef SkFloatToFixed 235 #define SkFloatToFixed(x) SkFloatToFixed_arm(x) 236 #endif 237 238 /////////////////////// Now define our macros to the portable versions if they weren't overridden 239 240 #ifndef SkFixedSquare 241 #define SkFixedSquare(x) SkFixedSquare_portable(x) 242 #endif 243 #ifndef SkFixedMul 244 #define SkFixedMul(x, y) SkFixedMul_portable(x, y) 245 #endif 246 #ifndef SkFractMul 247 #define SkFractMul(x, y) SkFractMul_portable(x, y) 248 #endif 249 #ifndef SkFixedMulAdd 250 #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a)) 251 #endif 252 253 #endif 254