diff options
Diffstat (limited to '')
-rw-r--r-- | src/svg/svg-affine.cpp | 138 |
1 files changed, 138 insertions, 0 deletions
diff --git a/src/svg/svg-affine.cpp b/src/svg/svg-affine.cpp new file mode 100644 index 0000000..336eeca --- /dev/null +++ b/src/svg/svg-affine.cpp @@ -0,0 +1,138 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * SVG data parser + * + * Authors: + * Lauris Kaplinski <lauris@kaplinski.com> + * Raph Levien <raph@acm.org> + * + * Copyright (C) 1999-2002 Lauris Kaplinski + * Copyright (C) 1999 Raph Levien + * + * Released under GNU GPL v2+, read the file 'COPYING' for more information. + */ + +#include <cstring> +#include <string> +#include <cstdlib> +#include <cstdio> +#include <glib.h> +#include <2geom/transforms.h> +#include "svg.h" +#include "preferences.h" + +std::string +sp_svg_transform_write(Geom::Affine const &transform) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + // this must be a bit grater than EPSILON + double e = 1e-5 * transform.descrim(); + int prec = prefs->getInt("/options/svgoutput/numericprecision", 8); + int min_exp = prefs->getInt("/options/svgoutput/minimumexponent", -8); + + // Special case: when all fields of the affine are zero, + // the optimized transformation is scale(0) + if (transform[0] == 0 && transform[1] == 0 && transform[2] == 0 && + transform[3] == 0 && transform[4] == 0 && transform[5] == 0) + { + return "scale(0)"; + } + + + std::stringstream c(""); // string buffer + + if (transform.isIdentity()) { + // We are more or less identity, so no transform attribute needed: + return {}; + } else if (transform.isScale()) { + // We are more or less a uniform scale + c << "scale("; + c << sp_svg_number_write_de(transform[0], prec, min_exp); + if (Geom::are_near(transform[0], transform[3], e)) { + c << ")"; + } else { + c << ","; + c << sp_svg_number_write_de(transform[3], prec, min_exp); + c << ")"; + } + } else if (transform.isTranslation()) { + // We are more or less a pure translation + c << "translate("; + c << sp_svg_number_write_de(transform[4], prec, min_exp); + if (Geom::are_near(transform[5], 0.0, e)) { + c << ")"; + } else { + c << ","; + c << sp_svg_number_write_de(transform[5], prec, min_exp); + c << ")"; + } + } else if (transform.isRotation()) { + // We are more or less a pure rotation + c << "rotate("; + double angle = std::atan2(transform[1], transform[0]) * (180 / M_PI); + c << sp_svg_number_write_de(angle, prec, min_exp); + c << ")"; + } else if (transform.withoutTranslation().isRotation()) { + // Solution found by Johan Engelen + // Refer to the matrix in svg-affine-test.h + + // We are a rotation about a special axis + c << "rotate("; + double angle = std::atan2(transform[1], transform[0]) * (180 / M_PI); + c << sp_svg_number_write_de(angle, prec, min_exp); + c << ","; + + Geom::Affine const& m = transform; + double tx = (m[2]*m[5]+m[4]-m[4]*m[3]) / (1-m[3]-m[0]+m[0]*m[3]-m[2]*m[1]); + + c << sp_svg_number_write_de(tx, prec, min_exp); + c << ","; + + double ty = (m[1]*tx + m[5]) / (1 - m[3]); + c << sp_svg_number_write_de(ty, prec, min_exp); + c << ")"; + } else if (transform.isHShear()) { + // We are more or less a pure skewX + c << "skewX("; + double angle = atan(transform[2]) * (180 / M_PI); + c << sp_svg_number_write_de(angle, prec, min_exp); + c << ")"; + } else if (transform.isVShear()) { + // We are more or less a pure skewY + c << "skewY("; + double angle = atan(transform[1]) * (180 / M_PI); + + c << sp_svg_number_write_de(angle, prec, min_exp); + c << ")"; + } else { + c << "matrix("; + c << sp_svg_number_write_de(transform[0], prec, min_exp); + c << ","; + c << sp_svg_number_write_de(transform[1], prec, min_exp); + c << ","; + c << sp_svg_number_write_de(transform[2], prec, min_exp); + c << ","; + c << sp_svg_number_write_de(transform[3], prec, min_exp); + c << ","; + c << sp_svg_number_write_de(transform[4], prec, min_exp); + c << ","; + c << sp_svg_number_write_de(transform[5], prec, min_exp); + c << ")"; + } + + assert(c.str().length() <= 256); + return c.str(); + +} + +/* + 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 : |