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