Home | History | Annotate | Download | only in svg
      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