1/* 2 * Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org> 3 * Copyright (C) 2004, 2005, 2006, 2007 Rob Buis <buis@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 32namespace WebCore { 33 34// Animated property definitions 35DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::xAttr, X, x) 36DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::yAttr, Y, y) 37DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::widthAttr, Width, width) 38DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::heightAttr, Height, height) 39DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::rxAttr, Rx, rx) 40DEFINE_ANIMATED_LENGTH(SVGRectElement, SVGNames::ryAttr, Ry, ry) 41DEFINE_ANIMATED_BOOLEAN(SVGRectElement, SVGNames::externalResourcesRequiredAttr, ExternalResourcesRequired, externalResourcesRequired) 42 43inline 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 54PassRefPtr<SVGRectElement> SVGRectElement::create(const QualifiedName& tagName, Document* document) 55{ 56 return adoptRef(new SVGRectElement(tagName, document)); 57} 58 59void 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 92void 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 124void 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 158AttributeToPropertyTypeMap& SVGRectElement::attributeToPropertyTypeMap() 159{ 160 DEFINE_STATIC_LOCAL(AttributeToPropertyTypeMap, s_attributeToPropertyTypeMap, ()); 161 return s_attributeToPropertyTypeMap; 162} 163 164void 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 177void 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 210bool 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