/* * Portable Agile C++ Classes (PACC) * Copyright (C) 2001-2003 by Marc Parizeau * http://manitou.gel.ulaval.ca/~parizeau/PACC * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * * Contact: * Laboratoire de Vision et Systemes Numeriques * Departement de genie electrique et de genie informatique * Universite Laval, Quebec, Canada, G1K 7P4 * http://vision.gel.ulaval.ca * */ /*! * \file PACC/SVG/Path.hpp * \brief Class definition for the SVG path primitive. * \author Marc Parizeau and Michel Fortin, Laboratoire de vision et systèmes numériques, Université Laval * $Revision: 1.5.2.1 $ * $Date: 2007/09/10 18:24:08 $ */ #ifndef PACC_SVG_Path_hpp_ #define PACC_SVG_Path_hpp_ #include "SVG/Primitives.hpp" #include "SVG/Styles.hpp" #include "SVG/Types.hpp" namespace PACC { namespace SVG { using namespace std; // forward declaration class PathData; /*!\brief Graphic primitive for paths. * \ingroup SVG * * \see pathcommands */ class Path : public Primitive { public: //! Make an empty path with style \c inStyle. explicit Path(const Style& inStyle = Style()) : Primitive("path", inStyle) {} /*!\brief Make a path command with data \c inPath and style \c inStyle. * * This constructor gives a already defined path. You can * always add more commands witht the += operator. */ Path(const PathData& inPath, const Style& inStyle = Style()) : Primitive("path", inStyle) { setAttribute("d", (string&)inPath); } //! Return the result of concatenating this path with path data \c inCommands. Path operator+(const PathData& inCommands) const { return Path(*this) += inCommands; } //! Append commands \c inCommands to this path. Path &operator+=(const PathData &inCommands) { string lDefinition = getAttribute("d"); lDefinition += string(" ") + (string&)inCommands; setAttribute("d", lDefinition); return *this; } }; /*!\brief %Data defining a path. * \ingroup SVG * * This is the base class for path commands. It is not possible to create * an instance of this class directly. Instead you should use one of the * subclasses that provide real functionalities. */ class PathData : protected string { public: //! Return the result of concatenating this path data with \c inData. PathData operator+(const PathData &inData) { return PathData((string &)(*this) + " " + inData); } protected: //! Make data path from string \c inValue. PathData(const string &inValue) : string(inValue) {} }; //! \brief %Path command for starting a new subpath at given coordinate. //! \ingroup SVG class MoveTo : public PathData { public: //! make moveto from point \c inPoint. MoveTo(const Point &inPoint) : PathData(string("M") + inPoint.getStringValue()) {} //! Make moveto from coordinates \c inX and \c inY. MoveTo(float inX, float inY) : PathData(string("M") + Point(inX, inY).getStringValue()) {} }; //! \brief %Path command for drawing a line. //! \ingroup SVG class LineTo : public PathData { public: //! Make lineto with point \c inPoint. LineTo(const Point &inPoint) : PathData(string("L") + inPoint.getStringValue()) {} //! Make lineto with coordinates \c inX and \c inY, LineTo(float inX, float inY) : PathData(string("L") + Point(inX, inY).getStringValue()) {} }; /*!\brief %Path command to close the current subpath. * \ingroup SVG * * This command close the subpath by drawing a straight line from the * current point to current subpath's initial point. */ class ClosePath : public PathData { public: //! Default constructor. ClosePath() : PathData("z") {} }; //! \brief %Path command to draw a cubic Bezier curve. //! \ingroup SVG class CubicCurveTo : public PathData { public: //! Make cubic curve to point \c inPoint, using control points \c inCtlPoint/ and \c inCtlPoint2; CubicCurveTo(const Point &inPoint, const Point &inCtlPoint1, const Point &inCtlPoint2) : PathData("C" + inCtlPoint1.getStringValue() + " " + inCtlPoint2.getStringValue() + " " + inPoint.getStringValue()) {} /*!\brief Make cubic curve to point \c inPoint, using a single control point \c inCtlPoint. * * The beginning control point is assumed to be the reflection of the * end control point on the previous command relative to the current * point. If previous command is not a CubicCurveTo, assume the end * control point is coincident with the current point. */ CubicCurveTo(const Point &inPoint, const Point &inCtlPoint) : PathData("S" + inCtlPoint.getStringValue() + " " + inPoint.getStringValue()) {} }; //! \brief %Path command to draw a quadratic Bezier curve. //! \ingroup SVG class QuadraticCurveTo : public PathData { public: //! Make quadratic curve to point \c inPoint, using control point \c inCtlPoint. QuadraticCurveTo(const Point &inPoint, const Point &inCtlPoint) : PathData("Q" + inCtlPoint.getStringValue() + " " + " " + inPoint.getStringValue()) {} /*!\brief Make quadratic curve to point \c inPoint, without using any control point. * * The control point is assumed to be the reflection of the control * point on the previous command relative to the current point. If * previous command is not a QuadraticCurveTo, assume the control point * is coincident with the current point. */ QuadraticCurveTo(const Point &inPoint) : PathData("S" + inPoint.getStringValue()) {} }; /*!\brief %Path command to draw an elliptical arc. * \ingroup SVG * * Draws an elliptical arc from the current point to given coordinates. The * size and orientation of the ellipse are defined by x-radius and y-radius * and an x-axis-rotation, which indicates how the ellipse as a whole is * rotated relative to the current coordinate system. The center of the * ellipse is calculated automatically to satisfy the constraints imposed * by the other parameters. Large-arc and sweep contribute to the automatic * calculations and help determine how the arc is drawn. * * For most situations, there are actually four different arcs (two * different ellipses, each with two different arc sweeps) that satisfy * these constraints. large-arc-flag and sweep-flag indicate which one of * the four arcs are drawn, as follows: * * */ class EllipticalArcTo : public PathData { public: /*!\brief Constructor. * \param inPoint A destination point for the curve. * \param inXRadius An x radius of the ellipse. * \param inYRadius An y radius of the ellipse. * \param inXAxisRotation A angle of rotation for the ellipse. * \param inLargeArc True for the path to follow the large arc, * false to follow the smaller one. * \param inSweep True to turn by a positive angle, false * for a negative one. */ EllipticalArcTo(const Point &inPoint, float inXRadius, float inYRadius, float inXAxisRotation, bool inLargeArc, bool inSweep) : PathData(string("A") + String::convert(inXRadius) + "," + String::convert(inYRadius) + " " + String::convert(inXAxisRotation) + " " + ( inLargeArc ? "1" : "0" ) + " " + ( inSweep ? "1" : "0" ) + " " + inPoint.getStringValue()) {} }; //! Short name for a cubic Bezier curve path command. typedef CubicCurveTo CurveTo; } // end of SVG namespace } // end of PACC namespace #endif // PACC_SVG_Path_hpp_