https://bugs.webkit.org/show_bug.cgi?id=99694
Reviewed by Eric Seidel.
Our SVG pending resource tracking is used for handling dynamic id changes. For example,
if an SVG element references an id that is not yet in the document (or has been removed),
the SVG element will be 'pending' an id. When styled elements are inserted into
the document, buildPendingResourcesIfNeeded() is called to force any pending elements
to resolve their dependencies. Only SVGStyledElement targets can be referenced using
this infrastructure, and that is not changed with this patch.
Previously, only SVGStyledElements could have pending resources. Some examples of where
this is violated are SVGAnimateElement and SVGMPathElement which are not a styled elements
but which can have pending references (they can reference styled elements and
paths, respectively). This patch changes the pending resource handling to allow
any SVGElement to have pending resources.
This patch is only a refactoring of code in preparation for WK99694 and does not
affect existing functionality or tests.
* svg/SVGDocumentExtensions.cpp:
(WebCore::SVGDocumentExtensions::addPendingResource):
(WebCore::SVGDocumentExtensions::isElementPendingResources):
(WebCore::SVGDocumentExtensions::isElementPendingResource):
(WebCore::SVGDocumentExtensions::removeElementFromPendingResources):
(WebCore::SVGDocumentExtensions::removeElementFromPendingResourcesForRemoval):
* svg/SVGDocumentExtensions.h:
(WebCore):
(SVGDocumentExtensions):
* svg/SVGElement.cpp:
(WebCore::SVGElement::~SVGElement):
(WebCore::SVGElement::removedFrom):
(WebCore::SVGElement::hasPendingResources):
(WebCore):
(WebCore::SVGElement::setHasPendingResources):
(WebCore::SVGElement::clearHasPendingResourcesIfPossible):
* svg/SVGElement.h:
(SVGElement):
(WebCore::SVGElement::buildPendingResource):
* svg/SVGStyledElement.cpp:
(WebCore):
(WebCore::SVGStyledElement::buildPendingResourcesIfNeeded):
(WebCore::SVGStyledElement::removedFrom):
* svg/SVGStyledElement.h:
(SVGStyledElement):
(WebCore::SVGStyledElement::selfHasRelativeLengths):
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@132847
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2012-10-29 Philip Rogers <pdr@google.com>
+
+ Let SVGElements have pending resources.
+ https://bugs.webkit.org/show_bug.cgi?id=99694
+
+ Reviewed by Eric Seidel.
+
+ Our SVG pending resource tracking is used for handling dynamic id changes. For example,
+ if an SVG element references an id that is not yet in the document (or has been removed),
+ the SVG element will be 'pending' an id. When styled elements are inserted into
+ the document, buildPendingResourcesIfNeeded() is called to force any pending elements
+ to resolve their dependencies. Only SVGStyledElement targets can be referenced using
+ this infrastructure, and that is not changed with this patch.
+
+ Previously, only SVGStyledElements could have pending resources. Some examples of where
+ this is violated are SVGAnimateElement and SVGMPathElement which are not a styled elements
+ but which can have pending references (they can reference styled elements and
+ paths, respectively). This patch changes the pending resource handling to allow
+ any SVGElement to have pending resources.
+
+ This patch is only a refactoring of code in preparation for WK99694 and does not
+ affect existing functionality or tests.
+
+ * svg/SVGDocumentExtensions.cpp:
+ (WebCore::SVGDocumentExtensions::addPendingResource):
+ (WebCore::SVGDocumentExtensions::isElementPendingResources):
+ (WebCore::SVGDocumentExtensions::isElementPendingResource):
+ (WebCore::SVGDocumentExtensions::removeElementFromPendingResources):
+ (WebCore::SVGDocumentExtensions::removeElementFromPendingResourcesForRemoval):
+ * svg/SVGDocumentExtensions.h:
+ (WebCore):
+ (SVGDocumentExtensions):
+ * svg/SVGElement.cpp:
+ (WebCore::SVGElement::~SVGElement):
+ (WebCore::SVGElement::removedFrom):
+ (WebCore::SVGElement::hasPendingResources):
+ (WebCore):
+ (WebCore::SVGElement::setHasPendingResources):
+ (WebCore::SVGElement::clearHasPendingResourcesIfPossible):
+ * svg/SVGElement.h:
+ (SVGElement):
+ (WebCore::SVGElement::buildPendingResource):
+ * svg/SVGStyledElement.cpp:
+ (WebCore):
+ (WebCore::SVGStyledElement::buildPendingResourcesIfNeeded):
+ (WebCore::SVGStyledElement::removedFrom):
+ * svg/SVGStyledElement.h:
+ (SVGStyledElement):
+ (WebCore::SVGStyledElement::selfHasRelativeLengths):
+
2012-10-29 Dan Carney <dcarney@google.com>
Remove ensureAuxiliaryContext
reportMessage(m_document, ErrorMessageLevel, "Error: " + message);
}
-void SVGDocumentExtensions::addPendingResource(const AtomicString& id, SVGStyledElement* element)
+void SVGDocumentExtensions::addPendingResource(const AtomicString& id, SVGElement* element)
{
ASSERT(element);
return m_pendingResources.contains(id);
}
-bool SVGDocumentExtensions::isElementPendingResources(SVGStyledElement* element) const
+bool SVGDocumentExtensions::isElementPendingResources(SVGElement* element) const
{
// This algorithm takes time proportional to the number of pending resources and need not.
// If performance becomes an issue we can keep a counted set of elements and answer the question efficiently.
return false;
}
-bool SVGDocumentExtensions::isElementPendingResource(SVGStyledElement* element, const AtomicString& id) const
+bool SVGDocumentExtensions::isElementPendingResource(SVGElement* element, const AtomicString& id) const
{
ASSERT(element);
return m_pendingResources.get(id)->contains(element);
}
-void SVGDocumentExtensions::removeElementFromPendingResources(SVGStyledElement* element)
+void SVGDocumentExtensions::removeElementFromPendingResources(SVGElement* element)
{
ASSERT(element);
m_pendingResourcesForRemoval.add(id, existing);
}
-SVGStyledElement* SVGDocumentExtensions::removeElementFromPendingResourcesForRemoval(const AtomicString& id)
+SVGElement* SVGDocumentExtensions::removeElementFromPendingResourcesForRemoval(const AtomicString& id)
{
if (id.isEmpty())
return 0;
return 0;
SVGPendingElements::iterator firstElement = resourceSet->begin();
- SVGStyledElement* element = *firstElement;
+ SVGElement* element = *firstElement;
resourceSet->remove(firstElement);
class SVGResourcesCache;
class SVGSMILElement;
class SVGSVGElement;
-class SVGStyledElement;
class SVGDocumentExtensions {
WTF_MAKE_NONCOPYABLE(SVGDocumentExtensions); WTF_MAKE_FAST_ALLOCATED;
public:
- typedef HashSet<SVGStyledElement*> SVGPendingElements;
+ typedef HashSet<SVGElement*> SVGPendingElements;
SVGDocumentExtensions(Document*);
~SVGDocumentExtensions();
public:
// This HashMap contains a list of pending resources. Pending resources, are such
// which are referenced by any object in the SVG document, but do NOT exist yet.
- // For instance, dynamically build gradients / patterns / clippers...
- void addPendingResource(const AtomicString& id, SVGStyledElement*);
+ // For instance, dynamically built gradients / patterns / clippers...
+ void addPendingResource(const AtomicString& id, SVGElement*);
bool hasPendingResource(const AtomicString& id) const;
- bool isElementPendingResources(SVGStyledElement*) const;
- bool isElementPendingResource(SVGStyledElement*, const AtomicString& id) const;
- void removeElementFromPendingResources(SVGStyledElement*);
+ bool isElementPendingResources(SVGElement*) const;
+ bool isElementPendingResource(SVGElement*, const AtomicString& id) const;
+ void removeElementFromPendingResources(SVGElement*);
PassOwnPtr<SVGPendingElements> removePendingResource(const AtomicString& id);
// The following two functions are used for scheduling a pending resource to be removed.
void markPendingResourcesForRemoval(const AtomicString&);
- SVGStyledElement* removeElementFromPendingResourcesForRemoval(const AtomicString&);
+ SVGElement* removeElementFromPendingResourcesForRemoval(const AtomicString&);
private:
PassOwnPtr<SVGPendingElements> removePendingResourceForRemoval(const AtomicString&);
if (!hasSVGRareData())
ASSERT(!SVGElementRareData::rareDataMap().contains(this));
else {
+ ASSERT(document());
+ if (hasPendingResources())
+ document()->accessSVGExtensions()->removeElementFromPendingResources(this);
+ ASSERT(!hasPendingResources());
SVGElementRareData::SVGElementRareDataMap& rareDataMap = SVGElementRareData::rareDataMap();
SVGElementRareData::SVGElementRareDataMap::iterator it = rareDataMap.find(this);
ASSERT(it != rareDataMap.end());
delete rareData;
rareDataMap.remove(it);
}
+ ASSERT(document());
document()->accessSVGExtensions()->removeAllAnimationElementsFromTarget(this);
document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this);
}
if (wasInDocument) {
document()->accessSVGExtensions()->removeAllAnimationElementsFromTarget(this);
document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this);
+ document()->accessSVGExtensions()->removeElementFromPendingResources(this);
}
}
svgAttributeChanged(name);
}
+bool SVGElement::hasPendingResources() const
+{
+ return hasSVGRareData() && svgRareData()->hasPendingResources();
+}
+
+void SVGElement::setHasPendingResources()
+{
+ ensureSVGRareData()->setHasPendingResources(true);
+}
+
+void SVGElement::clearHasPendingResourcesIfPossible()
+{
+ if (!document()->accessSVGExtensions()->isElementPendingResources(this))
+ ensureSVGRareData()->setHasPendingResources(false);
+}
+
void SVGElement::updateAnimatedSVGAttribute(const QualifiedName& name) const
{
if (isSynchronizingSVGAttributes() || areSVGAttributesValid())
virtual void svgAttributeChanged(const QualifiedName&) { }
+ bool hasPendingResources() const;
+ void setHasPendingResources();
+ void clearHasPendingResourcesIfPossible();
+ virtual void buildPendingResource() { }
+
virtual void animatedPropertyTypeForAttribute(const QualifiedName&, Vector<AnimatedPropertyType>&);
void sendSVGLoadEventIfPossible(bool sendParentLoadEvents = false);
registerAnimatedPropertiesForSVGStyledElement();
}
-SVGStyledElement::~SVGStyledElement()
-{
- if (hasPendingResources() && document())
- document()->accessSVGExtensions()->removeElementFromPendingResources(this);
-
- ASSERT(!hasPendingResources());
-}
-
String SVGStyledElement::title() const
{
// According to spec, we should not return titles when hovering over root <svg> elements (those
extensions->markPendingResourcesForRemoval(resourceId);
// Rebuild pending resources for each client of a pending resource that is being removed.
- while (SVGStyledElement* clientElement = extensions->removeElementFromPendingResourcesForRemoval(resourceId)) {
+ while (SVGElement* clientElement = extensions->removeElementFromPendingResourcesForRemoval(resourceId)) {
ASSERT(clientElement->hasPendingResources());
if (clientElement->hasPendingResources()) {
clientElement->buildPendingResource();
updateRelativeLengthsInformation(false, this);
SVGElement::removedFrom(rootParent);
SVGElementInstance::invalidateAllInstancesOfElement(this);
- Document* document = this->document();
- if (!rootParent->inDocument() || !document)
- return;
-
- document->accessSVGExtensions()->removeElementFromPendingResources(this);
}
void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta)
svgRareData()->setInstanceUpdatesBlocked(value);
}
-bool SVGStyledElement::hasPendingResources() const
-{
- return hasSVGRareData() && svgRareData()->hasPendingResources();
-}
-
-void SVGStyledElement::setHasPendingResources()
-{
- ensureSVGRareData()->setHasPendingResources(true);
-}
-
-void SVGStyledElement::clearHasPendingResourcesIfPossible()
-{
- if (!document()->accessSVGExtensions()->isElementPendingResources(this))
- ensureSVGRareData()->setHasPendingResources(false);
-}
-
AffineTransform SVGStyledElement::localCoordinateSpaceTransform(SVGLocatable::CTMScope) const
{
// To be overriden by SVGStyledLocatableElement/SVGStyledTransformableElement (or as special case SVGTextElement and SVGPatternElement)
class SVGStyledElement : public SVGElement,
public SVGStylable {
public:
- virtual ~SVGStyledElement();
-
virtual String title() const;
bool hasRelativeLengths() const { return !m_elementsWithRelativeLengths.isEmpty(); }
bool instanceUpdatesBlocked() const;
void setInstanceUpdatesBlocked(bool);
- bool hasPendingResources() const;
- void setHasPendingResources();
- void clearHasPendingResourcesIfPossible();
-
virtual void animatedPropertyTypeForAttribute(const QualifiedName&, Vector<AnimatedPropertyType>&);
static bool isAnimatableCSSProperty(const QualifiedName&);
virtual void parseAttribute(const Attribute&) OVERRIDE;
virtual bool isPresentationAttribute(const QualifiedName&) const OVERRIDE;
virtual void collectStyleForAttribute(const Attribute&, StylePropertySet*) OVERRIDE;
- virtual void svgAttributeChanged(const QualifiedName&);
+ virtual void svgAttributeChanged(const QualifiedName&) OVERRIDE;
virtual InsertionNotificationRequest insertedInto(ContainerNode*) OVERRIDE;
virtual void removedFrom(ContainerNode*) OVERRIDE;
void updateRelativeLengthsInformation(bool hasRelativeLengths, SVGStyledElement*);
virtual bool selfHasRelativeLengths() const { return false; }
- virtual void buildPendingResource() { }
private:
virtual bool isStyled() const { return true; }