mirror of
https://github.com/mapnik/mapnik.git
synced 2025-12-08 20:13:09 +00:00
204 lines
5.3 KiB
C++
204 lines
5.3 KiB
C++
/*****************************************************************************
|
|
*
|
|
* This file is part of Mapnik (c++ mapping toolkit)
|
|
*
|
|
* Copyright (C) 2012 Artem Pavlenko
|
|
*
|
|
* 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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|
*
|
|
*****************************************************************************/
|
|
|
|
#ifndef MAPNIK_TRANSFORM_EXPRESSION_HPP
|
|
#define MAPNIK_TRANSFORM_EXPRESSION_HPP
|
|
|
|
// mapnik
|
|
#include <mapnik/expression_node.hpp>
|
|
|
|
// boost
|
|
#include <boost/optional.hpp>
|
|
#include <boost/shared_ptr.hpp>
|
|
#include <boost/variant/variant.hpp>
|
|
|
|
// fusion
|
|
#include <boost/fusion/include/at.hpp>
|
|
#include <boost/fusion/include/vector.hpp>
|
|
|
|
// stl
|
|
#include <vector>
|
|
|
|
namespace mapnik {
|
|
|
|
struct identity_node {};
|
|
|
|
struct matrix_node
|
|
{
|
|
expr_node a_;
|
|
expr_node b_;
|
|
expr_node c_;
|
|
expr_node d_;
|
|
expr_node e_;
|
|
expr_node f_;
|
|
|
|
explicit matrix_node(double const* m)
|
|
: a_(m[0]), b_(m[1]), c_(m[2]), d_(m[3]), e_(m[4]), f_(m[5]) {}
|
|
|
|
template <typename T>
|
|
explicit matrix_node(T const& m)
|
|
: a_(m.sx), b_(m.shy), c_(m.shx), d_(m.sy), e_(m.tx), f_(m.ty) {}
|
|
|
|
matrix_node(expr_node const& a, expr_node const& b, expr_node const& c,
|
|
expr_node const& d, expr_node const& e, expr_node const& f)
|
|
: a_(a), b_(b), c_(c), d_(d), e_(e), f_(f) {}
|
|
};
|
|
|
|
struct translate_node
|
|
{
|
|
expr_node tx_;
|
|
expr_node ty_;
|
|
|
|
translate_node(expr_node const& tx,
|
|
boost::optional<expr_node> const& ty)
|
|
: tx_(tx)
|
|
, ty_(ty ? expr_node(*ty) : value_null()) {}
|
|
};
|
|
|
|
struct scale_node
|
|
{
|
|
expr_node sx_;
|
|
expr_node sy_;
|
|
|
|
scale_node(expr_node const& sx,
|
|
boost::optional<expr_node> const& sy)
|
|
: sx_(sx)
|
|
, sy_(sy ? expr_node(*sy) : value_null()) {}
|
|
};
|
|
|
|
struct rotate_node
|
|
{
|
|
typedef boost::fusion::vector2<expr_node, expr_node> coords_type;
|
|
|
|
expr_node angle_;
|
|
expr_node cx_;
|
|
expr_node cy_;
|
|
|
|
explicit rotate_node(expr_node const& angle)
|
|
: angle_(angle) {}
|
|
|
|
rotate_node(expr_node const& angle,
|
|
expr_node const& cx, expr_node const& cy)
|
|
: angle_(angle), cx_(cx), cy_(cy) {}
|
|
|
|
rotate_node(expr_node const& angle,
|
|
boost::optional<expr_node> const& cx,
|
|
boost::optional<expr_node> const& cy)
|
|
: angle_(angle)
|
|
, cx_(cx ? expr_node(*cx) : value_null())
|
|
, cy_(cy ? expr_node(*cy) : value_null()) {}
|
|
|
|
rotate_node(expr_node const& angle,
|
|
boost::optional<coords_type> const& center)
|
|
: angle_(angle)
|
|
{
|
|
if (center)
|
|
{
|
|
cx_ = boost::fusion::at_c<0>(*center);
|
|
cy_ = boost::fusion::at_c<1>(*center);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct skewX_node
|
|
{
|
|
expr_node angle_;
|
|
|
|
explicit skewX_node(expr_node const& angle)
|
|
: angle_(angle) {}
|
|
};
|
|
|
|
struct skewY_node
|
|
{
|
|
expr_node angle_;
|
|
|
|
explicit skewY_node(expr_node const& angle)
|
|
: angle_(angle) {}
|
|
};
|
|
|
|
namespace detail {
|
|
|
|
// boost::spirit::traits::clear<T>(T& val) [with T = boost::variant<...>]
|
|
// attempts to assign to the variant's current value a default-constructed
|
|
// value of the same type, which not only requires that each value-type is
|
|
// default-constructible, but also makes little sense with our variant of
|
|
// transform nodes...
|
|
|
|
typedef boost::variant< identity_node
|
|
, matrix_node
|
|
, translate_node
|
|
, scale_node
|
|
, rotate_node
|
|
, skewX_node
|
|
, skewY_node
|
|
> transform_variant;
|
|
|
|
// ... thus we wrap the variant-type in a distinct type and provide
|
|
// a custom clear overload, which resets the value to identity_node
|
|
|
|
struct transform_node
|
|
{
|
|
transform_variant base_;
|
|
|
|
transform_node()
|
|
: base_() {}
|
|
|
|
template <typename T>
|
|
transform_node(T const& val)
|
|
: base_(val) {}
|
|
|
|
template <typename T>
|
|
transform_node& operator= (T const& val)
|
|
{
|
|
base_ = val;
|
|
return *this;
|
|
}
|
|
|
|
transform_variant const& operator* () const
|
|
{
|
|
return base_;
|
|
}
|
|
|
|
transform_variant& operator* ()
|
|
{
|
|
return base_;
|
|
}
|
|
};
|
|
|
|
inline void clear(transform_node& val)
|
|
{
|
|
val.base_ = identity_node();
|
|
}
|
|
|
|
} // namespace detail
|
|
|
|
typedef detail::transform_node transform_node;
|
|
typedef std::vector<transform_node> transform_list;
|
|
typedef boost::shared_ptr<transform_list> transform_list_ptr;
|
|
|
|
MAPNIK_DECL std::string to_expression_string(transform_node const& node);
|
|
MAPNIK_DECL std::string to_expression_string(transform_list const& list);
|
|
|
|
} // namespace mapnik
|
|
|
|
#endif // MAPNIK_TRANSFORM_EXPRESSION_HPP
|