Home | History | Annotate | Download | only in svg
      1 /*
      2  * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann (at) kde.org>
      3  * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis (at) kde.org>
      4  *
      5  * This library is free software; you can redistribute it and/or
      6  * modify it under the terms of the GNU Library General Public
      7  * License as published by the Free Software Foundation; either
      8  * version 2 of the License, or (at your option) any later version.
      9  *
     10  * This library is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13  * Library General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Library General Public License
     16  * along with this library; see the file COPYING.LIB.  If not, write to
     17  * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18  * Boston, MA 02110-1301, USA.
     19  */
     20 
     21 #include "config.h"
     22 
     23 #include "core/svg/SVGPolyElement.h"
     24 
     25 #include "core/dom/Document.h"
     26 #include "core/rendering/svg/RenderSVGResource.h"
     27 #include "core/svg/SVGAnimatedPointList.h"
     28 #include "core/svg/SVGElementInstance.h"
     29 #include "core/svg/SVGParserUtilities.h"
     30 
     31 namespace WebCore {
     32 
     33 // Define custom animated property 'points'.
     34 const SVGPropertyInfo* SVGPolyElement::pointsPropertyInfo()
     35 {
     36     static const SVGPropertyInfo* s_propertyInfo = 0;
     37     if (!s_propertyInfo) {
     38         s_propertyInfo = new SVGPropertyInfo(AnimatedPoints,
     39                                              PropertyIsReadWrite,
     40                                              SVGNames::pointsAttr,
     41                                              SVGNames::pointsAttr.localName(),
     42                                              &SVGPolyElement::synchronizePoints,
     43                                              &SVGPolyElement::lookupOrCreatePointsWrapper);
     44     }
     45     return s_propertyInfo;
     46 }
     47 
     48 SVGPointList& SVGPolyElement::pointsCurrentValue()
     49 {
     50     SVGAnimatedProperty* wrapper = SVGAnimatedProperty::lookupWrapper<SVGPolyElement, SVGAnimatedPointList>(this, pointsPropertyInfo());
     51     if (wrapper && wrapper->isAnimating()) {
     52         if (SVGListPropertyTearOff<SVGPointList>* ap = animatedPoints())
     53             return ap->values();
     54     }
     55 
     56     return m_points.value;
     57 }
     58 
     59 // Animated property definitions
     60 DEFINE_ANIMATED_BOOLEAN(SVGPolyElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
     61 
     62 BEGIN_REGISTER_ANIMATED_PROPERTIES(SVGPolyElement)
     63     REGISTER_LOCAL_ANIMATED_PROPERTY(points)
     64     REGISTER_LOCAL_ANIMATED_PROPERTY(externalResourcesRequired)
     65     REGISTER_PARENT_ANIMATED_PROPERTIES(SVGGraphicsElement)
     66 END_REGISTER_ANIMATED_PROPERTIES
     67 
     68 SVGPolyElement::SVGPolyElement(const QualifiedName& tagName, Document& document)
     69     : SVGGeometryElement(tagName, document)
     70 {
     71     registerAnimatedPropertiesForSVGPolyElement();
     72 }
     73 
     74 bool SVGPolyElement::isSupportedAttribute(const QualifiedName& attrName)
     75 {
     76     DEFINE_STATIC_LOCAL(HashSet<QualifiedName>, supportedAttributes, ());
     77     if (supportedAttributes.isEmpty()) {
     78         SVGExternalResourcesRequired::addSupportedAttributes(supportedAttributes);
     79         supportedAttributes.add(SVGNames::pointsAttr);
     80     }
     81     return supportedAttributes.contains<SVGAttributeHashTranslator>(attrName);
     82 }
     83 
     84 void SVGPolyElement::parseAttribute(const QualifiedName& name, const AtomicString& value)
     85 {
     86     if (!isSupportedAttribute(name)) {
     87         SVGGeometryElement::parseAttribute(name, value);
     88         return;
     89     }
     90 
     91     if (name == SVGNames::pointsAttr) {
     92         SVGPointList newList;
     93         if (!pointsListFromSVGData(newList, value))
     94             document().accessSVGExtensions()->reportError("Problem parsing points=\"" + value + "\"");
     95 
     96         if (SVGAnimatedProperty* wrapper = SVGAnimatedProperty::lookupWrapper<SVGPolyElement, SVGAnimatedPointList>(this, pointsPropertyInfo()))
     97             static_cast<SVGAnimatedPointList*>(wrapper)->detachListWrappers(newList.size());
     98 
     99         m_points.value = newList;
    100         return;
    101     }
    102 
    103     if (SVGExternalResourcesRequired::parseAttribute(name, value))
    104         return;
    105 
    106     ASSERT_NOT_REACHED();
    107 }
    108 
    109 void SVGPolyElement::svgAttributeChanged(const QualifiedName& attrName)
    110 {
    111     if (!isSupportedAttribute(attrName)) {
    112         SVGGeometryElement::svgAttributeChanged(attrName);
    113         return;
    114     }
    115 
    116     SVGElementInstance::InvalidationGuard invalidationGuard(this);
    117 
    118     RenderSVGShape* renderer = toRenderSVGShape(this->renderer());
    119     if (!renderer)
    120         return;
    121 
    122     if (attrName == SVGNames::pointsAttr) {
    123         renderer->setNeedsShapeUpdate();
    124         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
    125         return;
    126     }
    127 
    128     if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) {
    129         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
    130         return;
    131     }
    132 
    133     ASSERT_NOT_REACHED();
    134 }
    135 
    136 void SVGPolyElement::synchronizePoints(SVGElement* contextElement)
    137 {
    138     ASSERT(contextElement);
    139     SVGPolyElement* ownerType = toSVGPolyElement(contextElement);
    140     if (!ownerType->m_points.shouldSynchronize)
    141         return;
    142     ownerType->m_points.synchronize(ownerType, pointsPropertyInfo()->attributeName, ownerType->m_points.value.valueAsString());
    143 }
    144 
    145 PassRefPtr<SVGAnimatedProperty> SVGPolyElement::lookupOrCreatePointsWrapper(SVGElement* contextElement)
    146 {
    147     ASSERT(contextElement);
    148     SVGPolyElement* ownerType = toSVGPolyElement(contextElement);
    149     return SVGAnimatedProperty::lookupOrCreateWrapper<SVGPolyElement, SVGAnimatedPointList, SVGPointList>
    150            (ownerType, pointsPropertyInfo(), ownerType->m_points.value);
    151 }
    152 
    153 SVGListPropertyTearOff<SVGPointList>* SVGPolyElement::points()
    154 {
    155     m_points.shouldSynchronize = true;
    156     return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_pointer_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->baseVal());
    157 }
    158 
    159 SVGListPropertyTearOff<SVGPointList>* SVGPolyElement::animatedPoints()
    160 {
    161     m_points.shouldSynchronize = true;
    162     return static_cast<SVGListPropertyTearOff<SVGPointList>*>(static_pointer_cast<SVGAnimatedPointList>(lookupOrCreatePointsWrapper(this))->animVal());
    163 }
    164 
    165 }
    166