1 /* 2 Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann (at) kde.org> 3 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 "SVGPathElement.h" 25 26 #include "MappedAttribute.h" 27 #include "RenderPath.h" 28 #include "SVGNames.h" 29 #include "SVGParserUtilities.h" 30 #include "SVGPathSegArc.h" 31 #include "SVGPathSegClosePath.h" 32 #include "SVGPathSegCurvetoCubic.h" 33 #include "SVGPathSegCurvetoCubicSmooth.h" 34 #include "SVGPathSegCurvetoQuadratic.h" 35 #include "SVGPathSegCurvetoQuadraticSmooth.h" 36 #include "SVGPathSegLineto.h" 37 #include "SVGPathSegLinetoHorizontal.h" 38 #include "SVGPathSegLinetoVertical.h" 39 #include "SVGPathSegList.h" 40 #include "SVGPathSegMoveto.h" 41 #include "SVGSVGElement.h" 42 43 namespace WebCore { 44 45 SVGPathElement::SVGPathElement(const QualifiedName& tagName, Document* doc) 46 : SVGStyledTransformableElement(tagName, doc) 47 , SVGTests() 48 , SVGLangSpace() 49 , SVGExternalResourcesRequired() 50 { 51 } 52 53 SVGPathElement::~SVGPathElement() 54 { 55 } 56 57 float SVGPathElement::getTotalLength() 58 { 59 // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached) 60 return toPathData().length(); 61 } 62 63 FloatPoint SVGPathElement::getPointAtLength(float length) 64 { 65 // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached) 66 bool ok = false; 67 return toPathData().pointAtLength(length, ok); 68 } 69 70 unsigned long SVGPathElement::getPathSegAtLength(float length, ExceptionCode& ec) 71 { 72 return pathSegList()->getPathSegAtLength(length, ec); 73 } 74 75 PassRefPtr<SVGPathSegClosePath> SVGPathElement::createSVGPathSegClosePath() 76 { 77 return SVGPathSegClosePath::create(); 78 } 79 80 PassRefPtr<SVGPathSegMovetoAbs> SVGPathElement::createSVGPathSegMovetoAbs(float x, float y) 81 { 82 return SVGPathSegMovetoAbs::create(x, y); 83 } 84 85 PassRefPtr<SVGPathSegMovetoRel> SVGPathElement::createSVGPathSegMovetoRel(float x, float y) 86 { 87 return SVGPathSegMovetoRel::create(x, y); 88 } 89 90 PassRefPtr<SVGPathSegLinetoAbs> SVGPathElement::createSVGPathSegLinetoAbs(float x, float y) 91 { 92 return SVGPathSegLinetoAbs::create(x, y); 93 } 94 95 PassRefPtr<SVGPathSegLinetoRel> SVGPathElement::createSVGPathSegLinetoRel(float x, float y) 96 { 97 return SVGPathSegLinetoRel::create(x, y); 98 } 99 100 PassRefPtr<SVGPathSegCurvetoCubicAbs> SVGPathElement::createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2) 101 { 102 return SVGPathSegCurvetoCubicAbs::create(x, y, x1, y1, x2, y2); 103 } 104 105 PassRefPtr<SVGPathSegCurvetoCubicRel> SVGPathElement::createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2) 106 { 107 return SVGPathSegCurvetoCubicRel::create(x, y, x1, y1, x2, y2); 108 } 109 110 PassRefPtr<SVGPathSegCurvetoQuadraticAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1) 111 { 112 return SVGPathSegCurvetoQuadraticAbs::create(x, y, x1, y1); 113 } 114 115 PassRefPtr<SVGPathSegCurvetoQuadraticRel> SVGPathElement::createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1) 116 { 117 return SVGPathSegCurvetoQuadraticRel::create(x, y, x1, y1); 118 } 119 120 PassRefPtr<SVGPathSegArcAbs> SVGPathElement::createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag) 121 { 122 return SVGPathSegArcAbs::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag); 123 } 124 125 PassRefPtr<SVGPathSegArcRel> SVGPathElement::createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag) 126 { 127 return SVGPathSegArcRel::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag); 128 } 129 130 PassRefPtr<SVGPathSegLinetoHorizontalAbs> SVGPathElement::createSVGPathSegLinetoHorizontalAbs(float x) 131 { 132 return SVGPathSegLinetoHorizontalAbs::create(x); 133 } 134 135 PassRefPtr<SVGPathSegLinetoHorizontalRel> SVGPathElement::createSVGPathSegLinetoHorizontalRel(float x) 136 { 137 return SVGPathSegLinetoHorizontalRel::create(x); 138 } 139 140 PassRefPtr<SVGPathSegLinetoVerticalAbs> SVGPathElement::createSVGPathSegLinetoVerticalAbs(float y) 141 { 142 return SVGPathSegLinetoVerticalAbs::create(y); 143 } 144 145 PassRefPtr<SVGPathSegLinetoVerticalRel> SVGPathElement::createSVGPathSegLinetoVerticalRel(float y) 146 { 147 return SVGPathSegLinetoVerticalRel::create(y); 148 } 149 150 PassRefPtr<SVGPathSegCurvetoCubicSmoothAbs> SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2) 151 { 152 return SVGPathSegCurvetoCubicSmoothAbs::create(x, y, x2, y2); 153 } 154 155 PassRefPtr<SVGPathSegCurvetoCubicSmoothRel> SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2) 156 { 157 return SVGPathSegCurvetoCubicSmoothRel::create(x, y, x2, y2); 158 } 159 160 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y) 161 { 162 return SVGPathSegCurvetoQuadraticSmoothAbs::create(x, y); 163 } 164 165 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothRel> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y) 166 { 167 return SVGPathSegCurvetoQuadraticSmoothRel::create(x, y); 168 } 169 170 void SVGPathElement::parseMappedAttribute(MappedAttribute* attr) 171 { 172 if (attr->name() == SVGNames::dAttr) { 173 ExceptionCode ec; 174 pathSegList()->clear(ec); 175 if (!pathSegListFromSVGData(pathSegList(), attr->value(), true)) 176 document()->accessSVGExtensions()->reportError("Problem parsing d=\"" + attr->value() + "\""); 177 } else if (attr->name() == SVGNames::pathLengthAttr) { 178 setPathLengthBaseValue(attr->value().toFloat()); 179 if (pathLengthBaseValue() < 0.0f) 180 document()->accessSVGExtensions()->reportError("A negative value for path attribute <pathLength> is not allowed"); 181 } else { 182 if (SVGTests::parseMappedAttribute(attr)) 183 return; 184 if (SVGLangSpace::parseMappedAttribute(attr)) 185 return; 186 if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) 187 return; 188 SVGStyledTransformableElement::parseMappedAttribute(attr); 189 } 190 } 191 192 void SVGPathElement::svgAttributeChanged(const QualifiedName& attrName) 193 { 194 SVGStyledTransformableElement::svgAttributeChanged(attrName); 195 196 if (!renderer()) 197 return; 198 199 if (attrName == SVGNames::dAttr || attrName == SVGNames::pathLengthAttr || 200 SVGTests::isKnownAttribute(attrName) || 201 SVGLangSpace::isKnownAttribute(attrName) || 202 SVGExternalResourcesRequired::isKnownAttribute(attrName) || 203 SVGStyledTransformableElement::isKnownAttribute(attrName)) 204 renderer()->setNeedsLayout(true); 205 } 206 207 void SVGPathElement::synchronizeProperty(const QualifiedName& attrName) 208 { 209 SVGStyledTransformableElement::synchronizeProperty(attrName); 210 211 if (attrName == anyQName()) { 212 synchronizePathLength(); 213 synchronizeExternalResourcesRequired(); 214 return; 215 } 216 217 if (attrName == SVGNames::pathLengthAttr) 218 synchronizePathLength(); 219 else if (SVGExternalResourcesRequired::isKnownAttribute(attrName)) 220 synchronizeExternalResourcesRequired(); 221 } 222 223 SVGPathSegList* SVGPathElement::pathSegList() const 224 { 225 if (!m_pathSegList) 226 m_pathSegList = SVGPathSegList::create(SVGNames::dAttr); 227 228 return m_pathSegList.get(); 229 } 230 231 SVGPathSegList* SVGPathElement::normalizedPathSegList() const 232 { 233 // TODO 234 return 0; 235 } 236 237 SVGPathSegList* SVGPathElement::animatedPathSegList() const 238 { 239 // TODO 240 return 0; 241 } 242 243 SVGPathSegList* SVGPathElement::animatedNormalizedPathSegList() const 244 { 245 // TODO 246 return 0; 247 } 248 249 Path SVGPathElement::toPathData() const 250 { 251 return pathSegList()->toPathData(); 252 } 253 254 } 255 256 #endif // ENABLE(SVG) 257