void DOMSVGPathSegList:: MaybeRemoveItemFromAnimValListAt(uint32_t aIndex, uint32_t aArgCountForItem) { NS_ABORT_IF_FALSE(!IsAnimValList(), "call from baseVal to animVal"); if (AttrIsAnimating()) { // animVal not a clone of baseVal return; } // This needs to be a strong reference; otherwise, the RemovingFromList call // below might drop the last reference to animVal before we're done with it. nsRefPtr<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::EnsureItemAt(uint32_t aIndex) { if (!ItemAt(aIndex)) { ItemAt(aIndex) = DOMSVGPathSeg::CreateFor(this, aIndex, IsAnimValList()); } }
void DOMSVGPathSegList:: MaybeInsertNullInAnimValListAt(uint32_t aIndex, uint32_t aInternalIndex, uint32_t 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(nullptr, aInternalIndex)); animVal->UpdateListIndicesFromIndex(aIndex + 1, 1 + aArgCountForItem); }
void DOMSVGPointList::MaybeInsertNullInAnimValListAt(PRUint32 aIndex) { 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 DOMSVGPointList *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, static_cast<DOMSVGPoint*>(nsnull)); UpdateListIndicesFromIndex(animVal->mItems, aIndex + 1); }
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::Initialize(DOMSVGPathSeg& aNewItem, ErrorResult& aError) { if (IsAnimValList()) { aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } // If aNewItem is already in a list we should insert a clone of aNewItem, // and for consistency, this should happen even if *this* is the list that // aNewItem is currently in. Note that in the case of aNewItem being in this // list, the Clear() call before the InsertItemBefore() call would remove it // from this list, and so the InsertItemBefore() call would not insert a // clone of aNewItem, it would actually insert aNewItem. To prevent that // from happening we have to do the clone here, if necessary. nsRefPtr<DOMSVGPathSeg> domItem = &aNewItem; if (aNewItem.HasOwner()) { domItem = aNewItem.Clone(); } Clear(aError); MOZ_ASSERT(!aError.Failed(), "How could this fail?"); return InsertItemBefore(*domItem, 0, aError); }
NS_IMETHODIMP DOMSVGPointList::Initialize(nsIDOMSVGPoint *aNewItem, nsIDOMSVGPoint **_retval) { *_retval = nsnull; if (IsAnimValList()) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } // If aNewItem is already in a list we should insert a clone of aNewItem, // and for consistency, this should happen even if *this* is the list that // aNewItem is currently in. Note that in the case of aNewItem being in this // list, the Clear() call before the InsertItemBefore() call would remove it // from this list, and so the InsertItemBefore() call would not insert a // clone of aNewItem, it would actually insert aNewItem. To prevent that // from happening we have to do the clone here, if necessary. nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem); if (!domItem) { return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR; } if (domItem->HasOwner() || domItem->IsReadonly()) { aNewItem = domItem->Clone(); } Clear(); return InsertItemBefore(aNewItem, 0, _retval); }
void DOMSVGPointList::EnsureItemAt(PRUint32 aIndex) { if (!mItems[aIndex]) { mItems[aIndex] = new DOMSVGPoint(this, aIndex, IsAnimValList()); } }
NS_IMETHODIMP DOMSVGPointList::Clear() { if (IsAnimValList()) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } if (Length() > 0) { nsAttrValue emptyOrOldValue = Element()->WillChangePointList(); // DOM list items that are to be removed must be removed before we change // the internal list, otherwise they wouldn't be able to copy their // internal counterparts' values! InternalListWillChangeTo(SVGPointList()); // clears mItems if (!AttrIsAnimating()) { // The anim val list is in sync with the base val list DOMSVGPointList *animList = GetDOMWrapperIfExists(InternalAList().GetAnimValKey()); if (animList) { animList->InternalListWillChangeTo(SVGPointList()); // clears its mItems } } InternalList().Clear(); Element()->DidChangePointList(emptyOrOldValue); if (AttrIsAnimating()) { Element()->AnimationNeedsResample(); } } return NS_OK; }
void DOMSVGLengthList::EnsureItemAt(PRUint32 aIndex) { if (!mItems[aIndex]) { mItems[aIndex] = new DOMSVGLength(this, AttrEnum(), aIndex, IsAnimValList()); } }
already_AddRefed<nsISVGPoint> DOMSVGPointList::Initialize(nsISVGPoint& aNewItem, ErrorResult& aError) { if (IsAnimValList()) { aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } // If aNewItem is already in a list we should insert a clone of aNewItem, // and for consistency, this should happen even if *this* is the list that // aNewItem is currently in. Note that in the case of aNewItem being in this // list, the Clear() call before the InsertItemBefore() call would remove it // from this list, and so the InsertItemBefore() call would not insert a // clone of aNewItem, it would actually insert aNewItem. To prevent that // from happening we have to do the clone here, if necessary. nsCOMPtr<nsISVGPoint> domItem = &aNewItem; if (domItem->HasOwner() || domItem->IsReadonly()) { domItem = domItem->Clone(); // must do this before changing anything! } ErrorResult rv; Clear(rv); MOZ_ASSERT(!rv.Failed()); return InsertItemBefore(*domItem, 0, aError); }
already_AddRefed<SVGTransform> DOMSVGTransformList::Initialize(SVGTransform& newItem, ErrorResult& error) { if (IsAnimValList()) { error.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } // If newItem is already in a list we should insert a clone of newItem, and // for consistency, this should happen even if *this* is the list that // newItem is currently in. Note that in the case of newItem being in this // list, the Clear() call before the InsertItemBefore() call would remove it // from this list, and so the InsertItemBefore() call would not insert a // clone of newItem, it would actually insert newItem. To prevent that from // happening we have to do the clone here, if necessary. nsRefPtr<SVGTransform> domItem = &newItem; if (domItem->HasOwner()) { domItem = newItem.Clone(); } Clear(error); MOZ_ASSERT(!error.Failed(), "How could this fail?"); return InsertItemBefore(*domItem, 0, error); }
already_AddRefed<SVGTransform> DOMSVGTransformList::Consolidate(ErrorResult& error) { if (IsAnimValList()) { error.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } if (LengthNoFlush() == 0) { return nullptr; } // Note that SVG 1.1 says, "The consolidation operation creates new // SVGTransform object as the first and only item in the list" hence, even if // LengthNoFlush() == 1 we can't return that one item (after making it a // matrix type). We must orphan the existing item and then make a new one. // First calculate our matrix gfxMatrix mx = InternalList().GetConsolidationMatrix(); // Then orphan the existing items Clear(error); MOZ_ASSERT(!error.Failed(), "How could this fail?"); // And append the new transform nsRefPtr<SVGTransform> transform = new SVGTransform(mx); return InsertItemBefore(*transform, LengthNoFlush(), error); }
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::Clear(ErrorResult& aError) { if (IsAnimValList()) { aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return; } if (LengthNoFlush() > 0) { AutoChangePathSegListNotifier notifier(this); // DOM list items that are to be removed must be removed before we change // the internal list, otherwise they wouldn't be able to copy their // internal counterparts' values! InternalListWillChangeTo(SVGPathData()); // clears mItems if (!AttrIsAnimating()) { // The anim val list is in sync with the base val list DOMSVGPathSegList *animList = GetDOMWrapperIfExists(InternalAList().GetAnimValKey()); if (animList) { animList->InternalListWillChangeTo(SVGPathData()); // clears its mItems } } InternalList().Clear(); } }
void DOMSVGPointList::MaybeRemoveItemFromAnimValListAt(uint32_t aIndex) { MOZ_ASSERT(!IsAnimValList(), "call from baseVal to animVal"); if (!AnimListMirrorsBaseList()) { return; } // This needs to be a strong reference; otherwise, the RemovingFromList call // below might drop the last reference to animVal before we're done with it. RefPtr<DOMSVGPointList> animVal = GetDOMWrapperIfExists(InternalAList().GetAnimValKey()); MOZ_ASSERT(animVal, "AnimListMirrorsBaseList() promised a non-null animVal"); MOZ_ASSERT(animVal->mItems.Length() == mItems.Length(), "animVal list not in sync!"); if (animVal->mItems[aIndex]) { animVal->mItems[aIndex]->RemovingFromList(); } animVal->mItems.RemoveElementAt(aIndex); UpdateListIndicesFromIndex(animVal->mItems, aIndex); }
already_AddRefed<SVGTransform> DOMSVGTransformList::RemoveItem(uint32_t index, ErrorResult& error) { if (IsAnimValList()) { error.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } if (index >= LengthNoFlush()) { error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return nullptr; } AutoChangeTransformListNotifier notifier(this); // 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(index); // We have to return the removed item, so get it, creating it if necessary: nsRefPtr<SVGTransform> result = GetItemAt(index); // Notify the DOM item of removal *before* modifying the lists so that the // DOM item can copy its *old* value: result->RemovingFromList(); InternalList().RemoveItem(index); mItems.RemoveElementAt(index); UpdateListIndicesFromIndex(mItems, index); return result.forget(); }
already_AddRefed<nsISVGPoint> DOMSVGPointList::InsertItemBefore(nsISVGPoint& aNewItem, uint32_t aIndex, ErrorResult& aError) { if (IsAnimValList()) { aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } aIndex = std::min(aIndex, LengthNoFlush()); if (aIndex >= nsISVGPoint::MaxListIndex()) { aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return nullptr; } nsCOMPtr<nsISVGPoint> domItem = &aNewItem; if (domItem->HasOwner() || domItem->IsReadonly()) { domItem = domItem->Clone(); // must do this before changing anything! } // Ensure we have enough memory so we can avoid complex error handling below: if (!mItems.SetCapacity(mItems.Length() + 1) || !InternalList().SetCapacity(InternalList().Length() + 1)) { aError.Throw(NS_ERROR_OUT_OF_MEMORY); return nullptr; } nsAttrValue emptyOrOldValue = Element()->WillChangePointList(); // Now that we know we're inserting, keep animVal list in sync as necessary. MaybeInsertNullInAnimValListAt(aIndex); InternalList().InsertItem(aIndex, domItem->ToSVGPoint()); mItems.InsertElementAt(aIndex, domItem); // This MUST come after the insertion into InternalList(), or else under the // insertion into InternalList() the values read from domItem would be bad // data from InternalList() itself!: domItem->InsertingIntoList(this, aIndex, IsAnimValList()); UpdateListIndicesFromIndex(mItems, aIndex + 1); Element()->DidChangePointList(emptyOrOldValue); if (AttrIsAnimating()) { Element()->AnimationNeedsResample(); } return domItem.forget(); }
SVGTransformList& DOMSVGTransformList::InternalList() const { SVGAnimatedTransformList *alist = Element()->GetAnimatedTransformList(); return IsAnimValList() && alist->mAnimVal ? *alist->mAnimVal : alist->mBaseVal; }
NS_IMETHODIMP DOMSVGLengthList::GetNumberOfItems(PRUint32 *aNumberOfItems) { if (IsAnimValList()) { Element()->FlushAnimations(); } *aNumberOfItems = Length(); return NS_OK; }
NS_IMETHODIMP DOMSVGLengthList::InsertItemBefore(nsIDOMSVGLength *newItem, PRUint32 index, nsIDOMSVGLength **_retval) { *_retval = nsnull; if (IsAnimValList()) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } nsCOMPtr<DOMSVGLength> domItem = do_QueryInterface(newItem); if (!domItem) { return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR; } index = NS_MIN(index, Length()); SVGLength length = domItem->ToSVGLength(); // get before setting domItem if (domItem->HasOwner()) { domItem = new DOMSVGLength(); } PRBool ok = !!InternalList().InsertItem(index, length); if (!ok) { return NS_ERROR_OUT_OF_MEMORY; } domItem->InsertingIntoList(this, AttrEnum(), index, IsAnimValList()); ok = !!mItems.InsertElementAt(index, domItem.get()); if (!ok) { InternalList().RemoveItem(index); return NS_ERROR_OUT_OF_MEMORY; } for (PRUint32 i = index + 1; i < Length(); ++i) { if (mItems[i]) { mItems[i]->UpdateListIndex(i); } } Element()->DidChangeLengthList(AttrEnum(), PR_TRUE); #ifdef MOZ_SMIL if (mAList->IsAnimating()) { Element()->AnimationNeedsResample(); } #endif *_retval = domItem.forget().get(); return NS_OK; }
NS_IMETHODIMP DOMSVGNumberList::ReplaceItem(nsIDOMSVGNumber *newItem, PRUint32 index, nsIDOMSVGNumber **_retval) { *_retval = nsnull; if (IsAnimValList()) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } nsCOMPtr<DOMSVGNumber> domItem = do_QueryInterface(newItem); if (!domItem) { return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR; } if (index >= Length()) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } if (domItem->HasOwner()) { domItem = domItem->Clone(); // must do this before changing anything! } if (mItems[index]) { // Notify any existing DOM item of removal *before* modifying the lists so // that the DOM item can copy the *old* value at its index: mItems[index]->RemovingFromList(); } InternalList()[index] = domItem->ToSVGNumber(); mItems[index] = domItem; // This MUST come after the ToSVGPoint() call, otherwise that call // would end up reading bad data from InternalList()! domItem->InsertingIntoList(this, AttrEnum(), index, IsAnimValList()); Element()->DidChangeNumberList(AttrEnum(), PR_TRUE); #ifdef MOZ_SMIL if (mAList->IsAnimating()) { Element()->AnimationNeedsResample(); } #endif NS_ADDREF(*_retval = domItem.get()); return NS_OK; }
already_AddRefed<SVGTransform> DOMSVGTransformList::InsertItemBefore(SVGTransform& newItem, uint32_t index, ErrorResult& error) { if (IsAnimValList()) { error.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } index = std::min(index, LengthNoFlush()); if (index >= SVGTransform::MaxListIndex()) { error.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return nullptr; } nsRefPtr<SVGTransform> domItem = &newItem; if (newItem.HasOwner()) { domItem = newItem.Clone(); // must do this before changing anything! } // Ensure we have enough memory so we can avoid complex error handling below: if (!mItems.SetCapacity(mItems.Length() + 1) || !InternalList().SetCapacity(InternalList().Length() + 1)) { error.Throw(NS_ERROR_OUT_OF_MEMORY); return nullptr; } AutoChangeTransformListNotifier notifier(this); // Now that we know we're inserting, keep animVal list in sync as necessary. MaybeInsertNullInAnimValListAt(index); InternalList().InsertItem(index, domItem->ToSVGTransform()); mItems.InsertElementAt(index, domItem.get()); // This MUST come after the insertion into InternalList(), or else under the // insertion into InternalList() the values read from domItem would be bad // data from InternalList() itself!: domItem->InsertingIntoList(this, index, IsAnimValList()); UpdateListIndicesFromIndex(mItems, index + 1); return domItem.forget(); }
already_AddRefed<nsIDOMSVGPoint> DOMSVGPointList::ReplaceItem(nsIDOMSVGPoint *aNewItem, uint32_t aIndex, ErrorResult& aError) { if (IsAnimValList()) { aError.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR); return nullptr; } nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem); if (!domItem) { aError.Throw(NS_ERROR_DOM_SVG_WRONG_TYPE_ERR); return nullptr; } if (aIndex >= LengthNoFlush()) { aError.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR); return nullptr; } if (domItem->HasOwner() || domItem->IsReadonly()) { domItem = domItem->Clone(); // must do this before changing anything! } nsAttrValue emptyOrOldValue = Element()->WillChangePointList(); if (mItems[aIndex]) { // Notify any existing DOM item of removal *before* modifying the lists so // that the DOM item can copy the *old* value at its index: mItems[aIndex]->RemovingFromList(); } InternalList()[aIndex] = domItem->ToSVGPoint(); mItems[aIndex] = domItem; // This MUST come after the ToSVGPoint() call, otherwise that call // would end up reading bad data from InternalList()! domItem->InsertingIntoList(this, aIndex, IsAnimValList()); Element()->DidChangePointList(emptyOrOldValue); if (AttrIsAnimating()) { Element()->AnimationNeedsResample(); } return domItem.forget(); }
NS_IMETHODIMP DOMSVGPointList::ReplaceItem(nsIDOMSVGPoint *aNewItem, PRUint32 aIndex, nsIDOMSVGPoint **_retval) { *_retval = nsnull; if (IsAnimValList()) { return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR; } nsCOMPtr<DOMSVGPoint> domItem = do_QueryInterface(aNewItem); if (!domItem) { return NS_ERROR_DOM_SVG_WRONG_TYPE_ERR; } if (aIndex >= Length()) { return NS_ERROR_DOM_INDEX_SIZE_ERR; } if (domItem->HasOwner() || domItem->IsReadonly()) { domItem = domItem->Clone(); // must do this before changing anything! } nsAttrValue emptyOrOldValue = Element()->WillChangePointList(); if (mItems[aIndex]) { // Notify any existing DOM item of removal *before* modifying the lists so // that the DOM item can copy the *old* value at its index: mItems[aIndex]->RemovingFromList(); } InternalList()[aIndex] = domItem->ToSVGPoint(); mItems[aIndex] = domItem; // This MUST come after the ToSVGPoint() call, otherwise that call // would end up reading bad data from InternalList()! domItem->InsertingIntoList(this, aIndex, IsAnimValList()); Element()->DidChangePointList(emptyOrOldValue); if (AttrIsAnimating()) { Element()->AnimationNeedsResample(); } NS_ADDREF(*_retval = domItem.get()); return NS_OK; }
already_AddRefed<nsISVGPoint> DOMSVGPointList::GetItemAt(uint32_t aIndex) { MOZ_ASSERT(aIndex < mItems.Length()); if (!mItems[aIndex]) { mItems[aIndex] = new DOMSVGPoint(this, aIndex, IsAnimValList()); } RefPtr<nsISVGPoint> result = mItems[aIndex]; return result.forget(); }
already_AddRefed<SVGTransform> DOMSVGTransformList::GetItemAt(uint32_t aIndex) { MOZ_ASSERT(aIndex < mItems.Length()); if (!mItems[aIndex]) { mItems[aIndex] = new SVGTransform(this, aIndex, IsAnimValList()); } nsRefPtr<SVGTransform> result = mItems[aIndex]; return result.forget(); }
already_AddRefed<DOMSVGPathSeg> DOMSVGPathSegList::GetItemAt(uint32_t aIndex) { MOZ_ASSERT(aIndex < mItems.Length()); if (!ItemAt(aIndex)) { ItemAt(aIndex) = DOMSVGPathSeg::CreateFor(this, aIndex, IsAnimValList()); } nsRefPtr<DOMSVGPathSeg> result = ItemAt(aIndex); return result.forget(); }
NS_IMETHODIMP DOMSVGNumberList::GetNumberOfItems(PRUint32 *aNumberOfItems) { #ifdef MOZ_SMIL if (IsAnimValList()) { Element()->FlushAnimations(); } #endif *aNumberOfItems = Length(); return NS_OK; }
nsIDOMSVGTransform* DOMSVGTransformList::GetItemAt(PRUint32 aIndex) { if (IsAnimValList()) { Element()->FlushAnimations(); } if (aIndex < Length()) { EnsureItemAt(aIndex); return mItems[aIndex]; } return nsnull; }
nsIDOMSVGPathSeg* DOMSVGPathSegList::GetItemWithoutAddRef(PRUint32 aIndex) { if (IsAnimValList()) { Element()->FlushAnimations(); } if (aIndex < Length()) { EnsureItemAt(aIndex); return ItemAt(aIndex); } return nsnull; }