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*/ 22typedef 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*/ 60typedef 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*/ 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) 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 123SkFixed 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 137#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 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 (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 193#if defined(SK_CPU_ARM) 194 /* This guy does not handle NaN or other obscurities, but is faster than 195 than (int)(x*65536) 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 "it cs \n" 207 "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 { 216 register int32_t t; 217 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 { 228 register int32_t t; 229 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 { 240 register int32_t t; 241 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 265#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 271#ifndef SkFixedMulAdd 272 #define SkFixedMulAdd(x, y, a) (SkFixedMul(x, y) + (a)) 273#endif 274 275/////////////////////////////////////////////////////////////////////////////// 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 285#ifdef SK_SCALAR_IS_FLOAT 286 #define SkScalarToFixed48(x) SkFloatToFixed48(x) 287#else 288 #define SkScalarToFixed48(x) SkFixedToFixed48(x) 289#endif 290 291#endif 292