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; }
size_t SkMemberInfo::getSize(const SkDisplayable* displayable) const { size_t byteSize; switch (fType) { case SkType_MemberProperty: byteSize = GetSize(propertyType()); break; case SkType_Array: { SkDisplayTypes type; if (displayable == NULL) return sizeof(int); if (displayable->getType() == SkType_Array) { SkDisplayArray* dispArray = (SkDisplayArray*) displayable; type = dispArray->values.getType(); } else type = propertyType(); SkTDOperandArray* array = (SkTDOperandArray*) memberData(displayable); byteSize = GetSize(type) * array->count(); } break; default: byteSize = GetSize((SkDisplayTypes) fType); } return byteSize; }
SkDisplayable* SkDisplayable::deepCopy(SkAnimateMaker* maker) { SkDisplayTypes type = getType(); if (type == SkType_Unknown) { SkASSERT(0); return NULL; } SkDisplayable* copy = SkDisplayType::CreateInstance(maker, type); int index = -1; int propIndex = 0; const SkMemberInfo* info; do { info = copy->getMember(++index); if (info == NULL) break; if (info->fType == SkType_MemberProperty) { SkScriptValue value; if (getProperty(propIndex, &value)) copy->setProperty(propIndex, value); propIndex++; continue; } if (info->fType == SkType_MemberFunction) continue; if (info->fType == SkType_Array) { SkTDOperandArray* array = (SkTDOperandArray*) info->memberData(this); int arrayCount; if (array == NULL || (arrayCount = array->count()) == 0) continue; SkTDOperandArray* copyArray = (SkTDOperandArray*) info->memberData(copy); copyArray->setCount(arrayCount); SkDisplayTypes elementType; if (type == SkType_Array) { SkDisplayArray* dispArray = (SkDisplayArray*) this; elementType = dispArray->values.getType(); } else elementType = info->arrayType(); size_t elementSize = SkMemberInfo::GetSize(elementType); size_t byteSize = elementSize * arrayCount; memcpy(copyArray->begin(), array->begin(), byteSize); continue; } if (SkDisplayType::IsDisplayable(maker, info->fType)) { SkDisplayable** displayable = (SkDisplayable**) info->memberData(this); if (*displayable == NULL || *displayable == (SkDisplayable*) -1) continue; SkDisplayable* deeper = (*displayable)->deepCopy(maker); info->setMemberData(copy, deeper, sizeof(deeper)); continue; } if (info->fType == SkType_String || info->fType == SkType_DynamicString) { SkString* string; info->getString(this, &string); info->setString(copy, string); continue; } void* data = info->memberData(this); size_t size = SkMemberInfo::GetSize(info->fType); info->setMemberData(copy, data, size); } while (true); copy->dirty(); return copy; }
void SkDisplayable::dumpAttrs(SkAnimateMaker* maker) { SkDisplayTypes type = getType(); if (type == SkType_Unknown) { //SkDebugf("/>\n"); return; } SkDisplayable* blankCopy = SkDisplayType::CreateInstance(maker, type); int index = -1; int propIndex = 0; const SkMemberInfo* info; const SkMemberInfo* blankInfo; SkScriptValue value; SkScriptValue blankValue; SkOperand values[2]; SkOperand blankValues[2]; do { info = this->getMember(++index); if (NULL == info) { //SkDebugf("\n"); break; } if (SkType_MemberProperty == info->fType) { if (getProperty(propIndex, &value)) { blankCopy->getProperty(propIndex, &blankValue); //last two are dummies dumpValues(info, value.fType, value.fOperand, blankValue.fOperand, value.fOperand, blankValue.fOperand); } propIndex++; continue; } if (SkDisplayType::IsDisplayable(maker, info->fType)) { continue; } if (info->fType == SkType_MemberFunction) continue; if (info->fType == SkType_Array) { SkTDOperandArray* array = (SkTDOperandArray*) info->memberData(this); int arrayCount; if (array == NULL || (arrayCount = array->count()) == 0) continue; SkDisplayTypes elementType; if (type == SkType_Array) { SkDisplayArray* dispArray = (SkDisplayArray*) this; elementType = dispArray->values.getType(); } else elementType = info->arrayType(); bool firstElem = true; SkDebugf("%s=\"[", info->fName); for (SkOperand* op = array->begin(); op < array->end(); op++) { if (!firstElem) SkDebugf(","); switch (elementType) { case SkType_Displayable: SkDebugf("%s", op->fDisplayable->id); break; case SkType_Int: SkDebugf("%d", op->fS32); break; case SkType_Float: #ifdef SK_CAN_USE_FLOAT SkDebugf("%g", SkScalarToFloat(op->fScalar)); #else SkDebugf("%x", op->fScalar); #endif break; case SkType_String: case SkType_DynamicString: SkDebugf("%s", op->fString->c_str()); break; default: break; } firstElem = false; } SkDebugf("]\" "); continue; } if (info->fType == SkType_String || info->fType == SkType_DynamicString) { SkString* string; info->getString(this, &string); if (string->isEmpty() == false) SkDebugf("%s=\"%s\"\t", info->fName, string->c_str()); continue; } blankInfo = blankCopy->getMember(index); int i = info->fCount; info->getValue(this, values, i); blankInfo->getValue(blankCopy, blankValues, i); dumpValues(info, info->fType, values[0], blankValues[0], values[1], blankValues[1]); } while (true); delete blankCopy; }