nsresult nsSVGAngle::SMILOrient::ValueFromString(const nsAString& aStr, const SVGAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, bool& aPreventCachingOfSandwich) const { nsSMILValue val(&SVGOrientSMILType::sSingleton); if (aStr.EqualsLiteral("auto")) { val.mU.mOrient.mOrientType = SVG_MARKER_ORIENT_AUTO; } else if (aStr.EqualsLiteral("auto-start-reverse")) { val.mU.mOrient.mOrientType = SVG_MARKER_ORIENT_AUTO_START_REVERSE; } else { float value; uint16_t unitType; if (!GetValueFromString(aStr, value, &unitType)) { return NS_ERROR_DOM_SYNTAX_ERR; } val.mU.mOrient.mAngle = value; val.mU.mOrient.mUnit = unitType; val.mU.mOrient.mOrientType = SVG_MARKER_ORIENT_ANGLE; } aValue.Swap(val); aPreventCachingOfSandwich = false; return NS_OK; }
nsresult nsSVGAngle::SMILOrient::ValueFromString(const nsAString& aStr, const nsISMILAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, PRBool& aPreventCachingOfSandwich) const { nsSMILValue val(&SVGOrientSMILType::sSingleton); if (aStr.EqualsLiteral("auto")) { val.mU.mOrient.mOrientType = nsIDOMSVGMarkerElement::SVG_MARKER_ORIENT_AUTO; } else { float value; PRUint16 unitType; nsresult rv = GetValueFromString(aStr, &value, &unitType); if (NS_FAILED(rv)) { return rv; } val.mU.mOrient.mAngle = value; val.mU.mOrient.mUnit = unitType; val.mU.mOrient.mOrientType = nsIDOMSVGMarkerElement::SVG_MARKER_ORIENT_ANGLE; } aValue.Swap(val); aPreventCachingOfSandwich = PR_FALSE; return NS_OK; }
void nsSVGAnimatedTransformList::SMILAnimatedTransformList::ParseValue( const nsAString& aSpec, const nsIAtom* aTransformType, nsSMILValue& aResult) { MOZ_ASSERT(aResult.IsNull(), "Unexpected type for SMIL value"); static_assert(SVGTransformSMILData::NUM_SIMPLE_PARAMS == 3, "nsSVGSMILTransform constructor should be expecting array " "with 3 params"); float params[3] = { 0.f }; int32_t numParsed = ParseParameterList(aSpec, params, 3); uint16_t transformType; if (aTransformType == nsGkAtoms::translate) { // tx [ty=0] if (numParsed != 1 && numParsed != 2) return; transformType = SVG_TRANSFORM_TRANSLATE; } else if (aTransformType == nsGkAtoms::scale) { // sx [sy=sx] if (numParsed != 1 && numParsed != 2) return; if (numParsed == 1) { params[1] = params[0]; } transformType = SVG_TRANSFORM_SCALE; } else if (aTransformType == nsGkAtoms::rotate) { // r [cx=0 cy=0] if (numParsed != 1 && numParsed != 3) return; transformType = SVG_TRANSFORM_ROTATE; } else if (aTransformType == nsGkAtoms::skewX) { // x-angle if (numParsed != 1) return; transformType = SVG_TRANSFORM_SKEWX; } else if (aTransformType == nsGkAtoms::skewY) { // y-angle if (numParsed != 1) return; transformType = SVG_TRANSFORM_SKEWY; } else { return; } nsSMILValue val(SVGTransformListSMILType::Singleton()); SVGTransformSMILData transform(transformType, params); if (NS_FAILED(SVGTransformListSMILType::AppendTransform(transform, val))) { return; // OOM } // Success! Populate our outparam with parsed value. aResult.Swap(val); }
void nsSVGTransformSMILAttr::ParseValue(const nsAString& aSpec, const nsIAtom* aTransformType, nsSMILValue& aResult) { NS_ASSERTION(aResult.IsNull(), "Unexpected type for SMIL value"); // nsSVGSMILTransform constructor should be expecting array with 3 params PR_STATIC_ASSERT(nsSVGSMILTransform::NUM_SIMPLE_PARAMS == 3); float params[3] = { 0.f }; PRInt32 numParsed = ParseParameterList(aSpec, params, 3); nsSVGSMILTransform::TransformType transformType; if (aTransformType == nsGkAtoms::translate) { // tx [ty=0] if (numParsed != 1 && numParsed != 2) return; transformType = nsSVGSMILTransform::TRANSFORM_TRANSLATE; } else if (aTransformType == nsGkAtoms::scale) { // sx [sy=sx] if (numParsed != 1 && numParsed != 2) return; if (numParsed == 1) { params[1] = params[0]; } transformType = nsSVGSMILTransform::TRANSFORM_SCALE; } else if (aTransformType == nsGkAtoms::rotate) { // r [cx=0 cy=0] if (numParsed != 1 && numParsed != 3) return; transformType = nsSVGSMILTransform::TRANSFORM_ROTATE; } else if (aTransformType == nsGkAtoms::skewX) { // x-angle if (numParsed != 1) return; transformType = nsSVGSMILTransform::TRANSFORM_SKEWX; } else if (aTransformType == nsGkAtoms::skewY) { // y-angle if (numParsed != 1) return; transformType = nsSVGSMILTransform::TRANSFORM_SKEWY; } else { return; } nsSMILValue val(&nsSVGTransformSMILType::sSingleton); nsSVGSMILTransform transform(transformType, params); if (NS_FAILED(nsSVGTransformSMILType::AppendTransform(transform, val))) { return; } // Success! Populate our outparam with parsed value. aResult.Swap(val); }
nsresult nsSVGClass::SMILString::ValueFromString(const nsAString& aStr, const nsISMILAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, bool& aPreventCachingOfSandwich) const { nsSMILValue val(&SMILStringType::sSingleton); *static_cast<nsAString*>(val.mU.mPtr) = aStr; aValue.Swap(val); aPreventCachingOfSandwich = false; return NS_OK; }
nsresult SVGAnimatedPathSegList:: SMILAnimatedPathSegList::ValueFromString(const nsAString& aStr, const nsISMILAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, bool& aPreventCachingOfSandwich) const { nsSMILValue val(&SVGPathSegListSMILType::sSingleton); SVGPathDataAndOwner *list = static_cast<SVGPathDataAndOwner*>(val.mU.mPtr); nsresult rv = list->SetValueFromString(aStr); if (NS_SUCCEEDED(rv)) { list->SetElement(mElement); aValue.Swap(val); } aPreventCachingOfSandwich = false; return rv; }
nsresult SVGAnimatedNumberList:: SMILAnimatedNumberList::ValueFromString(const nsAString& aStr, const nsISMILAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, bool& aPreventCachingOfSandwich) const { nsSMILValue val(&SVGNumberListSMILType::sSingleton); SVGNumberListAndInfo *nlai = static_cast<SVGNumberListAndInfo*>(val.mU.mPtr); nsresult rv = nlai->SetValueFromString(aStr); if (NS_SUCCEEDED(rv)) { nlai->SetInfo(mElement); aValue.Swap(val); } aPreventCachingOfSandwich = false; return rv; }
nsresult SVGAnimatedPointList:: SMILAnimatedPointList::ValueFromString(const nsAString& aStr, const nsISMILAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, PRBool& aPreventCachingOfSandwich) const { nsSMILValue val(&SVGPointListSMILType::sSingleton); SVGPointListAndInfo *list = static_cast<SVGPointListAndInfo*>(val.mU.mPtr); nsresult rv = list->SetValueFromString(aStr); if (NS_SUCCEEDED(rv)) { list->SetInfo(mElement); aValue.Swap(val); } aPreventCachingOfSandwich = PR_FALSE; return rv; }
nsresult nsSVGViewBox::SMILViewBox ::ValueFromString(const nsAString& aStr, const nsISMILAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, bool& aPreventCachingOfSandwich) const { nsSVGViewBoxRect viewBox; nsresult res = ToSVGViewBoxRect(aStr, &viewBox); if (NS_FAILED(res)) { return res; } nsSMILValue val(&SVGViewBoxSMILType::sSingleton); *static_cast<nsSVGViewBoxRect*>(val.mU.mPtr) = viewBox; aValue.Swap(val); aPreventCachingOfSandwich = false; return NS_OK; }
nsresult SVGAnimatedLengthList:: SMILAnimatedLengthList::ValueFromString(const nsAString& aStr, const nsISMILAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, bool& aPreventCachingOfSandwich) const { nsSMILValue val(&SVGLengthListSMILType::sSingleton); SVGLengthListAndInfo *llai = static_cast<SVGLengthListAndInfo*>(val.mU.mPtr); nsresult rv = llai->SetValueFromString(aStr); if (NS_SUCCEEDED(rv)) { llai->SetInfo(mElement, mAxis, mCanZeroPadList); aValue.Swap(val); // If any of the lengths in the list depend on their context, then we must // prevent caching of the entire animation sandwich. This is because the // units of a length at a given index can change from sandwich layer to // layer, and indeed even be different within a single sandwich layer. If // any length in the result of an animation sandwich is the result of the // addition of lengths where one or more of those lengths is context // dependent, then naturally the resultant length is also context // dependent, regardless of whether its actual unit is context dependent or // not. Unfortunately normal invalidation mechanisms won't cause us to // recalculate the result of the sandwich if the context changes, so we // take the (substantial) performance hit of preventing caching of the // sandwich layer, causing the animation sandwich to be recalculated every // single sample. aPreventCachingOfSandwich = PR_FALSE; for (PRUint32 i = 0; i < llai->Length(); ++i) { PRUint8 unit = (*llai)[i].GetUnit(); if (unit == nsIDOMSVGLength::SVG_LENGTHTYPE_PERCENTAGE || unit == nsIDOMSVGLength::SVG_LENGTHTYPE_EMS || unit == nsIDOMSVGLength::SVG_LENGTHTYPE_EXS) { aPreventCachingOfSandwich = PR_TRUE; break; } } } return rv; }
void nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr, nsSMILValue& aResult) { mHasChanged = PR_FALSE; // Skip animations that are inactive or in error if (!IsActiveOrFrozen() || mErrorFlags != 0) return; // Get the animation values nsSMILValueArray values; nsresult rv = GetValues(aSMILAttr, values); if (NS_FAILED(rv)) return; // Check that we have the right number of keySplines and keyTimes CheckValueListDependentAttrs(values.Length()); if (mErrorFlags != 0) return; // If this interval is active, we must have a non-negative mSampleTime NS_ABORT_IF_FALSE(mSampleTime >= 0 || !mIsActive, "Negative sample time for active animation"); NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() || mSimpleDuration.IsIndefinite() || mLastValue, "Unresolved simple duration for active or frozen animation"); nsSMILValue result(aResult.mType); if (mSimpleDuration.IsIndefinite() || (values.Length() == 1 && TreatSingleValueAsStatic())) { // Indefinite duration or only one value set: Always set the first value result = values[0]; } else if (mLastValue) { // Sampling last value const nsSMILValue& last = values[values.Length() - 1]; result = last; // See comment in AccumulateResult: to-animation does not accumulate if (!IsToAnimation() && GetAccumulate() && mRepeatIteration) { // If the target attribute type doesn't support addition Add will // fail leaving result = last result.Add(last, mRepeatIteration); } } else if (!mFrozenValue.IsNull() && !mHasChanged) { // Frozen to animation result = mFrozenValue; } else { // Interpolation if (NS_FAILED(InterpolateResult(values, result, aResult))) return; if (NS_FAILED(AccumulateResult(values, result))) return; if (IsToAnimation() && mIsFrozen) { mFrozenValue = result; } } // If additive animation isn't required or isn't supported, set the value. if (!IsAdditive() || NS_FAILED(aResult.SandwichAdd(result))) { aResult.Swap(result); // Note: The old value of aResult is now in |result|, and it will get // cleaned up when |result| goes out of scope, when this function returns. } }
void nsSMILAnimationFunction::ComposeResult(const nsISMILAttr& aSMILAttr, nsSMILValue& aResult) { mHasChanged = false; mPrevSampleWasSingleValueAnimation = false; mWasSkippedInPrevSample = false; // Skip animations that are inactive or in error if (!IsActiveOrFrozen() || mErrorFlags != 0) return; // Get the animation values nsSMILValueArray values; nsresult rv = GetValues(aSMILAttr, values); if (NS_FAILED(rv)) return; // Check that we have the right number of keySplines and keyTimes CheckValueListDependentAttrs(values.Length()); if (mErrorFlags != 0) return; // If this interval is active, we must have a non-negative mSampleTime NS_ABORT_IF_FALSE(mSampleTime >= 0 || !mIsActive, "Negative sample time for active animation"); NS_ABORT_IF_FALSE(mSimpleDuration.IsResolved() || mLastValue, "Unresolved simple duration for active or frozen animation"); // If we want to add but don't have a base value then just fail outright. // This can happen when we skipped getting the base value because there's an // animation function in the sandwich that should replace it but that function // failed unexpectedly. bool isAdditive = IsAdditive(); if (isAdditive && aResult.IsNull()) return; nsSMILValue result; if (values.Length() == 1 && !IsToAnimation()) { // Single-valued animation result = values[0]; mPrevSampleWasSingleValueAnimation = true; } else if (mLastValue) { // Sampling last value const nsSMILValue& last = values[values.Length() - 1]; result = last; // See comment in AccumulateResult: to-animation does not accumulate if (!IsToAnimation() && GetAccumulate() && mRepeatIteration) { // If the target attribute type doesn't support addition Add will // fail leaving result = last result.Add(last, mRepeatIteration); } } else { // Interpolation if (NS_FAILED(InterpolateResult(values, result, aResult))) return; if (NS_FAILED(AccumulateResult(values, result))) return; } // If additive animation isn't required or isn't supported, set the value. if (!isAdditive || NS_FAILED(aResult.SandwichAdd(result))) { aResult.Swap(result); // Note: The old value of aResult is now in |result|, and it will get // cleaned up when |result| goes out of scope, when this function returns. } }