| OLD | NEW |
| 1 /* | 1 /* |
| 2 * Copyright 2008 The Android Open Source Project | 2 * Copyright 2008 The Android Open Source Project |
| 3 * | 3 * |
| 4 * Use of this source code is governed by a BSD-style license that can be | 4 * Use of this source code is governed by a BSD-style license that can be |
| 5 * found in the LICENSE file. | 5 * found in the LICENSE file. |
| 6 */ | 6 */ |
| 7 | 7 |
| 8 #include "SkMathPriv.h" | 8 #include "SkMathPriv.h" |
| 9 #include "SkFloatBits.h" | 9 #include "SkFloatBits.h" |
| 10 #include "SkFloatingPoint.h" | 10 #include "SkFloatingPoint.h" |
| (...skipping 156 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 167 if (SkScalarNearlyZero(*cosValue)) { | 167 if (SkScalarNearlyZero(*cosValue)) { |
| 168 *cosValue = 0; | 168 *cosValue = 0; |
| 169 } | 169 } |
| 170 } | 170 } |
| 171 | 171 |
| 172 if (SkScalarNearlyZero(sinValue)) { | 172 if (SkScalarNearlyZero(sinValue)) { |
| 173 sinValue = 0; | 173 sinValue = 0; |
| 174 } | 174 } |
| 175 return sinValue; | 175 return sinValue; |
| 176 } | 176 } |
| 177 | |
| 178 #define INTERP_SINTABLE | |
| 179 #define BUILD_TABLE_AT_RUNTIMEx | |
| 180 | |
| 181 #define kTableSize 256 | |
| 182 | |
| 183 #ifdef BUILD_TABLE_AT_RUNTIME | |
| 184 static uint16_t gSkSinTable[kTableSize]; | |
| 185 | |
| 186 static void build_sintable(uint16_t table[]) { | |
| 187 for (int i = 0; i < kTableSize; i++) { | |
| 188 double rad = i * 3.141592653589793 / (2*kTableSize); | |
| 189 double val = sin(rad); | |
| 190 int ival = (int)(val * SK_Fixed1); | |
| 191 table[i] = SkToU16(ival); | |
| 192 } | |
| 193 } | |
| 194 #else | |
| 195 #include "SkSinTable.h" | |
| 196 #endif | |
| 197 | |
| 198 #define SK_Fract1024SizeOver2PI 0x28BE60 /* floatToFract(1024 / 2PI) */ | |
| 199 | |
| 200 #ifdef INTERP_SINTABLE | |
| 201 static SkFixed interp_table(const uint16_t table[], int index, int partial255) { | |
| 202 SkASSERT((unsigned)index < kTableSize); | |
| 203 SkASSERT((unsigned)partial255 <= 255); | |
| 204 | |
| 205 SkFixed lower = table[index]; | |
| 206 SkFixed upper = (index == kTableSize - 1) ? SK_Fixed1 : table[index + 1]; | |
| 207 | |
| 208 SkASSERT(lower < upper); | |
| 209 SkASSERT(lower >= 0); | |
| 210 SkASSERT(upper <= SK_Fixed1); | |
| 211 | |
| 212 partial255 += (partial255 >> 7); | |
| 213 return lower + ((upper - lower) * partial255 >> 8); | |
| 214 } | |
| 215 #endif | |
| 216 | |
| 217 SkFixed SkFixedSinCos(SkFixed radians, SkFixed* cosValuePtr) { | |
| 218 SkASSERT(SK_ARRAY_COUNT(gSkSinTable) == kTableSize); | |
| 219 | |
| 220 #ifdef BUILD_TABLE_AT_RUNTIME | |
| 221 static bool gFirstTime = true; | |
| 222 if (gFirstTime) { | |
| 223 build_sintable(gSinTable); | |
| 224 gFirstTime = false; | |
| 225 } | |
| 226 #endif | |
| 227 | |
| 228 // make radians positive | |
| 229 SkFixed sinValue, cosValue; | |
| 230 int32_t cosSign = 0; | |
| 231 int32_t sinSign = SkExtractSign(radians); | |
| 232 radians = SkApplySign(radians, sinSign); | |
| 233 // scale it to 0...1023 ... | |
| 234 | |
| 235 #ifdef INTERP_SINTABLE | |
| 236 radians = SkMulDiv(radians, 2 * kTableSize * 256, SK_FixedPI); | |
| 237 int findex = radians & (kTableSize * 256 - 1); | |
| 238 int index = findex >> 8; | |
| 239 int partial = findex & 255; | |
| 240 sinValue = interp_table(gSkSinTable, index, partial); | |
| 241 | |
| 242 findex = kTableSize * 256 - findex - 1; | |
| 243 index = findex >> 8; | |
| 244 partial = findex & 255; | |
| 245 cosValue = interp_table(gSkSinTable, index, partial); | |
| 246 | |
| 247 int quad = ((unsigned)radians / (kTableSize * 256)) & 3; | |
| 248 #else | |
| 249 radians = SkMulDiv(radians, 2 * kTableSize, SK_FixedPI); | |
| 250 int index = radians & (kTableSize - 1); | |
| 251 | |
| 252 if (index == 0) { | |
| 253 sinValue = 0; | |
| 254 cosValue = SK_Fixed1; | |
| 255 } else { | |
| 256 sinValue = gSkSinTable[index]; | |
| 257 cosValue = gSkSinTable[kTableSize - index]; | |
| 258 } | |
| 259 int quad = ((unsigned)radians / kTableSize) & 3; | |
| 260 #endif | |
| 261 | |
| 262 if (quad & 1) { | |
| 263 SkTSwap<SkFixed>(sinValue, cosValue); | |
| 264 } | |
| 265 if (quad & 2) { | |
| 266 sinSign = ~sinSign; | |
| 267 } | |
| 268 if (((quad - 1) & 2) == 0) { | |
| 269 cosSign = ~cosSign; | |
| 270 } | |
| 271 | |
| 272 // restore the sign for negative angles | |
| 273 sinValue = SkApplySign(sinValue, sinSign); | |
| 274 cosValue = SkApplySign(cosValue, cosSign); | |
| 275 | |
| 276 #ifdef SK_DEBUG | |
| 277 if (1) { | |
| 278 SkFixed sin2 = SkFixedMul(sinValue, sinValue); | |
| 279 SkFixed cos2 = SkFixedMul(cosValue, cosValue); | |
| 280 int diff = cos2 + sin2 - SK_Fixed1; | |
| 281 SkASSERT(SkAbs32(diff) <= 7); | |
| 282 } | |
| 283 #endif | |
| 284 | |
| 285 if (cosValuePtr) { | |
| 286 *cosValuePtr = cosValue; | |
| 287 } | |
| 288 return sinValue; | |
| 289 } | |
| OLD | NEW |