File indexing completed on 2024-04-28 15:24:38

0001 /*
0002     Copyright (C) 2004, 2005, 2006, 2008 Nikolas Zimmermann <zimmermann@kde.org>
0003                   2004, 2005, 2006, 2007 Rob Buis <buis@kde.org>
0004 
0005     This file is part of the KDE project
0006 
0007     This library is free software; you can redistribute it and/or
0008     modify it under the terms of the GNU Library General Public
0009     License as published by the Free Software Foundation; either
0010     version 2 of the License, or (at your option) any later version.
0011 
0012     This library is distributed in the hope that it will be useful,
0013     but WITHOUT ANY WARRANTY; without even the implied warranty of
0014     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0015     Library General Public License for more details.
0016 
0017     You should have received a copy of the GNU Library General Public License
0018     along with this library; see the file COPYING.LIB.  If not, write to
0019     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0020     Boston, MA 02110-1301, USA.
0021 */
0022 
0023 #include "wtf/Platform.h"
0024 
0025 #if ENABLE(SVG)
0026 #include "SVGPathElement.h"
0027 
0028 #include "RenderPath.h"
0029 #include "SVGNames.h"
0030 #include "SVGParserUtilities.h"
0031 #include "SVGPathSegArc.h"
0032 #include "SVGPathSegClosePath.h"
0033 #include "SVGPathSegCurvetoCubic.h"
0034 #include "SVGPathSegCurvetoCubicSmooth.h"
0035 #include "SVGPathSegCurvetoQuadratic.h"
0036 #include "SVGPathSegCurvetoQuadraticSmooth.h"
0037 #include "SVGPathSegLineto.h"
0038 #include "SVGPathSegLinetoHorizontal.h"
0039 #include "SVGPathSegLinetoVertical.h"
0040 #include "SVGPathSegList.h"
0041 #include "SVGPathSegMoveto.h"
0042 #include "SVGSVGElement.h"
0043 
0044 namespace WebCore
0045 {
0046 
0047 SVGPathElement::SVGPathElement(const QualifiedName &tagName, Document *doc)
0048     : SVGStyledTransformableElement(tagName, doc)
0049     , SVGTests()
0050     , SVGLangSpace()
0051     , SVGExternalResourcesRequired()
0052     , m_pathLength(0.0f)
0053 {
0054 }
0055 
0056 SVGPathElement::~SVGPathElement()
0057 {
0058 }
0059 
0060 ANIMATED_PROPERTY_DEFINITIONS(SVGPathElement, float, Number, number, PathLength, pathLength, SVGNames::pathLengthAttr, m_pathLength)
0061 
0062 float SVGPathElement::getTotalLength()
0063 {
0064     // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
0065     return toPathData().length();
0066 }
0067 
0068 FloatPoint SVGPathElement::getPointAtLength(float length)
0069 {
0070     // FIXME: this may wish to use the pathSegList instead of the pathdata if that's cheaper to build (or cached)
0071     bool ok = false;
0072     return toPathData().pointAtLength(length, ok);
0073 }
0074 
0075 unsigned long SVGPathElement::getPathSegAtLength(float length)
0076 {
0077     return pathSegList()->getPathSegAtLength(length);
0078 }
0079 
0080 PassRefPtr<SVGPathSegClosePath> SVGPathElement::createSVGPathSegClosePath()
0081 {
0082     return SVGPathSegClosePath::create();
0083 }
0084 
0085 PassRefPtr<SVGPathSegMovetoAbs> SVGPathElement::createSVGPathSegMovetoAbs(float x, float y)
0086 {
0087     return SVGPathSegMovetoAbs::create(x, y);
0088 }
0089 
0090 PassRefPtr<SVGPathSegMovetoRel> SVGPathElement::createSVGPathSegMovetoRel(float x, float y)
0091 {
0092     return SVGPathSegMovetoRel::create(x, y);
0093 }
0094 
0095 PassRefPtr<SVGPathSegLinetoAbs> SVGPathElement::createSVGPathSegLinetoAbs(float x, float y)
0096 {
0097     return SVGPathSegLinetoAbs::create(x, y);
0098 }
0099 
0100 PassRefPtr<SVGPathSegLinetoRel> SVGPathElement::createSVGPathSegLinetoRel(float x, float y)
0101 {
0102     return SVGPathSegLinetoRel::create(x, y);
0103 }
0104 
0105 PassRefPtr<SVGPathSegCurvetoCubicAbs> SVGPathElement::createSVGPathSegCurvetoCubicAbs(float x, float y, float x1, float y1, float x2, float y2)
0106 {
0107     return SVGPathSegCurvetoCubicAbs::create(x, y, x1, y1, x2, y2);
0108 }
0109 
0110 PassRefPtr<SVGPathSegCurvetoCubicRel> SVGPathElement::createSVGPathSegCurvetoCubicRel(float x, float y, float x1, float y1, float x2, float y2)
0111 {
0112     return SVGPathSegCurvetoCubicRel::create(x, y, x1, y1, x2, y2);
0113 }
0114 
0115 PassRefPtr<SVGPathSegCurvetoQuadraticAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticAbs(float x, float y, float x1, float y1)
0116 {
0117     return SVGPathSegCurvetoQuadraticAbs::create(x, y, x1, y1);
0118 }
0119 
0120 PassRefPtr<SVGPathSegCurvetoQuadraticRel> SVGPathElement::createSVGPathSegCurvetoQuadraticRel(float x, float y, float x1, float y1)
0121 {
0122     return SVGPathSegCurvetoQuadraticRel::create(x, y, x1, y1);
0123 }
0124 
0125 PassRefPtr<SVGPathSegArcAbs> SVGPathElement::createSVGPathSegArcAbs(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
0126 {
0127     return SVGPathSegArcAbs::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag);
0128 }
0129 
0130 PassRefPtr<SVGPathSegArcRel> SVGPathElement::createSVGPathSegArcRel(float x, float y, float r1, float r2, float angle, bool largeArcFlag, bool sweepFlag)
0131 {
0132     return SVGPathSegArcRel::create(x, y, r1, r2, angle, largeArcFlag, sweepFlag);
0133 }
0134 
0135 PassRefPtr<SVGPathSegLinetoHorizontalAbs> SVGPathElement::createSVGPathSegLinetoHorizontalAbs(float x)
0136 {
0137     return SVGPathSegLinetoHorizontalAbs::create(x);
0138 }
0139 
0140 PassRefPtr<SVGPathSegLinetoHorizontalRel> SVGPathElement::createSVGPathSegLinetoHorizontalRel(float x)
0141 {
0142     return SVGPathSegLinetoHorizontalRel::create(x);
0143 }
0144 
0145 PassRefPtr<SVGPathSegLinetoVerticalAbs> SVGPathElement::createSVGPathSegLinetoVerticalAbs(float y)
0146 {
0147     return SVGPathSegLinetoVerticalAbs::create(y);
0148 }
0149 
0150 PassRefPtr<SVGPathSegLinetoVerticalRel> SVGPathElement::createSVGPathSegLinetoVerticalRel(float y)
0151 {
0152     return SVGPathSegLinetoVerticalRel::create(y);
0153 }
0154 
0155 PassRefPtr<SVGPathSegCurvetoCubicSmoothAbs> SVGPathElement::createSVGPathSegCurvetoCubicSmoothAbs(float x, float y, float x2, float y2)
0156 {
0157     return SVGPathSegCurvetoCubicSmoothAbs::create(x, y, x2, y2);
0158 }
0159 
0160 PassRefPtr<SVGPathSegCurvetoCubicSmoothRel> SVGPathElement::createSVGPathSegCurvetoCubicSmoothRel(float x, float y, float x2, float y2)
0161 {
0162     return SVGPathSegCurvetoCubicSmoothRel::create(x, y, x2, y2);
0163 }
0164 
0165 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothAbs> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothAbs(float x, float y)
0166 {
0167     return SVGPathSegCurvetoQuadraticSmoothAbs::create(x, y);
0168 }
0169 
0170 PassRefPtr<SVGPathSegCurvetoQuadraticSmoothRel> SVGPathElement::createSVGPathSegCurvetoQuadraticSmoothRel(float x, float y)
0171 {
0172     return SVGPathSegCurvetoQuadraticSmoothRel::create(x, y);
0173 }
0174 
0175 void SVGPathElement::parseMappedAttribute(MappedAttribute *attr)
0176 {
0177     if (attr->name() == SVGNames::dAttr) {
0178         ExceptionCode ec;
0179         pathSegList()->clear(ec);
0180         pathSegListFromSVGData(pathSegList(), attr->value(), true);
0181         /*FIXME khtml if (!pathSegListFromSVGData(pathSegList(), attr->value(), true))
0182             document()->accessSVGExtensions()->reportError("Problem parsing d=\"" + attr->value() + "\"");*/
0183     } else if (attr->name() == SVGNames::pathLengthAttr) {
0184         m_pathLength = attr->value().toFloat();
0185         if (m_pathLength < 0.0f) {
0186             document()->accessSVGExtensions()->reportError("A negative value for path attribute <pathLength> is not allowed");
0187         }
0188     } else {
0189         if (SVGTests::parseMappedAttribute(attr)) {
0190             return;
0191         }
0192         if (SVGLangSpace::parseMappedAttribute(attr)) {
0193             return;
0194         }
0195         if (SVGExternalResourcesRequired::parseMappedAttribute(attr)) {
0196             return;
0197         }
0198         SVGStyledTransformableElement::parseMappedAttribute(attr);
0199     }
0200 }
0201 
0202 void SVGPathElement::svgAttributeChanged(const QualifiedName &attrName)
0203 {
0204     SVGStyledTransformableElement::svgAttributeChanged(attrName);
0205 
0206     if (!renderer()) {
0207         return;
0208     }
0209 
0210     if (attrName == SVGNames::dAttr || attrName == SVGNames::pathLengthAttr ||
0211             SVGTests::isKnownAttribute(attrName) ||
0212             SVGLangSpace::isKnownAttribute(attrName) ||
0213             SVGExternalResourcesRequired::isKnownAttribute(attrName) ||
0214             SVGStyledTransformableElement::isKnownAttribute(attrName)) {
0215         renderer()->setNeedsLayout(true);
0216     }
0217 }
0218 
0219 SVGPathSegList *SVGPathElement::pathSegList() const
0220 {
0221     if (!m_pathSegList) {
0222         m_pathSegList = SVGPathSegList::create(SVGNames::dAttr);
0223     }
0224 
0225     return m_pathSegList.get();
0226 }
0227 
0228 SVGPathSegList *SVGPathElement::normalizedPathSegList() const
0229 {
0230     // TODO
0231     return nullptr;
0232 }
0233 
0234 SVGPathSegList *SVGPathElement::animatedPathSegList() const
0235 {
0236     // TODO
0237     return nullptr;
0238 }
0239 
0240 SVGPathSegList *SVGPathElement::animatedNormalizedPathSegList() const
0241 {
0242     // TODO
0243     return nullptr;
0244 }
0245 
0246 Path SVGPathElement::toPathData() const
0247 {
0248     return pathSegList()->toPathData();
0249 }
0250 
0251 // KHTML ElementImpl pure virtual method
0252 quint32 SVGPathElement::id() const
0253 {
0254     return SVGNames::pathTag.id();
0255 }
0256 
0257 }
0258 
0259 #endif // ENABLE(SVG)