bool SkAnimatorScript::Unbox(void* m, SkScriptValue* scriptValue) { SkAnimateMaker* maker = (SkAnimateMaker*) m; SkASSERT((unsigned) scriptValue->fType == (unsigned) SkType_Displayable); SkDisplayable* displayable = (SkDisplayable*) scriptValue->fOperand.fObject; SkDisplayTypes type = displayable->getType(); switch (displayable->getType()) { case SkType_Array: { SkDisplayArray* boxedValue = (SkDisplayArray*) displayable; scriptValue->fOperand.fArray = &boxedValue->values; } break; case SkType_Boolean: { SkDisplayBoolean* boxedValue = (SkDisplayBoolean*) displayable; scriptValue->fOperand.fS32 = boxedValue->value; } break; case SkType_Int: { SkDisplayInt* boxedValue = (SkDisplayInt*) displayable; scriptValue->fOperand.fS32 = boxedValue->value; } break; case SkType_Float: { SkDisplayFloat* boxedValue = (SkDisplayFloat*) displayable; scriptValue->fOperand.fScalar = boxedValue->value; } break; case SkType_String: { SkDisplayString* boxedValue = (SkDisplayString*) displayable; scriptValue->fOperand.fString = SkNEW_ARGS(SkString, (boxedValue->value)); } break; default: { const char* id = NULL; bool success = maker->findKey(displayable, &id); SkASSERT(success); scriptValue->fOperand.fString = SkNEW_ARGS(SkString, (id)); type = SkType_String; } } scriptValue->fType = type; return true; }
bool SkMemberInfo::setValue(SkAnimateMaker& maker, SkTDOperandArray* arrayStorage, int storageOffset, int maxStorage, SkDisplayable* displayable, SkDisplayTypes outType, const char rawValue[], size_t rawValueLen) const { SkString valueStr(rawValue, rawValueLen); SkScriptValue scriptValue; scriptValue.fType = SkType_Unknown; scriptValue.fOperand.fS32 = 0; SkDisplayTypes type = getType(); SkAnimatorScript engine(maker, displayable, type); if (arrayStorage) displayable = NULL; bool success = true; void* untypedStorage = NULL; if (displayable && fType != SkType_MemberProperty && fType != SkType_MemberFunction) untypedStorage = (SkTDOperandArray*) memberData(displayable); if (type == SkType_ARGB) { // for both SpiderMonkey and SkiaScript, substitute any #xyz or #xxyyzz first // it's enough to expand the colors into 0xFFxxyyzz const char* poundPos; while ((poundPos = strchr(valueStr.c_str(), '#')) != NULL) { size_t offset = poundPos - valueStr.c_str(); if (valueStr.size() - offset < 4) break; char r = poundPos[1]; char g = poundPos[2]; char b = poundPos[3]; if (is_hex(r) == false || is_hex(g) == false || is_hex(b) == false) break; char hex = poundPos[4]; if (is_hex(hex) == false) { valueStr.insertUnichar(offset + 1, r); valueStr.insertUnichar(offset + 3, g); valueStr.insertUnichar(offset + 5, b); } *(char*) poundPos = '0'; // overwrite '#' valueStr.insert(offset + 1, "xFF"); } } if (SkDisplayType::IsDisplayable(&maker, type) || SkDisplayType::IsEnum(&maker, type) || type == SkType_ARGB) goto scriptCommon; switch (type) { case SkType_String: #if 0 if (displayable && displayable->isAnimate()) { goto noScriptString; } if (strncmp(rawValue, "#string:", sizeof("#string:") - 1) == 0) { SkASSERT(sizeof("string") == sizeof("script")); char* stringHeader = valueStr.writable_str(); memcpy(&stringHeader[1], "script", sizeof("script") - 1); rawValue = valueStr.c_str(); goto noScriptString; } else #endif if (strncmp(rawValue, "#script:", sizeof("#script:") - 1) != 0) goto noScriptString; valueStr.remove(0, 8); case SkType_Unknown: case SkType_Int: case SkType_MSec: // for the purposes of script, MSec is treated as a Scalar case SkType_Point: case SkType_3D_Point: case SkType_Float: case SkType_Array: scriptCommon: { const char* script = valueStr.c_str(); success = engine.evaluateScript(&script, &scriptValue); if (success == false) { maker.setScriptError(engine); return false; } } SkASSERT(success); if (scriptValue.fType == SkType_Displayable) { if (type == SkType_String) { const char* charPtr; maker.findKey(scriptValue.fOperand.fDisplayable, &charPtr); scriptValue.fOperand.fString = new SkString(charPtr); scriptValue.fType = SkType_String; engine.SkScriptEngine::track(scriptValue.fOperand.fString); break; } SkASSERT(SkDisplayType::IsDisplayable(&maker, type)); if (displayable) displayable->setReference(this, scriptValue.fOperand.fDisplayable); else arrayStorage->begin()[0].fDisplayable = scriptValue.fOperand.fDisplayable; return true; } if (type != scriptValue.fType) { if (scriptValue.fType == SkType_Array) { engine.forget(scriptValue.getArray()); goto writeStruct; // real structs have already been written by script } switch (type) { case SkType_String: success = engine.convertTo(SkType_String, &scriptValue); break; case SkType_MSec: case SkType_Float: success = engine.convertTo(SkType_Float, &scriptValue); break; case SkType_Int: success = engine.convertTo(SkType_Int, &scriptValue); break; case SkType_Array: success = engine.convertTo(arrayType(), &scriptValue); // !!! incomplete; create array of appropriate type and add scriptValue to it SkASSERT(0); break; case SkType_Displayable: case SkType_Drawable: return false; // no way to convert other types to this default: // to avoid warnings break; } if (success == false) return false; } if (type == SkType_MSec) scriptValue.fOperand.fMSec = SkScalarMulRound(scriptValue.fOperand.fScalar, 1000); scriptValue.fType = type; break; noScriptString: case SkType_DynamicString: if (fType == SkType_MemberProperty && displayable) { SkString string(rawValue, rawValueLen); SkScriptValue scriptValue; scriptValue.fOperand.fString = &string; scriptValue.fType = SkType_String; displayable->setProperty(propertyIndex(), scriptValue); } else if (displayable) { SkString* string = (SkString*) memberData(displayable); string->set(rawValue, rawValueLen); } else { SkASSERT(arrayStorage->count() == 1); arrayStorage->begin()->fString->set(rawValue, rawValueLen); } goto dirty; case SkType_Base64: { SkBase64 base64; base64.decode(rawValue, rawValueLen); *(SkBase64* ) untypedStorage = base64; } goto dirty; default: SkASSERT(0); break; } // if (SkDisplayType::IsStruct(type) == false) { writeStruct: if (writeValue(displayable, arrayStorage, storageOffset, maxStorage, untypedStorage, outType, scriptValue)) { maker.setErrorCode(SkDisplayXMLParserError::kUnexpectedType); return false; } } dirty: if (displayable) displayable->dirty(); return true; }