Index: skia/corecg/SkInterpolator.cpp |
=================================================================== |
--- skia/corecg/SkInterpolator.cpp (revision 16859) |
+++ skia/corecg/SkInterpolator.cpp (working copy) |
@@ -1,339 +0,0 @@ |
-/* |
- * Copyright (C) 2006-2008 The Android Open Source Project |
- * |
- * Licensed under the Apache License, Version 2.0 (the "License"); |
- * you may not use this file except in compliance with the License. |
- * You may obtain a copy of the License at |
- * |
- * http://www.apache.org/licenses/LICENSE-2.0 |
- * |
- * Unless required by applicable law or agreed to in writing, software |
- * distributed under the License is distributed on an "AS IS" BASIS, |
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
- * See the License for the specific language governing permissions and |
- * limitations under the License. |
- */ |
- |
-#include "SkInterpolator.h" |
-#include "SkMath.h" |
-#include "SkTSearch.h" |
- |
-SkInterpolatorBase::SkInterpolatorBase() { |
- fStorage = NULL; |
- fTimes = NULL; |
- SkDEBUGCODE(fTimesArray = NULL;) |
-} |
- |
-SkInterpolatorBase::~SkInterpolatorBase() { |
- if (fStorage) { |
- sk_free(fStorage); |
- } |
-} |
- |
-void SkInterpolatorBase::reset(int elemCount, int frameCount) { |
- fFlags = 0; |
- fElemCount = SkToU8(elemCount); |
- fFrameCount = SkToS16(frameCount); |
- fRepeat = SK_Scalar1; |
- if (fStorage) { |
- sk_free(fStorage); |
- fStorage = NULL; |
- fTimes = NULL; |
- SkDEBUGCODE(fTimesArray = NULL); |
- } |
-} |
- |
-/* Each value[] run is formated as: |
- <time (in msec)> |
- <blend> |
- <data[fElemCount]> |
- |
- Totaling fElemCount+2 entries per keyframe |
-*/ |
- |
-bool SkInterpolatorBase::getDuration(SkMSec* startTime, SkMSec* endTime) const { |
- if (fFrameCount == 0) { |
- return false; |
- } |
- |
- if (startTime) { |
- *startTime = fTimes[0].fTime; |
- } |
- if (endTime) { |
- *endTime = fTimes[fFrameCount - 1].fTime; |
- } |
- return true; |
-} |
- |
-SkScalar SkInterpolatorBase::ComputeRelativeT(SkMSec time, SkMSec prevTime, |
- SkMSec nextTime, const SkScalar blend[4]) { |
- SkASSERT(time > prevTime && time < nextTime); |
- |
- SkScalar t = SkScalarDiv((SkScalar)(time - prevTime), |
- (SkScalar)(nextTime - prevTime)); |
- return blend ? |
- SkUnitCubicInterp(t, blend[0], blend[1], blend[2], blend[3]) : t; |
-} |
- |
-SkInterpolatorBase::Result SkInterpolatorBase::timeToT(SkMSec time, SkScalar* T, |
- int* indexPtr, SkBool* exactPtr) const { |
- SkASSERT(fFrameCount > 0); |
- Result result = kNormal_Result; |
- if (fRepeat != SK_Scalar1) { |
- SkMSec startTime = 0, endTime = 0; |
- this->getDuration(&startTime, &endTime); |
- SkMSec totalTime = endTime - startTime; |
- SkMSec offsetTime = time - startTime; |
- endTime = SkScalarMulFloor(fRepeat, totalTime); |
- if (offsetTime >= endTime) { |
- SkScalar fraction = SkScalarFraction(fRepeat); |
- offsetTime = fraction == 0 && fRepeat > 0 ? totalTime : |
- SkScalarMulFloor(fraction, totalTime); |
- result = kFreezeEnd_Result; |
- } else { |
- int mirror = fFlags & kMirror; |
- offsetTime = offsetTime % (totalTime << mirror); |
- if (offsetTime > totalTime) { // can only be true if fMirror is true |
- offsetTime = (totalTime << 1) - offsetTime; |
- } |
- } |
- time = offsetTime + startTime; |
- } |
- |
- int index = SkTSearch<SkMSec>(&fTimes[0].fTime, fFrameCount, time, |
- sizeof(SkTimeCode)); |
- |
- bool exact = true; |
- |
- if (index < 0) { |
- index = ~index; |
- if (index == 0) { |
- result = kFreezeStart_Result; |
- } else if (index == fFrameCount) { |
- if (fFlags & kReset) { |
- index = 0; |
- } else { |
- index -= 1; |
- } |
- result = kFreezeEnd_Result; |
- } else { |
- exact = false; |
- } |
- } |
- SkASSERT(index < fFrameCount); |
- const SkTimeCode* nextTime = &fTimes[index]; |
- SkMSec nextT = nextTime[0].fTime; |
- if (exact) { |
- *T = 0; |
- } else { |
- SkMSec prevT = nextTime[-1].fTime; |
- *T = ComputeRelativeT(time, prevT, nextT, nextTime[-1].fBlend); |
- } |
- *indexPtr = index; |
- *exactPtr = exact; |
- return result; |
-} |
- |
- |
-SkInterpolator::SkInterpolator() { |
- INHERITED::reset(0, 0); |
- fValues = NULL; |
- SkDEBUGCODE(fScalarsArray = NULL;) |
-} |
- |
-SkInterpolator::SkInterpolator(int elemCount, int frameCount) { |
- SkASSERT(elemCount > 0); |
- this->reset(elemCount, frameCount); |
-} |
- |
-void SkInterpolator::reset(int elemCount, int frameCount) { |
- INHERITED::reset(elemCount, frameCount); |
- fStorage = sk_malloc_throw((sizeof(SkScalar) * elemCount + |
- sizeof(SkTimeCode)) * frameCount); |
- fTimes = (SkTimeCode*) fStorage; |
- fValues = (SkScalar*) ((char*) fStorage + sizeof(SkTimeCode) * frameCount); |
-#ifdef SK_DEBUG |
- fTimesArray = (SkTimeCode(*)[10]) fTimes; |
- fScalarsArray = (SkScalar(*)[10]) fValues; |
-#endif |
-} |
- |
-#define SK_Fixed1Third (SK_Fixed1/3) |
-#define SK_Fixed2Third (SK_Fixed1*2/3) |
- |
-static const SkScalar gIdentityBlend[4] = { |
-#ifdef SK_SCALAR_IS_FLOAT |
- 0.33333333f, 0.33333333f, 0.66666667f, 0.66666667f |
-#else |
- SK_Fixed1Third, SK_Fixed1Third, SK_Fixed2Third, SK_Fixed2Third |
-#endif |
-}; |
- |
-bool SkInterpolator::setKeyFrame(int index, SkMSec time, |
- const SkScalar values[], const SkScalar blend[4]) { |
- SkASSERT(values != NULL); |
- |
- if (blend == NULL) { |
- blend = gIdentityBlend; |
- } |
- |
- bool success = ~index == SkTSearch<SkMSec>(&fTimes->fTime, index, time, |
- sizeof(SkTimeCode)); |
- SkASSERT(success); |
- if (success) { |
- SkTimeCode* timeCode = &fTimes[index]; |
- timeCode->fTime = time; |
- memcpy(timeCode->fBlend, blend, sizeof(timeCode->fBlend)); |
- SkScalar* dst = &fValues[fElemCount * index]; |
- memcpy(dst, values, fElemCount * sizeof(SkScalar)); |
- } |
- return success; |
-} |
- |
-SkInterpolator::Result SkInterpolator::timeToValues(SkMSec time, |
- SkScalar values[]) const { |
- SkScalar T; |
- int index; |
- SkBool exact; |
- Result result = timeToT(time, &T, &index, &exact); |
- if (values) { |
- const SkScalar* nextSrc = &fValues[index * fElemCount]; |
- |
- if (exact) { |
- memcpy(values, nextSrc, fElemCount * sizeof(SkScalar)); |
- } else { |
- SkASSERT(index > 0); |
- |
- const SkScalar* prevSrc = nextSrc - fElemCount; |
- |
- for (int i = fElemCount - 1; i >= 0; --i) { |
- values[i] = SkScalarInterp(prevSrc[i], nextSrc[i], T); |
- } |
- } |
- } |
- return result; |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-typedef int Dot14; |
-#define Dot14_ONE (1 << 14) |
-#define Dot14_HALF (1 << 13) |
- |
-#define Dot14ToFloat(x) ((x) / 16384.f) |
- |
-static inline Dot14 Dot14Mul(Dot14 a, Dot14 b) { |
- return (a * b + Dot14_HALF) >> 14; |
-} |
- |
-static inline Dot14 eval_cubic(Dot14 t, Dot14 A, Dot14 B, Dot14 C) { |
- return Dot14Mul(Dot14Mul(Dot14Mul(C, t) + B, t) + A, t); |
-} |
- |
-static inline Dot14 pin_and_convert(SkScalar x) { |
- if (x <= 0) { |
- return 0; |
- } |
- if (x >= SK_Scalar1) { |
- return Dot14_ONE; |
- } |
- return SkScalarToFixed(x) >> 2; |
-} |
- |
-SkScalar SkUnitCubicInterp(SkScalar value, SkScalar bx, SkScalar by, |
- SkScalar cx, SkScalar cy) { |
- // pin to the unit-square, and convert to 2.14 |
- Dot14 x = pin_and_convert(value); |
- |
- if (x == 0) return 0; |
- if (x == Dot14_ONE) return SK_Scalar1; |
- |
- Dot14 b = pin_and_convert(bx); |
- Dot14 c = pin_and_convert(cx); |
- |
- // Now compute our coefficients from the control points |
- // t -> 3b |
- // t^2 -> 3c - 6b |
- // t^3 -> 3b - 3c + 1 |
- Dot14 A = 3*b; |
- Dot14 B = 3*(c - 2*b); |
- Dot14 C = 3*(b - c) + Dot14_ONE; |
- |
- // Now search for a t value given x |
- Dot14 t = Dot14_HALF; |
- Dot14 dt = Dot14_HALF; |
- for (int i = 0; i < 13; i++) { |
- dt >>= 1; |
- Dot14 guess = eval_cubic(t, A, B, C); |
- if (x < guess) { |
- t -= dt; |
- } else { |
- t += dt; |
- } |
- } |
- |
- // Now we have t, so compute the coeff for Y and evaluate |
- b = pin_and_convert(by); |
- c = pin_and_convert(cy); |
- A = 3*b; |
- B = 3*(c - 2*b); |
- C = 3*(b - c) + Dot14_ONE; |
- return SkFixedToScalar(eval_cubic(t, A, B, C) << 2); |
-} |
- |
-/////////////////////////////////////////////////////////////////////////////// |
-/////////////////////////////////////////////////////////////////////////////// |
- |
-#ifdef SK_DEBUG |
- |
-#ifdef SK_SUPPORT_UNITTEST |
- static SkScalar* iset(SkScalar array[3], int a, int b, int c) { |
- array[0] = SkIntToScalar(a); |
- array[1] = SkIntToScalar(b); |
- array[2] = SkIntToScalar(c); |
- return array; |
- } |
-#endif |
- |
-void SkInterpolator::UnitTest() { |
-#ifdef SK_SUPPORT_UNITTEST |
- SkInterpolator inter(3, 2); |
- SkScalar v1[3], v2[3], v[3], vv[3]; |
- Result result; |
- |
- inter.setKeyFrame(0, 100, iset(v1, 10, 20, 30), 0); |
- inter.setKeyFrame(1, 200, iset(v2, 110, 220, 330)); |
- |
- result = inter.timeToValues(0, v); |
- SkASSERT(result == kFreezeStart_Result); |
- SkASSERT(memcmp(v, v1, sizeof(v)) == 0); |
- |
- result = inter.timeToValues(99, v); |
- SkASSERT(result == kFreezeStart_Result); |
- SkASSERT(memcmp(v, v1, sizeof(v)) == 0); |
- |
- result = inter.timeToValues(100, v); |
- SkASSERT(result == kNormal_Result); |
- SkASSERT(memcmp(v, v1, sizeof(v)) == 0); |
- |
- result = inter.timeToValues(200, v); |
- SkASSERT(result == kNormal_Result); |
- SkASSERT(memcmp(v, v2, sizeof(v)) == 0); |
- |
- result = inter.timeToValues(201, v); |
- SkASSERT(result == kFreezeEnd_Result); |
- SkASSERT(memcmp(v, v2, sizeof(v)) == 0); |
- |
- result = inter.timeToValues(150, v); |
- SkASSERT(result == kNormal_Result); |
- SkASSERT(memcmp(v, iset(vv, 60, 120, 180), sizeof(v)) == 0); |
- |
- result = inter.timeToValues(125, v); |
- SkASSERT(result == kNormal_Result); |
- result = inter.timeToValues(175, v); |
- SkASSERT(result == kNormal_Result); |
-#endif |
-} |
- |
-#endif |
- |