diff options
author | Allan Sandfeld Jensen <allan.jensen@digia.com> | 2013-09-13 12:51:20 +0200 |
---|---|---|
committer | The Qt Project <gerrit-noreply@qt-project.org> | 2013-09-19 20:50:05 +0200 |
commit | d441d6f39bb846989d95bcf5caf387b42414718d (patch) | |
tree | e367e64a75991c554930278175d403c072de6bb8 /Source/WebCore/svg/SVGUseElement.cpp | |
parent | 0060b2994c07842f4c59de64b5e3e430525c4b90 (diff) | |
download | qtwebkit-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.cpp | 152 |
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) |