path-string.h revision 7079a43aa387066c2f67402d77dbe3db981b1054
3294N/A/**
500N/A * Inkscape::SVG::PathString - builder for SVG path strings
500N/A *
500N/A * Copyright 2007 MenTaLguY <mental@rydia.net>
500N/A * Copyright 2008 Jasper van de Gronde <th.v.d.gronde@hccnet.nl>
500N/A *
500N/A * This program is free software; you can redistribute it and/or
500N/A * modify it under the terms of the GNU General Public License
500N/A * as published by the Free Software Foundation; either version 2
500N/A * of the License, or (at your option) any later version.
500N/A *
500N/A * See the file COPYING for details.
500N/A *
500N/A */
500N/A
500N/A#ifndef SEEN_INKSCAPE_SVG_PATH_STRING_H
500N/A#define SEEN_INKSCAPE_SVG_PATH_STRING_H
500N/A
500N/A#include <glibmm/ustring.h>
500N/A#include <string>
500N/A#include <stdio.h>
5680N/A#include <2geom/point.h>
5680N/A
5569N/Anamespace Inkscape {
500N/A
500N/Anamespace SVG {
500N/A
500N/Aclass PathString {
500N/Apublic:
3294N/A PathString();
3294N/A
3294N/A // default copy
3294N/A // default assign
3294N/A
3294N/A std::string const &string() {
500N/A std::string const &t = tail();
3294N/A final.reserve(commonbase.size()+t.size());
500N/A final = commonbase;
3294N/A final += tail();
3294N/A return final;
3294N/A }
3294N/A
3294N/A operator std::string const &() {
3294N/A return string();
500N/A }
3294N/A
3294N/A operator Glib::ustring const () const {
3294N/A return commonbase + tail();
3294N/A }
3294N/A
3294N/A char const *c_str() {
3294N/A return string().c_str();
3294N/A }
3294N/A
500N/A PathString &moveTo(Geom::Coord x, Geom::Coord y) {
3294N/A return moveTo(Geom::Point(x, y));
3294N/A }
3294N/A
3294N/A PathString &moveTo(Geom::Point p) {
3294N/A _appendOp('M','m');
500N/A _appendPoint(p, true);
3294N/A
500N/A _initial_point = _current_point;
3294N/A return *this;
3294N/A }
500N/A
3294N/A PathString &lineTo(Geom::Coord x, Geom::Coord y) {
3294N/A return lineTo(Geom::Point(x, y));
3294N/A }
3294N/A
3294N/A PathString &lineTo(Geom::Point p) {
3294N/A _appendOp('L','l');
3294N/A _appendPoint(p, true);
3294N/A return *this;
3294N/A }
500N/A
3294N/A PathString &horizontalLineTo(Geom::Coord x) {
3294N/A _appendOp('H','h');
3294N/A _appendX(x, true);
3294N/A return *this;
500N/A }
3294N/A
500N/A PathString &verticalLineTo(Geom::Coord y) {
500N/A _appendOp('V','v');
3294N/A _appendY(y, true);
3294N/A return *this;
3294N/A }
500N/A
5569N/A PathString &quadTo(Geom::Coord cx, Geom::Coord cy, Geom::Coord x, Geom::Coord y) {
5569N/A return quadTo(Geom::Point(cx, cy), Geom::Point(x, y));
5569N/A }
3294N/A
5569N/A PathString &quadTo(Geom::Point c, Geom::Point p) {
5569N/A _appendOp('Q','q');
5569N/A _appendPoint(c, false);
5569N/A _appendPoint(p, true);
5569N/A return *this;
5569N/A }
5569N/A
5569N/A PathString &curveTo(Geom::Coord x0, Geom::Coord y0,
5569N/A Geom::Coord x1, Geom::Coord y1,
5569N/A Geom::Coord x, Geom::Coord y)
5569N/A {
3294N/A return curveTo(Geom::Point(x0, y0), Geom::Point(x1, y1), Geom::Point(x, y));
5569N/A }
5569N/A
5569N/A PathString &curveTo(Geom::Point c0, Geom::Point c1, Geom::Point p) {
5569N/A _appendOp('C','c');
5569N/A _appendPoint(c0, false);
5569N/A _appendPoint(c1, false);
5569N/A _appendPoint(p, true);
5569N/A return *this;
5569N/A }
5569N/A
5569N/A /**
5569N/A * \param rot the angle in degrees
5569N/A */
5569N/A PathString &arcTo(Geom::Coord rx, Geom::Coord ry, Geom::Coord rot,
5569N/A bool large_arc, bool sweep,
5569N/A Geom::Point p)
5569N/A {
5569N/A _appendOp('A','a');
5569N/A _appendValue(Geom::Point(rx,ry));
5569N/A _appendValue(rot);
5569N/A _appendFlag(large_arc);
5569N/A _appendFlag(sweep);
5569N/A _appendPoint(p, true);
3294N/A return *this;
3294N/A }
5569N/A
3294N/A PathString &closePath() {
3294N/A _abs_state.appendOp('z');
3294N/A _rel_state.appendOp('z');
3294N/A _current_point = _initial_point;
3294N/A return *this;
3294N/A }
3294N/A
3294N/Aprivate:
3294N/A
5569N/A void _appendOp(char abs_op, char rel_op);
5569N/A
5569N/A void _appendFlag(bool flag) {
3294N/A _abs_state.append(flag);
3294N/A _rel_state.append(flag);
3294N/A }
3294N/A
3294N/A void _appendValue(Geom::Coord v) {
3294N/A _abs_state.append(v);
3294N/A _rel_state.append(v);
3294N/A }
3294N/A
3294N/A void _appendValue(Geom::Point p) {
3294N/A _abs_state.append(p);
3294N/A _rel_state.append(p);
3294N/A }
3294N/A
3294N/A void _appendX(Geom::Coord x, bool sc) {
3294N/A double rx;
3294N/A _abs_state.append(x, rx);
3294N/A _rel_state.appendRelative(rx, _current_point[Geom::X]);
5569N/A if (sc) _current_point[Geom::X] = rx;
3294N/A }
500N/A
3294N/A void _appendY(Geom::Coord y, bool sc) {
3294N/A double ry;
3294N/A _abs_state.append(y, ry);
3294N/A _rel_state.appendRelative(ry, _current_point[Geom::Y]);
5569N/A if (sc) _current_point[Geom::Y] = ry;
3294N/A }
5569N/A
5569N/A void _appendPoint(Geom::Point p, bool sc) {
3294N/A Geom::Point rp;
3294N/A _abs_state.append(p, rp);
3294N/A _rel_state.appendRelative(rp, _current_point);
5569N/A if (sc) _current_point = rp;
3294N/A }
3294N/A
3294N/A struct State {
3294N/A State() { prevop = 0; switches = 0; }
3294N/A
2213N/A void appendOp(char op) {
3294N/A if (prevop != 0) str += ' ';
5569N/A str += op;
5569N/A prevop = ( op == 'M' ? 'L' : op == 'm' ? 'l' : op );
5569N/A }
3294N/A
3294N/A void append(bool flag) {
3294N/A str += ' ';
3294N/A str += ( flag ? '1' : '0' );
3294N/A }
3294N/A
3294N/A void append(Geom::Coord v);
3294N/A void append(Geom::Point v);
3294N/A void append(Geom::Coord v, Geom::Coord& rv);
3294N/A void append(Geom::Point p, Geom::Point& rp);
3294N/A void appendRelative(Geom::Coord v, Geom::Coord r);
3294N/A void appendRelative(Geom::Point p, Geom::Point r);
5569N/A
5569N/A bool operator<=(const State& s) const {
3294N/A if ( str.size() < s.str.size() ) return true;
3294N/A if ( str.size() > s.str.size() ) return false;
3294N/A if ( switches < s.switches ) return true;
3294N/A if ( switches > s.switches ) return false;
3294N/A return true;
3294N/A }
3294N/A
3294N/A // Note: changing this to Glib::ustring might cause problems in path-string.cpp because it assumes that
3294N/A // size() returns the size of the string in BYTES (and Glib::ustring::resize is terribly slow)
3294N/A std::string str;
3294N/A unsigned int switches;
3294N/A char prevop;
3294N/A
3294N/A private:
void appendNumber(double v, int precision=numericprecision, int minexp=minimumexponent);
void appendNumber(double v, double &rv, int precision=numericprecision, int minexp=minimumexponent);
void appendRelativeCoord(Geom::Coord v, Geom::Coord r);
} _abs_state, _rel_state; // State with the last operator being an absolute/relative operator
Geom::Point _initial_point;
Geom::Point _current_point;
// If both states have a common prefix it is stored here.
// Separating out the common prefix prevents repeated copying between the states
// to cause a quadratic time complexity (in the number of characters/operators)
std::string commonbase;
std::string final;
std::string const &tail() const { return ((_abs_state <= _rel_state || !allow_relative_coordinates) ? _abs_state.str : _rel_state.str); }
bool const allow_relative_coordinates;
bool const force_repeat_commands;
static int numericprecision;
static int minimumexponent;
};
}
}
#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:encoding=utf-8:textwidth=99 :