From c8abad09b2b3c386947ed97437bf35b3375c9b6b Mon Sep 17 00:00:00 2001 From: Daniel Holbert Date: Tue, 15 Feb 2011 23:54:37 -0800 Subject: [PATCH] Bug 632143 patch 3: Update animVal after modifying baseVal length, for DOMSVGPathSegList. r=roc a=blocking-final+ --- content/svg/content/src/DOMSVGPathSegList.cpp | 69 ++++++++++++++++++- content/svg/content/src/DOMSVGPathSegList.h | 6 ++ 2 files changed, 74 insertions(+), 1 deletion(-) diff --git a/content/svg/content/src/DOMSVGPathSegList.cpp b/content/svg/content/src/DOMSVGPathSegList.cpp index a45488b72d0..d62d69d18fc 100644 --- a/content/svg/content/src/DOMSVGPathSegList.cpp +++ b/content/svg/content/src/DOMSVGPathSegList.cpp @@ -349,6 +349,9 @@ DOMSVGPathSegList::InsertItemBefore(nsIDOMSVGPathSeg *aNewItem, return NS_ERROR_OUT_OF_MEMORY; } + // Now that we know we're inserting, keep animVal list in sync as necessary. + MaybeInsertNullInAnimValListAt(aIndex, internalIndex, argCount); + float segAsRaw[1 + NS_SVG_PATH_SEG_MAX_ARGS]; domItem->ToSVGPathSegEncodedData(segAsRaw); @@ -462,6 +465,11 @@ DOMSVGPathSegList::RemoveItem(PRUint32 aIndex, PRUint32 segType = SVGPathSegUtils::DecodeType(InternalList().mData[internalIndex]); PRUint32 argCount = SVGPathSegUtils::ArgCountForType(segType); + // Now that we know we're removing, keep animVal list in sync as necessary. + // Do this *before* touching InternalList() so the removed item can get its + // internal value. + MaybeRemoveItemFromAnimValListAt(aIndex, argCount); + InternalList().mData.RemoveElementsAt(internalIndex, 1 + argCount); mItems.RemoveElementAt(aIndex); @@ -491,11 +499,70 @@ DOMSVGPathSegList::EnsureItemAt(PRUint32 aIndex) } } +void +DOMSVGPathSegList:: + MaybeInsertNullInAnimValListAt(PRUint32 aIndex, + PRUint32 aInternalIndex, + PRUint32 aArgCountForItem) +{ + NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal"); + + if (AttrIsAnimating()) { + // animVal not a clone of baseVal + return; + } + + // The anim val list is in sync with the base val list + DOMSVGPathSegList *animVal = + GetDOMWrapperIfExists(InternalAList().GetAnimValKey()); + if (!animVal) { + // No animVal list wrapper + return; + } + + NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(), + "animVal list not in sync!"); + + animVal->mItems.InsertElementAt(aIndex, ItemProxy(nsnull, aInternalIndex)); + + animVal->UpdateListIndicesFromIndex(aIndex + 1, 1 + aArgCountForItem); +} + +void +DOMSVGPathSegList:: + MaybeRemoveItemFromAnimValListAt(PRUint32 aIndex, + PRUint32 aArgCountForItem) +{ + NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal"); + + if (AttrIsAnimating()) { + // animVal not a clone of baseVal + return; + } + + DOMSVGPathSegList *animVal = + GetDOMWrapperIfExists(InternalAList().GetAnimValKey()); + if (!animVal) { + // No animVal list wrapper + return; + } + + NS_ABORT_IF_FALSE(animVal->mItems.Length() == mItems.Length(), + "animVal list not in sync!"); + + if (animVal->ItemAt(aIndex)) { + animVal->ItemAt(aIndex)->RemovingFromList(); + } + animVal->mItems.RemoveElementAt(aIndex); + + animVal->UpdateListIndicesFromIndex(aIndex, -(1 + aArgCountForItem)); +} + void DOMSVGPathSegList::UpdateListIndicesFromIndex(PRUint32 aStartingIndex, PRInt32 aInternalDataIndexDelta) { - PRUint32 length = Length(); + PRUint32 length = mItems.Length(); for (PRUint32 i = aStartingIndex; i < length; ++i) { mItems[i].mInternalDataIndex += aInternalDataIndexDelta; diff --git a/content/svg/content/src/DOMSVGPathSegList.h b/content/svg/content/src/DOMSVGPathSegList.h index 5bc5e3fc36c..74a9d2d3978 100644 --- a/content/svg/content/src/DOMSVGPathSegList.h +++ b/content/svg/content/src/DOMSVGPathSegList.h @@ -190,6 +190,12 @@ private: // aIndex, if it doesn't already exist. void EnsureItemAt(PRUint32 aIndex); + void MaybeInsertNullInAnimValListAt(PRUint32 aIndex, + PRUint32 aInternalIndex, + PRUint32 aArgCountForItem); + void MaybeRemoveItemFromAnimValListAt(PRUint32 aIndex, + PRUint32 aArgCountForItem); + // Calls UpdateListIndex on all elements in |mItems| that satisfy ItemAt(), // from |aStartingIndex| to the end of |mItems|. Also adjusts // |mItems.mInternalDataIndex| by the requested amount.