void nsSMILCompositor::ComposeAttribute(bool& aMightHavePendingStyleUpdates) { if (!mKey.mElement) return; // FIRST: Get the nsISMILAttr (to grab base value from, and to eventually // give animated value to) nsAutoPtr<nsISMILAttr> smilAttr(CreateSMILAttr()); if (!smilAttr) { // Target attribute not found (or, out of memory) return; } if (mAnimationFunctions.IsEmpty()) { // No active animation functions. (We can still have a nsSMILCompositor in // that case if an animation function has *just* become inactive) smilAttr->ClearAnimValue(); // Removing the animation effect may require a style update. aMightHavePendingStyleUpdates = true; return; } // SECOND: Sort the animationFunctions, to prepare for compositing. nsSMILAnimationFunction::Comparator comparator; mAnimationFunctions.Sort(comparator); // THIRD: Step backwards through animation functions to find out // which ones we actually care about. uint32_t firstFuncToCompose = GetFirstFuncToAffectSandwich(); // FOURTH: Get & cache base value nsSMILValue sandwichResultValue; if (!mAnimationFunctions[firstFuncToCompose]->WillReplace()) { sandwichResultValue = smilAttr->GetBaseValue(); } UpdateCachedBaseValue(sandwichResultValue); if (!mForceCompositing) { return; } // FIFTH: Compose animation functions aMightHavePendingStyleUpdates = true; uint32_t length = mAnimationFunctions.Length(); for (uint32_t i = firstFuncToCompose; i < length; ++i) { mAnimationFunctions[i]->ComposeResult(*smilAttr, sandwichResultValue); } if (sandwichResultValue.IsNull()) { smilAttr->ClearAnimValue(); return; } // SIXTH: Set the animated value to the final composited result. nsresult rv = smilAttr->SetAnimValue(sandwichResultValue); if (NS_FAILED(rv)) { NS_WARNING("nsISMILAttr::SetAnimValue failed"); } }
void nsSMILCompositor::ClearAnimationEffects() { if (!mKey.mElement || !mKey.mAttributeName) return; nsAutoPtr<nsISMILAttr> smilAttr(CreateSMILAttr()); if (!smilAttr) { // Target attribute not found (or, out of memory) return; } smilAttr->ClearAnimValue(); }