diff options
Diffstat (limited to 'WebCore/svg/SVGStyledElement.cpp')
-rw-r--r-- | WebCore/svg/SVGStyledElement.cpp | 106 |
1 files changed, 66 insertions, 40 deletions
diff --git a/WebCore/svg/SVGStyledElement.cpp b/WebCore/svg/SVGStyledElement.cpp index 22c2008..9a3f950 100644 --- a/WebCore/svg/SVGStyledElement.cpp +++ b/WebCore/svg/SVGStyledElement.cpp @@ -41,8 +41,8 @@ #include "SVGNames.h" #include "SVGRenderStyle.h" #include "SVGRenderSupport.h" -#include "SVGResource.h" #include "SVGSVGElement.h" +#include "SVGUseElement.h" #include <wtf/Assertions.h> namespace WebCore { @@ -63,7 +63,50 @@ SVGStyledElement::SVGStyledElement(const QualifiedName& tagName, Document* doc) SVGStyledElement::~SVGStyledElement() { - SVGResource::removeClient(this); +} + +String SVGStyledElement::title() const +{ + // According to spec, we should not return titles when hovering over <svg> elements (those + // <title> elements are the title of the document, not a tooltip) so we instantly return. + if (hasTagName(SVGNames::svgTag)) + return String(); + + // Walk up the tree, to find out whether we're inside a <use> shadow tree, to find the right title. + Node* parent = const_cast<SVGStyledElement*>(this); + while (parent) { + if (!parent->isShadowNode()) { + parent = parent->parentNode(); + continue; + } + + // Get the <use> element. + Node* shadowParent = parent->shadowParentNode(); + if (shadowParent && shadowParent->isSVGElement() && shadowParent->hasTagName(SVGNames::useTag)) { + SVGUseElement* useElement = static_cast<SVGUseElement*>(shadowParent); + // If the <use> title is not empty we found the title to use. + String useTitle(useElement->title()); + if (useTitle.isEmpty()) + break; + return useTitle; + } + parent = parent->parentNode(); + } + + // If we aren't an instance in a <use> or the <use> title was not found, then find the first + // <title> child of this element. + Element* titleElement = firstElementChild(); + for (; titleElement; titleElement = titleElement->nextElementSibling()) { + if (titleElement->hasTagName(SVGNames::titleTag) && titleElement->isSVGElement()) + break; + } + + // If a title child was found, return the text contents. + if (titleElement) + return titleElement->innerText(); + + // Otherwise return a null/empty string. + return String(); } bool SVGStyledElement::rendererIsNeeded(RenderStyle* style) @@ -200,19 +243,21 @@ void SVGStyledElement::svgAttributeChanged(const QualifiedName& attrName) if (attrName.matches(HTMLNames::classAttr)) classAttributeChanged(className()); + RenderObject* object = renderer(); + if (attrName == idAttributeName()) { // Notify resources about id changes, this is important as we cache resources by id in SVGDocumentExtensions - if (renderer() && renderer()->isSVGResource()) { - RenderSVGResource* resource = renderer()->toRenderSVGResource(); - resource->idChanged(); - } + if (object && object->isSVGResourceContainer()) + object->toRenderSVGResourceContainer()->idChanged(); } - // If we're the child of a resource element, be sure to invalidate it. - invalidateResourcesInAncestorChain(); + if (!document()->parsing() && object) { + // If we're the child of a resource element, tell the resource (and eventually its resources) that we've changed. + invalidateResourcesInAncestorChain(); - // If the element is using resources, invalidate them. - invalidateResources(); + // If we're referencing resources, tell them we've changed. + deregisterFromResources(object); + } // Invalidate all SVGElementInstances associated with us SVGElementInstance::invalidateAllInstancesOfElement(this); @@ -226,20 +271,6 @@ void SVGStyledElement::synchronizeProperty(const QualifiedName& attrName) synchronizeClassName(); } -void SVGStyledElement::invalidateResources() -{ - RenderObject* object = renderer(); - if (!object) - return; - - Document* document = this->document(); - - if (document->parsing()) - return; - - deregisterFromResources(object); -} - void SVGStyledElement::invalidateResourcesInAncestorChain() const { Node* node = parentNode(); @@ -248,25 +279,25 @@ void SVGStyledElement::invalidateResourcesInAncestorChain() const break; SVGElement* element = static_cast<SVGElement*>(node); - if (SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element->isStyled() ? element : 0)) - styledElement->invalidateCanvasResources(); + if (SVGStyledElement* styledElement = static_cast<SVGStyledElement*>(element->isStyled() ? element : 0)) { + styledElement->invalidateResourceClients(); + + // If we found the first resource in the ancestor chain, immediately stop. + break; + } node = node->parentNode(); } } -void SVGStyledElement::invalidateCanvasResources() +void SVGStyledElement::invalidateResourceClients() { RenderObject* object = renderer(); if (!object) return; - if (object->isSVGResource()) - object->toRenderSVGResource()->invalidateClients(); - - // The following lines will be removed soon, once all resources are handled by renderers. - if (SVGResource* resource = canvasResource(object)) - resource->invalidate(); + if (object->isSVGResourceContainer()) + object->toRenderSVGResourceContainer()->invalidateClients(); } void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, Node* afterChange, int childCountDelta) @@ -274,7 +305,8 @@ void SVGStyledElement::childrenChanged(bool changedByParser, Node* beforeChange, SVGElement::childrenChanged(changedByParser, beforeChange, afterChange, childCountDelta); // Invalidate all SVGElementInstances associated with us - SVGElementInstance::invalidateAllInstancesOfElement(this); + if (!changedByParser) + SVGElementInstance::invalidateAllInstancesOfElement(this); } PassRefPtr<RenderStyle> SVGStyledElement::resolveStyle(RenderStyle* parentStyle) @@ -309,12 +341,6 @@ PassRefPtr<CSSValue> SVGStyledElement::getPresentationAttribute(const String& na return cssSVGAttr->style()->getPropertyCSSValue(name); } -void SVGStyledElement::detach() -{ - SVGResource::removeClient(this); - SVGElement::detach(); -} - bool SVGStyledElement::instanceUpdatesBlocked() const { return hasRareSVGData() && rareSVGData()->instanceUpdatesBlocked(); |