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 "core/XLinkNames.h"
     25 #include "core/dom/Document.h"
     26 #include "core/svg/SVGAnimateMotionElement.h"
     27 #include "core/svg/SVGDocumentExtensions.h"
     28 #include "core/svg/SVGPathElement.h"
     29 
     30 namespace blink {
     31 
     32 inline SVGMPathElement::SVGMPathElement(Document& document)
     33     : SVGElement(SVGNames::mpathTag, document)
     34     , SVGURIReference(this)
     35 {
     36 }
     37 
     38 DEFINE_NODE_FACTORY(SVGMPathElement)
     39 
     40 SVGMPathElement::~SVGMPathElement()
     41 {
     42 #if !ENABLE(OILPAN)
     43     clearResourceReferences();
     44 #endif
     45 }
     46 
     47 void SVGMPathElement::buildPendingResource()
     48 {
     49     clearResourceReferences();
     50     if (!inDocument())
     51         return;
     52 
     53     AtomicString id;
     54     Element* target = SVGURIReference::targetElementFromIRIString(hrefString(), treeScope(), &id);
     55     if (!target) {
     56         // Do not register as pending if we are already pending this resource.
     57         if (document().accessSVGExtensions().isElementPendingResource(this, id))
     58             return;
     59 
     60         if (!id.isEmpty()) {
     61             document().accessSVGExtensions().addPendingResource(id, this);
     62             ASSERT(hasPendingResources());
     63         }
     64     } else if (isSVGPathElement(target)) {
     65         // Register us with the target in the dependencies map. Any change of hrefElement
     66         // that leads to relayout/repainting now informs us, so we can react to it.
     67         addReferenceTo(toSVGElement(target));
     68     }
     69 
     70     targetPathChanged();
     71 }
     72 
     73 void SVGMPathElement::clearResourceReferences()
     74 {
     75     removeAllOutgoingReferences();
     76 }
     77 
     78 Node::InsertionNotificationRequest SVGMPathElement::insertedInto(ContainerNode* rootParent)
     79 {
     80     SVGElement::insertedInto(rootParent);
     81     if (rootParent->inDocument())
     82         buildPendingResource();
     83     return InsertionDone;
     84 }
     85 
     86 void SVGMPathElement::removedFrom(ContainerNode* rootParent)
     87 {
     88     SVGElement::removedFrom(rootParent);
     89     notifyParentOfPathChange(rootParent);
     90     if (rootParent->inDocument())
     91         clearResourceReferences();
     92 }
     93 
     94 bool SVGMPathElement::isSupportedAttribute(const QualifiedName& attrName)
     95 {
     96     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
     97     if (supportedAttributes.isEmpty()) {
     98         SVGURIReference::addSupportedAttributes(supportedAttributes);
     99     }
    100     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
    101 }
    102 
    103 void SVGMPathElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
    104 {
    105     SVGParsingError parseError = NoError;
    106 
    107     if (!isSupportedAttribute(name)) {
    108         SVGElement::parseAttribute(name, value);
    109     } else if (SVGURIReference::parseAttribute(name, value, parseError)) {
    110     } else {
    111         ASSERT_NOT_REACHED();
    112     }
    113 
    114     reportAttributeParsingError(parseError, name, value);
    115 }
    116 
    117 void SVGMPathElement::svgAttributeChanged(const QualifiedName& attrName)
    118 {
    119     if (!isSupportedAttribute(attrName)) {
    120         SVGElement::svgAttributeChanged(attrName);
    121         return;
    122     }
    123 
    124     SVGElement::InvalidationGuard invalidationGuard(this);
    125 
    126     if (SVGURIReference::isKnownAttribute(attrName)) {
    127         buildPendingResource();
    128         return;
    129     }
    130 
    131     ASSERT_NOT_REACHED();
    132 }
    133 
    134 SVGPathElement* SVGMPathElement::pathElement()
    135 {
    136     Element* target = targetElementFromIRIString(hrefString(), treeScope());
    137     return isSVGPathElement(target) ? toSVGPathElement(target) : 0;
    138 }
    139 
    140 void SVGMPathElement::targetPathChanged()
    141 {
    142     notifyParentOfPathChange(parentNode());
    143 }
    144 
    145 void SVGMPathElement::notifyParentOfPathChange(ContainerNode* parent)
    146 {
    147     if (isSVGAnimateMotionElement(parent))
    148         toSVGAnimateMotionElement(parent)->updateAnimationPath();
    149 }
    150 
    151 } // namespace blink
    152