grab from latest android



git-svn-id: http://skia.googlecode.com/svn/trunk@27 2bbb7eff-a529-9590-31e7-b0007b416f81
diff --git a/src/animator/SkAnimateActive.cpp b/src/animator/SkAnimateActive.cpp
new file mode 100644
index 0000000..4ee7ded
--- /dev/null
+++ b/src/animator/SkAnimateActive.cpp
@@ -0,0 +1,509 @@
+/* libs/graphics/animator/SkAnimateActive.cpp
+**
+** Copyright 2006, 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 "SkAnimateActive.h"
+#include "SkAnimateBase.h"
+#include "SkAnimateMaker.h"
+#include "SkAnimateSet.h"
+#include "SkDrawGroup.h"
+#ifdef SK_DEBUG
+#include "SkTime.h"
+#endif
+
+// SkActive holds array of interpolators
+
+SkActive::SkActive(SkApply& apply, SkAnimateMaker& maker) : fApply(apply),
+    fMaxTime(0), fMaker(maker), fDrawIndex(0), fDrawMax(0) {
+}
+
+void SkActive::init() 
+{
+    fAnimators = fApply.fAnimators;
+    int animators = fAnimators.count();
+    fInterpolators.setCount(animators);
+    memset(fInterpolators.begin(), 0, animators * sizeof(SkOperandInterpolator*));
+    fState.setCount(animators);
+    int index;
+    for (index = 0; index < animators; index++)
+        fInterpolators[index] = SkNEW(SkOperandInterpolator);
+    initState(&fApply, 0);
+//  for (index = 0; index < animators; index++)
+//      fState[index].bumpSave();
+    SkASSERT(fInterpolators.count() == fAnimators.count());
+}
+
+SkActive::~SkActive() {
+    int index;
+    for (index = 0; index < fSaveRestore.count(); index++)
+        delete[] fSaveRestore[index];
+    for (index = 0; index < fSaveInterpolators.count(); index++)
+        delete[] fSaveInterpolators[index];
+    for (index = 0; index < fInterpolators.count(); index++)
+        delete fInterpolators[index];
+}
+
+void SkActive::advance() {
+    if (fDrawMax < fDrawIndex)
+        fDrawMax = fDrawIndex;
+    fDrawIndex += fAnimators.count();
+}
+
+void SkActive::append(SkApply* apply) {
+    int oldCount = fAnimators.count();
+    SkTDAnimateArray& animates = apply->fAnimators;
+    int newCount = animates.count();
+    int index;
+    int total = oldCount + newCount;
+    if (total == 0)
+        return;
+    fInterpolators.setCount(total);
+    memset(&fInterpolators.begin()[oldCount], 0, newCount * sizeof(SkOperandInterpolator*));
+    for (index = oldCount; index < total; index++)
+        fInterpolators[index] = SkNEW(SkOperandInterpolator);
+    fAnimators.setCount(total);
+    memcpy(&fAnimators[oldCount], animates.begin(), sizeof(fAnimators[0]) *
+        newCount);
+    fState.setCount(total);
+    initState(apply, oldCount);
+    SkASSERT(fApply.scope == apply->scope);
+    for (index = 0; index < newCount; index++) {
+        SkAnimateBase* test = animates[index];
+//      SkASSERT(fApply.scope == test->fTarget || fApply.scope->contains(test->fTarget));
+        SkActive::SkState& testState = fState[oldCount + index];
+        for (int inner = 0; inner < oldCount; inner++) {
+            SkAnimateBase* oldGuard = fAnimators[inner];
+            SkActive::SkState& oldState = fState[inner];
+            if (oldGuard->fTarget == test->fTarget && oldGuard->fFieldInfo == test->fFieldInfo &&
+                    testState.fBegin == oldState.fBegin) {
+                delete fInterpolators[inner];
+                fInterpolators.remove(inner);
+                fAnimators.remove(inner);
+                testState.fSave = oldState.fSave;
+                if (oldState.fUnpostedEndEvent) {
+//                  SkDEBUGF(("%8x %8x active append: post on end\n", this, oldGuard));
+                    fMaker.postOnEnd(oldGuard, oldState.fBegin + oldState.fDuration);
+                }
+                fState.remove(inner);
+                if (fApply.restore) {
+                    int saveIndex = fSaveRestore.count();
+                    SkASSERT(fSaveInterpolators.count() == saveIndex);
+                    saveIndex += inner;
+                    do {
+                        saveIndex -= oldCount;
+                        delete[] fSaveRestore[saveIndex];
+                        fSaveRestore.remove(saveIndex);
+                        delete[] fSaveInterpolators[saveIndex]; 
+                        fSaveInterpolators.remove(saveIndex);
+                    } while (saveIndex > 0);
+                }
+                oldCount--;
+                break;
+            }
+        }
+    }
+//  total = oldCount + newCount;
+//  for (index = oldCount; index < total; index++)
+//      fState[index].bumpSave();
+    SkASSERT(fInterpolators.count() == fAnimators.count());
+}
+
+void SkActive::appendSave(int oldCount) {
+    SkASSERT(fDrawMax == 0);    // if true, we can optimize below quite a bit
+    int newCount = fAnimators.count();
+    int saveIndex = fSaveRestore.count();
+    SkASSERT(fSaveInterpolators.count() == saveIndex);
+    int records = saveIndex / oldCount;
+    int newTotal = records * newCount;
+    fSaveRestore.setCount(newTotal);
+    do {
+        saveIndex -= oldCount;
+        newTotal -= newCount;
+        SkASSERT(saveIndex >= 0);
+        SkASSERT(newTotal >= 0);
+        memmove(&fSaveRestore[newTotal], &fSaveRestore[saveIndex], oldCount);
+        memset(&fSaveRestore[newTotal + oldCount], 0, 
+            sizeof(fSaveRestore[0]) * (newCount - oldCount));
+        memmove(&fSaveInterpolators[newTotal], 
+            &fSaveInterpolators[saveIndex], oldCount);
+        memset(&fSaveInterpolators[newTotal + oldCount], 0, 
+            sizeof(fSaveRestore[0]) * (newCount - oldCount));
+    } while (saveIndex > 0);
+    SkASSERT(newTotal == 0);
+}
+
+void SkActive::calcDurations(int index) 
+{
+    SkAnimateBase* animate = fAnimators[index];
+    SkMSec duration = animate->dur;
+    SkState& state = fState[index];
+    if (state.fMode == SkApply::kMode_immediate || state.fMode == SkApply::kMode_create)
+        duration = state.fSteps ? state.fSteps * SK_MSec1 : 1;
+//  else if (state.fMode == SkApply::kMode_hold) {
+//      int entries = animate->entries();
+//      SkScriptValue value;
+//      value.fOperand = animate->getValues()[entries - 1];
+//      value.fType = animate->getValuesType();
+//      bool result = SkScriptEngine::ConvertTo(NULL, SkType_Int, &value);
+//      SkASSERT(result);
+//      duration = value.fOperand.fS32 * SK_MSec1;
+//  }
+    state.fDuration = duration;
+    SkMSec maxTime = state.fBegin + duration;
+    if (fMaxTime < maxTime)
+        fMaxTime = maxTime;
+}
+
+void SkActive::create(SkDrawable* drawable, SkMSec time) {
+    fApply.fLastTime = time;
+    fApply.refresh(fMaker);
+    for (int index = 0; index < fAnimators.count(); index++) {
+        SkAnimateBase* animate = fAnimators[index];
+        SkOperandInterpolator& interpolator = *fInterpolators[index];
+        int count = animate->components();
+        if (animate->formula.size() > 0) {
+            SkTDOperandArray values;
+            values.setCount(count);
+            bool success = animate->fFieldInfo->setValue(fMaker, &values, 0, 0, NULL, 
+                animate->getValuesType(), animate->formula);
+            SkASSERT(success);
+            fApply.applyValues(index, values.begin(), count, animate->getValuesType(), time);
+        } else {
+            SkAutoSTMalloc<16, SkOperand> values(count);
+            interpolator.timeToValues(time, values.get());
+            fApply.applyValues(index, values.get(), count, animate->getValuesType(), time);
+        }
+    }
+    drawable->enable(fMaker);
+    SkASSERT(fAnimators.count() == fInterpolators.count());
+}
+
+bool SkActive::immediate(bool enable) {
+    SkMSec time = 0;
+    bool result = false;
+    SkDrawable* drawable = fApply.scope;
+    SkMSec final = fMaxTime;
+    do {
+        bool applied = fAnimators.count() == 0;
+        fApply.fLastTime = time;
+        fApply.refresh(fMaker);
+        for (int index = 0; index < fAnimators.count(); index++) {
+            SkAnimateBase* animate = fAnimators[index];
+            SkState& state = fState[index];
+            if (state.fMode != SkApply::kMode_immediate)
+                continue;
+            if (state.fBegin > time)
+                continue;
+            if (time > state.fBegin + state.fDuration)
+                continue;
+            applied = true;
+            SkOperandInterpolator& interpolator = *fInterpolators[index];
+            int count = animate->components();
+            if (animate->formula.size() > 0) {
+                SkTDOperandArray values;
+                values.setCount(count);
+                bool success = animate->fFieldInfo->setValue(fMaker, &values, 0, 0, NULL, 
+                    animate->getValuesType(), animate->formula);
+                SkASSERT(success);
+                fApply.applyValues(index, values.begin(), count, animate->getValuesType(), time);
+            } else {
+                SkAutoSTMalloc<16, SkOperand> values(count);
+                interpolator.timeToValues(time, values.get());
+                fApply.applyValues(index, values.get(), count, animate->getValuesType(), time);
+            }
+        }
+        if (enable)
+            drawable->enable(fMaker);
+        else if (applied)
+            result |= drawable->draw(fMaker);
+        time += SK_MSec1;
+    } while (time <= final);
+    return result;
+}
+
+void SkActive::fixInterpolator(SkBool save) {
+    int animators = fAnimators.count();
+    for (int index = 0; index < animators; index++) {
+        SkAnimateBase* animate = fAnimators[index];
+        if (save) { // saved slots increased
+            animate->refresh(fMaker);
+            SkOperand* values = animate->getValues();
+            setInterpolator(index, values);
+            saveInterpolatorValues(index);
+        } else
+            restoreInterpolatorValues(index);
+    }
+}
+
+SkMSec SkActive::getTime(SkMSec inTime, int animatorIndex) {
+    fState[animatorIndex].fTicks = inTime;
+    return inTime - fState[animatorIndex].fStartTime;
+}
+
+bool SkActive::initializeSave() {
+    int animators = fAnimators.count();
+    int activeTotal = fDrawIndex + animators;
+    int oldCount = fSaveRestore.count();
+    if (oldCount < activeTotal) {
+        fSaveRestore.setCount(activeTotal);
+        memset(&fSaveRestore[oldCount], 0, sizeof(fSaveRestore[0]) * (activeTotal - oldCount));
+        SkASSERT(fSaveInterpolators.count() == oldCount);
+        fSaveInterpolators.setCount(activeTotal);
+        memset(&fSaveInterpolators[oldCount], 0, 
+            sizeof(fSaveInterpolators[0]) * (activeTotal - oldCount));
+        return true;
+    }
+    return false;
+}
+
+void SkActive::initState(SkApply* apply, int offset) {
+    int count = fState.count();
+    for (int index = offset; index < count; index++) {
+        SkState& state = fState[index];
+        SkAnimateBase* animate = fAnimators[index];
+#if 0 // def SK_DEBUG
+        if (animate->fHasEndEvent)
+            SkDebugf("%8x %8x active initState:\n", this, animate);
+#endif
+        SkOperand* from = animate->getValues();
+        state.fStartTime = state.fBegin = apply->begin + animate->begin;
+        state.fMode = apply->mode;
+        state.fTransition = apply->transition;
+#if 0
+        state.fPickup = (SkBool8) apply->pickup;
+#endif
+        state.fRestore = (SkBool8) apply->restore;
+        state.fSave = apply->begin;
+        state.fStarted = false;
+        state.fSteps = apply->steps;
+        state.fTicks = 0;
+        state.fUnpostedEndEvent = (SkBool8) animate->fHasEndEvent; 
+        calcDurations(index);
+        setInterpolator(index, from);
+    }
+    if (count == 0 && (apply->mode == SkApply::kMode_immediate || apply->mode == SkApply::kMode_create))
+        fMaxTime = apply->begin + apply->steps * SK_MSec1;
+}
+
+void SkActive::pickUp(SkActive* existing) {
+    SkTDOperandArray existingValues;
+    for (int index = 0; index < fAnimators.count(); index++) {
+        SkAnimateBase* animate = fAnimators[index];
+        SkASSERT(animate->getValuesType() == SkType_Float);
+        int components = animate->components();
+        SkOperand* from = animate->getValues();
+        SkOperand* to = &from[animate->components()];
+        existingValues.setCount(components);
+        existing->fInterpolators[index]->timeToValues(
+            existing->fState[index].fTicks - existing->fState[index].fStartTime, existingValues.begin());
+        SkScalar originalSum = 0;
+        SkScalar workingSum = 0;
+        for (int cIndex = 0; cIndex < components; cIndex++) {
+            SkScalar delta = to[cIndex].fScalar - from[cIndex].fScalar;
+            originalSum += SkScalarMul(delta, delta);
+            delta = to[cIndex].fScalar - existingValues[cIndex].fScalar;
+            workingSum += SkScalarMul(delta, delta);
+        }
+        if (workingSum < originalSum) {
+            SkScalar originalDistance = SkScalarSqrt(originalSum);
+            SkScalar workingDistance = SkScalarSqrt(workingSum);
+            existing->fState[index].fDuration = (SkMSec) SkScalarMulDiv(fState[index].fDuration, 
+                workingDistance, originalDistance);
+        }
+        fInterpolators[index]->reset(components, 2, SkType_Float);
+        fInterpolators[index]->setKeyFrame(0, 0, existingValues.begin(), animate->blend[0]);
+        fInterpolators[index]->setKeyFrame(1, fState[index].fDuration, to, animate->blend[0]);
+    }
+}
+
+void SkActive::resetInterpolators() {
+    int animators = fAnimators.count();
+    for (int index = 0; index < animators; index++) {
+        SkAnimateBase* animate = fAnimators[index];
+        SkOperand* values = animate->getValues();
+        setInterpolator(index, values);
+    }
+}
+
+void SkActive::resetState() {
+    fDrawIndex = 0;
+    int count = fState.count();
+    for (int index = 0; index < count; index++) {
+        SkState& state = fState[index];
+        SkAnimateBase* animate = fAnimators[index];
+#if 0 // def SK_DEBUG
+        if (animate->fHasEndEvent)
+            SkDebugf("%8x %8x active resetState: has end event\n", this, animate);
+#endif
+        state.fStartTime = state.fBegin = fApply.begin + animate->begin;
+        state.fStarted = false;
+        state.fTicks = 0;
+    }
+}
+
+void SkActive::restoreInterpolatorValues(int index) {
+    SkOperandInterpolator& interpolator = *fInterpolators[index];
+    index += fDrawIndex ;
+    int count = interpolator.getValuesCount();
+    memcpy(interpolator.getValues(), fSaveInterpolators[index], count * sizeof(SkOperand));
+}
+
+void SkActive::saveInterpolatorValues(int index) {
+    SkOperandInterpolator& interpolator = *fInterpolators[index];
+    index += fDrawIndex ;
+    int count = interpolator.getValuesCount();
+    SkOperand* cache = new SkOperand[count];    // this should use sk_malloc/sk_free since SkOperand does not have a constructor/destructor
+    fSaveInterpolators[index] = cache;
+    memcpy(cache,   interpolator.getValues(), count * sizeof(SkOperand));
+}
+
+void SkActive::setInterpolator(int index, SkOperand* from) {
+    if (from == NULL) // legitimate for set string
+        return;
+    SkAnimateBase* animate = fAnimators[index];
+    int entries = animate->entries();
+    SkASSERT(entries > 0);
+    SkMSec duration = fState[index].fDuration;
+    int components = animate->components();
+    SkOperandInterpolator& interpolator = *fInterpolators[index];
+    interpolator.reset(components, entries == 1 ? 2 : entries, animate->getValuesType()); 
+    interpolator.setMirror(SkToBool(animate->fMirror));
+    interpolator.setReset(SkToBool(animate->fReset));
+    interpolator.setRepeatCount(animate->repeat);
+    if (entries == 1) {
+        interpolator.setKeyFrame(0, 0, from, animate->blend[0]);
+        interpolator.setKeyFrame(1, duration, from, animate->blend[0]);
+        return;
+    }
+    for (int entry = 0; entry < entries; entry++) {
+        int blendIndex = SkMin32(animate->blend.count() - 1, entry);
+        interpolator.setKeyFrame(entry, entry * duration / (entries - 1), from, 
+            animate->blend[blendIndex]);
+        from += components;
+    }
+}
+
+void SkActive::setSteps(int steps) {
+    int count = fState.count();
+    fMaxTime = 0;
+    for (int index = 0; index < count; index++) {
+        SkState& state = fState[index];
+        state.fSteps = steps;
+        calcDurations(index);
+    }
+}
+
+void SkActive::start() {
+    int count = fState.count();
+    SkASSERT(count == fAnimators.count());
+    SkASSERT(count == fInterpolators.count());
+    for (int index = 0; index < count; index++) {
+        SkState& state = fState[index];
+        if (state.fStarted)
+            continue;
+        state.fStarted = true;
+#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
+        SkString debugOut;
+        SkMSec time = fMaker.getAppTime();
+        debugOut.appendS32(time - fMaker.fDebugTimeBase);
+        debugOut.append(" active start adjust delay id=");
+        debugOut.append(fApply._id);
+        debugOut.append("; ");
+        debugOut.append(fAnimators[index]->_id);
+        debugOut.append("=");
+        debugOut.appendS32(fAnimators[index]->fStart - fMaker.fDebugTimeBase);
+        debugOut.append(":");
+        debugOut.appendS32(state.fStartTime);
+#endif
+        if (state.fStartTime > 0) {
+            SkMSec future = fAnimators[index]->fStart + state.fStartTime;
+            if (future > fMaker.fEnableTime)
+                fMaker.notifyInvalTime(future);
+            else
+                fMaker.notifyInval();
+#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
+            debugOut.append(":");
+            debugOut.appendS32(future - fMaker.fDebugTimeBase);
+#endif
+        }
+        if (state.fStartTime >= fMaker.fAdjustedStart) {
+            state.fStartTime -= fMaker.fAdjustedStart;
+#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
+            debugOut.append(" (less adjust = ");
+            debugOut.appendS32(fMaker.fAdjustedStart);
+#endif
+        }
+        state.fStartTime += fAnimators[index]->fStart;
+#if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING
+        debugOut.append(") new start = ");
+        debugOut.appendS32(state.fStartTime - fMaker.fDebugTimeBase);
+        SkDebugf("%s\n", debugOut.c_str());
+//      SkASSERT((int) (state.fStartTime - fMaker.fDebugTimeBase) >= 0);
+#endif
+    }
+    SkASSERT(fAnimators.count() == fInterpolators.count());
+}
+
+#ifdef SK_DEBUG
+void SkActive::validate() {
+    int count = fState.count();
+    SkASSERT(count == fAnimators.count());
+    SkASSERT(count == fInterpolators.count());
+    for (int index = 0; index < count; index++) {
+        SkASSERT(fAnimators[index]);
+        SkASSERT(fInterpolators[index]);
+//      SkAnimateBase* test = fAnimators[index];
+//      SkASSERT(fApply.scope == test->fTarget || fApply.scope->contains(test->fTarget));
+    }
+}
+#endif
+
+// think about this
+// there should only be one animate object, not two, to go up and down
+// when the apply with reverse came into play, it needs to pick up the value
+// of the existing animate object then remove it from the list
+// the code below should only be bumping fSave, and there shouldn't be anything
+// it needs to be synchronized with
+
+// however, if there are two animates both operating on the same field, then 
+// when one replaces the other, it may make sense to pick up the old value as a starting 
+// value for the new one somehow.
+
+//void SkActive::SkState::bumpSave() {
+//  if (fMode != SkApply::kMode_hold) 
+//      return;
+//  if (fTransition == SkApply::kTransition_reverse) {
+//      if (fSave > 0)
+//          fSave -= SK_MSec1;
+//  } else if (fSave < fDuration)
+//      fSave += SK_MSec1;
+//}
+
+SkMSec SkActive::SkState::getRelativeTime(SkMSec time) {
+    SkMSec result = time;
+//  if (fMode == SkApply::kMode_hold)
+//      result = fSave;
+//  else
+    if (fTransition == SkApply::kTransition_reverse) {
+        if (SkMSec_LT(fDuration, time))
+            result = 0;
+        else
+            result = fDuration - time;
+    }
+    return result;
+}
+
+