diff options
Diffstat (limited to 'Source/WebCore/svg/SVGPathSegList.cpp')
-rw-r--r-- | Source/WebCore/svg/SVGPathSegList.cpp | 106 |
1 files changed, 92 insertions, 14 deletions
diff --git a/Source/WebCore/svg/SVGPathSegList.cpp b/Source/WebCore/svg/SVGPathSegList.cpp index 705c968c0..403ce33a6 100644 --- a/Source/WebCore/svg/SVGPathSegList.cpp +++ b/Source/WebCore/svg/SVGPathSegList.cpp @@ -1,7 +1,4 @@ /* - * Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org> - * Copyright (C) 2004, 2005 Rob Buis <buis@kde.org> - * Copyright (C) 2007 Eric Seidel <eric@webkit.org> * Copyright (C) Research In Motion Limited 2010. All rights reserved. * * This library is free software; you can redistribute it and/or @@ -21,29 +18,110 @@ */ #include "config.h" - -#if ENABLE(SVG) #include "SVGPathSegList.h" -#include "SVGNames.h" +#include "SVGAnimatedPathSegListPropertyTearOff.h" #include "SVGPathElement.h" -#include "SVGPathUtilities.h" +#include "SVGPathSegWithContext.h" namespace WebCore { -String SVGPathSegList::valueAsString() const +void SVGPathSegList::clearContextAndRoles() +{ + ASSERT(m_values); + for (auto& item : *m_values) + static_cast<SVGPathSegWithContext*>(item.get())->setContextAndRole(nullptr, PathSegUndefinedRole); +} + +ExceptionOr<void> SVGPathSegList::clear() +{ + ASSERT(m_values); + if (m_values->isEmpty()) + return { }; + + clearContextAndRoles(); + return Base::clearValues(); +} + +ExceptionOr<SVGPathSegList::PtrListItemType> SVGPathSegList::getItem(unsigned index) { - String pathString; - buildStringFromSVGPathSegList(*this, pathString, UnalteredParsing); - return pathString; + return Base::getItemValues(index); } -void SVGPathSegList::commitChange(SVGElement* contextElement, ListModification listModification) +ExceptionOr<SVGPathSegList::PtrListItemType> SVGPathSegList::replaceItem(PtrListItemType newItem, unsigned index) { + // Not specified, but FF/Opera do it this way, and it's just sane. + if (!newItem) + return Exception { SVGException::SVG_WRONG_TYPE_ERR }; + + if (index < m_values->size()) { + ListItemType replacedItem = m_values->at(index); + ASSERT(replacedItem); + static_cast<SVGPathSegWithContext*>(replacedItem.get())->setContextAndRole(nullptr, PathSegUndefinedRole); + } + + return Base::replaceItemValues(newItem, index); +} + +ExceptionOr<SVGPathSegList::PtrListItemType> SVGPathSegList::removeItem(unsigned index) +{ + auto result = Base::removeItemValues(index); + if (result.hasException()) + return result; + auto removedItem = result.releaseReturnValue(); + if (removedItem) + static_cast<SVGPathSegWithContext&>(*removedItem).setContextAndRole(nullptr, PathSegUndefinedRole); + return WTFMove(removedItem); +} + +SVGPathElement* SVGPathSegList::contextElement() const +{ + SVGElement* contextElement = m_animatedProperty->contextElement(); ASSERT(contextElement); - toSVGPathElement(contextElement)->pathSegListChanged(m_role, listModification); + return downcast<SVGPathElement>(contextElement); } +bool SVGPathSegList::processIncomingListItemValue(const ListItemType& newItem, unsigned* indexToModify) +{ + SVGPathSegWithContext* newItemWithContext = static_cast<SVGPathSegWithContext*>(newItem.get()); + RefPtr<SVGAnimatedProperty> animatedPropertyOfItem = newItemWithContext->animatedProperty(); + + // Alter the role, after calling animatedProperty(), as that may influence the returned animated property. + newItemWithContext->setContextAndRole(contextElement(), m_pathSegRole); + + if (!animatedPropertyOfItem) + return true; + + // newItem belongs to a SVGPathElement, but its associated SVGAnimatedProperty is not an animated list tear off. + // (for example: "pathElement.pathSegList.appendItem(pathElement.createSVGPathSegClosepath())") + if (!animatedPropertyOfItem->isAnimatedListTearOff()) + return true; + + // Spec: If newItem is already in a list, it is removed from its previous list before it is inserted into this list. + // 'newItem' is already living in another list. If it's not our list, synchronize the other lists wrappers after the removal. + bool livesInOtherList = animatedPropertyOfItem != m_animatedProperty; + RefPtr<SVGAnimatedPathSegListPropertyTearOff> propertyTearOff = static_pointer_cast<SVGAnimatedPathSegListPropertyTearOff>(animatedPropertyOfItem); + int indexToRemove = propertyTearOff->findItem(newItem.get()); + ASSERT(indexToRemove != -1); + + // Do not remove newItem if already in this list at the target index. + if (!livesInOtherList && indexToModify && static_cast<unsigned>(indexToRemove) == *indexToModify) + return false; + + propertyTearOff->removeItemFromList(indexToRemove, livesInOtherList); + + if (!indexToModify) + return true; + + // If the item lived in our list, adjust the insertion index. + if (!livesInOtherList) { + unsigned& index = *indexToModify; + // Spec: If the item is already in this list, note that the index of the item to (replace|insert before) is before the removal of the item. + if (static_cast<unsigned>(indexToRemove) < index) + --index; + } + + return true; } -#endif // ENABLE(SVG) +} |