diff options
Diffstat (limited to 'src/livarot/path-description.h')
-rw-r--r-- | src/livarot/path-description.h | 262 |
1 files changed, 262 insertions, 0 deletions
diff --git a/src/livarot/path-description.h b/src/livarot/path-description.h new file mode 100644 index 0000000..57c9eb1 --- /dev/null +++ b/src/livarot/path-description.h @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/** @file + * TODO: insert short description here + *//* + * Authors: see git history + * + * Copyright (C) 2018 Authors + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ +#ifndef SEEN_INKSCAPE_LIVAROT_PATH_DESCRIPTION_H +#define SEEN_INKSCAPE_LIVAROT_PATH_DESCRIPTION_H + +#include <2geom/point.h> +#include "svg/stringstream.h" + +// path description commands +/* FIXME: these should be unnecessary once the refactoring of the path +** description stuff is finished. +*/ + +/** + * An enum to store the path command type. A number is assigned to each type and the + * PathDescr class stores a flag variable that stores the number to know which type it is. + */ +enum +{ + descr_moveto = 0, /*!< A MoveTo path command */ + descr_lineto = 1, /*!< A LineTo path command */ + descr_cubicto = 2, /*!< A CubicTo path command. Basically a cubic Bezier */ + descr_bezierto = 3, /*!< A BezierTo path command is a quadratic Bezier spline. It can contain as many control points as you want to + add. The BezierTo instruction only stores the final point and the total number of control points. The actual + control points are stored in descr_interm_bezier instructions. One for each control point. */ + descr_arcto = 4, /*!< An elliptical arc */ + descr_close = 5, /*!< A close path command */ + descr_interm_bezier = 6, /*!< Control point for the last BezierTo instruction */ + descr_forced = 7, /*!< Not exactly sure what a forced point means. As far as I have seen in the simplify code, a forced + point is preferred to be kept. The simplification algorithm would make sure the forced point makes + its way to the final result. However, as far as I can see, forced point stuff is not used in Inkscape. + TODO: Explore how forced points might be being used when Simplify is done after Boolean Ops */ + descr_type_mask = 15 /*!< As mentioned above, the flag variable of PathDescr stores the type of the command using this enum. The higher bits + (after the first four (bit 0 to bit 3) could be used for other flag stuff, so this descr_type_mask can be used to just + extract the type. 15 in HEX is 0xF and in BIN is 0000 1111 so ANDing with it will zero any higher bits just leaving you + with the type. */ +}; + +/** + * A base class for Livarot's path commands. Each curve type such as Line, CubicBezier + * derives from this base class. + */ +struct PathDescr +{ + PathDescr() : flags(0), associated(-1), tSt(0), tEn(1) {} + PathDescr(int f) : flags(f), associated(-1), tSt(0), tEn(1) {} + virtual ~PathDescr() = default; + + int getType() const { return flags & descr_type_mask; } + void setType(int t) { + flags &= ~descr_type_mask; + flags |= t; + } + + /** + * A virtual function that derived classes will implement. Dumps the SVG path d attribute + * for this path description. + * + * @param s The stream to put the SVG description in. + * @param last The last point before this path description. This is needed for the computation + * of SVG descriptions of instructions such as Cubic and Arc. + */ + virtual void dumpSVG(Inkscape::SVGOStringStream &/*s*/, Geom::Point const &/*last*/) const {} + + /** + * A virtual function that derived classes will implement. Returns a newly allocated copy + * of the path description. + */ + virtual PathDescr *clone() const = 0; + + /** + * A virtual function that derived classes will implement. Similar to dumpSVG however this + * prints a simpler path description that's not SVG, only used for debugging purposes. Maybe + * the motivation was to support instructions such as BezierTo and IntermBezierTo which do + * not have SVG path description equivalents. + * + * @param s The stream to print to. + */ + virtual void dump(std::ostream &/*s*/) const {} + + int flags; /*!< Lower 4 bits contain the type of the path description as decided by the enum + above, upper bits could contain other information but don't know if they really do at all */ + int associated; /*!< Index of the last polyline point associated with this path description. Interestingly, Path::ConvertWithBackData + doesn't set this field at all while Path::Convert and Path::ConvertEvenLines do. */ + double tSt; /*!< By default set to 0. No idea if this is used at all. TODO */ + double tEn; /*!< By default set to 1. No idea if this is used at all. TODO */ +}; + +/** + * A MoveTo path command. + */ +struct PathDescrMoveTo : public PathDescr +{ + PathDescrMoveTo(Geom::Point const &pp) + : PathDescr(descr_moveto), p(pp) {} + + void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const override; + PathDescr *clone() const override; + void dump(std::ostream &s) const override; + + Geom::Point p; /*!< The point to move to. */ +}; + +/** + * A LineTo path command. + */ +struct PathDescrLineTo : public PathDescr +{ + PathDescrLineTo(Geom::Point const &pp) + : PathDescr(descr_lineto), p(pp) {} + + void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const override; + PathDescr *clone() const override; + void dump(std::ostream &s) const override; + + Geom::Point p; /*!< The point to draw a line to. */ +}; + +// quadratic bezier curves: a set of control points, and an endpoint + +/** + * A quadratic bezier spline + * + * Stores the final point as well as the total number of control points. The control + * points will exist in the path commands following this one which would be of the type + * PathDescrIntermBezierTo. + */ +struct PathDescrBezierTo : public PathDescr +{ + PathDescrBezierTo(Geom::Point const &pp, int n) + : PathDescr(descr_bezierto), p(pp), nb(n) {} + + PathDescr *clone() const override; + void dump(std::ostream &s) const override; + + Geom::Point p; /*!< The final point of the quadratic Bezier spline. */ + int nb; /*!< The total number of control points. The path commands following this one of the type PathDescrIntermBezierTo + will store these control points, one in each one. */ +}; + +/* FIXME: I don't think this should be necessary */ + +/** + * Intermediate quadratic Bezier spline command. + * + * These store the control points needed by the PathDescrBezierTo instruction. + */ +struct PathDescrIntermBezierTo : public PathDescr +{ + PathDescrIntermBezierTo() + : PathDescr(descr_interm_bezier) , p(0, 0) {} + PathDescrIntermBezierTo(Geom::Point const &pp) + : PathDescr(descr_interm_bezier), p(pp) {} + + PathDescr *clone() const override; + void dump(std::ostream &s) const override; + + Geom::Point p; /*!< The control point. */ +}; + +/** + * Cubic Bezier path command. + * + * There is something funny about this one. A typical BezierCurve consists of points + * p0, p1, p2, p3 where p1 and p2 are control points. This is a command so it's + * quite expected that p0 is not needed. What's interesting is that instead of storing + * p1 and p2, (p1 - p0) * 3 and (p3 - p2) * 3 are stored in start and end respectively. + * I can't see a good reason for why this was done. Because of this, there is additional + * mess required in the formulas for bezier curve splitting. + */ +struct PathDescrCubicTo : public PathDescr +{ + PathDescrCubicTo(Geom::Point const &pp, Geom::Point const &s, Geom::Point const& e) + : PathDescr(descr_cubicto), p(pp), start(s), end(e) {} + + void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const override; + PathDescr *clone() const override; + void dump(std::ostream &s) const override; + + Geom::Point p; /*!< The final point of the bezier curve. */ + Geom::Point start; /*!< 3 * (p1 - p0) where p0 is the start point of the cubic bezier and + p1 is the first control point. */ + Geom::Point end; /*!< 3 * (p3 - p2) where p3 is the final point of the cubic bezier and + p2 is the second control point. */ +}; + +/** + * Elliptical Arc path command. + * + * Exactly the equivalent of an SVG elliptical arc description. + */ +struct PathDescrArcTo : public PathDescr +{ + PathDescrArcTo(Geom::Point const &pp, double x, double y, double a, bool l, bool c) + : PathDescr(descr_arcto), p(pp), rx(x), ry(y), angle(a), large(l), clockwise(c) {} + + void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const override; + PathDescr *clone() const override; + void dump(std::ostream &s) const override; + + Geom::Point p; /*!< The final point of the arc. */ + double rx; /*!< The radius in the x direction. */ + double ry; /*!< The radius in the y direction. */ + double angle; /*!< The angle it makes with the x axis in degrees. TODO confirm that */ + bool large; /*!< The large arc or the small one? */ + bool clockwise; /*!< Clockwise arc or anti-clockwise one? */ +}; + +/** + * A forced point path command. + * + * TODO: This needs more research. Why is this useful and where? + */ +struct PathDescrForced : public PathDescr +{ + PathDescrForced() : PathDescr(descr_forced), p(0, 0) {} + + PathDescr *clone() const override; + + /* FIXME: not sure whether _forced should have a point associated with it; + ** Path::ConvertForcedToMoveTo suggests that maybe it should. + */ + Geom::Point p; /*!< The forced point itself? */ +}; + + +/** + * Close Path instruction. + */ +struct PathDescrClose : public PathDescr +{ + PathDescrClose() : PathDescr(descr_close) {} + + void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const override; + PathDescr *clone() const override; + + /* FIXME: not sure whether _forced should have a point associated with it; + ** Path::ConvertForcedToMoveTo suggests that maybe it should. + */ + Geom::Point p; /*!< Useless since close instruction needs no point. */ +}; + +#endif + + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : |