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 "SVGRectElement.h"
     25 
     26 #include "Attribute.h"
     27 #include "RenderSVGPath.h"
     28 #include "RenderSVGResource.h"
     29 #include "SVGLength.h"
     30 #include "SVGNames.h"
     31 
     32 namespace WebCore {
     33 
     34 // Animated property definitions
     35 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::xAttr, X, x)
     36 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::yAttr, Y, y)
     37 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::widthAttr, Width, width)
     38 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::heightAttr, Height, height)
     39 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::rxAttr, Rx, rx)
     40 DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::ryAttr, Ry, ry)
     41 DEFINE_ANIMATED_BOOLEAN(SVGRectElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired)
     42 
     43 inline SVGRectElement::SVGRectElement(const QualifiedName& tagName, Document* document)
     44     : SVGStyledTransformableElement(tagName, document)
     45     , m_x(LengthModeWidth)
     46     , m_y(LengthModeHeight)
     47     , m_width(LengthModeWidth)
     48     , m_height(LengthModeHeight)
     49     , m_rx(LengthModeWidth)
     50     , m_ry(LengthModeHeight)
     51 {
     52 }
     53 
     54 PassRefPtr<SVGRectElement> SVGRectElement::create(const QualifiedName& tagName, Document* document)
     55 {
     56     return adoptRef(new SVGRectElement(tagName, document));
     57 }
     58 
     59 void SVGRectElement::parseMappedAttribute(Attribute* attr)
     60 {
     61     if (attr->name() == SVGNames::xAttr)
     62         setXBaseValue(SVGLength(LengthModeWidth, attr->value()));
     63     else if (attr->name() == SVGNames::yAttr)
     64         setYBaseValue(SVGLength(LengthModeHeight, attr->value()));
     65     else if (attr->name() == SVGNames::rxAttr) {
     66         setRxBaseValue(SVGLength(LengthModeWidth, attr->value()));
     67         if (rxBaseValue().value(this) < 0.0)
     68             document()->accessSVGExtensions()->reportError("A negative value for rect <rx> is not allowed");
     69     } else if (attr->name() == SVGNames::ryAttr) {
     70         setRyBaseValue(SVGLength(LengthModeHeight, attr->value()));
     71         if (ryBaseValue().value(this) < 0.0)
     72             document()->accessSVGExtensions()->reportError("A negative value for rect <ry> is not allowed");
     73     } else if (attr->name() == SVGNames::widthAttr) {
     74         setWidthBaseValue(SVGLength(LengthModeWidth, attr->value()));
     75         if (widthBaseValue().value(this) < 0.0)
     76             document()->accessSVGExtensions()->reportError("A negative value for rect <width> is not allowed");
     77     } else if (attr->name() == SVGNames::heightAttr) {
     78         setHeightBaseValue(SVGLength(LengthModeHeight, attr->value()));
     79         if (heightBaseValue().value(this) < 0.0)
     80             document()->accessSVGExtensions()->reportError("A negative value for rect <height> is not allowed");
     81     } else {
     82         if (SVGTests::parseMappedAttribute(attr))
     83             return;
     84         if (SVGLangSpace::parseMappedAttribute(attr))
     85             return;
     86         if (SVGExternalResourcesRequired::parseMappedAttribute(attr))
     87             return;
     88         SVGStyledTransformableElement::parseMappedAttribute(attr);
     89     }
     90 }
     91 
     92 void SVGRectElement::svgAttributeChanged(const QualifiedName& attrName)
     93 {
     94     SVGStyledTransformableElement::svgAttributeChanged(attrName);
     95 
     96     bool isLengthAttribute = attrName == SVGNames::xAttr
     97                           || attrName == SVGNames::yAttr
     98                           || attrName == SVGNames::widthAttr
     99                           || attrName == SVGNames::heightAttr
    100                           || attrName == SVGNames::rxAttr
    101                           || attrName == SVGNames::ryAttr;
    102 
    103     if (isLengthAttribute)
    104         updateRelativeLengthsInformation();
    105 
    106     if (SVGTests::handleAttributeChange(this, attrName))
    107         return;
    108 
    109     RenderSVGPath* renderer = static_cast<RenderSVGPath*>(this->renderer());
    110     if (!renderer)
    111         return;
    112 
    113     if (isLengthAttribute) {
    114         renderer->setNeedsPathUpdate();
    115         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
    116         return;
    117     }
    118 
    119     if (SVGLangSpace::isKnownAttribute(attrName)
    120         || SVGExternalResourcesRequired::isKnownAttribute(attrName))
    121         RenderSVGResource::markForLayoutAndParentResourceInvalidation(renderer);
    122 }
    123 
    124 void SVGRectElement::synchronizeProperty(const QualifiedName& attrName)
    125 {
    126     SVGStyledTransformableElement::synchronizeProperty(attrName);
    127 
    128     if (attrName == anyQName()) {
    129         synchronizeX();
    130         synchronizeY();
    131         synchronizeWidth();
    132         synchronizeHeight();
    133         synchronizeRx();
    134         synchronizeRy();
    135         synchronizeExternalResourcesRequired();
    136         SVGTests::synchronizeProperties(this, attrName);
    137         return;
    138     }
    139 
    140     if (attrName == SVGNames::xAttr)
    141         synchronizeX();
    142     else if (attrName == SVGNames::yAttr)
    143         synchronizeY();
    144     else if (attrName == SVGNames::widthAttr)
    145         synchronizeWidth();
    146     else if (attrName == SVGNames::heightAttr)
    147         synchronizeHeight();
    148     else if (attrName == SVGNames::rxAttr)
    149         synchronizeRx();
    150     else if (attrName == SVGNames::ryAttr)
    151         synchronizeRy();
    152     else if (SVGExternalResourcesRequired::isKnownAttribute(attrName))
    153         synchronizeExternalResourcesRequired();
    154     else if (SVGTests::isKnownAttribute(attrName))
    155         SVGTests::synchronizeProperties(this, attrName);
    156 }
    157 
    158 AttributeToPropertyTypeMap& SVGRectElement::attributeToPropertyTypeMap()
    159 {
    160     DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ());
    161     return s_attributeToPropertyTypeMap;
    162 }
    163 
    164 void SVGRectElement::fillAttributeToPropertyTypeMap()
    165 {
    166     AttributeToPropertyTypeMap& attributeToPropertyTypeMap = this->attributeToPropertyTypeMap();
    167 
    168     SVGStyledTransformableElement::fillPassedAttributeToPropertyTypeMap(attributeToPropertyTypeMap);
    169     attributeToPropertyTypeMap.set(SVGNames::xAttr, AnimatedLength);
    170     attributeToPropertyTypeMap.set(SVGNames::yAttr, AnimatedLength);
    171     attributeToPropertyTypeMap.set(SVGNames::widthAttr, AnimatedLength);
    172     attributeToPropertyTypeMap.set(SVGNames::heightAttr, AnimatedLength);
    173     attributeToPropertyTypeMap.set(SVGNames::rxAttr, AnimatedLength);
    174     attributeToPropertyTypeMap.set(SVGNames::ryAttr, AnimatedLength);
    175 }
    176 
    177 void SVGRectElement::toPathData(Path& path) const
    178 {
    179     ASSERT(path.isEmpty());
    180 
    181     float widthValue = width().value(this);
    182     if (widthValue <= 0)
    183         return;
    184 
    185     float heightValue = height().value(this);
    186     if (heightValue <= 0)
    187         return;
    188 
    189     float xValue = x().value(this);
    190     float yValue = y().value(this);
    191 
    192     FloatRect rect(xValue, yValue, widthValue, heightValue);
    193 
    194     bool hasRx = hasAttribute(SVGNames::rxAttr);
    195     bool hasRy = hasAttribute(SVGNames::ryAttr);
    196     if (hasRx || hasRy) {
    197         float rxValue = rx().value(this);
    198         float ryValue = ry().value(this);
    199         if (!hasRx)
    200             rxValue = ryValue;
    201         else if (!hasRy)
    202             ryValue = rxValue;
    203         path.addRoundedRect(rect, FloatSize(rxValue, ryValue));
    204         return;
    205     }
    206 
    207     path.addRect(rect);
    208 }
    209 
    210 bool SVGRectElement::selfHasRelativeLengths() const
    211 {
    212     return x().isRelative()
    213         || y().isRelative()
    214         || width().isRelative()
    215         || height().isRelative()
    216         || rx().isRelative()
    217         || ry().isRelative();
    218 }
    219 
    220 }
    221 
    222 #endif // ENABLE(SVG)
    223