Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2007 Eric Seidel <eric (at) webkit.org>
      3  *
      4  * This library is free software; you can redistribute it and/or
      5  * modify it under the terms of the GNU Library General Public
      6  * License as published by the Free Software Foundation; either
      7  * version 2 of the License, or (at your option) any later version.
      8  *
      9  * This library is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  * Library General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU Library General Public License
     15  * along with this library; see the file COPYING.LIB.  If not, write to
     16  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     17  * Boston, MA 02110-1301, USA.
     18  */
     19 
     20 #include "config.h"
     21 
     22 #include "core/svg/SVGMPathElement.h"
     23 
     24 #include "SVGNames.h"
     25 #include "XLinkNames.h"
     26 #include "core/dom/Document.h"
     27 #include "core/svg/SVGAnimateMotionElement.h"
     28 #include "core/svg/SVGDocumentExtensions.h"
     29 #include "core/svg/SVGPathElement.h"
     30 
     31 namespace WebCore {
     32 
     33 // Animated property definitions
     34 DEFINE_ANIMATED_STRING(SVGMPathElement, XLinkNames::hrefAttr, Href, href)
     35 DEFINE_ANIMATED_BOOLEAN(SVGMPathElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
     36 
     37 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGMPathElement)
     38     REGISTER_LOCAL_ANIMATED_PROPERTY(href)
     39     REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
     40 END_REGISTER_ANIMATED_PROPERTIES
     41 
     42 inline SVGMPathElement::SVGMPathElement(const QualifiedName& tagName, Document* document)
     43     : SVGElement(tagName, document)
     44 {
     45     ASSERT(hasTagName(SVGNames::mpathTag));
     46     ScriptWrappable::init(this);
     47     registerAnimatedPropertiesForSVGMPathElement();
     48 }
     49 
     50 PassRefPtr<SVGMPathElement> SVGMPathElement::create(const QualifiedName& tagName, Document* document)
     51 {
     52     return adoptRef(new SVGMPathElement(tagName, document));
     53 }
     54 
     55 SVGMPathElement::~SVGMPathElement()
     56 {
     57     clearResourceReferences();
     58 }
     59 
     60 void SVGMPathElement::buildPendingResource()
     61 {
     62     clearResourceReferences();
     63     if (!inDocument())
     64         return;
     65 
     66     String id;
     67     Element* target = SVGURIReference::targetElementFromIRIString(hrefCurrentValue(), document(), &id);
     68     if (!target) {
     69         // Do not register as pending if we are already pending this resource.
     70         if (document()->accessSVGExtensions()->isElementPendingResource(this, id))
     71             return;
     72 
     73         if (!id.isEmpty()) {
     74             document()->accessSVGExtensions()->addPendingResource(id, this);
     75             ASSERT(hasPendingResources());
     76         }
     77     } else if (target->isSVGElement()) {
     78         // Register us with the target in the dependencies map. Any change of hrefElement
     79         // that leads to relayout/repainting now informs us, so we can react to it.
     80         document()->accessSVGExtensions()->addElementReferencingTarget(this, toSVGElement(target));
     81     }
     82 
     83     targetPathChanged();
     84 }
     85 
     86 void SVGMPathElement::clearResourceReferences()
     87 {
     88     ASSERT(document());
     89     document()->accessSVGExtensions()->removeAllTargetReferencesForElement(this);
     90 }
     91 
     92 Node::InsertionNotificationRequest SVGMPathElement::insertedInto(ContainerNode* rootParent)
     93 {
     94     SVGElement::insertedInto(rootParent);
     95     if (rootParent->inDocument())
     96         buildPendingResource();
     97     return InsertionDone;
     98 }
     99 
    100 void SVGMPathElement::removedFrom(ContainerNode* rootParent)
    101 {
    102     SVGElement::removedFrom(rootParent);
    103     notifyParentOfPathChange(rootParent);
    104     if (rootParent->inDocument())
    105         clearResourceReferences();
    106 }
    107 
    108 bool SVGMPathElement::isSupportedAttribute(const QualifiedName& attrName)
    109 {
    110     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
    111     if (supportedAttributes.isEmpty()) {
    112         SVGURIReference::addSupportedAttributes(supportedAttributes);
    113         SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
    114     }
    115     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
    116 }
    117 
    118 void SVGMPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    119 {
    120     if (!isSupportedAttribute(name)) {
    121         SVGElement::parseAttribute(name, value);
    122         return;
    123     }
    124 
    125     if (SVGURIReference::parseAttribute(name, value))
    126         return;
    127     if (SVGExternalResourcesRequired::parseAttribute(name, value))
    128         return;
    129 
    130     ASSERT_NOT_REACHED();
    131 }
    132 
    133 void SVGMPathElement::svgAttributeChanged(const QualifiedName& attrName)
    134 {
    135     if (!isSupportedAttribute(attrName)) {
    136         SVGElement::svgAttributeChanged(attrName);
    137         return;
    138     }
    139 
    140     SVGElementInstance::InvalidationGuard invalidationGuard(this);
    141 
    142     if (SVGURIReference::isKnownAttribute(attrName)) {
    143         buildPendingResource();
    144         return;
    145     }
    146 
    147     if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
    148         return;
    149 
    150     ASSERT_NOT_REACHED();
    151 }
    152 
    153 SVGPathElement* SVGMPathElement::pathElement()
    154 {
    155     Element* target = targetElementFromIRIString(hrefCurrentValue(), document());
    156     if (target && target->hasTagName(SVGNames::pathTag))
    157         return toSVGPathElement(target);
    158     return 0;
    159 }
    160 
    161 void SVGMPathElement::targetPathChanged()
    162 {
    163     notifyParentOfPathChange(parentNode());
    164 }
    165 
    166 void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent)
    167 {
    168     if (parent && parent->hasTagName(SVGNames::animateMotionTag))
    169         static_cast<SVGAnimateMotionElement*>(parent)->updateAnimationPath();
    170 }
    171 
    172 } // namespace WebCore
    173