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 #if ENABLE(SVG)
     24 #include "SVGCircleElement.h"
     25 
     26 #include "Attribute.h"
     27 #include "FloatPoint.h"
     28 #include "RenderSVGPath.h"
     29 #include "RenderSVGResource.h"
     30 #include "SVGLength.h"
     31 #include "SVGNames.h"
     32 
     33 namespace WebCore {
     34 
     35 // Animated property definitions
     36 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::cxAttr, Cx, cx)
     37 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::cyAttr, Cy, cy)
     38 DEFINE_ANIMATED_LENGTH(SVGCircleElement, SVGNames::rAttr, R, r)
     39 DEFINE_ANIMATED_BOOLEAN(SVGCircleElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
     40 
     41 inline SVGCircleElement::SVGCircleElement(const QualifiedName& tagName, Document* document)
     42     : SVGStyledTransformableElement(tagName, document)
     43     , m_cx(LengthModeWidth)
     44     , m_cy(LengthModeHeight)
     45     , m_r(LengthModeOther)
     46 {
     47 }
     48 
     49 PassRefPtr<SVGCircleElement> SVGCircleElement::create(const QualifiedName& tagName, Document* document)
     50 {
     51     return adoptRef(new SVGCircleElement(tagName, document));
     52 }
     53 
     54 void SVGCircleElement::parseMappedAttribute(Attribute* attr)
     55 {
     56     if (attr->name() == SVGNames::cxAttr)
     57         setCxBaseValue(SVGLength(LengthModeWidth, attr->value()));
     58     else if (attr->name() == SVGNames::cyAttr)
     59         setCyBaseValue(SVGLength(LengthModeHeight, attr->value()));
     60     else if (attr->name() == SVGNames::rAttr) {
     61         setRBaseValue(SVGLength(LengthModeOther, attr->value()));
     62         if (rBaseValue().value(this) < 0.0)
     63             document()->accessSVGExtensions()->reportError("A negative value for circle <r> is not allowed");
     64     } else {
     65         if (SVGTests::parseMappedAttribute(attr))
     66             return;
     67         if (SVGLangSpace::parseMappedAttribute(attr))
     68             return;
     69         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
     70             return;
     71         SVGStyledTransformableElement::parseMappedAttribute(attr);
     72     }
     73 }
     74 
     75 void SVGCircleElement::svgAttributeChanged(const QualifiedName& attrName)
     76 {
     77     SVGStyledTransformableElement::svgAttributeChanged(attrName);
     78 
     79     bool isLengthAttribute = attrName == SVGNames::cxAttr
     80                           || attrName == SVGNames::cyAttr
     81                           || attrName == SVGNames::rAttr;
     82 
     83     if (isLengthAttribute)
     84         updateRelativeLengthsInformation();
     85 
     86     if (SVGTests::handleAttributeChange(this, attrName))
     87         return;
     88 
     89     RenderSVGPath* renderer = static_cast<RenderSVGPath*>(this->renderer());
     90     if (!renderer)
     91         return;
     92 
     93     if (isLengthAttribute) {
     94         renderer->setNeedsPathUpdate();
     95         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
     96         return;
     97     }
     98 
     99     if (SVGLangSpace::isKnownAttribute(attrName)
    100         || SVGExternalResourcesRequired::isKnownAttribute(attrName))
    101         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
    102 }
    103 
    104 void SVGCircleElement::synchronizeProperty(const QualifiedName& attrName)
    105 {
    106     SVGStyledTransformableElement::synchronizeProperty(attrName);
    107 
    108     if (attrName == anyQName()) {
    109         synchronizeCx();
    110         synchronizeCy();
    111         synchronizeR();
    112         synchronizeExternalResourcesRequired();
    113         SVGTests::synchronizeProperties(this, attrName);
    114         return;
    115     }
    116 
    117     if (attrName == SVGNames::cxAttr)
    118         synchronizeCx();
    119     else if (attrName == SVGNames::cyAttr)
    120         synchronizeCy();
    121     else if (attrName == SVGNames::rAttr)
    122         synchronizeR();
    123     else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
    124         synchronizeExternalResourcesRequired();
    125     else if (SVGTests::isKnownAttribute(attrName))
    126         SVGTests::synchronizeProperties(this, attrName);
    127 }
    128 
    129 AttributeToPropertyTypeMap& SVGCircleElement::attributeToPropertyTypeMap()
    130 {
    131     DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
    132     return s_attributeToPropertyTypeMap;
    133 }
    134 
    135 void SVGCircleElement::fillAttributeToPropertyTypeMap()
    136 {
    137     AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap();
    138 
    139     SVGStyledTransformableElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap);
    140     attributeToPropertyTypeMap.set(SVGNames::cxAttr, AnimatedLength);
    141     attributeToPropertyTypeMap.set(SVGNames::cyAttr, AnimatedLength);
    142     attributeToPropertyTypeMap.set(SVGNames::rAttr, AnimatedLength);
    143 }
    144 
    145 void SVGCircleElement::toPathData(Path& path) const
    146 {
    147     ASSERT(path.isEmpty());
    148 
    149     float radius = r().value(this);
    150 
    151     if (radius <= 0)
    152         return;
    153 
    154     path.addEllipse(FloatRect(cx().value(this) - radius, cy().value(this) - radius, radius * 2, radius * 2));
    155 }
    156 
    157 bool SVGCircleElement::selfHasRelativeLengths() const
    158 {
    159     return cx().isRelative()
    160         || cy().isRelative()
    161         || r().isRelative();
    162 }
    163 
    164 }
    165 
    166 #endif // ENABLE(SVG)
    167