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 |