| OLD | NEW |
| (Empty) |
| 1 /* | |
| 2 * Copyright 2006 The Android Open Source Project | |
| 3 * | |
| 4 * Use of this source code is governed by a BSD-style license that can be | |
| 5 * found in the LICENSE file. | |
| 6 */ | |
| 7 | |
| 8 #ifndef SkFixed_DEFINED | |
| 9 #define SkFixed_DEFINED | |
| 10 | |
| 11 #include "SkTypes.h" | |
| 12 | |
| 13 /** \file SkFixed.h | |
| 14 | |
| 15 Types and macros for 16.16 fixed point | |
| 16 */ | |
| 17 | |
| 18 /** 32 bit signed integer used to represent fractions values with 16 bits to the
right of the decimal point | |
| 19 */ | |
| 20 typedef int32_t SkFixed; | |
| 21 #define SK_Fixed1 (1 << 16) | |
| 22 #define SK_FixedHalf (1 << 15) | |
| 23 #define SK_FixedMax (0x7FFFFFFF) | |
| 24 #define SK_FixedMin (-SK_FixedMax) | |
| 25 #define SK_FixedPI (0x3243F) | |
| 26 #define SK_FixedSqrt2 (92682) | |
| 27 #define SK_FixedTanPIOver8 (0x6A0A) | |
| 28 #define SK_FixedRoot2Over2 (0xB505) | |
| 29 | |
| 30 #define SkFixedToFloat(x) ((x) * 1.52587890625e-5f) | |
| 31 #if 1 | |
| 32 #define SkFloatToFixed(x) ((SkFixed)((x) * SK_Fixed1)) | |
| 33 #else | |
| 34 // pins over/under flows to max/min int32 (slower than just a cast) | |
| 35 static inline SkFixed SkFloatToFixed(float x) { | |
| 36 int64_t n = x * SK_Fixed1; | |
| 37 return (SkFixed)n; | |
| 38 } | |
| 39 #endif | |
| 40 | |
| 41 #ifdef SK_DEBUG | |
| 42 static inline SkFixed SkFloatToFixed_Check(float x) { | |
| 43 int64_t n64 = (int64_t)(x * SK_Fixed1); | |
| 44 SkFixed n32 = (SkFixed)n64; | |
| 45 SkASSERT(n64 == n32); | |
| 46 return n32; | |
| 47 } | |
| 48 #else | |
| 49 #define SkFloatToFixed_Check(x) SkFloatToFixed(x) | |
| 50 #endif | |
| 51 | |
| 52 #define SkFixedToDouble(x) ((x) * 1.52587890625e-5) | |
| 53 #define SkDoubleToFixed(x) ((SkFixed)((x) * SK_Fixed1)) | |
| 54 | |
| 55 /** Converts an integer to a SkFixed, asserting that the result does not overflo
w | |
| 56 a 32 bit signed integer | |
| 57 */ | |
| 58 #ifdef SK_DEBUG | |
| 59 inline SkFixed SkIntToFixed(int n) | |
| 60 { | |
| 61 SkASSERT(n >= -32768 && n <= 32767); | |
| 62 // Left shifting a negative value has undefined behavior in C, so we cas
t to unsigned before | |
| 63 // shifting. | |
| 64 return (unsigned)n << 16; | |
| 65 } | |
| 66 #else | |
| 67 // Left shifting a negative value has undefined behavior in C, so we cast to
unsigned before | |
| 68 // shifting. Then we force the cast to SkFixed to ensure that the answer is
signed (like the | |
| 69 // debug version). | |
| 70 #define SkIntToFixed(n) (SkFixed)((unsigned)(n) << 16) | |
| 71 #endif | |
| 72 | |
| 73 #define SkFixedRoundToInt(x) (((x) + SK_FixedHalf) >> 16) | |
| 74 #define SkFixedCeilToInt(x) (((x) + SK_Fixed1 - 1) >> 16) | |
| 75 #define SkFixedFloorToInt(x) ((x) >> 16) | |
| 76 | |
| 77 #define SkFixedRoundToFixed(x) (((x) + SK_FixedHalf) & 0xFFFF0000) | |
| 78 #define SkFixedCeilToFixed(x) (((x) + SK_Fixed1 - 1) & 0xFFFF0000) | |
| 79 #define SkFixedFloorToFixed(x) ((x) & 0xFFFF0000) | |
| 80 | |
| 81 #define SkFixedAbs(x) SkAbs32(x) | |
| 82 #define SkFixedAve(a, b) (((a) + (b)) >> 1) | |
| 83 | |
| 84 // Blink layout tests are baselined to Clang optimizing through undefined behavi
or in SkDivBits. | |
| 85 #if defined(SK_SUPPORT_LEGACY_DIVBITS_UB) | |
| 86 #define SkFixedDiv(numer, denom) SkDivBits(numer, denom, 16) | |
| 87 #else | |
| 88 // The divide may exceed 32 bits. Clamp to a signed 32 bit result. | |
| 89 #define SkFixedDiv(numer, denom) \ | |
| 90 SkToS32(SkTPin<int64_t>((SkLeftShift((int64_t)numer, 16) / denom), SK_Mi
nS32, SK_MaxS32)) | |
| 91 #endif | |
| 92 | |
| 93 ////////////////////////////////////////////////////////////////////////////////
////////////////////// | |
| 94 // Now look for ASM overrides for our portable versions (should consider putting
this in its own file) | |
| 95 | |
| 96 inline SkFixed SkFixedMul_longlong(SkFixed a, SkFixed b) { | |
| 97 return (SkFixed)((int64_t)a * b >> 16); | |
| 98 } | |
| 99 #define SkFixedMul(a,b) SkFixedMul_longlong(a,b) | |
| 100 | |
| 101 | |
| 102 #if defined(SK_CPU_ARM32) | |
| 103 /* This guy does not handle NaN or other obscurities, but is faster than | |
| 104 than (int)(x*65536). When built on Android with -Os, needs forcing | |
| 105 to inline or we lose the speed benefit. | |
| 106 */ | |
| 107 SK_ALWAYS_INLINE SkFixed SkFloatToFixed_arm(float x) | |
| 108 { | |
| 109 int32_t y, z; | |
| 110 asm("movs %1, %3, lsl #1 \n" | |
| 111 "mov %2, #0x8E \n" | |
| 112 "sub %1, %2, %1, lsr #24 \n" | |
| 113 "mov %2, %3, lsl #8 \n" | |
| 114 "orr %2, %2, #0x80000000 \n" | |
| 115 "mov %1, %2, lsr %1 \n" | |
| 116 "it cs \n" | |
| 117 "rsbcs %1, %1, #0 \n" | |
| 118 : "=r"(x), "=&r"(y), "=&r"(z) | |
| 119 : "r"(x) | |
| 120 : "cc" | |
| 121 ); | |
| 122 return y; | |
| 123 } | |
| 124 inline SkFixed SkFixedMul_arm(SkFixed x, SkFixed y) | |
| 125 { | |
| 126 int32_t t; | |
| 127 asm("smull %0, %2, %1, %3 \n" | |
| 128 "mov %0, %0, lsr #16 \n" | |
| 129 "orr %0, %0, %2, lsl #16 \n" | |
| 130 : "=r"(x), "=&r"(y), "=r"(t) | |
| 131 : "r"(x), "1"(y) | |
| 132 : | |
| 133 ); | |
| 134 return x; | |
| 135 } | |
| 136 #undef SkFixedMul | |
| 137 #define SkFixedMul(x, y) SkFixedMul_arm(x, y) | |
| 138 | |
| 139 #undef SkFloatToFixed | |
| 140 #define SkFloatToFixed(x) SkFloatToFixed_arm(x) | |
| 141 #endif | |
| 142 | |
| 143 /////////////////////////////////////////////////////////////////////////////// | |
| 144 | |
| 145 typedef int64_t SkFixed3232; // 32.32 | |
| 146 | |
| 147 #define SkIntToFixed3232(x) (SkLeftShift((SkFixed3232)(x), 32)) | |
| 148 #define SkFixed3232ToInt(x) ((int)((x) >> 32)) | |
| 149 #define SkFixedToFixed3232(x) (SkLeftShift((SkFixed3232)(x), 16)) | |
| 150 #define SkFixed3232ToFixed(x) ((SkFixed)((x) >> 16)) | |
| 151 #define SkFloatToFixed3232(x) ((SkFixed3232)((x) * (65536.0f * 65536.0f))) | |
| 152 | |
| 153 #define SkScalarToFixed3232(x) SkFloatToFixed3232(x) | |
| 154 | |
| 155 #endif | |
| OLD | NEW |