summaryrefslogtreecommitdiff
path: root/Source/WebCore/svg/SVGUseElement.cpp
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@digia.com>2013-09-13 12:51:20 +0200
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-09-19 20:50:05 +0200
commitd441d6f39bb846989d95bcf5caf387b42414718d (patch)
treee367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/svg/SVGUseElement.cpp
parent0060b2994c07842f4c59de64b5e3e430525c4b90 (diff)
downloadqtwebkit-d441d6f39bb846989d95bcf5caf387b42414718d.tar.gz
Import Qt5x2 branch of QtWebkit for Qt 5.2
Importing a new snapshot of webkit. Change-Id: I2d01ad12cdc8af8cb015387641120a9d7ea5f10c Reviewed-by: Allan Sandfeld Jensen <allan.jensen@digia.com>
Diffstat (limited to 'Source/WebCore/svg/SVGUseElement.cpp')
-rw-r--r--Source/WebCore/svg/SVGUseElement.cpp152
1 files changed, 81 insertions, 71 deletions
diff --git a/Source/WebCore/svg/SVGUseElement.cpp b/Source/WebCore/svg/SVGUseElement.cpp
index dd467d5c5..30372157c 100644
--- a/Source/WebCore/svg/SVGUseElement.cpp
+++ b/Source/WebCore/svg/SVGUseElement.cpp
@@ -30,12 +30,14 @@
#include "Attribute.h"
#include "CachedResourceLoader.h"
#include "CachedResourceRequest.h"
+#include "CachedSVGDocument.h"
#include "Document.h"
#include "ElementShadow.h"
#include "Event.h"
#include "EventListener.h"
#include "HTMLNames.h"
#include "NodeRenderStyle.h"
+#include "NodeTraversal.h"
#include "RegisteredEventListener.h"
#include "RenderSVGResource.h"
#include "RenderSVGTransformableContainer.h"
@@ -77,12 +79,11 @@ BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGUseElement)
REGISTER_LOCAL_ANIMATED_PROPERTY(height)
REGISTER_LOCAL_ANIMATED_PROPERTY(href)
REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
- REGISTER_PARENT_ANIMATED_PROPERTIES(SVGStyledTransformableElement)
- REGISTER_PARENT_ANIMATED_PROPERTIES(SVGTests)
+ REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement)
END_REGISTER_ANIMATED_PROPERTIES
inline SVGUseElement::SVGUseElement(const QualifiedName& tagName, Document* document, bool wasInsertedByParser)
- : SVGStyledTransformableElement(tagName, document)
+ : SVGGraphicsElement(tagName, document)
, m_x(LengthModeWidth)
, m_y(LengthModeHeight)
, m_width(LengthModeWidth)
@@ -92,7 +93,7 @@ inline SVGUseElement::SVGUseElement(const QualifiedName& tagName, Document* docu
, m_needsShadowTreeRecreation(false)
, m_svgLoadEventTimer(this, &SVGElement::svgLoadEventTimerFired)
{
- ASSERT(hasCustomCallbacks());
+ ASSERT(hasCustomStyleCallbacks());
ASSERT(hasTagName(SVGNames::useTag));
registerAnimatedPropertiesForSVGUseElement();
}
@@ -101,24 +102,17 @@ PassRefPtr<SVGUseElement> SVGUseElement::create(const QualifiedName& tagName, Do
{
// Always build a #shadow-root for SVGUseElement.
RefPtr<SVGUseElement> use = adoptRef(new SVGUseElement(tagName, document, wasInsertedByParser));
- use->createShadowSubtree();
+ use->ensureUserAgentShadowRoot();
return use.release();
}
SVGUseElement::~SVGUseElement()
{
- if (m_cachedDocument)
- m_cachedDocument->removeClient(this);
+ setCachedDocument(0);
clearResourceReferences();
}
-void SVGUseElement::createShadowSubtree()
-{
- ASSERT(!shadow());
- ShadowRoot::create(this, ShadowRoot::UserAgentShadowRoot);
-}
-
SVGElementInstance* SVGUseElement::instanceRoot()
{
// If there is no element instance tree, force immediate SVGElementInstance tree
@@ -141,7 +135,6 @@ bool SVGUseElement::isSupportedAttribute(const QualifiedName& attrName)
{
DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
if (supportedAttributes.isEmpty()) {
- SVGTests::addSupportedAttributes(supportedAttributes);
SVGLangSpace::addSupportedAttributes(supportedAttributes);
SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
SVGURIReference::addSupportedAttributes(supportedAttributes);
@@ -150,7 +143,7 @@ bool SVGUseElement::isSupportedAttribute(const QualifiedName& attrName)
supportedAttributes.add(SVGNames::widthAttr);
supportedAttributes.add(SVGNames::heightAttr);
}
- return supportedAttributes.contains<QualifiedName, SVGAttributeHashTranslator>(attrName);
+ return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
}
void SVGUseElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
@@ -158,7 +151,7 @@ void SVGUseElement::parseAttribute(const QualifiedName& name, const AtomicString
SVGParsingError parseError = NoError;
if (!isSupportedAttribute(name))
- SVGStyledTransformableElement::parseAttribute(name, value);
+ SVGGraphicsElement::parseAttribute(name, value);
else if (name == SVGNames::xAttr)
setXBaseValue(SVGLength::construct(LengthModeWidth, value, parseError));
else if (name == SVGNames::yAttr)
@@ -167,8 +160,7 @@ void SVGUseElement::parseAttribute(const QualifiedName& name, const AtomicString
setWidthBaseValue(SVGLength::construct(LengthModeWidth, value, parseError, ForbidNegativeLengths));
else if (name == SVGNames::heightAttr)
setHeightBaseValue(SVGLength::construct(LengthModeHeight, value, parseError, ForbidNegativeLengths));
- else if (SVGTests::parseAttribute(name, value)
- || SVGLangSpace::parseAttribute(name, value)
+ else if (SVGLangSpace::parseAttribute(name, value)
|| SVGExternalResourcesRequired::parseAttribute(name, value)
|| SVGURIReference::parseAttribute(name, value)) {
} else
@@ -187,7 +179,7 @@ static inline bool isWellFormedDocument(Document* document)
Node::InsertionNotificationRequest SVGUseElement::insertedInto(ContainerNode* rootParent)
{
// This functions exists to assure assumptions made in the code regarding SVGElementInstance creation/destruction are satisfied.
- SVGStyledTransformableElement::insertedInto(rootParent);
+ SVGGraphicsElement::insertedInto(rootParent);
if (!rootParent->inDocument())
return InsertionDone;
ASSERT(!m_targetElementInstance || !isWellFormedDocument(document()));
@@ -200,7 +192,7 @@ Node::InsertionNotificationRequest SVGUseElement::insertedInto(ContainerNode* ro
void SVGUseElement::removedFrom(ContainerNode* rootParent)
{
- SVGStyledTransformableElement::removedFrom(rootParent);
+ SVGGraphicsElement::removedFrom(rootParent);
if (rootParent->inDocument())
clearResourceReferences();
}
@@ -227,7 +219,7 @@ Document* SVGUseElement::externalDocument() const
void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
{
if (!isSupportedAttribute(attrName)) {
- SVGStyledTransformableElement::svgAttributeChanged(attrName);
+ SVGGraphicsElement::svgAttributeChanged(attrName);
return;
}
@@ -244,9 +236,6 @@ void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
return;
}
- if (SVGTests::handleAttributeChange(this, attrName))
- return;
-
if (SVGExternalResourcesRequired::handleAttributeChange(this, attrName))
return;
@@ -257,18 +246,14 @@ void SVGUseElement::svgAttributeChanged(const QualifiedName& attrName)
if (url.hasFragmentIdentifier()) {
CachedResourceRequest request(ResourceRequest(url.string()));
request.setInitiator(this);
- m_cachedDocument = document()->cachedResourceLoader()->requestSVGDocument(request);
- if (m_cachedDocument)
- m_cachedDocument->addClient(this);
+ setCachedDocument(document()->cachedResourceLoader()->requestSVGDocument(request));
}
- }
+ } else
+ setCachedDocument(0);
- if (m_cachedDocument && !isExternalReference) {
- m_cachedDocument->removeClient(this);
- m_cachedDocument = 0;
- }
if (!m_wasInsertedByParser)
buildPendingResource();
+
return;
}
@@ -298,7 +283,7 @@ static void dumpInstanceTree(unsigned int& depth, String& text, SVGElementInstan
ASSERT(element);
if (element->hasTagName(SVGNames::useTag)) {
- if (static_cast<SVGUseElement*>(element)->cachedDocumentIsStillLoading())
+ if (toSVGUseElement(element)->cachedDocumentIsStillLoading())
return;
}
@@ -358,7 +343,7 @@ static bool isDisallowedElement(Node* node)
if (!node->isSVGElement())
return true;
- Element* element = static_cast<Element*>(node);
+ Element* element = toElement(node);
DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, allowedElementTags, ());
if (allowedElementTags.isEmpty()) {
@@ -384,7 +369,7 @@ static bool isDisallowedElement(Node* node)
allowedElementTags.add(SVGNames::tspanTag);
allowedElementTags.add(SVGNames::useTag);
}
- return !allowedElementTags.contains<QualifiedName, SVGAttributeHashTranslator>(element->tagQName());
+ return !allowedElementTags.contains<SVGAttributeHashTranslator>(element->tagQName());
}
static bool subtreeContainsDisallowedElement(Node* start)
@@ -403,8 +388,8 @@ static bool subtreeContainsDisallowedElement(Node* start)
void SVGUseElement::clearResourceReferences()
{
// FIXME: We should try to optimize this, to at least allow partial reclones.
- if (ShadowRoot* shadowTreeRootElement = shadow()->oldestShadowRoot())
- shadowTreeRootElement->removeAllChildren();
+ if (ShadowRoot* shadowTreeRootElement = shadow()->shadowRoot())
+ shadowTreeRootElement->removeChildren();
if (m_targetElementInstance) {
m_targetElementInstance->detach();
@@ -419,10 +404,10 @@ void SVGUseElement::clearResourceReferences()
void SVGUseElement::buildPendingResource()
{
- if (!referencedDocument())
+ if (!referencedDocument() || isInShadowTree())
return;
clearResourceReferences();
- if (!inDocument() || isInShadowTree())
+ if (!inDocument())
return;
String id;
@@ -440,8 +425,11 @@ void SVGUseElement::buildPendingResource()
return;
}
- if (target->isSVGElement())
- buildShadowAndInstanceTree(static_cast<SVGElement*>(target));
+ if (target->isSVGElement()) {
+ buildShadowAndInstanceTree(toSVGElement(target));
+ invalidateDependentShadowTrees();
+ }
+
ASSERT(!m_needsShadowTreeRecreation);
}
@@ -492,7 +480,7 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target)
ASSERT(m_targetElementInstance->directUseElement() == this);
ASSERT(m_targetElementInstance->correspondingElement() == target);
- ShadowRoot* shadowTreeRootElement = shadow()->oldestShadowRoot();
+ ShadowRoot* shadowTreeRootElement = shadow()->shadowRoot();
ASSERT(shadowTreeRootElement);
// Build shadow tree from instance tree
@@ -527,10 +515,6 @@ void SVGUseElement::buildShadowAndInstanceTree(SVGElement* target)
// Update relative length information.
updateRelativeLengthsInformation();
- // Rebuild all dependent use elements.
- ASSERT(document());
- document()->accessSVGExtensions()->removeAllElementReferencesForTarget(this);
-
// Eventually dump instance tree
#ifdef DUMP_INSTANCE_TREE
String text;
@@ -572,12 +556,12 @@ void SVGUseElement::toClipPath(Path& path)
if (!n)
return;
- if (n->isSVGElement() && static_cast<SVGElement*>(n)->isStyledTransformable()) {
+ if (n->isSVGElement() && toSVGElement(n)->isSVGGraphicsElement()) {
if (!isDirectReference(n))
// Spec: Indirect references are an error (14.3.5)
document()->accessSVGExtensions()->reportError("Not allowed to use indirect reference in <clip-path>");
else {
- static_cast<SVGStyledTransformableElement*>(n)->toClipPath(path);
+ toSVGGraphicsElement(n)->toClipPath(path);
// FIXME: Avoid manual resolution of x/y here. Its potentially harmful.
SVGLengthContext lengthContext(this);
path.translate(FloatSize(x().value(lengthContext), y().value(lengthContext)));
@@ -593,7 +577,7 @@ RenderObject* SVGUseElement::rendererClipChild() const
return 0;
if (n->isSVGElement() && isDirectReference(n))
- return static_cast<SVGElement*>(n)->renderer();
+ return toSVGElement(n)->renderer();
return 0;
}
@@ -608,11 +592,11 @@ void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* ta
bool targetHasUseTag = target->hasTagName(SVGNames::useTag);
SVGElement* newTarget = 0;
if (targetHasUseTag) {
- foundProblem = hasCycleUseReferencing(static_cast<SVGUseElement*>(target), targetInstance, newTarget);
+ foundProblem = hasCycleUseReferencing(toSVGUseElement(target), targetInstance, newTarget);
if (foundProblem)
return;
- // We only need to track fist degree <use> dependencies. Indirect references are handled
+ // We only need to track first degree <use> dependencies. Indirect references are handled
// as the invalidation bubbles up the dependency chain.
if (!foundUse) {
ASSERT(document());
@@ -634,7 +618,7 @@ void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* ta
for (Node* node = target->firstChild(); node; node = node->nextSibling()) {
SVGElement* element = 0;
if (node->isSVGElement())
- element = static_cast<SVGElement*>(node);
+ element = toSVGElement(node);
// Skip any non-svg nodes or any disallowed element.
if (!element || isDisallowedElement(element))
@@ -654,7 +638,7 @@ void SVGUseElement::buildInstanceTree(SVGElement* target, SVGElementInstance* ta
if (!targetHasUseTag || !newTarget)
return;
- RefPtr<SVGElementInstance> newInstance = SVGElementInstance::create(this, static_cast<SVGUseElement*>(target), newTarget);
+ RefPtr<SVGElementInstance> newInstance = SVGElementInstance::create(this, toSVGUseElement(target), newTarget);
SVGElementInstance* newInstancePtr = newInstance.get();
targetInstance->appendChild(newInstance.release());
buildInstanceTree(newTarget, newInstancePtr, foundProblem, foundUse);
@@ -665,7 +649,7 @@ bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstanc
Element* targetElement = SVGURIReference::targetElementFromIRIString(use->href(), referencedDocument());
newTarget = 0;
if (targetElement && targetElement->isSVGElement())
- newTarget = static_cast<SVGElement*>(targetElement);
+ newTarget = toSVGElement(targetElement);
if (!newTarget)
return false;
@@ -679,8 +663,7 @@ bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstanc
while (instance) {
SVGElement* element = instance->correspondingElement();
- // FIXME: This should probably be using getIdAttribute instead of idForStyleResolution.
- if (element->hasID() && element->idForStyleResolution() == targetId && element->document() == newTarget->document())
+ if (element->hasID() && element->getIdAttribute() == targetId && element->document() == newTarget->document())
return true;
instance = instance->parentNode();
@@ -688,18 +671,18 @@ bool SVGUseElement::hasCycleUseReferencing(SVGUseElement* use, SVGElementInstanc
return false;
}
-static inline void removeDisallowedElementsFromSubtree(Node* subtree)
+static inline void removeDisallowedElementsFromSubtree(Element* subtree)
{
ASSERT(!subtree->inDocument());
- Node* node = subtree->firstChild();
- while (node) {
- if (isDisallowedElement(node)) {
- Node* next = node->traverseNextSibling(subtree);
+ Element* element = ElementTraversal::firstWithin(subtree);
+ while (element) {
+ if (isDisallowedElement(element)) {
+ Element* next = ElementTraversal::nextSkippingChildren(element, subtree);
// The subtree is not in document so this won't generate events that could mutate the tree.
- node->parentNode()->removeChild(node);
- node = next;
+ element->parentNode()->removeChild(element);
+ element = next;
} else
- node = node->traverseNextNode(subtree);
+ element = ElementTraversal::next(element, subtree);
}
}
@@ -719,7 +702,7 @@ void SVGUseElement::buildShadowTree(SVGElement* target, SVGElementInstance* targ
if (subtreeContainsDisallowedElement(newChild.get()))
removeDisallowedElementsFromSubtree(newChild.get());
- shadow()->oldestShadowRoot()->appendChild(newChild.release());
+ shadow()->shadowRoot()->appendChild(newChild.release());
}
void SVGUseElement::expandUseElementsInShadowTree(Node* element)
@@ -732,13 +715,13 @@ void SVGUseElement::expandUseElementsInShadowTree(Node* element)
// actual shadow tree (after the special case modification for svg/symbol) we have
// to walk it completely and expand all <use> elements.
if (element->hasTagName(SVGNames::useTag)) {
- SVGUseElement* use = static_cast<SVGUseElement*>(element);
+ SVGUseElement* use = toSVGUseElement(element);
ASSERT(!use->cachedDocumentIsStillLoading());
Element* targetElement = SVGURIReference::targetElementFromIRIString(use->href(), referencedDocument());
SVGElement* target = 0;
if (targetElement && targetElement->isSVGElement())
- target = static_cast<SVGElement*>(targetElement);
+ target = toSVGElement(targetElement);
// Don't ASSERT(target) here, it may be "pending", too.
// Setup sub-shadow tree root node
@@ -859,7 +842,7 @@ void SVGUseElement::associateInstancesWithShadowTreeElements(Node* target, SVGEl
SVGElement* element = 0;
if (target->isSVGElement())
- element = static_cast<SVGElement*>(target);
+ element = toSVGElement(target);
ASSERT(!targetInstance->shadowTreeElement());
targetInstance->setShadowTreeElement(element);
@@ -916,6 +899,20 @@ void SVGUseElement::invalidateShadowTree()
return;
m_needsShadowTreeRecreation = true;
setNeedsStyleRecalc();
+ invalidateDependentShadowTrees();
+}
+
+void SVGUseElement::invalidateDependentShadowTrees()
+{
+ // Recursively invalidate dependent <use> shadow trees
+ const HashSet<SVGElementInstance*>& instances = instancesForElement();
+ const HashSet<SVGElementInstance*>::const_iterator end = instances.end();
+ for (HashSet<SVGElementInstance*>::const_iterator it = instances.begin(); it != end; ++it) {
+ if (SVGUseElement* element = (*it)->correspondingUseElement()) {
+ ASSERT(element->inDocument());
+ element->invalidateShadowTree();
+ }
+ }
}
void SVGUseElement::transferUseAttributesToReplacedElement(SVGElement* from, SVGElement* to) const
@@ -944,10 +941,10 @@ bool SVGUseElement::selfHasRelativeLengths() const
return false;
SVGElement* element = m_targetElementInstance->correspondingElement();
- if (!element || !element->isStyled())
+ if (!element || !element->isSVGStyledElement())
return false;
- return static_cast<SVGStyledElement*>(element)->hasRelativeLengths();
+ return toSVGStyledElement(element)->hasRelativeLengths();
}
void SVGUseElement::notifyFinished(CachedResource* resource)
@@ -984,7 +981,7 @@ bool SVGUseElement::instanceTreeIsLoading(SVGElementInstance* targetElementInsta
void SVGUseElement::finishParsingChildren()
{
- SVGStyledTransformableElement::finishParsingChildren();
+ SVGGraphicsElement::finishParsingChildren();
SVGExternalResourcesRequired::finishParsingChildren();
if (m_wasInsertedByParser) {
buildPendingResource();
@@ -992,6 +989,19 @@ void SVGUseElement::finishParsingChildren()
}
}
+void SVGUseElement::setCachedDocument(CachedResourceHandle<CachedSVGDocument> cachedDocument)
+{
+ if (m_cachedDocument == cachedDocument)
+ return;
+
+ if (m_cachedDocument)
+ m_cachedDocument->removeClient(this);
+
+ m_cachedDocument = cachedDocument;
+ if (m_cachedDocument)
+ m_cachedDocument->addClient(this);
+}
+
}
#endif // ENABLE(SVG)