nsresult SVGAnimatedPathSegList:: SMILAnimatedPathSegList::ValueFromString(const nsAString& aStr, const dom::SVGAnimationElement* /*aSrcElement*/, nsSMILValue& aValue, bool& aPreventCachingOfSandwich) const { nsSMILValue val(SVGPathSegListSMILType::Singleton()); SVGPathDataAndInfo *list = static_cast<SVGPathDataAndInfo*>(val.mU.mPtr); nsresult rv = list->SetValueFromString(aStr); if (NS_SUCCEEDED(rv)) { list->SetElement(mElement); aValue = Move(val); } aPreventCachingOfSandwich = false; return rv; }
nsSMILValue SVGAnimatedPathSegList::SMILAnimatedPathSegList::GetBaseValue() const { // To benefit from Return Value Optimization and avoid copy constructor calls // due to our use of return-by-value, we must return the exact same object // from ALL return points. This function must only return THIS variable: nsSMILValue val; nsSMILValue tmp(SVGPathSegListSMILType::Singleton()); SVGPathDataAndInfo *list = static_cast<SVGPathDataAndInfo*>(tmp.mU.mPtr); nsresult rv = list->CopyFrom(mVal->mBaseVal); if (NS_SUCCEEDED(rv)) { list->SetElement(mElement); val = Move(tmp); } return val; }
/** * Helper function for Add & Interpolate, to add multiples of two path-segment * lists. * * NOTE: aList1 and aList2 are assumed to have their segment-types and * segment-count match exactly (unless aList1 is an identity value). * * NOTE: aResult, the output list, is expected to either be an identity value * (in which case we'll grow it) *or* to already have the exactly right length * (e.g. in cases where aList1 and aResult are actually the same list). * * @param aCoeff1 The coefficient to use on the first path segment list. * @param aList1 The first path segment list. Allowed to be identity. * @param aCoeff2 The coefficient to use on the second path segment list. * @param aList2 The second path segment list. * @param [out] aResultSeg The resulting path segment list. Allowed to be * identity, in which case we'll grow it to the right * size. Also allowed to be the same list as aList1. */ static nsresult AddWeightedPathSegLists(double aCoeff1, const SVGPathDataAndInfo& aList1, double aCoeff2, const SVGPathDataAndInfo& aList2, SVGPathDataAndInfo& aResult) { MOZ_ASSERT(aCoeff1 >= 0.0 && aCoeff2 >= 0.0, "expecting non-negative coefficients"); MOZ_ASSERT(!aList2.IsIdentity(), "expecting 2nd list to be non-identity"); MOZ_ASSERT(aList1.IsIdentity() || aList1.Length() == aList2.Length(), "expecting 1st list to be identity or to have same " "length as 2nd list"); MOZ_ASSERT(aResult.IsIdentity() || aResult.Length() == aList2.Length(), "expecting result list to be identity or to have same " "length as 2nd list"); SVGPathDataAndInfo::const_iterator iter1, end1; if (aList1.IsIdentity()) { iter1 = end1 = nullptr; // indicate that this is an identity list } else { iter1 = aList1.begin(); end1 = aList1.end(); } SVGPathDataAndInfo::const_iterator iter2 = aList2.begin(); SVGPathDataAndInfo::const_iterator end2 = aList2.end(); // Grow |aResult| if necessary. (NOTE: It's possible that aResult and aList1 // are the same list, so this may implicitly resize aList1. That's fine, // because in that case, we will have already set iter1 to nullptr above, to // record that our first operand is an identity value.) if (aResult.IsIdentity()) { if (!aResult.SetLength(aList2.Length())) { return NS_ERROR_OUT_OF_MEMORY; } aResult.SetElement(aList2.Element()); // propagate target element info! } SVGPathDataAndInfo::iterator resultIter = aResult.begin(); while ((!iter1 || iter1 != end1) && iter2 != end2) { AddWeightedPathSegs(aCoeff1, iter1, aCoeff2, iter2, resultIter); } MOZ_ASSERT( (!iter1 || iter1 == end1) && iter2 == end2 && resultIter == aResult.end(), "Very, very bad - path data corrupt"); return NS_OK; }