2007-01-02 Eric Seidel <eric@webkit.org>
[WebKit-https.git] / WebCore / ksvg2 / svg / SVGPathSegList.cpp
1 /*
2     Copyright (C) 2004, 2005, 2006 Nikolas Zimmermann <zimmermann@kde.org>
3                   2004, 2005 Rob Buis <buis@kde.org>
4     Copyright (C) 2007 Eric Seidel <eric@webkit.org>
5  
6     This file is part of the WebKit project
7  
8     This library is free software; you can redistribute it and/or
9     modify it under the terms of the GNU Library General Public
10     License as published by the Free Software Foundation; either
11     version 2 of the License, or (at your option) any later version.
12
13     This library is distributed in the hope that it will be useful,
14     but WITHOUT ANY WARRANTY; without even the implied warranty of
15     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16     Library General Public License for more details.
17
18     You should have received a copy of the GNU Library General Public License
19     along with this library; see the file COPYING.LIB.  If not, write to
20     the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21     Boston, MA 02111-1307, USA.
22 */
23
24 #include "config.h"
25
26 #ifdef SVG_SUPPORT
27 #include "SVGPathSegList.h"
28
29 #include "FloatPoint.h"
30 #include "Path.h"
31 #include "PathTraversalState.h"
32 #include "SVGPathSegMoveTo.h"
33 #include "SVGPathSegLineTo.h"
34 #include "SVGPathSegCurvetoCubic.h"
35
36 namespace WebCore {
37
38 SVGPathSegList::SVGPathSegList(const SVGStyledElement* context)
39     : SVGList<RefPtr<SVGPathSeg> >()
40     , m_context(context)
41 {
42 }
43
44 SVGPathSegList::~SVGPathSegList()
45 {
46 }
47
48 const SVGStyledElement* SVGPathSegList::context() const
49 {
50     return m_context;
51 }
52
53 unsigned SVGPathSegList::getPathSegAtLength(double)
54 {
55     // FIXME : to be useful this will need to support non-normalized SVGPathSegLists
56     ExceptionCode ec = 0;
57     int len = numberOfItems();
58     // FIXME: Eventually this will likely move to a "path applier"-like model, until then PathTraversalState is less useful as we could just use locals
59     PathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength);
60     for (int i = 0; i < len; ++i) {
61         SVGPathSeg* segment = getItem(i, ec).get();
62         float segmentLength = 0;
63         switch (segment->pathSegType()) {
64         case SVGPathSeg::PATHSEG_MOVETO_ABS:
65         {
66             SVGPathSegMovetoAbs* moveTo = static_cast<SVGPathSegMovetoAbs*>(segment);
67             segmentLength = traversalState.moveTo(FloatPoint(moveTo->x(), moveTo->y()));
68             break;
69         }
70         case SVGPathSeg::PATHSEG_LINETO_ABS:
71         {
72             SVGPathSegLinetoAbs* lineTo = static_cast<SVGPathSegLinetoAbs*>(segment);
73             segmentLength = traversalState.lineTo(FloatPoint(lineTo->x(), lineTo->y()));
74             break;
75         }
76         case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
77         {
78             SVGPathSegCurvetoCubicAbs* curveTo = static_cast<SVGPathSegCurvetoCubicAbs*>(segment);
79             segmentLength = traversalState.cubicBezierTo(FloatPoint(curveTo->x1(), curveTo->y1()),
80                                       FloatPoint(curveTo->x2(), curveTo->y2()),
81                                       FloatPoint(curveTo->x(), curveTo->y()));
82             break;
83         }
84         case SVGPathSeg::PATHSEG_CLOSEPATH:
85             segmentLength = traversalState.closeSubpath();
86             break;
87         default:
88             ASSERT(false); // FIXME: This only works with normalized/processed path data.
89             break;
90         }
91         traversalState.m_totalLength += segmentLength;
92         if ((traversalState.m_action == PathTraversalState::TraversalSegmentAtLength)
93             && (traversalState.m_totalLength > traversalState.m_desiredLength)) {
94             return traversalState.m_segmentIndex;
95         }
96         traversalState.m_segmentIndex++;
97     }
98     
99     return 0; // The SVG spec is unclear as to what to return when the distance is not on the path    
100 }
101
102 Path SVGPathSegList::toPathData()
103 {
104     // FIXME : This should also support non-normalized PathSegLists
105     Path pathData;
106     ExceptionCode ec = 0;
107     int len = numberOfItems();
108     for (int i = 0; i < len; ++i) {
109         SVGPathSeg* segment = getItem(i, ec).get();;
110         switch (segment->pathSegType())
111         {
112             case SVGPathSeg::PATHSEG_MOVETO_ABS:
113             {
114                 SVGPathSegMovetoAbs* moveTo = static_cast<SVGPathSegMovetoAbs*>(segment);
115                 pathData.moveTo(FloatPoint(moveTo->x(), moveTo->y()));
116                 break;
117             }
118             case SVGPathSeg::PATHSEG_LINETO_ABS:
119             {
120                 SVGPathSegLinetoAbs* lineTo = static_cast<SVGPathSegLinetoAbs*>(segment);
121                 pathData.addLineTo(FloatPoint(lineTo->x(), lineTo->y()));
122                 break;
123             }
124             case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS:
125             {
126                 SVGPathSegCurvetoCubicAbs* curveTo = static_cast<SVGPathSegCurvetoCubicAbs*>(segment);
127                 pathData.addBezierCurveTo(FloatPoint(curveTo->x1(), curveTo->y1()),
128                                           FloatPoint(curveTo->x2(), curveTo->y2()),
129                                           FloatPoint(curveTo->x(), curveTo->y()));
130                 break;
131             }
132             case SVGPathSeg::PATHSEG_CLOSEPATH:
133                 pathData.closeSubpath();
134                 break;
135             default:
136                 ASSERT(false); // FIXME: This only works with normalized/processed path data.
137                 break;
138         }
139     }
140     
141     return pathData;
142 }
143
144 }
145
146 #endif // SVG_SUPPORT
147
148 // vim:ts=4:noet