void SkInclude::onEndElement(SkAnimateMaker& maker) { maker.fInInclude = true; if (src.size() == 0 || maker.decodeURI(src.c_str()) == false) { if (maker.getErrorCode() != SkXMLParserError::kNoError || maker.getNativeCode() != -1) { maker.setInnerError(&maker, src); maker.setErrorCode(SkDisplayXMLParserError::kInInclude); } else { maker.setErrorNoun(src); maker.setErrorCode(SkDisplayXMLParserError::kIncludeNameUnknownOrMissing); } } maker.fInInclude = false; }
void SkDrawShape2DPathEffect::onEndElement(SkAnimateMaker& maker) { if (addPath == nullptr || (addPath->isPath() == false && addPath->isApply() == false) || matrix == nullptr) maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error else fPathEffect = new SkShape2DPathEffect(this, &maker, matrix->getMatrix()); }
void SkSet::onEndElement(SkAnimateMaker& maker) { if (resolveCommon(maker) == false) return; if (fFieldInfo == NULL) { maker.setErrorCode(SkDisplayXMLParserError::kFieldNotInTarget); return; } fReset = dur != 1; SkDisplayTypes outType = fFieldInfo->getType(); int comps = outType == SkType_String || outType == SkType_DynamicString ? 1 : fFieldInfo->getSize((const SkDisplayable*) fTarget) / sizeof(int); if (fValues.getType() == SkType_Unknown) { fValues.setType(outType); fValues.setCount(comps); if (outType == SkType_String || outType == SkType_DynamicString) fValues[0].fString = SkNEW(SkString); else memset(fValues.begin(), 0, fValues.count() * sizeof(fValues.begin()[0])); } else { SkASSERT(fValues.getType() == outType); if (fFieldInfo->fType == SkType_Array) comps = fValues.count(); else SkASSERT(fValues.count() == comps); } if (formula.size() > 0) { comps = 1; outType = SkType_MSec; } fFieldInfo->setValue(maker, &fValues, fFieldOffset, comps, this, outType, formula.size() > 0 ? formula : to); fComponents = fValues.count(); }
void SkApply::onEndElement(SkAnimateMaker& maker) { SkDrawable* scopePtr = scope; while (scopePtr && scopePtr->isApply()) { SkApply* scopedApply = (SkApply*) scopePtr; if (scopedApply->scope == this) { maker.setErrorCode(SkDisplayXMLParserError::kApplyScopesItself); return; } scopePtr = scopedApply->scope; } if (mode == kMode_create) return; if (scope != NULL && steps >= 0 && scope->isApply() == false && scope->isDrawable()) scope->setSteps(steps); for (SkAnimateBase** animPtr = fAnimators.begin(); animPtr < fAnimators.end(); animPtr++) { SkAnimateBase* anim = *animPtr; //for reusing apply statements with dynamic scope if (anim->fTarget == NULL || anim->fTargetIsScope) { anim->fTargetIsScope = true; if (scope) anim->fTarget = scope; else anim->setTarget(maker); anim->onEndElement(maker); // allows animate->fFieldInfo to be set } if (scope != NULL && steps >= 0 && anim->fTarget != scope && anim->fTarget->isDrawable()) anim->fTarget->setSteps(steps); } }
bool SkDrawMatrix::add(SkAnimateMaker& maker, SkDisplayable* child) { SkASSERT(child && child->isMatrixPart()); SkMatrixPart* part = (SkMatrixPart*) child; *fParts.append() = part; if (part->add()) maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToMatrix); return true; }
bool SkDrawPath::add(SkAnimateMaker& maker, SkDisplayable* child) { SkASSERT(child && child->isPathPart()); SkPathPart* part = (SkPathPart*) child; *fParts.append() = part; if (part->add()) maker.setErrorCode(SkDisplayXMLParserError::kErrorAddingToPath); fDirty = false; return true; }
void SkTextToPath::onEndElement(SkAnimateMaker& maker) { if (paint == NULL || path == NULL || text == NULL) { // !!! add error message here maker.setErrorCode(SkDisplayXMLParserError::kErrorInAttributeValue); return; } SkPaint realPaint; paint->setupPaint(&realPaint); realPaint.getTextPath(text->getText(), text->getSize(), text->x, text->y, &path->getPath()); }
void SkDisplayMovie::buildMovie() { if (fMovieBuilt) return; SkAnimateMaker* movieMaker = fMovie.fMaker; SkAnimateMaker* parentMaker = movieMaker->fParentMaker; if (src.size() == 0 || parentMaker == NULL) return; movieMaker->fPrefix.set(parentMaker->fPrefix); fDecodedSuccessfully = fMovie.fMaker->decodeURI(src.c_str()); if (fDecodedSuccessfully == false) { if (movieMaker->getErrorCode() != SkXMLParserError::kNoError || movieMaker->getNativeCode() != -1) { movieMaker->setInnerError(parentMaker, src); parentMaker->setErrorCode(SkDisplayXMLParserError::kInMovie); } else { parentMaker->setErrorNoun(src); parentMaker->setErrorCode(SkDisplayXMLParserError::kMovieNameUnknownOrMissing); } } fMovieBuilt = true; }
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); }
void SkAnimateBase::setTarget(SkAnimateMaker& maker) { if (target.size()) { SkAnimatorScript engine(maker, this, SkType_Displayable); const char* script = target.c_str(); SkScriptValue scriptValue; bool success = engine.evaluateScript(&script, &scriptValue); if (success && scriptValue.fType == SkType_Displayable) fTarget = scriptValue.fOperand.fDrawable; else if (maker.find(target.c_str(), (SkDisplayable**) &fTarget) == false) { if (fApply->getMode() == SkApply::kMode_create) return; // may not be an error if (engine.getError() != SkScriptEngine::kNoError) maker.setScriptError(engine); else { maker.setErrorNoun(target); maker.setErrorCode(SkDisplayXMLParserError::kTargetIDNotFound); } return; } if (fApply && fApply->getMode() != SkApply::kMode_create) target.reset(); } }
void SkSaveLayer::onEndElement(SkAnimateMaker& maker) { if (!bounds) maker.setErrorCode(SkDisplayXMLParserError::kSaveLayerNeedsBounds); INHERITED::onEndElement(maker); }
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; }
bool SkApply::enable(SkAnimateMaker& maker) { fEnabled = true; bool initialized = fActive != NULL; if (dynamicScope.size() > 0) enableDynamic(maker); if (maker.fError.hasError()) return false; int animators = fAnimators.count(); int index; for (index = 0; index < animators; index++) { SkAnimateBase* animator = fAnimators[index]; animator->fStart = maker.fEnableTime; animator->fResetPending = animator->fReset; } if (scope && scope->isApply()) ((SkApply*) scope)->setEmbedded(); /* if (mode == kMode_once) { if (scope) { activate(maker); interpolate(maker, maker.fEnableTime); inactivate(maker); } return true; }*/ if ((mode == kMode_immediate || mode == kMode_create) && scope == NULL) return false; // !!! error? bool enableMe = scope && (scope->hasEnable() || scope->isApply() || scope->isDrawable() == false); if (mode == kMode_immediate && enableMe || mode == kMode_create) activate(maker); // for non-drawables like post, prime them here if (mode == kMode_immediate && enableMe) fActive->enable(); if (mode == kMode_create && scope != NULL) { enableCreate(maker); return true; } if (mode == kMode_immediate) { return scope->isApply() || scope->isDrawable() == false; } refresh(maker); SkDisplayList& displayList = maker.fDisplayList; SkDrawable* drawable; #if defined SK_DEBUG && defined SK_DEBUG_ANIMATION_TIMING SkString debugOut; SkMSec time = maker.getAppTime(); debugOut.appendS32(time - maker.fDebugTimeBase); debugOut.append(" apply enable id="); debugOut.append(_id); debugOut.append("; start="); debugOut.appendS32(maker.fEnableTime - maker.fDebugTimeBase); SkDebugf("%s\n", debugOut.c_str()); #endif if (scope == NULL || scope->isApply() || scope->getType() == SkType_Movie || scope->isDrawable() == false) { activate(maker); // for non-drawables like post, prime them here if (initialized) { append(this); } fEnabling = true; interpolate(maker, maker.fEnableTime); fEnabling = false; if (scope != NULL && dontDraw == false) scope->enable(maker); return true; } else if (initialized && restore == false) append(this); #if 0 bool wasActive = inactivate(maker); // start fresh if (wasActive) { activate(maker); interpolate(maker, maker.fEnableTime); return true; } #endif // start here; // now that one apply might embed another, only the parent apply should replace the scope // or get appended to the display list // similarly, an apply added by an add immediate has already been located in the display list // and should not get moved or added again here if (fEmbedded) { return false; // already added to display list by embedder } drawable = (SkDrawable*) scope; SkTDDrawableArray* parentList; SkTDDrawableArray* grandList; SkGroup* parentGroup; SkGroup* thisGroup; int old = displayList.findGroup(drawable, &parentList, &parentGroup, &thisGroup, &grandList); if (old < 0) goto append; else if (fContainsScope) { if ((*parentList)[old] != this || restore == true) { append: if (parentGroup) parentGroup->markCopySize(old); if (parentList->count() < 10000) { fAppended = true; *parentList->append() = this; } else maker.setErrorCode(SkDisplayXMLParserError::kDisplayTreeTooDeep); old = -1; } else reset(); } else { SkASSERT(old < parentList->count()); if ((*parentList)[old]->isApply()) { SkApply* apply = (SkApply*) (*parentList)[old]; if (apply != this && apply->fActive == NULL) apply->activate(maker); apply->append(this); parentGroup = NULL; } else { if (parentGroup) parentGroup->markCopySize(old); SkDrawable** newApplyLocation = &(*parentList)[old]; SkGroup* pGroup; int oldApply = displayList.findGroup(this, &parentList, &pGroup, &thisGroup, &grandList); if (oldApply >= 0) { (*parentList)[oldApply] = (SkDrawable*) SkDisplayType::CreateInstance(&maker, SkType_Apply); parentGroup = NULL; fDeleteScope = true; } *newApplyLocation = this; } } if (parentGroup) { parentGroup->markCopySet(old); fDeleteScope = dynamicScope.size() == 0; } return true; }
void SkDrawShape1DPathEffect::onEndElement(SkAnimateMaker& maker) { if (addPath == NULL || (addPath->isPath() == false && addPath->isApply() == false)) maker.setErrorCode(SkDisplayXMLParserError::kUnknownError); // !!! add error else fPathEffect = new SkShape1DPathEffect(this, &maker); }
bool SkAdd::enable(SkAnimateMaker& maker ) { SkDisplayTypes type = getType(); SkDisplayList& displayList = maker.fDisplayList; SkTDDrawableArray* parentList = displayList.getDrawList(); if (type == SkType_Add) { if (use == NULL) // not set in apply yet return true; } bool skipAddToParent = true; SkASSERT(type != SkType_Replace || where); SkTDDrawableArray* grandList SK_INIT_TO_AVOID_WARNING; SkGroup* parentGroup = NULL; SkGroup* thisGroup = NULL; int index = where ? displayList.findGroup(where, &parentList, &parentGroup, &thisGroup, &grandList) : 0; if (index < 0) return true; int max = parentList->count(); if (where == NULL && type == SkType_Move) index = max; if (offset != SK_MaxS32) { index += offset; if (index > max) { maker.setErrorCode(SkDisplayXMLParserError::kIndexOutOfRange); return true; // caller should not add } } if (offset < 0 && where == NULL) index += max + 1; switch (type) { case SkType_Add: if (offset == SK_MaxS32 && where == NULL) { if (use->isDrawable()) { skipAddToParent = mode == kMode_immediate; if (skipAddToParent) { if (where == NULL) { SkTDDrawableArray* useParentList; index = displayList.findGroup(this, &useParentList, &parentGroup, &thisGroup, &grandList); if (index >= 0) { parentGroup->markCopySize(index); parentGroup->markCopySet(index); useParentList->begin()[index] = use; break; } } *parentList->append() = use; } } break; } else { if (thisGroup) thisGroup->markCopySize(index); *parentList->insert(index) = use; if (thisGroup) thisGroup->markCopySet(index); if (use->isApply()) ((SkApply*) use)->setEmbedded(); } break; case SkType_Move: { int priorLocation = parentList->find(use); if (priorLocation < 0) break; *parentList->insert(index) = use; if (index < priorLocation) priorLocation++; parentList->remove(priorLocation); } break; case SkType_Remove: { SkDisplayable* old = (*parentList)[index]; if (((SkRemove*)(this))->fDelete) { delete old; goto noHelperNeeded; } for (int inner = 0; inner < maker.fChildren.count(); inner++) { SkDisplayable* child = maker.fChildren[inner]; if (child == old || child->contains(old)) goto noHelperNeeded; } if (maker.fHelpers.find(old) < 0) maker.helperAdd(old); noHelperNeeded: parentList->remove(index); } break; case SkType_Replace: if (thisGroup) { thisGroup->markCopySize(index); if (thisGroup->markedForDelete(index)) { SkDisplayable* old = (*parentList)[index]; if (maker.fHelpers.find(old) < 0) maker.helperAdd(old); } } (*parentList)[index] = use; if (thisGroup) thisGroup->markCopySet(index); break; default: SkASSERT(0); } if (type == SkType_Remove) return true; if (use->hasEnable()) use->enable(maker); return skipAddToParent; // append if indirect: *parentList->append() = this; }