+ SVG markers initial import
This commit is contained in:
parent
4584b05ff0
commit
823b7ba0fc
14 changed files with 2371 additions and 1 deletions
76
include/mapnik/svg/agg_svg_parser.h
Normal file
76
include/mapnik/svg/agg_svg_parser.h
Normal file
|
@ -0,0 +1,76 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG parser.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#ifndef AGG_SVG_PARSER_INCLUDED
|
||||
#define AGG_SVG_PARSER_INCLUDED
|
||||
|
||||
#include "agg_svg_path_renderer.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
|
||||
class parser
|
||||
{
|
||||
enum buf_size_e { buf_size = 256 };
|
||||
public:
|
||||
|
||||
~parser();
|
||||
parser(path_renderer& path);
|
||||
|
||||
void parse(const char* fname);
|
||||
const char* title() const { return m_title; }
|
||||
|
||||
private:
|
||||
// XML event handlers
|
||||
static void start_element(void* data, const char* el, const char** attr);
|
||||
static void end_element(void* data, const char* el);
|
||||
static void content(void* data, const char* s, int len);
|
||||
|
||||
void parse_attr(const char** attr);
|
||||
void parse_circle(const char** attr);
|
||||
void parse_ellipse(const char** attr);
|
||||
void parse_path(const char** attr);
|
||||
void parse_poly(const char** attr, bool close_flag);
|
||||
void parse_rect(const char** attr);
|
||||
void parse_line(const char** attr);
|
||||
void parse_style(const char* str);
|
||||
bool parse_attr(const char* name, const char* value);
|
||||
bool parse_name_value(const char* nv_start, const char* nv_end);
|
||||
void copy_name(const char* start, const char* end);
|
||||
void copy_value(const char* start, const char* end);
|
||||
|
||||
private:
|
||||
path_renderer& m_path;
|
||||
char* m_buf;
|
||||
char* m_title;
|
||||
unsigned m_title_len;
|
||||
bool m_title_flag;
|
||||
bool m_path_flag;
|
||||
char* m_attr_name;
|
||||
char* m_attr_value;
|
||||
unsigned m_attr_name_len;
|
||||
unsigned m_attr_value_len;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
327
include/mapnik/svg/agg_svg_path_renderer.h
Normal file
327
include/mapnik/svg/agg_svg_path_renderer.h
Normal file
|
@ -0,0 +1,327 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG path renderer.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
#ifndef AGG_SVG_PATH_RENDERER_INCLUDED
|
||||
#define AGG_SVG_PATH_RENDERER_INCLUDED
|
||||
|
||||
#include "agg_path_storage.h"
|
||||
#include "agg_conv_transform.h"
|
||||
#include "agg_conv_stroke.h"
|
||||
#include "agg_conv_contour.h"
|
||||
#include "agg_conv_curve.h"
|
||||
#include "agg_color_rgba.h"
|
||||
#include "agg_renderer_scanline.h"
|
||||
#include "agg_bounding_rect.h"
|
||||
#include "agg_rasterizer_scanline_aa.h"
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
template<class VertexSource> class conv_count
|
||||
{
|
||||
public:
|
||||
conv_count(VertexSource& vs) : m_source(&vs), m_count(0) {}
|
||||
|
||||
void count(unsigned n) { m_count = n; }
|
||||
unsigned count() const { return m_count; }
|
||||
|
||||
void rewind(unsigned path_id) { m_source->rewind(path_id); }
|
||||
unsigned vertex(double* x, double* y)
|
||||
{
|
||||
++m_count;
|
||||
return m_source->vertex(x, y);
|
||||
}
|
||||
|
||||
private:
|
||||
VertexSource* m_source;
|
||||
unsigned m_count;
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
//============================================================================
|
||||
// Basic path attributes
|
||||
struct path_attributes
|
||||
{
|
||||
unsigned index;
|
||||
rgba8 fill_color;
|
||||
rgba8 stroke_color;
|
||||
bool fill_flag;
|
||||
bool stroke_flag;
|
||||
bool even_odd_flag;
|
||||
line_join_e line_join;
|
||||
line_cap_e line_cap;
|
||||
double miter_limit;
|
||||
double stroke_width;
|
||||
trans_affine transform;
|
||||
|
||||
// Empty constructor
|
||||
path_attributes() :
|
||||
index(0),
|
||||
fill_color(rgba(0,0,0)),
|
||||
stroke_color(rgba(0,0,0)),
|
||||
fill_flag(true),
|
||||
stroke_flag(false),
|
||||
even_odd_flag(false),
|
||||
line_join(miter_join),
|
||||
line_cap(butt_cap),
|
||||
miter_limit(4.0),
|
||||
stroke_width(1.0),
|
||||
transform()
|
||||
{
|
||||
}
|
||||
|
||||
// Copy constructor
|
||||
path_attributes(const path_attributes& attr) :
|
||||
index(attr.index),
|
||||
fill_color(attr.fill_color),
|
||||
stroke_color(attr.stroke_color),
|
||||
fill_flag(attr.fill_flag),
|
||||
stroke_flag(attr.stroke_flag),
|
||||
even_odd_flag(attr.even_odd_flag),
|
||||
line_join(attr.line_join),
|
||||
line_cap(attr.line_cap),
|
||||
miter_limit(attr.miter_limit),
|
||||
stroke_width(attr.stroke_width),
|
||||
transform(attr.transform)
|
||||
{
|
||||
}
|
||||
|
||||
// Copy constructor with new index value
|
||||
path_attributes(const path_attributes& attr, unsigned idx) :
|
||||
index(idx),
|
||||
fill_color(attr.fill_color),
|
||||
stroke_color(attr.stroke_color),
|
||||
fill_flag(attr.fill_flag),
|
||||
stroke_flag(attr.stroke_flag),
|
||||
even_odd_flag(attr.even_odd_flag),
|
||||
line_join(attr.line_join),
|
||||
line_cap(attr.line_cap),
|
||||
miter_limit(attr.miter_limit),
|
||||
stroke_width(attr.stroke_width),
|
||||
transform(attr.transform)
|
||||
{
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//============================================================================
|
||||
// Path container and renderer.
|
||||
class path_renderer
|
||||
{
|
||||
public:
|
||||
typedef pod_bvector<path_attributes> attr_storage;
|
||||
|
||||
typedef conv_curve<path_storage> curved;
|
||||
typedef conv_count<curved> curved_count;
|
||||
|
||||
typedef conv_stroke<curved_count> curved_stroked;
|
||||
typedef conv_transform<curved_stroked> curved_stroked_trans;
|
||||
|
||||
typedef conv_transform<curved_count> curved_trans;
|
||||
typedef conv_contour<curved_trans> curved_trans_contour;
|
||||
|
||||
path_renderer();
|
||||
|
||||
void remove_all();
|
||||
|
||||
// Use these functions as follows:
|
||||
// begin_path() when the XML tag <path> comes ("start_element" handler)
|
||||
// parse_path() on "d=" tag attribute
|
||||
// end_path() when parsing of the entire tag is done.
|
||||
void begin_path();
|
||||
//void parse_path(path_tokenizer& tok);
|
||||
void end_path();
|
||||
|
||||
// The following functions are essentially a "reflection" of
|
||||
// the respective SVG path commands.
|
||||
void move_to(double x, double y, bool rel=false); // M, m
|
||||
void line_to(double x, double y, bool rel=false); // L, l
|
||||
void hline_to(double x, bool rel=false); // H, h
|
||||
void vline_to(double y, bool rel=false); // V, v
|
||||
void curve3(double x1, double y1, // Q, q
|
||||
double x, double y, bool rel=false);
|
||||
void curve3(double x, double y, bool rel=false); // T, t
|
||||
void curve4(double x1, double y1, // C, c
|
||||
double x2, double y2,
|
||||
double x, double y, bool rel=false);
|
||||
void curve4(double x2, double y2, // S, s
|
||||
double x, double y, bool rel=false);
|
||||
|
||||
void arc_to(double rx, double rx, // A, a
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x, double y,bool rel=false);
|
||||
|
||||
void close_subpath(); // Z, z
|
||||
|
||||
// template<class VertexSource>
|
||||
// void add_path(VertexSource& vs,
|
||||
// unsigned path_id = 0,
|
||||
// bool solid_path = true)
|
||||
// {
|
||||
// m_storage.add_path(vs, path_id, solid_path);
|
||||
// }
|
||||
|
||||
|
||||
unsigned vertex_count() const { return m_curved_count.count(); }
|
||||
|
||||
|
||||
// Call these functions on <g> tag (start_element, end_element respectively)
|
||||
void push_attr();
|
||||
void pop_attr();
|
||||
|
||||
// Attribute setting functions.
|
||||
void fill(const rgba8& f);
|
||||
void stroke(const rgba8& s);
|
||||
void even_odd(bool flag);
|
||||
void stroke_width(double w);
|
||||
void fill_none();
|
||||
void stroke_none();
|
||||
void fill_opacity(double op);
|
||||
void stroke_opacity(double op);
|
||||
void line_join(line_join_e join);
|
||||
void line_cap(line_cap_e cap);
|
||||
void miter_limit(double ml);
|
||||
trans_affine& transform();
|
||||
|
||||
// Make all polygons CCW-oriented
|
||||
void arrange_orientations()
|
||||
{
|
||||
m_storage.arrange_orientations_all_paths(path_flags_ccw);
|
||||
}
|
||||
|
||||
// Expand all polygons
|
||||
void expand(double value)
|
||||
{
|
||||
m_curved_trans_contour.width(value);
|
||||
}
|
||||
|
||||
unsigned operator [](unsigned idx)
|
||||
{
|
||||
m_transform = m_attr_storage[idx].transform;
|
||||
return m_attr_storage[idx].index;
|
||||
}
|
||||
|
||||
void bounding_rect(double* x1, double* y1, double* x2, double* y2)
|
||||
{
|
||||
agg::conv_transform<agg::path_storage> trans(m_storage, m_transform);
|
||||
agg::bounding_rect(trans, *this, 0, m_attr_storage.size(), x1, y1, x2, y2);
|
||||
}
|
||||
|
||||
// Rendering. One can specify two additional parameters:
|
||||
// trans_affine and opacity. They can be used to transform the whole
|
||||
// image and/or to make it translucent.
|
||||
template<class Rasterizer, class Scanline, class Renderer>
|
||||
void render(Rasterizer& ras,
|
||||
Scanline& sl,
|
||||
Renderer& ren,
|
||||
const trans_affine& mtx,
|
||||
const rect_i& cb,
|
||||
double opacity=1.0)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
ras.clip_box(cb.x1, cb.y1, cb.x2, cb.y2);
|
||||
m_curved_count.count(0);
|
||||
|
||||
for(i = 0; i < m_attr_storage.size(); i++)
|
||||
{
|
||||
const path_attributes& attr = m_attr_storage[i];
|
||||
m_transform = attr.transform;
|
||||
m_transform *= mtx;
|
||||
double scl = m_transform.scale();
|
||||
//m_curved.approximation_method(curve_inc);
|
||||
m_curved.approximation_scale(scl);
|
||||
m_curved.angle_tolerance(0.0);
|
||||
|
||||
rgba8 color;
|
||||
|
||||
if(attr.fill_flag)
|
||||
{
|
||||
ras.reset();
|
||||
ras.filling_rule(attr.even_odd_flag ? fill_even_odd : fill_non_zero);
|
||||
if(fabs(m_curved_trans_contour.width()) < 0.0001)
|
||||
{
|
||||
ras.add_path(m_curved_trans, attr.index);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_curved_trans_contour.miter_limit(attr.miter_limit);
|
||||
ras.add_path(m_curved_trans_contour, attr.index);
|
||||
}
|
||||
|
||||
color = attr.fill_color;
|
||||
color.opacity(color.opacity() * opacity);
|
||||
ren.color(color);
|
||||
agg::render_scanlines(ras, sl, ren);
|
||||
}
|
||||
|
||||
if(attr.stroke_flag)
|
||||
{
|
||||
m_curved_stroked.width(attr.stroke_width);
|
||||
//m_curved_stroked.line_join((attr.line_join == miter_join) ? miter_join_round : attr.line_join);
|
||||
m_curved_stroked.line_join(attr.line_join);
|
||||
m_curved_stroked.line_cap(attr.line_cap);
|
||||
m_curved_stroked.miter_limit(attr.miter_limit);
|
||||
m_curved_stroked.inner_join(inner_round);
|
||||
m_curved_stroked.approximation_scale(scl);
|
||||
|
||||
// If the *visual* line width is considerable we
|
||||
// turn on processing of curve cusps.
|
||||
//---------------------
|
||||
if(attr.stroke_width * scl > 1.0)
|
||||
{
|
||||
m_curved.angle_tolerance(0.2);
|
||||
}
|
||||
ras.reset();
|
||||
ras.filling_rule(fill_non_zero);
|
||||
ras.add_path(m_curved_stroked_trans, attr.index);
|
||||
color = attr.stroke_color;
|
||||
color.opacity(color.opacity() * opacity);
|
||||
ren.color(color);
|
||||
agg::render_scanlines(ras, sl, ren);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
path_attributes& cur_attr();
|
||||
|
||||
path_storage m_storage;
|
||||
attr_storage m_attr_storage;
|
||||
attr_storage m_attr_stack;
|
||||
trans_affine m_transform;
|
||||
|
||||
curved m_curved;
|
||||
curved_count m_curved_count;
|
||||
|
||||
curved_stroked m_curved_stroked;
|
||||
curved_stroked_trans m_curved_stroked_trans;
|
||||
|
||||
curved_trans m_curved_trans;
|
||||
curved_trans_contour m_curved_trans_contour;
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
59
include/mapnik/svg/marker_cache.hpp
Normal file
59
include/mapnik/svg/marker_cache.hpp
Normal file
|
@ -0,0 +1,59 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2009 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//$Id$
|
||||
|
||||
#ifndef MAPNIK_MARKER_CACHE_HPP
|
||||
#define MAPNIK_MARKER_CACHE_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/utils.hpp>
|
||||
#include <mapnik/config.hpp>
|
||||
#include <mapnik/image_data.hpp>
|
||||
|
||||
// boost
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#include <boost/thread/mutex.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
typedef boost::shared_ptr<image_data_32> path_ptr;
|
||||
|
||||
struct MAPNIK_DECL image_cache :
|
||||
public singleton <image_cache, CreateStatic>,
|
||||
private boost::noncopyable
|
||||
{
|
||||
|
||||
friend class CreateStatic<image_cache>;
|
||||
static boost::mutex mutex_;
|
||||
static boost::unordered_map<std::string,image_ptr> cache_;
|
||||
static bool insert(std::string const& key, image_ptr);
|
||||
static boost::optional<image_ptr> find(std::string const& key, bool update_cache = false);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // MAPNIK_MARKER_CACHE_HPP
|
255
include/mapnik/svg/svg_path_commands.hpp
Normal file
255
include/mapnik/svg/svg_path_commands.hpp
Normal file
|
@ -0,0 +1,255 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2010 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 SVG_COMMANDS_HPP
|
||||
#define SVG_COMMANDS_HPP
|
||||
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
using namespace boost::fusion;
|
||||
|
||||
template <typename PathType>
|
||||
struct move_to
|
||||
{
|
||||
template <typename T0, typename T1>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit move_to(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
void operator() (T0 v, T1 rel) const
|
||||
{
|
||||
path_.move_to(at_c<0>(v),at_c<1>(v),rel); // impl
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
template <typename PathType>
|
||||
struct hline_to
|
||||
{
|
||||
template <typename T0, typename T1>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit hline_to(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
void operator() (T0 const& x, T1 rel) const
|
||||
{
|
||||
path_.hline_to(x,rel);
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
|
||||
template <typename PathType>
|
||||
struct vline_to
|
||||
{
|
||||
template <typename T0, typename T1>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit vline_to(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
void operator() (T0 const& y, T1 rel) const
|
||||
{
|
||||
path_.vline_to(y,rel);
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
template <typename PathType>
|
||||
struct line_to
|
||||
{
|
||||
template <typename T0, typename T1>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit line_to(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
void operator() (T0 const& v, T1 rel) const
|
||||
{
|
||||
path_.line_to(at_c<0>(v),at_c<1>(v),rel); // impl
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
|
||||
template <typename PathType>
|
||||
struct curve4
|
||||
{
|
||||
template <typename T0, typename T1, typename T2, typename T3>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit curve4(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1,typename T2, typename T3>
|
||||
void operator() (T0 const& v0, T1 const& v1, T2 const& v2, T3 rel) const
|
||||
{
|
||||
path_.curve4(at_c<0>(v0),at_c<1>(v0),
|
||||
at_c<0>(v1),at_c<1>(v1),
|
||||
at_c<0>(v2),at_c<1>(v2),
|
||||
rel); // impl
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
|
||||
template <typename PathType>
|
||||
struct curve4_smooth
|
||||
{
|
||||
template <typename T0, typename T1, typename T2>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit curve4_smooth(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1,typename T2>
|
||||
void operator() (T0 const& v0, T1 const& v1, T2 rel) const
|
||||
{
|
||||
path_.curve4(at_c<0>(v0),at_c<1>(v0),
|
||||
at_c<0>(v1),at_c<1>(v1),
|
||||
rel); // impl
|
||||
}
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
template <typename PathType>
|
||||
struct curve3
|
||||
{
|
||||
template <typename T0, typename T1, typename T2>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit curve3(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1,typename T2>
|
||||
void operator() (T0 const& v0, T1 const& v1, T2 rel) const
|
||||
{
|
||||
path_.curve3(at_c<0>(v0),at_c<1>(v0),
|
||||
at_c<0>(v1),at_c<1>(v1),
|
||||
rel); // impl
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
template <typename PathType>
|
||||
struct curve3_smooth
|
||||
{
|
||||
template <typename T0, typename T1>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit curve3_smooth(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1>
|
||||
void operator() (T0 const& v0, T1 rel) const
|
||||
{
|
||||
path_.curve3(at_c<0>(v0),at_c<1>(v0),
|
||||
rel); // impl
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
template <typename PathType>
|
||||
struct arc_to
|
||||
{
|
||||
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit arc_to(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
template <typename T0, typename T1,typename T2, typename T3, typename T4, typename T5>
|
||||
void operator() (T0 const& rv, T1 const& angle, T2 large_arc_flag, T3 sweep_flag, T4 const& v, T5 rel) const
|
||||
{
|
||||
path_.arc_to(at_c<0>(rv),at_c<1>(rv),
|
||||
deg2rad(angle),large_arc_flag,sweep_flag,
|
||||
at_c<0>(v),at_c<1>(v),
|
||||
rel);
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
template <typename PathType>
|
||||
struct close
|
||||
{
|
||||
typedef void result_type;
|
||||
|
||||
explicit close(PathType & path)
|
||||
: path_(path) {}
|
||||
|
||||
void operator()() const
|
||||
{
|
||||
path_.close_subpath();
|
||||
}
|
||||
|
||||
PathType & path_;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif // SVG_COMMANDS_HPP
|
159
include/mapnik/svg/svg_path_grammar.hpp
Normal file
159
include/mapnik/svg/svg_path_grammar.hpp
Normal file
|
@ -0,0 +1,159 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2010 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 SVG_PATH_GRAMMAR_HPP
|
||||
#define SVG_PATH_GRAMMAR_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/svg/svg_path_commands.hpp>
|
||||
// spirit
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
using namespace boost::spirit;
|
||||
using namespace boost::fusion;
|
||||
using namespace boost::phoenix;
|
||||
|
||||
inline double deg2rad(double deg)
|
||||
{
|
||||
return (M_PI * deg)/180.0;
|
||||
}
|
||||
|
||||
|
||||
template <typename Iterator, typename SkipType, typename PathType>
|
||||
struct svg_path_grammar : qi::grammar<Iterator,SkipType>
|
||||
{
|
||||
explicit svg_path_grammar(PathType & path)
|
||||
: svg_path_grammar::base_type(start),
|
||||
move_to_(move_to<PathType>(path)),
|
||||
hline_to_(hline_to<PathType>(path)),
|
||||
vline_to_(vline_to<PathType>(path)),
|
||||
line_to_(line_to<PathType>(path)),
|
||||
curve4_(curve4<PathType>(path)),
|
||||
curve4_smooth_(curve4_smooth<PathType>(path)),
|
||||
curve3_(curve3<PathType>(path)),
|
||||
curve3_smooth_(curve3_smooth<PathType>(path)),
|
||||
arc_to_(arc_to<PathType>(path)),
|
||||
close_(close<PathType>(path))
|
||||
{
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_3;
|
||||
using qi::_4;
|
||||
using qi::_5;
|
||||
using qi::_a;
|
||||
using qi::lit;
|
||||
using qi::double_;
|
||||
using qi::int_;
|
||||
using qi::no_case;
|
||||
|
||||
start = +cmd;
|
||||
cmd = M | L | H | V | C | S | Q | T | A | Z;
|
||||
|
||||
M = (lit('M')[_a = false] | lit('m')[_a = true] )
|
||||
>> coord[move_to_(_1,_a)] // move_to
|
||||
>> *(-lit(',') >> coord [ line_to_(_1,_a) ] ); // *line_to
|
||||
|
||||
H = (lit('H')[_a = false] | lit('h')[_a = true])
|
||||
>> +double_[ hline_to_(_1,_a) ] ; // +hline_to
|
||||
|
||||
V = (lit('V')[_a = false] | lit('v')[_a = true])
|
||||
>> +double_ [ vline_to_(_1,_a) ]; // +vline_to
|
||||
|
||||
L = (lit('L')[_a = false] | lit('l')[_a = true])
|
||||
>> +coord [ line_to_(_1,_a) ]; // +line_to
|
||||
|
||||
C = (lit('C')[_a = false] | lit('c')[_a = true])
|
||||
>> +(coord
|
||||
>> -lit(',')
|
||||
>> coord
|
||||
>> -lit(',')
|
||||
>> coord) [ curve4_(_1,_2,_3,_a) ]; // +curve4
|
||||
|
||||
S = (lit('S')[_a = false] | lit('s')[_a = true])
|
||||
>> +(coord
|
||||
>> -lit(',')
|
||||
>> coord) [ curve4_smooth_(_1,_2,_a) ]; // +curve4_smooth (smooth curveto)
|
||||
|
||||
Q = (lit('Q')[_a = false] | lit('q')[_a = true])
|
||||
>> +(coord
|
||||
>> -lit(',')
|
||||
>> coord) [ curve3_(_1,_2,_a) ]; // +curve3 (quadratic-bezier-curveto)
|
||||
|
||||
T = (lit('T')[_a = false] | lit('t')[_a = true])
|
||||
>> +(coord ) [ curve3_smooth_(_1,_a) ]; // +curve3_smooth (smooth-quadratic-bezier-curveto)
|
||||
|
||||
A = (lit('A')[_a = false] | lit('a')[_a = true])
|
||||
>> +(coord
|
||||
>> -lit(',')
|
||||
>> double_
|
||||
>> -lit(',')
|
||||
>> int_
|
||||
>> -lit(',')
|
||||
>> int_
|
||||
>> -lit(',')
|
||||
>> coord) [arc_to_(_1,_2,_3,_4,_5,_a)]; // arc_to;
|
||||
|
||||
|
||||
|
||||
Z = no_case[lit('z')] [close_()]; // close path
|
||||
|
||||
coord = double_ >> -lit(',') >> double_;
|
||||
}
|
||||
|
||||
// rules
|
||||
qi::rule<Iterator,SkipType> start;
|
||||
qi::rule<Iterator,SkipType> cmd;
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> M; // M,m
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> L; // L,l
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> H; // H,h
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> V; // V,v
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> C; // C,c
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> S; // S,s
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> Q; // Q,q
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> T; // T,t
|
||||
qi::rule<Iterator,qi::locals<bool>,SkipType> A; // A,a
|
||||
qi::rule<Iterator,SkipType> Z; // Z,z
|
||||
|
||||
qi::rule<Iterator,vector2<double,double>(),SkipType> coord;
|
||||
|
||||
// commands
|
||||
function<move_to<PathType> > move_to_;
|
||||
function<hline_to<PathType> > hline_to_;
|
||||
function<vline_to<PathType> > vline_to_;
|
||||
function<line_to<PathType> > line_to_;
|
||||
function<curve4<PathType> > curve4_;
|
||||
function<curve4_smooth<PathType> > curve4_smooth_;
|
||||
function<curve3<PathType> > curve3_;
|
||||
function<curve3_smooth<PathType> > curve3_smooth_;
|
||||
function<arc_to<PathType> > arc_to_;
|
||||
function<close<PathType> > close_;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif // SVG_PATH_GRAMMAR_HPP
|
42
include/mapnik/svg/svg_path_parser.hpp
Normal file
42
include/mapnik/svg/svg_path_parser.hpp
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2010 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 SVG_PATH_PARSER_HPP
|
||||
#define SVG_PATH_PARSER_HPP
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
template <typename PathType>
|
||||
bool parse_path(std::string const& wkt, PathType & p);
|
||||
|
||||
template <typename PathType>
|
||||
bool parse_points(std::string const& wkt, PathType & p);
|
||||
|
||||
template <typename TransformType>
|
||||
bool parse_transform(std::string const& wkt, TransformType & tr);
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif // SVG_PATH_PARSER_HPP
|
72
include/mapnik/svg/svg_points_grammar.hpp
Normal file
72
include/mapnik/svg/svg_points_grammar.hpp
Normal file
|
@ -0,0 +1,72 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2010 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 SVG_POINTS_GRAMMAR_HPP
|
||||
#define SVG_POINTS_GRAMMAR_HPP
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/svg/svg_path_commands.hpp>
|
||||
// spirit
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
using namespace boost::spirit;
|
||||
using namespace boost::fusion;
|
||||
using namespace boost::phoenix;
|
||||
|
||||
template <typename Iterator, typename SkipType, typename PathType>
|
||||
struct svg_points_grammar : qi::grammar<Iterator,SkipType>
|
||||
{
|
||||
explicit svg_points_grammar(PathType & path)
|
||||
: svg_points_grammar::base_type(start),
|
||||
move_to_(move_to<PathType>(path)),
|
||||
line_to_(line_to<PathType>(path)),
|
||||
close_(close<PathType>(path))
|
||||
{
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::double_;
|
||||
|
||||
start = coord[move_to_(_1,false)] // move_to
|
||||
>> *(-lit(',') >> coord [ line_to_(_1,false) ] ); // *line_to
|
||||
|
||||
coord = double_ >> -lit(',') >> double_;
|
||||
}
|
||||
|
||||
// rules
|
||||
qi::rule<Iterator,SkipType> start;
|
||||
qi::rule<Iterator,vector2<double,double>(),SkipType> coord;
|
||||
|
||||
// commands
|
||||
function<move_to<PathType> > move_to_;
|
||||
function<line_to<PathType> > line_to_;
|
||||
function<close<PathType> > close_;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
|
||||
#endif // SVG_POINTS_GRAMMAR_HPP
|
260
include/mapnik/svg/svg_transform_grammar.hpp
Normal file
260
include/mapnik/svg/svg_transform_grammar.hpp
Normal file
|
@ -0,0 +1,260 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2010 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
//$Id$
|
||||
|
||||
#ifndef SVG_TRANSFORM_GRAMMAR_HPP
|
||||
#define SVG_TRANSFORM_GRAMMAR_HPP
|
||||
|
||||
|
||||
// agg
|
||||
#include "agg_trans_affine.h"
|
||||
// spirit
|
||||
#include <boost/spirit/include/qi.hpp>
|
||||
#include <boost/spirit/include/phoenix_function.hpp>
|
||||
#include <boost/spirit/include/phoenix_core.hpp>
|
||||
#include <boost/spirit/include/phoenix_operator.hpp>
|
||||
#include <boost/spirit/home/phoenix/object/construct.hpp>
|
||||
|
||||
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
using namespace boost::spirit;
|
||||
using namespace boost::fusion;
|
||||
using namespace boost::phoenix;
|
||||
|
||||
inline double deg2rad(double d)
|
||||
{
|
||||
return M_PI * d / 180.0;
|
||||
}
|
||||
|
||||
template <typename TransformType>
|
||||
struct process_matrix
|
||||
{
|
||||
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit process_matrix( TransformType & tr)
|
||||
:tr_(tr) {}
|
||||
|
||||
void operator () (double a, double b, double c, double d, double e, double f) const
|
||||
{
|
||||
tr_ *= agg::trans_affine(a,b,c,d,e,f);
|
||||
}
|
||||
|
||||
TransformType & tr_;
|
||||
};
|
||||
|
||||
template <typename TransformType>
|
||||
struct process_rotate
|
||||
{
|
||||
template <typename T0, typename T1, typename T2>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit process_rotate( TransformType & tr)
|
||||
:tr_(tr) {}
|
||||
|
||||
template <typename T0,typename T1,typename T2>
|
||||
void operator () (T0 a, T1 cx, T2 cy) const
|
||||
{
|
||||
if (cx == 0.0 && cy == 0.0)
|
||||
{
|
||||
tr_ *= agg::trans_affine_rotation(deg2rad(a));
|
||||
}
|
||||
else
|
||||
{
|
||||
agg::trans_affine t = agg::trans_affine_translation(-cx,-cy);
|
||||
t *= agg::trans_affine_rotation(deg2rad(a));
|
||||
t *= agg::trans_affine_translation(cx, cy);
|
||||
tr_ *= t;
|
||||
}
|
||||
}
|
||||
|
||||
TransformType & tr_;
|
||||
};
|
||||
|
||||
template <typename TransformType>
|
||||
struct process_translate
|
||||
{
|
||||
template <typename T0, typename T1>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit process_translate( TransformType & tr)
|
||||
:tr_(tr) {}
|
||||
|
||||
template <typename T0,typename T1>
|
||||
void operator () (T0 tx, T1 ty) const
|
||||
{
|
||||
if (ty) tr_ *= agg::trans_affine_translation(tx,*ty);
|
||||
else tr_ *= agg::trans_affine_translation(tx,0.0);
|
||||
}
|
||||
|
||||
TransformType & tr_;
|
||||
};
|
||||
|
||||
template <typename TransformType>
|
||||
struct process_scale
|
||||
{
|
||||
template <typename T0, typename T1>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit process_scale( TransformType & tr)
|
||||
:tr_(tr) {}
|
||||
|
||||
template <typename T0,typename T1>
|
||||
void operator () (T0 sx, T1 sy) const
|
||||
{
|
||||
if (sy) tr_ *= agg::trans_affine_scaling(sx,*sy);
|
||||
else tr_ *= agg::trans_affine_scaling(sx,sx);
|
||||
}
|
||||
|
||||
TransformType & tr_;
|
||||
};
|
||||
|
||||
|
||||
template <typename TransformType>
|
||||
struct process_skew
|
||||
{
|
||||
template <typename T0, typename T1>
|
||||
struct result
|
||||
{
|
||||
typedef void type;
|
||||
};
|
||||
|
||||
explicit process_skew( TransformType & tr)
|
||||
:tr_(tr) {}
|
||||
|
||||
template <typename T0,typename T1>
|
||||
void operator () (T0 skew_x, T1 skew_y) const
|
||||
{
|
||||
tr_ *= agg::trans_affine_skewing(deg2rad(skew_x),deg2rad(skew_y));
|
||||
}
|
||||
|
||||
TransformType & tr_;
|
||||
};
|
||||
|
||||
struct print_action
|
||||
{
|
||||
template <typename T>
|
||||
void operator()(T const& c, qi::unused_type, qi::unused_type) const
|
||||
{
|
||||
std::cerr << typeid(c).name() << std::endl;
|
||||
}
|
||||
};
|
||||
|
||||
template <typename Iterator, typename SkipType, typename TransformType>
|
||||
struct svg_transform_grammar : qi::grammar<Iterator,SkipType>
|
||||
{
|
||||
explicit svg_transform_grammar(TransformType & tr)
|
||||
: svg_transform_grammar::base_type(start),
|
||||
matrix_action(process_matrix<TransformType>(tr)),
|
||||
rotate_action(process_rotate<TransformType>(tr)),
|
||||
translate_action(process_translate<TransformType>(tr)),
|
||||
scale_action(process_scale<TransformType>(tr)),
|
||||
skew_action(process_skew<TransformType>(tr))
|
||||
{
|
||||
using qi::_1;
|
||||
using qi::_2;
|
||||
using qi::_3;
|
||||
using qi::_4;
|
||||
using qi::_5;
|
||||
using qi::_6;
|
||||
using qi::_a;
|
||||
using qi::_b;
|
||||
using qi::_c;
|
||||
using qi::_val;
|
||||
using qi::double_;
|
||||
using qi::no_case;
|
||||
|
||||
start = +transform_ ;
|
||||
|
||||
transform_ = matrix | rotate | translate | scale | rotate | skewX | skewY ;
|
||||
|
||||
matrix = no_case[lit("matrix")]
|
||||
>> lit('(')
|
||||
>> (
|
||||
double_ >> -lit(',')
|
||||
>> double_ >> -lit(',')
|
||||
>> double_ >> -lit(',')
|
||||
>> double_ >> -lit(',')
|
||||
>> double_ >> -lit(',')
|
||||
>> double_) [ matrix_action(_1,_2,_3,_4,_5,_6) ]
|
||||
>> lit(')')
|
||||
;
|
||||
|
||||
translate = no_case[lit("translate")]
|
||||
>> lit('(')
|
||||
>> (double_ >> -lit(',')
|
||||
>> -double_) [ translate_action(_1,_2) ]
|
||||
>> lit(')');
|
||||
|
||||
scale = no_case[lit("scale")]
|
||||
>> lit('(')
|
||||
>> (double_ >> -lit(',')
|
||||
>> -double_ )[ scale_action(_1,_2)]
|
||||
>> lit(')');
|
||||
|
||||
rotate = no_case[lit("rotate")]
|
||||
>> lit('(')
|
||||
>> double_[_a = _1] >> -lit(',')
|
||||
>> -(double_ [_b = _1] >> -lit(',') >> double_[_c = _1])
|
||||
>> lit(')') [ rotate_action(_a,_b,_c)];
|
||||
|
||||
skewX = no_case[lit("skewX")] >> lit('(') >> double_ [ skew_action(_1, 0.0)] >> lit(')');
|
||||
|
||||
skewY = no_case[lit("skewY")] >> lit('(') >> double_ [ skew_action(0.0, _1)] >> lit(')');
|
||||
|
||||
}
|
||||
|
||||
// rules
|
||||
qi::rule<Iterator,SkipType> start;
|
||||
qi::rule<Iterator,SkipType> transform_;
|
||||
qi::rule<Iterator,SkipType> matrix;
|
||||
qi::rule<Iterator,SkipType> translate;
|
||||
qi::rule<Iterator,SkipType> scale;
|
||||
qi::rule<Iterator,qi::locals<double,double,double>, SkipType> rotate;
|
||||
qi::rule<Iterator,SkipType> skewX;
|
||||
qi::rule<Iterator,SkipType> skewY;
|
||||
|
||||
// actions
|
||||
function<process_matrix<TransformType> > matrix_action;
|
||||
function<process_rotate<TransformType> > rotate_action;
|
||||
function<process_translate<TransformType> > translate_action;
|
||||
function<process_scale<TransformType> > scale_action;
|
||||
function<process_skew<TransformType> > skew_action;
|
||||
};
|
||||
|
||||
}}
|
||||
|
||||
#endif // SVG_TRANSFORM_GRAMMAR_HPP
|
|
@ -38,6 +38,10 @@ regex = 'boost_regex%s' % env['BOOST_APPEND']
|
|||
|
||||
libraries = ['freetype','ltdl','png','tiff','z','jpeg','proj',env['ICU_LIB_NAME'],filesystem,regex]
|
||||
|
||||
### WARNING! temp solution.
|
||||
libraries.append('expat')
|
||||
###
|
||||
|
||||
if '-DHAVE_CAIRO' in env['CXXFLAGS']:
|
||||
# add cairo and cairomm-1.0 to libs
|
||||
libraries.append([lib for lib in env['LIBS'] if lib.startswith('cairo')])
|
||||
|
@ -110,9 +114,21 @@ source = Split(
|
|||
arrow.cpp
|
||||
unicode.cpp
|
||||
glyph_symbolizer.cpp
|
||||
"""
|
||||
"""
|
||||
)
|
||||
|
||||
|
||||
if True :
|
||||
source += Split(
|
||||
"""
|
||||
agg_svg_parser.cpp
|
||||
agg_svg_path_renderer.cpp
|
||||
svg_path_parser.cpp
|
||||
svg_points_parser.cpp
|
||||
svg_transform_parser.cpp
|
||||
"""
|
||||
)
|
||||
|
||||
if 'cairo' in env['LIBS']:
|
||||
source += Split(
|
||||
"""
|
||||
|
|
663
src/agg_svg_parser.cpp
Normal file
663
src/agg_svg_parser.cpp
Normal file
|
@ -0,0 +1,663 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG parser.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <cmath>
|
||||
#include <cstdlib>
|
||||
#include <limits.h>
|
||||
#include <expat.h>
|
||||
|
||||
#include <mapnik/svg/agg_svg_parser.h>
|
||||
#include <mapnik/svg/svg_path_parser.hpp>
|
||||
#include <mapnik/color_factory.hpp>
|
||||
#include <boost/tokenizer.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
parser::~parser()
|
||||
{
|
||||
delete [] m_attr_value;
|
||||
delete [] m_attr_name;
|
||||
delete [] m_buf;
|
||||
delete [] m_title;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
parser::parser(path_renderer& path) :
|
||||
m_path(path),
|
||||
m_buf(new char[buf_size]),
|
||||
m_title(new char[256]),
|
||||
m_title_len(0),
|
||||
m_title_flag(false),
|
||||
m_path_flag(false),
|
||||
m_attr_name(new char[128]),
|
||||
m_attr_value(new char[1024]),
|
||||
m_attr_name_len(127),
|
||||
m_attr_value_len(1023)
|
||||
{
|
||||
m_title[0] = 0;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::parse(const char* fname)
|
||||
{
|
||||
char msg[1024];
|
||||
XML_Parser p = XML_ParserCreate(NULL);
|
||||
if(p == 0)
|
||||
{
|
||||
throw std::runtime_error("Couldn't allocate memory for parser");
|
||||
}
|
||||
|
||||
XML_SetUserData(p, this);
|
||||
XML_SetElementHandler(p, start_element, end_element);
|
||||
XML_SetCharacterDataHandler(p, content);
|
||||
|
||||
FILE* fd = fopen(fname, "r");
|
||||
if(fd == 0)
|
||||
{
|
||||
sprintf(msg, "Couldn't open file %s", fname);
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
|
||||
bool done = false;
|
||||
do
|
||||
{
|
||||
size_t len = fread(m_buf, 1, buf_size, fd);
|
||||
done = len < buf_size;
|
||||
if(!XML_Parse(p, m_buf, len, done))
|
||||
{
|
||||
sprintf(msg,
|
||||
"%s at line %d\n",
|
||||
XML_ErrorString(XML_GetErrorCode(p)),
|
||||
XML_GetCurrentLineNumber(p));
|
||||
throw std::runtime_error(msg);
|
||||
}
|
||||
}
|
||||
while(!done);
|
||||
fclose(fd);
|
||||
XML_ParserFree(p);
|
||||
|
||||
char* ts = m_title;
|
||||
while(*ts)
|
||||
{
|
||||
if(*ts < ' ') *ts = ' ';
|
||||
++ts;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::start_element(void* data, const char* el, const char** attr)
|
||||
{
|
||||
parser& self = *(parser*)data;
|
||||
|
||||
if(strcmp(el, "title") == 0)
|
||||
{
|
||||
self.m_title_flag = true;
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "g") == 0)
|
||||
{
|
||||
self.m_path.push_attr();
|
||||
self.parse_attr(attr);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "path") == 0)
|
||||
{
|
||||
if(self.m_path_flag)
|
||||
{
|
||||
throw std::runtime_error("start_element: Nested path");
|
||||
}
|
||||
self.m_path.begin_path();
|
||||
self.parse_path(attr);
|
||||
self.m_path.end_path();
|
||||
self.m_path_flag = true;
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "rect") == 0)
|
||||
{
|
||||
self.parse_rect(attr);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "line") == 0)
|
||||
{
|
||||
self.parse_line(attr);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "polyline") == 0)
|
||||
{
|
||||
self.parse_poly(attr, false);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "polygon") == 0)
|
||||
{
|
||||
self.parse_poly(attr, true);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "circle") == 0)
|
||||
{
|
||||
self.parse_circle(attr);
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "ellipse") == 0)
|
||||
{
|
||||
self.parse_ellipse(attr);
|
||||
}
|
||||
//else
|
||||
//if(strcmp(el, "<OTHER_ELEMENTS>") == 0)
|
||||
//{
|
||||
//}
|
||||
// . . .
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::end_element(void* data, const char* el)
|
||||
{
|
||||
parser& self = *(parser*)data;
|
||||
|
||||
if(strcmp(el, "title") == 0)
|
||||
{
|
||||
self.m_title_flag = false;
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "g") == 0)
|
||||
{
|
||||
self.m_path.pop_attr();
|
||||
}
|
||||
else
|
||||
if(strcmp(el, "path") == 0)
|
||||
{
|
||||
self.m_path_flag = false;
|
||||
}
|
||||
//else
|
||||
//if(strcmp(el, "<OTHER_ELEMENTS>") == 0)
|
||||
//{
|
||||
//}
|
||||
// . . .
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::content(void* data, const char* s, int len)
|
||||
{
|
||||
parser& self = *(parser*)data;
|
||||
|
||||
// m_title_flag signals that the <title> tag is being parsed now.
|
||||
// The following code concatenates the pieces of content of the <title> tag.
|
||||
if(self.m_title_flag)
|
||||
{
|
||||
if(len + self.m_title_len > 255) len = 255 - self.m_title_len;
|
||||
if(len > 0)
|
||||
{
|
||||
memcpy(self.m_title + self.m_title_len, s, len);
|
||||
self.m_title_len += len;
|
||||
self.m_title[self.m_title_len] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void parser::parse_attr(const char** attr)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(strcmp(attr[i], "style") == 0)
|
||||
{
|
||||
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
boost::char_separator<char> sep(";");
|
||||
std::string str(attr[i+1]);
|
||||
std::cerr << str << std::endl;
|
||||
tokenizer tok(str,sep);
|
||||
for (tokenizer::iterator tok_iter = tok.begin();
|
||||
tok_iter != tok.end(); ++tok_iter)
|
||||
{
|
||||
parse_style(tok_iter->c_str());
|
||||
}
|
||||
//parse_style(attr[i+1]);
|
||||
}
|
||||
else
|
||||
{
|
||||
parse_attr(attr[i], attr[i + 1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_path(const char** attr)
|
||||
{
|
||||
|
||||
int i;
|
||||
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
// The <path> tag can consist of the path itself ("d=")
|
||||
// as well as of other parameters like "style=", "transform=", etc.
|
||||
// In the last case we simply rely on the function of parsing
|
||||
// attributes (see 'else' branch).
|
||||
if(strcmp(attr[i], "d") == 0)
|
||||
{
|
||||
std::string wkt(attr[i+1]);
|
||||
if (!mapnik::svg::parse_path(wkt, m_path))
|
||||
{
|
||||
std::runtime_error("can't parse PATH\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Create a temporary single pair "name-value" in order
|
||||
// to avoid multiple calls for the same attribute.
|
||||
const char* tmp[4];
|
||||
tmp[0] = attr[i];
|
||||
tmp[1] = attr[i + 1];
|
||||
tmp[2] = 0;
|
||||
tmp[3] = 0;
|
||||
parse_attr(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
rgba8 parse_color(const char* str)
|
||||
{
|
||||
mapnik::color c(100,100,100);
|
||||
try
|
||||
{
|
||||
mapnik::color_factory::init_from_string(c,str);
|
||||
}
|
||||
catch (mapnik::config_error & ex)
|
||||
{
|
||||
std::cerr << ex.what() << std::endl;
|
||||
}
|
||||
return rgba8(c.red(), c.green(), c.blue(), c.alpha());
|
||||
}
|
||||
|
||||
double parse_double(const char* str)
|
||||
{
|
||||
while(*str == ' ') ++str;
|
||||
return atof(str);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
bool parser::parse_attr(const char* name, const char* value)
|
||||
{
|
||||
if(strcmp(name, "style") == 0)
|
||||
{
|
||||
typedef boost::tokenizer<boost::char_separator<char> > tokenizer;
|
||||
boost::char_separator<char> sep(";");
|
||||
std::string str(value);
|
||||
std::cerr << str << std::endl;
|
||||
tokenizer tok(str,sep);
|
||||
for (tokenizer::iterator tok_iter = tok.begin();
|
||||
tok_iter != tok.end(); ++tok_iter)
|
||||
{
|
||||
parse_style(tok_iter->c_str());
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "fill") == 0)
|
||||
{
|
||||
if(strcmp(value, "none") == 0)
|
||||
{
|
||||
m_path.fill_none();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path.fill(parse_color(value));
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "fill-opacity") == 0)
|
||||
{
|
||||
m_path.fill_opacity(parse_double(value));
|
||||
}
|
||||
else if(strcmp(name, "stroke") == 0)
|
||||
{
|
||||
if(strcmp(value, "none") == 0)
|
||||
{
|
||||
m_path.stroke_none();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path.stroke(parse_color(value));
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "fill-rule") == 0)
|
||||
{
|
||||
if (strcmp(value, "evenodd") == 0)
|
||||
{
|
||||
m_path.even_odd(true);
|
||||
}
|
||||
}
|
||||
else if(strcmp(name, "stroke-width") == 0)
|
||||
{
|
||||
m_path.stroke_width(parse_double(value));
|
||||
}
|
||||
else if(strcmp(name, "stroke-linecap") == 0)
|
||||
{
|
||||
if(strcmp(value, "butt") == 0) m_path.line_cap(butt_cap);
|
||||
else if(strcmp(value, "round") == 0) m_path.line_cap(round_cap);
|
||||
else if(strcmp(value, "square") == 0) m_path.line_cap(square_cap);
|
||||
}
|
||||
else
|
||||
if(strcmp(name, "stroke-linejoin") == 0)
|
||||
{
|
||||
if(strcmp(value, "miter") == 0) m_path.line_join(miter_join);
|
||||
else if(strcmp(value, "round") == 0) m_path.line_join(round_join);
|
||||
else if(strcmp(value, "bevel") == 0) m_path.line_join(bevel_join);
|
||||
}
|
||||
else if(strcmp(name, "stroke-miterlimit") == 0)
|
||||
{
|
||||
m_path.miter_limit(parse_double(value));
|
||||
}
|
||||
else if(strcmp(name, "stroke-opacity") == 0)
|
||||
{
|
||||
m_path.stroke_opacity(parse_double(value));
|
||||
}
|
||||
else if(strcmp(name, "transform") == 0)
|
||||
{
|
||||
agg::trans_affine tr;
|
||||
mapnik::svg::parse_transform(value,tr);
|
||||
m_path.transform().premultiply(tr);
|
||||
}
|
||||
else if(strcmp(name,"opacity") == 0)
|
||||
{
|
||||
double opacity = parse_double(value);
|
||||
m_path.stroke_opacity(opacity);
|
||||
m_path.fill_opacity(opacity);
|
||||
}
|
||||
//else
|
||||
//if(strcmp(el, "<OTHER_ATTRIBUTES>") == 0)
|
||||
//{
|
||||
//}
|
||||
// . . .
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::copy_name(const char* start, const char* end)
|
||||
{
|
||||
unsigned len = unsigned(end - start);
|
||||
if(m_attr_name_len == 0 || len > m_attr_name_len)
|
||||
{
|
||||
delete [] m_attr_name;
|
||||
m_attr_name = new char[len + 1];
|
||||
m_attr_name_len = len;
|
||||
}
|
||||
if(len) memcpy(m_attr_name, start, len);
|
||||
m_attr_name[len] = 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::copy_value(const char* start, const char* end)
|
||||
{
|
||||
unsigned len = unsigned(end - start);
|
||||
if(m_attr_value_len == 0 || len > m_attr_value_len)
|
||||
{
|
||||
delete [] m_attr_value;
|
||||
m_attr_value = new char[len + 1];
|
||||
m_attr_value_len = len;
|
||||
}
|
||||
if(len) memcpy(m_attr_value, start, len);
|
||||
m_attr_value[len] = 0;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
bool parser::parse_name_value(const char* nv_start, const char* nv_end)
|
||||
{
|
||||
const char* str = nv_start;
|
||||
while(str < nv_end && *str != ':') ++str;
|
||||
|
||||
const char* val = str;
|
||||
|
||||
// Right Trim
|
||||
while(str > nv_start &&
|
||||
(*str == ':' || isspace(*str))) --str;
|
||||
++str;
|
||||
|
||||
copy_name(nv_start, str);
|
||||
|
||||
while(val < nv_end && (*val == ':' || isspace(*val))) ++val;
|
||||
|
||||
copy_value(val, nv_end);
|
||||
|
||||
return parse_attr(m_attr_name, m_attr_value);
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_style(const char* str)
|
||||
{
|
||||
while(*str)
|
||||
{
|
||||
// Left Trim
|
||||
while(*str && isspace(*str)) ++str;
|
||||
const char* nv_start = str;
|
||||
while(*str && *str != ';') ++str;
|
||||
const char* nv_end = str;
|
||||
|
||||
// Right Trim
|
||||
while(nv_end > nv_start &&
|
||||
(*nv_end == ';' || isspace(*nv_end))) --nv_end;
|
||||
++nv_end;
|
||||
|
||||
parse_name_value(nv_start, nv_end);
|
||||
if(*str) ++str;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_rect(const char** attr)
|
||||
{
|
||||
int i;
|
||||
double x = 0.0;
|
||||
double y = 0.0;
|
||||
double w = 0.0;
|
||||
double h = 0.0;
|
||||
double rx = 0.0;
|
||||
double ry = 0.0;
|
||||
|
||||
m_path.begin_path();
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(!parse_attr(attr[i], attr[i + 1]))
|
||||
{
|
||||
if(strcmp(attr[i], "x") == 0) x = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "y") == 0) y = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "width") == 0) w = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "height") == 0) h = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "rx") == 0) rx = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "ry") == 0) ry = parse_double(attr[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(w != 0.0 && h != 0.0)
|
||||
{
|
||||
if(w < 0.0) throw std::runtime_error("parse_rect: Invalid width: %f");//, w);
|
||||
if(h < 0.0) throw std::runtime_error("parse_rect: Invalid height: %f");//, h);
|
||||
if(rx < 0.0) throw std::runtime_error("parse_rect: Invalid rx: %f");//, rx);
|
||||
if(ry < 0.0) throw std::runtime_error("parse_rect: Invalid ry: %f");// ry);
|
||||
|
||||
if(rx > 0.0 && ry > 0.0)
|
||||
{
|
||||
m_path.move_to(x + rx,y);
|
||||
m_path.line_to(x + w -rx,y);
|
||||
m_path.arc_to (rx,ry,0,0,1,x + w, y + ry);
|
||||
m_path.line_to(x + w, y + h - ry);
|
||||
m_path.arc_to (rx,ry,0,0,1,x + w - rx, y + h);
|
||||
m_path.line_to(x + rx, y + h);
|
||||
m_path.arc_to(rx,ry,0,0,1,x,y + h - ry);
|
||||
m_path.line_to(x,y+ry);
|
||||
m_path.arc_to(rx,ry,0,0,1,x + rx,y);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_path.move_to(x, y);
|
||||
m_path.line_to(x + w, y);
|
||||
m_path.line_to(x + w, y + h);
|
||||
m_path.line_to(x, y + h);
|
||||
m_path.close_subpath();
|
||||
}
|
||||
}
|
||||
m_path.end_path();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_circle(const char** attr)
|
||||
{
|
||||
int i;
|
||||
double cx = 0.0;
|
||||
double cy = 0.0;
|
||||
double r = 0.0;
|
||||
|
||||
m_path.begin_path();
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(!parse_attr(attr[i], attr[i + 1]))
|
||||
{
|
||||
if(strcmp(attr[i], "cx") == 0) cx = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "cy") == 0) cy = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "r") == 0) r = parse_double(attr[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if(r != 0.0)
|
||||
{
|
||||
if(r < 0.0) throw std::runtime_error("parse_cirle: Invalid radius: %f");// r);
|
||||
m_path.move_to(cx+r,cy);
|
||||
m_path.arc_to(r,r,0,1,0,cx-r,cy);
|
||||
m_path.arc_to(r,r,0,1,0,cx+r,cy);
|
||||
}
|
||||
m_path.end_path();
|
||||
}
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_ellipse(const char** attr)
|
||||
{
|
||||
double cx = 0.0;
|
||||
double cy = 0.0;
|
||||
double rx = 0.0;
|
||||
double ry = 0.0;
|
||||
|
||||
m_path.begin_path();
|
||||
for(int i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(!parse_attr(attr[i], attr[i + 1]))
|
||||
{
|
||||
if(strcmp(attr[i], "cx") == 0) cx = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "cy") == 0) cy = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "rx") == 0) rx = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "ry") == 0) ry = parse_double(attr[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
if(rx != 0.0 && ry != 0.0)
|
||||
{
|
||||
if(rx < 0.0) throw std::runtime_error("parse_cirle: Invalid rx: %f");
|
||||
if(ry < 0.0) throw std::runtime_error("parse_cirle: Invalid ry: %f");
|
||||
m_path.move_to(cx+rx,cy);
|
||||
m_path.arc_to(rx,ry,0,1,0,cx-rx,cy);
|
||||
m_path.arc_to(rx,ry,0,1,0,cx+rx,cy);
|
||||
}
|
||||
m_path.end_path();
|
||||
}
|
||||
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_line(const char** attr)
|
||||
{
|
||||
int i;
|
||||
double x1 = 0.0;
|
||||
double y1 = 0.0;
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
|
||||
m_path.begin_path();
|
||||
for(i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(!parse_attr(attr[i], attr[i + 1]))
|
||||
{
|
||||
if(strcmp(attr[i], "x1") == 0) x1 = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "y1") == 0) y1 = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "x2") == 0) x2 = parse_double(attr[i + 1]);
|
||||
if(strcmp(attr[i], "y2") == 0) y2 = parse_double(attr[i + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
m_path.move_to(x1, y1);
|
||||
m_path.line_to(x2, y2);
|
||||
m_path.end_path();
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------------------
|
||||
void parser::parse_poly(const char** attr, bool close_flag)
|
||||
{
|
||||
m_path.begin_path();
|
||||
for(int i = 0; attr[i]; i += 2)
|
||||
{
|
||||
if(!parse_attr(attr[i], attr[i + 1]))
|
||||
{
|
||||
if(strcmp(attr[i], "points") == 0)
|
||||
{
|
||||
if (!mapnik::svg::parse_points(attr[i+1], m_path))
|
||||
{
|
||||
throw std::runtime_error("can't parse POINTS\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if(close_flag)
|
||||
{
|
||||
m_path.close_subpath();
|
||||
}
|
||||
m_path.end_path();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
300
src/agg_svg_path_renderer.cpp
Normal file
300
src/agg_svg_path_renderer.cpp
Normal file
|
@ -0,0 +1,300 @@
|
|||
//----------------------------------------------------------------------------
|
||||
// Anti-Grain Geometry - Version 2.3
|
||||
// Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com)
|
||||
//
|
||||
// Permission to copy, use, modify, sell and distribute this software
|
||||
// is granted provided this copyright notice appears in all copies.
|
||||
// This software is provided "as is" without express or implied
|
||||
// warranty, and with no claim as to its suitability for any purpose.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
// Contact: mcseem@antigrain.com
|
||||
// mcseemagg@yahoo.com
|
||||
// http://www.antigrain.com
|
||||
//----------------------------------------------------------------------------
|
||||
//
|
||||
// SVG path renderer.
|
||||
//
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdexcept>
|
||||
#include <mapnik/svg/agg_svg_path_renderer.h>
|
||||
|
||||
namespace agg
|
||||
{
|
||||
namespace svg
|
||||
{
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
path_renderer::path_renderer() :
|
||||
m_curved(m_storage),
|
||||
m_curved_count(m_curved),
|
||||
|
||||
m_curved_stroked(m_curved_count),
|
||||
m_curved_stroked_trans(m_curved_stroked, m_transform),
|
||||
|
||||
m_curved_trans(m_curved_count, m_transform),
|
||||
m_curved_trans_contour(m_curved_trans)
|
||||
{
|
||||
m_curved_trans_contour.auto_detect_orientation(false);
|
||||
}
|
||||
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::remove_all()
|
||||
{
|
||||
m_storage.remove_all();
|
||||
m_attr_storage.remove_all();
|
||||
m_attr_stack.remove_all();
|
||||
m_transform.reset();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::begin_path()
|
||||
{
|
||||
push_attr();
|
||||
unsigned idx = m_storage.start_new_path();
|
||||
m_attr_storage.add(path_attributes(cur_attr(), idx));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::end_path()
|
||||
{
|
||||
if(m_attr_storage.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("end_path : The path was not begun");
|
||||
}
|
||||
path_attributes attr = cur_attr();
|
||||
unsigned idx = m_attr_storage[m_attr_storage.size() - 1].index;
|
||||
attr.index = idx;
|
||||
m_attr_storage[m_attr_storage.size() - 1] = attr;
|
||||
pop_attr();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::move_to(double x, double y, bool rel) // M, m
|
||||
{
|
||||
if(rel) m_storage.rel_to_abs(&x, &y);
|
||||
m_storage.move_to(x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::line_to(double x, double y, bool rel) // L, l
|
||||
{
|
||||
if(rel) m_storage.rel_to_abs(&x, &y);
|
||||
m_storage.line_to(x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::hline_to(double x, bool rel) // H, h
|
||||
{
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
if(m_storage.total_vertices())
|
||||
{
|
||||
m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2);
|
||||
if(rel) x += x2;
|
||||
m_storage.line_to(x, y2);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::vline_to(double y, bool rel) // V, v
|
||||
{
|
||||
double x2 = 0.0;
|
||||
double y2 = 0.0;
|
||||
if(m_storage.total_vertices())
|
||||
{
|
||||
m_storage.vertex(m_storage.total_vertices() - 1, &x2, &y2);
|
||||
if(rel) y += y2;
|
||||
m_storage.line_to(x2, y);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::curve3(double x1, double y1, // Q, q
|
||||
double x, double y, bool rel)
|
||||
{
|
||||
if(rel)
|
||||
{
|
||||
m_storage.rel_to_abs(&x1, &y1);
|
||||
m_storage.rel_to_abs(&x, &y);
|
||||
}
|
||||
m_storage.curve3(x1, y1, x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::curve3(double x, double y, bool rel) // T, t
|
||||
{
|
||||
// throw std::runtime_error("curve3(x, y) : NOT IMPLEMENTED YET");
|
||||
if(rel)
|
||||
{
|
||||
m_storage.curve3_rel(x, y);
|
||||
} else
|
||||
{
|
||||
m_storage.curve3(x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::curve4(double x1, double y1, // C, c
|
||||
double x2, double y2,
|
||||
double x, double y, bool rel)
|
||||
{
|
||||
if(rel)
|
||||
{
|
||||
m_storage.rel_to_abs(&x1, &y1);
|
||||
m_storage.rel_to_abs(&x2, &y2);
|
||||
m_storage.rel_to_abs(&x, &y);
|
||||
}
|
||||
m_storage.curve4(x1, y1, x2, y2, x, y);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::curve4(double x2, double y2, // S, s
|
||||
double x, double y, bool rel)
|
||||
{
|
||||
//throw std::runtime_error("curve4(x2, y2, x, y) : NOT IMPLEMENTED YET");
|
||||
if(rel)
|
||||
{
|
||||
m_storage.curve4_rel(x2, y2, x, y);
|
||||
} else
|
||||
{
|
||||
m_storage.curve4(x2, y2, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::arc_to(double rx, double ry, // A, a
|
||||
double angle,
|
||||
bool large_arc_flag,
|
||||
bool sweep_flag,
|
||||
double x, double y,
|
||||
bool rel)
|
||||
{
|
||||
if(rel)
|
||||
{
|
||||
m_storage.arc_rel(rx, ry, angle, large_arc_flag, sweep_flag, x, y);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_storage.arc_to(rx, ry, angle, large_arc_flag, sweep_flag, x, y);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::close_subpath()
|
||||
{
|
||||
m_storage.end_poly(path_flags_close);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
path_attributes& path_renderer::cur_attr()
|
||||
{
|
||||
if(m_attr_stack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("cur_attr : Attribute stack is empty");
|
||||
}
|
||||
return m_attr_stack[m_attr_stack.size() - 1];
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::push_attr()
|
||||
{
|
||||
m_attr_stack.add(m_attr_stack.size() ?
|
||||
m_attr_stack[m_attr_stack.size() - 1] :
|
||||
path_attributes());
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::pop_attr()
|
||||
{
|
||||
if(m_attr_stack.size() == 0)
|
||||
{
|
||||
throw std::runtime_error("pop_attr : Attribute stack is empty");
|
||||
}
|
||||
m_attr_stack.remove_last();
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::fill(const rgba8& f)
|
||||
{
|
||||
path_attributes& attr = cur_attr();
|
||||
attr.fill_color = f;
|
||||
attr.fill_flag = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::stroke(const rgba8& s)
|
||||
{
|
||||
path_attributes& attr = cur_attr();
|
||||
attr.stroke_color = s;
|
||||
attr.stroke_flag = true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::even_odd(bool flag)
|
||||
{
|
||||
cur_attr().even_odd_flag = flag;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::stroke_width(double w)
|
||||
{
|
||||
cur_attr().stroke_width = w;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::fill_none()
|
||||
{
|
||||
cur_attr().fill_flag = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::stroke_none()
|
||||
{
|
||||
cur_attr().stroke_flag = false;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::fill_opacity(double op)
|
||||
{
|
||||
cur_attr().fill_color.opacity(op);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::stroke_opacity(double op)
|
||||
{
|
||||
cur_attr().stroke_color.opacity(op);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::line_join(line_join_e join)
|
||||
{
|
||||
cur_attr().line_join = join;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::line_cap(line_cap_e cap)
|
||||
{
|
||||
cur_attr().line_cap = cap;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
void path_renderer::miter_limit(double ml)
|
||||
{
|
||||
cur_attr().miter_limit = ml;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------
|
||||
trans_affine& path_renderer::transform()
|
||||
{
|
||||
return cur_attr().transform;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
47
src/svg_path_parser.cpp
Normal file
47
src/svg_path_parser.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2010 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/svg/svg_path_parser.hpp>
|
||||
#include <mapnik/svg/svg_path_grammar.hpp>
|
||||
// agg
|
||||
#include <mapnik/svg/agg_svg_path_renderer.h>
|
||||
// stl
|
||||
#include <string>
|
||||
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
template <typename PathType>
|
||||
bool parse_path(std::string const& wkt, PathType & p)
|
||||
{
|
||||
using namespace boost::spirit;
|
||||
typedef std::string::const_iterator iterator_type;
|
||||
typedef ascii::space_type skip_type;
|
||||
svg_path_grammar<iterator_type,skip_type,PathType> g(p);
|
||||
iterator_type first = wkt.begin();
|
||||
iterator_type last = wkt.end();
|
||||
return qi::phrase_parse(first, last, g, skip_type());
|
||||
}
|
||||
|
||||
template bool parse_path<agg::svg::path_renderer>(std::string const&, agg::svg::path_renderer&) ;
|
||||
|
||||
}}
|
47
src/svg_points_parser.cpp
Normal file
47
src/svg_points_parser.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2010 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/svg/svg_path_parser.hpp>
|
||||
#include <mapnik/svg/svg_points_grammar.hpp>
|
||||
// agg
|
||||
#include <mapnik/svg/agg_svg_path_renderer.h>
|
||||
// stl
|
||||
#include <string>
|
||||
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
template <typename PathType>
|
||||
bool parse_points(std::string const& wkt, PathType & p)
|
||||
{
|
||||
using namespace boost::spirit;
|
||||
typedef std::string::const_iterator iterator_type;
|
||||
typedef ascii::space_type skip_type;
|
||||
svg_points_grammar<iterator_type,skip_type,PathType> g(p);
|
||||
iterator_type first = wkt.begin();
|
||||
iterator_type last = wkt.end();
|
||||
return qi::phrase_parse(first, last, g, skip_type());
|
||||
}
|
||||
|
||||
template bool parse_points<agg::svg::path_renderer>(std::string const&, agg::svg::path_renderer&);
|
||||
|
||||
}}
|
47
src/svg_transform_parser.cpp
Normal file
47
src/svg_transform_parser.cpp
Normal file
|
@ -0,0 +1,47 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2010 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
|
||||
*
|
||||
*****************************************************************************/
|
||||
|
||||
// mapnik
|
||||
#include <mapnik/svg/svg_path_parser.hpp>
|
||||
#include <mapnik/svg/svg_transform_grammar.hpp>
|
||||
// agg
|
||||
#include "agg_trans_affine.h"
|
||||
// stl
|
||||
#include <string>
|
||||
|
||||
namespace mapnik { namespace svg {
|
||||
|
||||
template <typename TransformType>
|
||||
bool parse_transform(std::string const& wkt, TransformType & p)
|
||||
{
|
||||
using namespace boost::spirit;
|
||||
typedef std::string::const_iterator iterator_type;
|
||||
typedef ascii::space_type skip_type;
|
||||
svg_transform_grammar<iterator_type,skip_type,TransformType> g(p);
|
||||
iterator_type first = wkt.begin();
|
||||
iterator_type last = wkt.end();
|
||||
return qi::phrase_parse(first, last, g, skip_type());
|
||||
}
|
||||
|
||||
template bool parse_transform<agg::trans_affine>(std::string const&, agg::trans_affine&);
|
||||
|
||||
}}
|
Loading…
Add table
Reference in a new issue