bool SkAnimatorScript::EvalMemberCommon(SkScriptEngine* engine, const SkMemberInfo* info, SkDisplayable* displayable, SkScriptValue* value) { SkDisplayTypes original; SkDisplayTypes type = original = (SkDisplayTypes) info->getType(); if (info->fType == SkType_Array) type = SkType_Array; switch (type) { case SkType_ARGB: type = SkType_Int; case SkType_Boolean: case SkType_Int: case SkType_MSec: case SkType_Float: SkASSERT(info->getCount() == 1); if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) value->fOperand.fS32 = *(int32_t*) info->memberData(displayable); // OK for SkScalar too if (type == SkType_MSec) { value->fOperand.fScalar = SkScalarDiv((SkScalar) value->fOperand.fS32, 1000); // dividing two ints is the same as dividing two scalars type = SkType_Float; } break; case SkType_String: { SkString* displayableString; if (info->fType != SkType_MemberProperty && info->fType != SkType_MemberFunction) { info->getString(displayable, &displayableString); value->fOperand.fString = new SkString(*displayableString); } } break; case SkType_Array: { SkASSERT(info->fType != SkType_MemberProperty); // !!! incomplete SkTDOperandArray* displayableArray = (SkTDOperandArray*) info->memberData(displayable); if (displayable->getType() == SkType_Array) { SkDisplayArray* typedArray = (SkDisplayArray*) displayable; original = typedArray->values.getType(); } SkASSERT(original != SkType_Unknown); SkTypedArray* array = value->fOperand.fArray = new SkTypedArray(original); engine->track(array); int count = displayableArray->count(); if (count > 0) { array->setCount(count); memcpy(array->begin(), displayableArray->begin(), count * sizeof(SkOperand)); } } break; default: SkASSERT(0); // unimplemented } value->fType = type; return true; }
void SkApply::applyValues(int animatorIndex, SkOperand* values, int count, SkDisplayTypes valuesType, SkMSec time) { SkAnimateBase* animator = fActive->fAnimators[animatorIndex]; const SkMemberInfo * info = animator->fFieldInfo; SkASSERT(animator); SkASSERT(info != NULL); SkDisplayTypes type = (SkDisplayTypes) info->fType; SkDisplayable* target = getTarget(animator); if (animator->hasExecute() || type == SkType_MemberFunction || type == SkType_MemberProperty) { SkDisplayable* executor = animator->hasExecute() ? animator : target; if (type != SkType_MemberProperty) { SkTDArray<SkScriptValue> typedValues; for (int index = 0; index < count; index++) { SkScriptValue temp; temp.fType = valuesType; temp.fOperand = values[index]; *typedValues.append() = temp; } executor->executeFunction(target, info->functionIndex(), typedValues, info->getType(), NULL); } else { SkScriptValue scriptValue; scriptValue.fOperand = values[0]; scriptValue.fType = info->getType(); target->setProperty(info->propertyIndex(), scriptValue); } } else { SkTypedArray converted; if (type == SkType_ARGB) { if (count == 4) { // !!! assert that it is SkType_Float ? animator->packARGB(&values->fScalar, count, &converted); values = converted.begin(); count = converted.count(); } else { SkASSERT(count == 1); } } // SkASSERT(type == SkType_ARGB || type == SkType_String ||info->isSettable()); if (type == SkType_String || type == SkType_DynamicString) info->setString(target, values->fString); else if (type == SkType_Drawable || type == SkType_Displayable) target->setReference(info, values->fDisplayable); else info->setValue(target, values, count); } }
void SkAnimate::onEndElement(SkAnimateMaker& maker) { bool resolved = resolveCommon(maker); if (resolved && fFieldInfo == NULL) { maker.setErrorNoun(field); maker.setErrorCode(SkDisplayXMLParserError::kFieldNotInTarget); } if (resolved == false || fFieldInfo == NULL) return; SkDisplayTypes outType = fFieldInfo->getType(); if (fHasValues) { SkASSERT(to.size() > 0); fFieldInfo->setValue(maker, &fValues, 0, 0, NULL, outType, to); SkASSERT(0); // !!! this needs to set fComponents return; } fComponents = fFieldInfo->getCount(); if (fFieldInfo->fType == SkType_Array) { SkTypedArray* array = (SkTypedArray*) fFieldInfo->memberData(fTarget); int count = array->count(); if (count > 0) fComponents = count; } if (outType == SkType_ARGB) { fComponents <<= 2; // four color components outType = SkType_Float; } fValues.setType(outType); if (formula.size() > 0){ fComponents = 1; from.set("0"); to.set("dur"); outType = SkType_MSec; } int max = fComponents * 2; fValues.setCount(max); memset(fValues.begin(), 0, max * sizeof(fValues.begin()[0])); fFieldInfo->setValue(maker, &fValues, fFieldOffset, max, this, outType, from); fFieldInfo->setValue(maker, &fValues, fComponents + fFieldOffset, max, this, outType, to); }
bool SkMemberInfo::writeValue(SkDisplayable* displayable, SkTDOperandArray* arrayStorage, int storageOffset, int maxStorage, void* untypedStorage, SkDisplayTypes outType, SkScriptValue& scriptValue) const { SkOperand* storage = untypedStorage ? (SkOperand*) untypedStorage : arrayStorage ? arrayStorage->begin() : NULL; if (storage) storage += storageOffset; SkDisplayTypes type = getType(); if (fType == SkType_MemberProperty) { if(displayable) displayable->setProperty(propertyIndex(), scriptValue); else { SkASSERT(storageOffset < arrayStorage->count()); switch (scriptValue.fType) { case SkType_Boolean: case SkType_Float: case SkType_Int: memcpy(&storage->fScalar, &scriptValue.fOperand.fScalar, sizeof(SkScalar)); break; case SkType_Array: memcpy(&storage->fScalar, scriptValue.fOperand.fArray->begin(), scriptValue.fOperand.fArray->count() * sizeof(SkScalar)); break; case SkType_String: storage->fString->set(*scriptValue.fOperand.fString); break; default: SkASSERT(0); // type isn't handled yet } } } else if (fType == SkType_MemberFunction) { SkASSERT(scriptValue.fType == SkType_Array); if (displayable) displayable->executeFunction(displayable, this, scriptValue.fOperand.fArray, NULL); else { int count = scriptValue.fOperand.fArray->count(); // SkASSERT(maxStorage == 0 || count == maxStorage); if (arrayStorage->count() == 2) arrayStorage->setCount(2 * count); else { storageOffset *= count; SkASSERT(count + storageOffset <= arrayStorage->count()); } memcpy(&(*arrayStorage)[storageOffset], scriptValue.fOperand.fArray->begin(), count * sizeof(SkOperand)); } } else if (fType == SkType_Array) { SkTypedArray* destArray = (SkTypedArray*) (untypedStorage ? untypedStorage : arrayStorage); SkASSERT(destArray); // destArray->setCount(0); if (scriptValue.fType != SkType_Array) { SkASSERT(type == scriptValue.fType); // SkASSERT(storageOffset + 1 <= maxStorage); destArray->setCount(storageOffset + 1); (*destArray)[storageOffset] = scriptValue.fOperand; } else { if (type == SkType_Unknown) { type = scriptValue.fOperand.fArray->getType(); destArray->setType(type); } SkASSERT(type == scriptValue.fOperand.fArray->getType()); int count = scriptValue.fOperand.fArray->count(); // SkASSERT(storageOffset + count <= maxStorage); destArray->setCount(storageOffset + count); memcpy(destArray->begin() + storageOffset, scriptValue.fOperand.fArray->begin(), sizeof(SkOperand) * count); } } else if (type == SkType_String) { SkString* string = untypedStorage ? (SkString*) untypedStorage : (*arrayStorage)[storageOffset].fString; string->set(*scriptValue.fOperand.fString); } else if (type == SkType_ARGB && outType == SkType_Float) { SkTypedArray* array = scriptValue.fOperand.fArray; SkASSERT(scriptValue.fType == SkType_Int || scriptValue.fType == SkType_ARGB || scriptValue.fType == SkType_Array); SkASSERT(scriptValue.fType != SkType_Array || (array != NULL && array->getType() == SkType_Int)); int numberOfColors = scriptValue.fType == SkType_Array ? array->count() : 1; int numberOfComponents = numberOfColors * 4; // SkASSERT(maxStorage == 0 || maxStorage == numberOfComponents); if (maxStorage == 0) arrayStorage->setCount(numberOfComponents); for (int index = 0; index < numberOfColors; index++) { SkColor color = scriptValue.fType == SkType_Array ? (SkColor) array->begin()[index].fS32 : (SkColor) scriptValue.fOperand.fS32; storage[0].fScalar = SkIntToScalar(SkColorGetA(color)); storage[1].fScalar = SkIntToScalar(SkColorGetR(color)); storage[2].fScalar = SkIntToScalar(SkColorGetG(color)); storage[3].fScalar = SkIntToScalar(SkColorGetB(color)); storage += 4; } } else if (SkDisplayType::IsStruct(NULL /* !!! maker*/, type)) { if (scriptValue.fType != SkType_Array) return true; // error SkASSERT(sizeof(SkScalar) == sizeof(SkOperand)); // !!! no 64 bit pointer support yet int count = scriptValue.fOperand.fArray->count(); if (count > 0) { SkASSERT(fCount == count); memcpy(storage, scriptValue.fOperand.fArray->begin(), count * sizeof(SkOperand)); } } else if (scriptValue.fType == SkType_Array) { SkASSERT(scriptValue.fOperand.fArray->getType() == type); SkASSERT(scriptValue.fOperand.fArray->count() == getCount()); memcpy(storage, scriptValue.fOperand.fArray->begin(), getCount() * sizeof(SkOperand)); } else { memcpy(storage, &scriptValue.fOperand, sizeof(SkOperand)); } return false; }
bool SkApply::interpolate(SkAnimateMaker& maker, SkMSec rawTime) { if (fActive == NULL) return false; bool result = false; #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING SkMSec time = maker.getAppTime(); if (lastTime == (SkMSec) -1) lastTime = rawTime - 1; if (fActive != NULL && strcmp(id, "a3") == 0 && rawTime > lastTime) { lastTime += 1000; SkString debugOut; debugOut.appendS32(time - maker.fDebugTimeBase); debugOut.append(" apply id="); debugOut.append(_id); debugOut.append("; "); debugOut.append(fActive->fAnimators[0]->_id); debugOut.append("="); debugOut.appendS32(rawTime - fActive->fState[0].fStartTime); debugOut.append(")"); SkDebugf("%s\n", debugOut.c_str()); } #endif fActive->start(); if (restore) fActive->initializeSave(); int animators = fActive->fAnimators.count(); for (int inner = 0; inner < animators; inner++) { SkAnimateBase* animate = fActive->fAnimators[inner]; if (animate->fChanged) { animate->fChanged = false; animate->fStart = rawTime; // SkTypedArray values; // int count = animate->fValues.count(); // values.setCount(count); // memcpy(values.begin(), animate->fValues.begin(), sizeof(SkOperand) * count); animate->onEndElement(maker); // if (memcmp(values.begin(), animate->fValues.begin(), sizeof(SkOperand) * count) != 0) { fActive->append(this); fActive->start(); // } } SkMSec time = fActive->getTime(rawTime, inner); SkActive::SkState& state = fActive->fState[inner]; if (SkMSec_LT(rawTime, state.fStartTime)) { if (fEnabling) { animate->fDelayed = true; maker.delayEnable(this, state.fStartTime); } continue; } else animate->fDelayed = false; SkMSec innerTime = fLastTime = state.getRelativeTime(time); if (restore) fActive->restoreInterpolatorValues(inner); if (animate->fReset) { if (transition != SkApply::kTransition_reverse) { if (SkMSec_LT(state.fBegin + state.fDuration, innerTime)) { if (animate->fResetPending) { innerTime = 0; animate->fResetPending = false; } else continue; } } else if (innerTime == 0) { if (animate->fResetPending) { innerTime = state.fBegin + state.fDuration; animate->fResetPending = false; } else continue; } } int count = animate->components(); SkAutoSTMalloc<16, SkOperand> values(count); SkInterpolatorBase::Result interpResult = fActive->fInterpolators[inner]->timeToValues( innerTime, values.get()); result |= (interpResult != SkInterpolatorBase::kFreezeEnd_Result); if ((transition != SkApply::kTransition_reverse && interpResult == SkInterpolatorBase::kFreezeEnd_Result || transition == SkApply::kTransition_reverse && fLastTime == 0) && state.fUnpostedEndEvent) { // SkDEBUGF(("interpolate: post on end\n")); state.fUnpostedEndEvent = false; maker.postOnEnd(animate, state.fBegin + state.fDuration); maker.fAdjustedStart = 0; // !!! left over from synchronizing animation days, undoubtably out of date (and broken) } if (animate->formula.size() > 0) { if (fLastTime > animate->dur) fLastTime = animate->dur; SkTypedArray formulaValues; formulaValues.setCount(count); bool success = animate->fFieldInfo->setValue(maker, &formulaValues, 0, 0, NULL, animate->getValuesType(), animate->formula); SkASSERT(success); if (restore) save(inner); // save existing value applyValues(inner, formulaValues.begin(), count, animate->getValuesType(), innerTime); } else { if (restore) save(inner); // save existing value applyValues(inner, values.get(), count, animate->getValuesType(), innerTime); } } return result; }