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

0001 /*
0002     Copyright (C) 2004, 2005, 2006, 2007, 2008 Nikolas Zimmermann <zimmermann@kde.org>
0003                   2004, 2005 Rob Buis <buis@kde.org>
0004     Copyright (C) 2007 Eric Seidel <eric@webkit.org>
0005 
0006     This file is part of the WebKit project
0007 
0008     This library is free software; you can redistribute it and/or
0009     modify it under the terms of the GNU Library General Public
0010     License as published by the Free Software Foundation; either
0011     version 2 of the License, or (at your option) any later version.
0012 
0013     This library is distributed in the hope that it will be useful,
0014     but WITHOUT ANY WARRANTY; without even the implied warranty of
0015     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0016     Library General Public License for more details.
0017 
0018     You should have received a copy of the GNU Library General Public License
0019     along with this library; see the file COPYING.LIB.  If not, write to
0020     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0021     Boston, MA 02110-1301, USA.
0022 */
0023 
0024 #include "wtf/Platform.h"
0025 
0026 #if ENABLE(SVG)
0027 #include "SVGPathSegList.h"
0028 
0029 #include "FloatPoint.h"
0030 #include "Path.h"
0031 #include "PathTraversalState.h"
0032 #include "SVGPathSegMoveto.h"
0033 #include "SVGPathSegLineto.h"
0034 #include "SVGPathSegCurvetoCubic.h"
0035 
0036 namespace WebCore
0037 {
0038 
0039 SVGPathSegList::SVGPathSegList(const QualifiedName &attributeName)
0040     : SVGList<RefPtr<SVGPathSeg> >(attributeName)
0041 {
0042 }
0043 
0044 SVGPathSegList::~SVGPathSegList()
0045 {
0046 }
0047 
0048 unsigned SVGPathSegList::getPathSegAtLength(double)
0049 {
0050     // FIXME : to be useful this will need to support non-normalized SVGPathSegLists
0051     ExceptionCode ec = 0;
0052     int len = numberOfItems();
0053     // FIXME: Eventually this will likely move to a "path applier"-like model, until then PathTraversalState is less useful as we could just use locals
0054     PathTraversalState traversalState(PathTraversalState::TraversalSegmentAtLength);
0055     for (int i = 0; i < len; ++i) {
0056         SVGPathSeg *segment = getItem(i, ec).get();
0057         float segmentLength = 0;
0058         switch (segment->pathSegType()) {
0059         case SVGPathSeg::PATHSEG_MOVETO_ABS: {
0060             SVGPathSegMovetoAbs *moveTo = static_cast<SVGPathSegMovetoAbs *>(segment);
0061             segmentLength = traversalState.moveTo(FloatPoint(moveTo->x(), moveTo->y()));
0062             break;
0063         }
0064         case SVGPathSeg::PATHSEG_LINETO_ABS: {
0065             SVGPathSegLinetoAbs *lineTo = static_cast<SVGPathSegLinetoAbs *>(segment);
0066             segmentLength = traversalState.lineTo(FloatPoint(lineTo->x(), lineTo->y()));
0067             break;
0068         }
0069         case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS: {
0070             SVGPathSegCurvetoCubicAbs *curveTo = static_cast<SVGPathSegCurvetoCubicAbs *>(segment);
0071             segmentLength = traversalState.cubicBezierTo(FloatPoint(curveTo->x1(), curveTo->y1()),
0072                             FloatPoint(curveTo->x2(), curveTo->y2()),
0073                             FloatPoint(curveTo->x(), curveTo->y()));
0074             break;
0075         }
0076         case SVGPathSeg::PATHSEG_CLOSEPATH:
0077             segmentLength = traversalState.closeSubpath();
0078             break;
0079         default:
0080             ASSERT(false); // FIXME: This only works with normalized/processed path data.
0081             break;
0082         }
0083         traversalState.m_totalLength += segmentLength;
0084         if ((traversalState.m_action == PathTraversalState::TraversalSegmentAtLength)
0085                 && (traversalState.m_totalLength > traversalState.m_desiredLength)) {
0086             return traversalState.m_segmentIndex;
0087         }
0088         traversalState.m_segmentIndex++;
0089     }
0090 
0091     return 0; // The SVG spec is unclear as to what to return when the distance is not on the path
0092 }
0093 
0094 khtml::Path SVGPathSegList::toPathData()
0095 {
0096     // FIXME : This should also support non-normalized PathSegLists
0097     Path pathData;
0098     ExceptionCode ec = 0;
0099     int len = numberOfItems();
0100     for (int i = 0; i < len; ++i) {
0101         SVGPathSeg *segment = getItem(i, ec).get();
0102         switch (segment->pathSegType()) {
0103         case SVGPathSeg::PATHSEG_MOVETO_ABS: {
0104             SVGPathSegMovetoAbs *moveTo = static_cast<SVGPathSegMovetoAbs *>(segment);
0105             pathData.moveTo(FloatPoint(moveTo->x(), moveTo->y()));
0106             break;
0107         }
0108         case SVGPathSeg::PATHSEG_LINETO_ABS: {
0109             SVGPathSegLinetoAbs *lineTo = static_cast<SVGPathSegLinetoAbs *>(segment);
0110             pathData.addLineTo(FloatPoint(lineTo->x(), lineTo->y()));
0111             break;
0112         }
0113         case SVGPathSeg::PATHSEG_CURVETO_CUBIC_ABS: {
0114             SVGPathSegCurvetoCubicAbs *curveTo = static_cast<SVGPathSegCurvetoCubicAbs *>(segment);
0115             pathData.addBezierCurveTo(FloatPoint(curveTo->x1(), curveTo->y1()),
0116                                       FloatPoint(curveTo->x2(), curveTo->y2()),
0117                                       FloatPoint(curveTo->x(), curveTo->y()));
0118             break;
0119         }
0120         case SVGPathSeg::PATHSEG_CLOSEPATH:
0121             pathData.closeSubpath();
0122             break;
0123         default:
0124             ASSERT(false); // FIXME: This only works with normalized/processed path data.
0125             break;
0126         }
0127     }
0128 
0129     return pathData;
0130 }
0131 
0132 }
0133 
0134 #endif // ENABLE(SVG)