Merge pull request #2222 from mapnik/expr-v2

Expr v2
This commit is contained in:
Dane Springmeyer 2014-04-24 23:16:27 -07:00
commit 169e7ee4b6
479 changed files with 14510 additions and 9397 deletions

View file

@ -400,6 +400,7 @@ opts.AddVariables(
BoolVariable('PGSQL2SQLITE', 'Compile and install a utility to convert postgres tables to sqlite', 'False'),
BoolVariable('SHAPEINDEX', 'Compile and install a utility to generate shapefile indexes in the custom format (.index) Mapnik supports', 'True'),
BoolVariable('SVG2PNG', 'Compile and install a utility to generate render an svg file to a png on the command line', 'False'),
BoolVariable('NIK2IMG', 'Compile and install a utility to generate render a map to an image', 'True'),
BoolVariable('COLOR_PRINT', 'Print build status information in color', 'True'),
BoolVariable('SAMPLE_INPUT_PLUGINS', 'Compile and install sample plugins', 'False'),
BoolVariable('BIGINT', 'Compile support for 64-bit integers in mapnik::value', 'True'),
@ -1218,6 +1219,7 @@ if not preconfigured:
temp_env = env.Clone()
temp_env['LIBS'] = []
try:
# TODO - freetype-config accepts --static as of v2.5.3
temp_env.ParseConfig('%s --libs' % env['FREETYPE_CONFIG'])
if 'bz2' in temp_env['LIBS']:
env['EXTRA_FREETYPE_LIBS'].append('bz2')
@ -1981,6 +1983,8 @@ if not HELP_REQUESTED:
SConscript('utils/pgsql2sqlite/build.py')
if env['SVG2PNG']:
SConscript('utils/svg2png/build.py')
if env['NIK2IMG']:
SConscript('utils/nik2img/build.py')
# devtools not ready for public
#SConscript('utils/ogrindex/build.py')
env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])

View file

@ -285,11 +285,15 @@ class _Color(Color,_injector):
def __repr__(self):
return "Color(R=%d,G=%d,B=%d,A=%d)" % (self.r,self.g,self.b,self.a)
class _Symbolizers(Symbolizers,_injector):
class _SymbolizerBase(SymbolizerBase,_injector):
# back compatibility
@property
def filename(self):
return self['file']
def __getitem__(self, idx):
sym = Symbolizers._c___getitem__(self, idx)
return sym.symbol()
@filename.setter
def filename(self, val):
self['file'] = val
def _add_symbol_method_to_symbolizers(vars=globals()):

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
* Copyright (C) 2013 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -20,19 +20,26 @@
*
*****************************************************************************/
#ifndef MAPNIK_BINDINGS_PYTHON_ENUMERATION_WRAPPPER
#define MAPNIK_BINDINGS_PYTHON_ENUMERATION_WRAPPPER
// mapnik
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/symbolizer.hpp>
namespace mapnik
// boost
#include <boost/python.hpp>
namespace boost { namespace python {
struct mapnik_enumeration_wrapper_to_python
{
static const char * line_rasterizer_strings[] = {
"full",
"fast",
""
};
IMPLEMENT_ENUM( line_rasterizer_e, line_rasterizer_strings )
static PyObject* convert(mapnik::enumeration_wrapper const& v)
{
return ::PyLong_FromLongLong(v.value); // FIXME: this is a temp hack!!
}
};
}}
#endif // MAPNIK_BINDINGS_PYTHON_ENUMERATION_WRAPPPER

View file

@ -23,8 +23,6 @@
#include "boost_std_shared_shim.hpp"
// boost
#include <boost/python/suite/indexing/indexing_suite.hpp>
//#include <boost/python/suite/indexing/map_indexing_suite.hpp>
#include <boost/python/iterator.hpp>
#include <boost/python/call_method.hpp>
#include <boost/python/tuple.hpp>

View file

@ -58,7 +58,6 @@ void export_python();
void export_expression();
void export_rule();
void export_style();
void export_stroke();
void export_feature();
void export_featureset();
void export_fontset();
@ -76,6 +75,7 @@ void export_raster_symbolizer();
void export_text_placement();
void export_shield_symbolizer();
void export_debug_symbolizer();
void export_group_symbolizer();
void export_font_engine();
void export_projection();
void export_proj_transform();
@ -99,6 +99,7 @@ void export_wkt_reader();
#include "python_grid_utils.hpp"
#endif
#include "mapnik_value_converter.hpp"
#include "mapnik_enumeration_wrapper_converter.hpp"
#include "mapnik_threads.hpp"
#include "python_optional.hpp"
#include <mapnik/marker_cache.hpp>
@ -108,7 +109,6 @@ void export_wkt_reader();
namespace mapnik {
class font_set;
class stroke;
class layer;
class color;
class label_collision_detector4;
@ -565,7 +565,6 @@ BOOST_PYTHON_MODULE(_mapnik)
export_rule();
export_style();
export_layer();
export_stroke();
export_datasource_cache();
export_symbolizer();
export_markers_symbolizer();
@ -579,6 +578,7 @@ BOOST_PYTHON_MODULE(_mapnik)
export_text_placement();
export_shield_symbolizer();
export_debug_symbolizer();
export_group_symbolizer();
export_font_engine();
export_projection();
export_proj_transform();
@ -599,17 +599,6 @@ BOOST_PYTHON_MODULE(_mapnik)
">>> clear_cache()\n"
);
#if defined(GRID_RENDERER)
def("render_grid",&mapnik::render_grid,
( arg("map"),
arg("layer"),
args("key")="__id__",
arg("resolution")=4,
arg("fields")=boost::python::list()
)
);
#endif
def("render_to_file",&render_to_file1,
"\n"
"Render Map to file using explicit image type.\n"
@ -860,12 +849,10 @@ BOOST_PYTHON_MODULE(_mapnik)
def("has_png", &has_png, "Get png read/write support status");
def("has_tiff", &has_tiff, "Get tiff read/write support status");
def("has_webp", &has_webp, "Get webp read/write support status");
def("has_svg_renderer", &has_svg_renderer, "Get svg_renderer status");
def("has_grid_renderer", &has_grid_renderer, "Get grid_renderer status");
def("has_cairo", &has_cairo, "Get cairo library status");
def("has_pycairo", &has_pycairo, "Get pycairo module status");
python_optional<mapnik::stroke>();
python_optional<mapnik::font_set>();
python_optional<mapnik::color>();
python_optional<mapnik::box2d<double> >();
@ -882,4 +869,5 @@ BOOST_PYTHON_MODULE(_mapnik)
register_ptr_to_python<mapnik::path_expression_ptr>();
to_python_converter<mapnik::value_holder,mapnik_param_to_python>();
to_python_converter<mapnik::value,mapnik_value_to_python>();
to_python_converter<mapnik::enumeration_wrapper,mapnik_enumeration_wrapper_to_python>();
}

View file

@ -28,9 +28,11 @@
// mapnik
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/symbolizer.hpp>
using mapnik::raster_colorizer;
using mapnik::raster_colorizer_ptr;
using mapnik::symbolizer_base;
using mapnik::colorizer_stop;
using mapnik::colorizer_stops;
using mapnik::colorizer_mode_enum;
@ -81,6 +83,8 @@ void export_raster_colorizer()
{
using namespace boost::python;
implicitly_convertible<raster_colorizer_ptr, mapnik::symbolizer_base::value_type>();
class_<raster_colorizer,raster_colorizer_ptr>("RasterColorizer",
"A Raster Colorizer object.",
init<colorizer_mode_enum, color>(args("default_mode","default_color"))

View file

@ -45,6 +45,7 @@ using mapnik::shield_symbolizer;
using mapnik::text_symbolizer;
using mapnik::building_symbolizer;
using mapnik::markers_symbolizer;
using mapnik::group_symbolizer;
using mapnik::symbolizer;
using mapnik::to_expression_string;
@ -61,6 +62,7 @@ void export_rule()
implicitly_convertible<shield_symbolizer,symbolizer>();
implicitly_convertible<text_symbolizer,symbolizer>();
implicitly_convertible<markers_symbolizer,symbolizer>();
implicitly_convertible<group_symbolizer,symbolizer>();
class_<rule::symbolizers>("Symbolizers",init<>("TODO"))
.def(vector_indexing_suite<rule::symbolizers>())

View file

@ -1,154 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c+mapping toolkit)
*
* Copyright (C) 2006 Artem Pavlenko, Jean-Francois Doyon
*
* 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
*
*****************************************************************************/
#include "boost_std_shared_shim.hpp"
// boost
#include <boost/python.hpp>
// mapnik
#include <mapnik/stroke.hpp>
#include "mapnik_enumeration.hpp"
using namespace mapnik;
namespace {
using namespace boost::python;
list get_dashes_list(stroke const& stroke)
{
list l;
if (stroke.has_dash()) {
mapnik::dash_array const& dash = stroke.get_dash_array();
mapnik::dash_array::const_iterator iter = dash.begin();
mapnik::dash_array::const_iterator end = dash.end();
for (; iter != end; ++iter) {
l.append(make_tuple(iter->first, iter->second));
}
}
return l;
}
void set_dasharray(stroke & stroke, list const& l)
{
for (int i=0; i<len(l); ++i)
{
boost::python::tuple dash = extract<boost::python::tuple>(l[i]);
if (len(dash) == 2)
{
double d1 = extract<double>(dash[0]);
double d2 = extract<double>(dash[1]);
stroke.add_dash(d1,d2);
}
}
}
}
void export_stroke ()
{
using namespace boost::python;
enumeration_<line_cap_e>("line_cap",
"The possible values for a line cap used when drawing\n"
"with a stroke.\n")
.value("BUTT_CAP",BUTT_CAP)
.value("SQUARE_CAP",SQUARE_CAP)
.value("ROUND_CAP",ROUND_CAP)
;
enumeration_<line_join_e>("line_join",
"The possible values for the line joining mode\n"
"when drawing with a stroke.\n")
.value("MITER_JOIN",MITER_JOIN)
.value("MITER_REVERT_JOIN",MITER_REVERT_JOIN)
.value("ROUND_JOIN",ROUND_JOIN)
.value("BEVEL_JOIN",BEVEL_JOIN)
;
class_<stroke>("Stroke",init<>(
"Creates a new default black stroke with the width of 1.\n"))
.def(init<color,float>(
(arg("color"),arg("width")),
"Creates a new stroke object with a specified color and width.\n")
)
.add_property("color",make_function
(&stroke::get_color,return_value_policy<copy_const_reference>()),
&stroke::set_color,
"Gets or sets the stroke color.\n"
"Returns a new Color object on retrieval.\n")
.add_property("width",
&stroke::get_width,
&stroke::set_width,
"Gets or sets the stroke width in pixels.\n")
.add_property("opacity",
&stroke::get_opacity,
&stroke::set_opacity,
"Gets or sets the opacity of this stroke.\n"
"The value is a float between 0 and 1.\n")
.add_property("gamma",
&stroke::get_gamma,
&stroke::set_gamma,
"Gets or sets the gamma of this stroke.\n"
"The value is a float between 0 and 1.\n")
.add_property("gamma_method",
&stroke::get_gamma_method,
&stroke::set_gamma_method,
"Set/get the gamma correction method of this stroke")
.add_property("line_cap",
&stroke::get_line_cap,
&stroke::set_line_cap,
"Gets or sets the line cap of this stroke. (alias of linecap)\n")
.add_property("linecap",
&stroke::get_line_cap,
&stroke::set_line_cap,
"Gets or sets the linecap of this stroke.\n")
.add_property("line_join",
&stroke::get_line_join,
&stroke::set_line_join,
"Returns the line join mode of this stroke. (alias of linejoin)\n")
.add_property("linejoin",
&stroke::get_line_join,
&stroke::set_line_join,
"Returns the linejoin mode of this stroke.\n")
.add_property("miterlimit",
&stroke::get_miterlimit,
&stroke::set_miterlimit,
"Returns the miterlimit mode of this stroke.\n")
.def("add_dash",&stroke::add_dash,
(arg("length"),arg("gap")),
"Adds a dash segment to the dash patterns of this stroke.\n")
.def("get_dashes", get_dashes_list,
"Returns the list of dash segments for this stroke.\n")
.add_property("dasharray",
get_dashes_list,
set_dasharray,
"Gets or sets dasharray string of this stroke. (alternate property to add_dash/get_dashes)\n")
.add_property("dash_offset",
&stroke::dash_offset,
&stroke::set_dash_offset,
"Gets or sets dash offset of this stroke. (alias of dashoffet)\n")
.add_property("dashoffset",
&stroke::dash_offset,
&stroke::set_dash_offset,
"Gets or sets dash offset of this stroke.\n")
;
}

View file

@ -20,23 +20,23 @@
*
*****************************************************************************/
#include "boost_std_shared_shim.hpp"
/* The functions in this file produce deprecation warnings.
* But as shield symbolizer doesn't fully support more than one
* placement from python yet these functions are actually the
* correct ones.
*/
#include "boost_std_shared_shim.hpp" // FIXME - do we need it?
// The functions in this file produce deprecation warnings.
// But as shield symbolizer doesn't fully support more than one
// placement from python yet these functions are actually the
// correct ones.
#define NO_DEPRECATION_WARNINGS
// boost
#include <boost/python.hpp>
#include <boost/variant.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
// mapnik
//symbolizer typdef here rather than mapnik/symbolizer.hpp
#include <mapnik/rule.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/symbolizer_hash.hpp>
#include <mapnik/symbolizer_utils.hpp>
#include <mapnik/symbolizer_keys.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/path_expression.hpp>
@ -46,10 +46,14 @@
#include <mapnik/expression_node.hpp>
#include <mapnik/value_error.hpp>
#include <mapnik/marker_cache.hpp> // for known_svg_prefix_
#include <mapnik/pixel_position.hpp>
#include <mapnik/group/group_layout.hpp>
#include <mapnik/group/group_rule.hpp>
#include <mapnik/group/group_symbolizer_properties.hpp>
// stl
#include <sstream>
using mapnik::symbolizer;
using mapnik::rule;
using mapnik::point_symbolizer;
using mapnik::line_symbolizer;
using mapnik::line_pattern_symbolizer;
@ -60,6 +64,9 @@ using mapnik::shield_symbolizer;
using mapnik::text_symbolizer;
using mapnik::building_symbolizer;
using mapnik::markers_symbolizer;
using mapnik::debug_symbolizer;
using mapnik::group_symbolizer;
using mapnik::symbolizer_base;
using mapnik::color;
using mapnik::path_processor_type;
using mapnik::path_expression_ptr;
@ -67,176 +74,68 @@ using mapnik::guess_type;
using mapnik::expression_ptr;
using mapnik::parse_path;
namespace {
using namespace boost::python;
tuple get_shield_displacement(const shield_symbolizer& s)
void __setitem__(mapnik::symbolizer_base & sym, std::string const& name, mapnik::symbolizer_base::value_type const& val)
{
mapnik::pixel_position const& pos = s.get_shield_displacement();
return boost::python::make_tuple(pos.x, pos.y);
put(sym, mapnik::get_key(name), val);
}
void set_shield_displacement(shield_symbolizer & s, boost::python::tuple arg)
std::shared_ptr<mapnik::symbolizer_base::value_type> numeric_wrapper(const object& arg)
{
s.get_placement_options()->defaults.displacement.x = extract<double>(arg[0]);
s.get_placement_options()->defaults.displacement.y = extract<double>(arg[1]);
std::shared_ptr<mapnik::symbolizer_base::value_type> result;
if (PyBool_Check(arg.ptr()))
{
mapnik::value_bool val = extract<mapnik::value_bool>(arg);
result.reset(new mapnik::symbolizer_base::value_type(val));
}
tuple get_text_displacement(const shield_symbolizer& t)
else if (PyFloat_Check(arg.ptr()))
{
mapnik::pixel_position const& pos = t.get_placement_options()->defaults.displacement;
return boost::python::make_tuple(pos.x, pos.y);
}
void set_text_displacement(shield_symbolizer & t, boost::python::tuple arg)
{
t.set_displacement(extract<double>(arg[0]),extract<double>(arg[1]));
}
void set_marker_type(mapnik::markers_symbolizer & symbolizer, std::string const& marker_type)
{
std::string filename;
if (marker_type == "ellipse")
{
filename = mapnik::marker_cache::instance().known_svg_prefix_ + "ellipse";
}
else if (marker_type == "arrow")
{
filename = mapnik::marker_cache::instance().known_svg_prefix_ + "arrow";
mapnik::value_double val = extract<mapnik::value_double>(arg);
result.reset(new mapnik::symbolizer_base::value_type(val));
}
else
{
throw mapnik::value_error("Unknown marker-type: '" + marker_type + "'");
mapnik::value_integer val = extract<mapnik::value_integer>(arg);
result.reset(new mapnik::symbolizer_base::value_type(val));
}
symbolizer.set_filename(parse_path(filename));
return result;
}
struct extract_python_object : public boost::static_visitor<boost::python::object>
{
typedef boost::python::object result_type;
struct get_symbolizer_type : public boost::static_visitor<std::string>
template <typename T>
auto operator() (T const& val) const -> result_type
{
public:
std::string operator () (point_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("point");
}
std::string operator () ( line_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("line");
}
std::string operator () (line_pattern_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("line_pattern");
}
std::string operator () (polygon_symbolizer const& sym ) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("polygon");
}
std::string operator () (polygon_pattern_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("polygon_pattern");
}
std::string operator () (raster_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("raster");
}
std::string operator () (shield_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("shield");
}
std::string operator () (text_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("text");
}
std::string operator () (building_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("building");
}
std::string operator () (markers_symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("markers");
}
template <typename Symbolizer>
std::string operator() ( Symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return std::string("unknown");
return result_type(val); // wrap into python object
}
};
std::string get_symbol_type(symbolizer const& symbol)
boost::python::object __getitem__(mapnik::symbolizer_base const& sym, std::string const& name)
{
std::string type = boost::apply_visitor( get_symbolizer_type(), symbol);
return type;
typedef symbolizer_base::cont_type::const_iterator const_iterator;
mapnik::keys key = mapnik::get_key(name);
const_iterator itr = sym.properties.find(key);
if (itr != sym.properties.end())
{
return boost::apply_visitor(extract_python_object(), itr->second);
}
//mapnik::property_meta_type const& meta = mapnik::get_meta(key);
//return boost::apply_visitor(extract_python_object(), std::get<1>(meta));
return boost::python::object();
}
const point_symbolizer& point_(symbolizer const& symbol )
std::string __str__(mapnik::symbolizer const& sym)
{
return boost::get<point_symbolizer>(symbol);
return boost::apply_visitor(mapnik::symbolizer_to_json(), sym);
}
const line_symbolizer& line_( const symbolizer& symbol )
std::string get_symbolizer_type(symbolizer const& sym)
{
return boost::get<line_symbolizer>(symbol);
}
const polygon_symbolizer& polygon_( const symbolizer& symbol )
{
return boost::get<polygon_symbolizer>(symbol);
}
const raster_symbolizer& raster_( const symbolizer& symbol )
{
return boost::get<raster_symbolizer>(symbol);
}
const text_symbolizer& text_( const symbolizer& symbol )
{
return boost::get<text_symbolizer>(symbol);
}
const shield_symbolizer& shield_( const symbolizer& symbol )
{
return boost::get<shield_symbolizer>(symbol);
}
const line_pattern_symbolizer& line_pattern_( const symbolizer& symbol )
{
return boost::get<line_pattern_symbolizer>(symbol);
}
const polygon_pattern_symbolizer& polygon_pattern_( const symbolizer& symbol )
{
return boost::get<polygon_pattern_symbolizer>(symbol);
}
const building_symbolizer& building_( const symbolizer& symbol )
{
return boost::get<building_symbolizer>(symbol);
}
const markers_symbolizer& markers_( const symbolizer& symbol )
{
return boost::get<markers_symbolizer>(symbol);
return mapnik::symbolizer_name(sym); // FIXME - do we need this ?
}
struct symbolizer_hash_visitor : public boost::static_visitor<std::size_t>
@ -254,15 +153,23 @@ std::size_t hash_impl(symbolizer const& sym)
}
template <typename T>
std::string get_file_impl(T const& sym)
std::size_t hash_impl_2(T const& sym)
{
return path_processor_type::to_string(*sym.get_filename());
return mapnik::symbolizer_hash::value<T>(sym);
}
template <typename T>
void set_file_impl(T & sym, std::string const& file_expr)
struct extract_underlying_type_visitor : boost::static_visitor<boost::python::object>
{
sym.set_filename(parse_path(file_expr));
template <typename T>
boost::python::object operator() (T const& sym) const
{
return boost::python::object(sym);
}
};
boost::python::object extract_underlying_type(symbolizer const& sym)
{
return boost::apply_visitor(extract_underlying_type_visitor(), sym);
}
}
@ -271,41 +178,37 @@ void export_symbolizer()
{
using namespace boost::python;
//implicitly_convertible<mapnik::value_bool, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::value_integer, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::value_double, mapnik::symbolizer_base::value_type>();
implicitly_convertible<std::string, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::color, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::expression_ptr, mapnik::symbolizer_base::value_type>();
implicitly_convertible<mapnik::enumeration_wrapper, mapnik::symbolizer_base::value_type>();
implicitly_convertible<std::shared_ptr<mapnik::group_symbolizer_properties>, mapnik::symbolizer_base::value_type>();
enum_<mapnik::keys>("keys")
.value("gamma", mapnik::keys::gamma)
.value("gamma_method",mapnik::keys::gamma_method)
;
class_<symbolizer>("Symbolizer",no_init)
.def("type",get_symbol_type)
.def("type",get_symbolizer_type)
.def("__hash__",hash_impl)
.def("extract", extract_underlying_type)
;
.def("point",point_,
return_value_policy<copy_const_reference>())
class_<symbolizer_base::value_type>("NumericWrapper")
.def("__init__", make_constructor(numeric_wrapper))
;
.def("line",line_,
return_value_policy<copy_const_reference>())
.def("line_pattern",line_pattern_,
return_value_policy<copy_const_reference>())
.def("polygon",polygon_,
return_value_policy<copy_const_reference>())
.def("polygon_pattern",polygon_pattern_,
return_value_policy<copy_const_reference>())
.def("raster",raster_,
return_value_policy<copy_const_reference>())
.def("shield",shield_,
return_value_policy<copy_const_reference>())
.def("text",text_,
return_value_policy<copy_const_reference>())
.def("building",building_,
return_value_policy<copy_const_reference>())
.def("markers",markers_,
return_value_policy<copy_const_reference>())
class_<symbolizer_base>("SymbolizerBase",no_init)
.def("__setitem__",&__setitem__)
.def("__setattr__",&__setitem__)
.def("__getitem__",&__getitem__)
.def("__getattr__",&__getitem__)
.def("__str__", &__str__)
.def(self == self) // __eq__
;
}
@ -314,169 +217,19 @@ void export_shield_symbolizer()
{
using namespace boost::python;
class_< shield_symbolizer, bases<text_symbolizer> >("ShieldSymbolizer",
init<expression_ptr,
std::string const&,
unsigned, mapnik::color const&,
path_expression_ptr>()
)
.add_property("allow_overlap",
&shield_symbolizer::get_allow_overlap,
&shield_symbolizer::set_allow_overlap,
"Set/get the allow_overlap property of the label")
.add_property("avoid_edges",
&shield_symbolizer::get_avoid_edges,
&shield_symbolizer::set_avoid_edges,
"Set/get the avoid_edge property of the label")
.add_property("character_spacing",
&shield_symbolizer::get_character_spacing,
&shield_symbolizer::set_character_spacing,
"Set/get the character_spacing property of the label")
.add_property("displacement",
&get_text_displacement,
&set_text_displacement)
.add_property("face_name",
make_function(&shield_symbolizer::get_face_name,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_face_name,
"Set/get the face_name property of the label")
.add_property("fill",
make_function(&shield_symbolizer::get_fill,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_fill)
.add_property("fontset",
make_function(&shield_symbolizer::get_fontset,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_fontset)
.add_property("force_odd_labels",
&shield_symbolizer::get_force_odd_labels,
&shield_symbolizer::set_force_odd_labels)
.add_property("halo_fill",
make_function(&shield_symbolizer::get_halo_fill,return_value_policy<copy_const_reference>()),
&shield_symbolizer::set_halo_fill)
.add_property("halo_radius",
&shield_symbolizer::get_halo_radius,
&shield_symbolizer::set_halo_radius)
.add_property("horizontal_alignment",
&shield_symbolizer::get_horizontal_alignment,
&shield_symbolizer::set_horizontal_alignment,
"Set/get the horizontal alignment of the label")
.add_property("justify_alignment",
&shield_symbolizer::get_justify_alignment,
&shield_symbolizer::set_justify_alignment,
"Set/get the text justification")
.add_property("label_placement",
&shield_symbolizer::get_label_placement,
&shield_symbolizer::set_label_placement,
"Set/get the placement of the label")
.add_property("label_position_tolerance",
&shield_symbolizer::get_label_position_tolerance,
&shield_symbolizer::set_label_position_tolerance)
.add_property("label_spacing",
&shield_symbolizer::get_label_spacing,
&shield_symbolizer::set_label_spacing)
.add_property("line_spacing",
&shield_symbolizer::get_line_spacing,
&shield_symbolizer::set_line_spacing)
.add_property("max_char_angle_delta",
&shield_symbolizer::get_max_char_angle_delta,
&shield_symbolizer::set_max_char_angle_delta)
.add_property("minimum_distance",
&shield_symbolizer::get_minimum_distance,
&shield_symbolizer::set_minimum_distance)
.add_property("minimum_padding",
&shield_symbolizer::get_minimum_padding,
&shield_symbolizer::set_minimum_padding)
.add_property("name",&shield_symbolizer::get_name,
&shield_symbolizer::set_name)
.add_property("opacity",
&shield_symbolizer::get_opacity,
&shield_symbolizer::set_opacity,
"Set/get the shield opacity")
.add_property("shield_displacement",
get_shield_displacement,
set_shield_displacement)
.add_property("text_opacity",
&shield_symbolizer::get_text_opacity,
&shield_symbolizer::set_text_opacity,
"Set/get the text opacity")
.add_property("text_transform",
&shield_symbolizer::get_text_transform,
&shield_symbolizer::set_text_transform,
"Set/get the text conversion method")
.add_property("text_ratio",
&shield_symbolizer::get_text_ratio,
&shield_symbolizer::set_text_ratio)
.add_property("text_size",
&shield_symbolizer::get_text_size,
&shield_symbolizer::set_text_size)
.add_property("vertical_alignment",
&shield_symbolizer::get_vertical_alignment,
&shield_symbolizer::set_vertical_alignment,
"Set/get the vertical alignment of the label")
.add_property("wrap_width",
&shield_symbolizer::get_wrap_width,
&shield_symbolizer::set_wrap_width)
.add_property("wrap_character",
&shield_symbolizer::get_wrap_char_string,
&shield_symbolizer::set_wrap_char_from_string)
.add_property("wrap_before",
&shield_symbolizer::get_wrap_before,
&shield_symbolizer::set_wrap_before)
.add_property("unlock_image",
&shield_symbolizer::get_unlock_image,
&shield_symbolizer::set_unlock_image)
.add_property("filename",
get_file_impl<shield_symbolizer>,
set_file_impl<shield_symbolizer>)
.add_property("transform",
mapnik::get_svg_transform<shield_symbolizer>,
mapnik::set_svg_transform<shield_symbolizer>)
.add_property("comp_op",
&shield_symbolizer::comp_op,
&shield_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&shield_symbolizer::clip,
&shield_symbolizer::set_clip,
"Set/get the shield geometry's clipping status")
init<>("Default ctor"))
.def("__hash__",hash_impl_2<shield_symbolizer>)
;
}
void export_polygon_symbolizer()
{
using namespace boost::python;
class_<polygon_symbolizer>("PolygonSymbolizer",
init<>("Default PolygonSymbolizer - solid fill grey"))
.def(init<color const&>("TODO"))
.add_property("fill",make_function
(&polygon_symbolizer::get_fill,
return_value_policy<copy_const_reference>()),
&polygon_symbolizer::set_fill)
.add_property("fill_opacity",
&polygon_symbolizer::get_opacity,
&polygon_symbolizer::set_opacity)
.add_property("gamma",
&polygon_symbolizer::get_gamma,
&polygon_symbolizer::set_gamma)
.add_property("gamma_method",
&polygon_symbolizer::get_gamma_method,
&polygon_symbolizer::set_gamma_method,
"gamma correction method")
.add_property("comp_op",
&polygon_symbolizer::comp_op,
&polygon_symbolizer::set_comp_op,
"Set/get the polygon comp-op")
.add_property("clip",
&polygon_symbolizer::clip,
&polygon_symbolizer::set_clip,
"Set/get the polygon geometry's clipping status")
.add_property("smooth",
&polygon_symbolizer::smooth,
&polygon_symbolizer::set_smooth,
"Set/get the polygon geometry's smooth value")
.add_property("simplify_tolerance",
&polygon_symbolizer::simplify_tolerance,
&polygon_symbolizer::set_simplify_tolerance,
"simplfication tolerance measure")
.def("__hash__", hash_impl)
class_<polygon_symbolizer, bases<symbolizer_base> >("PolygonSymbolizer",
init<>("Default ctor"))
.def("__hash__",hash_impl_2<polygon_symbolizer>)
;
}
@ -491,144 +244,17 @@ void export_polygon_pattern_symbolizer()
;
class_<polygon_pattern_symbolizer>("PolygonPatternSymbolizer",
init<path_expression_ptr>("<path_expression_ptr>"))
.add_property("alignment",
&polygon_pattern_symbolizer::get_alignment,
&polygon_pattern_symbolizer::set_alignment,
"Set/get the alignment of the pattern")
.add_property("transform",
mapnik::get_svg_transform<polygon_pattern_symbolizer>,
mapnik::set_svg_transform<polygon_pattern_symbolizer>)
.add_property("filename",
&get_file_impl<polygon_pattern_symbolizer>,
&set_file_impl<polygon_pattern_symbolizer>)
.add_property("opacity",
&polygon_pattern_symbolizer::get_opacity,
&polygon_pattern_symbolizer::set_opacity)
.add_property("gamma",
&polygon_pattern_symbolizer::get_gamma,
&polygon_pattern_symbolizer::set_gamma)
.add_property("gamma_method",
&polygon_pattern_symbolizer::get_gamma_method,
&polygon_pattern_symbolizer::set_gamma_method,
"Set/get the gamma correction method of the polygon")
.add_property("comp_op",
&polygon_pattern_symbolizer::comp_op,
&polygon_pattern_symbolizer::set_comp_op,
"Set/get the pattern comp-op")
.add_property("clip",
&polygon_pattern_symbolizer::clip,
&polygon_pattern_symbolizer::set_clip,
"Set/get the pattern geometry's clipping status")
.add_property("smooth",
&polygon_pattern_symbolizer::smooth,
&polygon_pattern_symbolizer::set_smooth,
"Set/get the pattern geometry's smooth value")
init<>("Default ctor"))
.def("__hash__",hash_impl_2<polygon_pattern_symbolizer>)
;
}
void export_raster_symbolizer()
{
using namespace boost::python;
class_<raster_symbolizer>("RasterSymbolizer",
class_<raster_symbolizer, bases<symbolizer_base> >("RasterSymbolizer",
init<>("Default ctor"))
.add_property("mode",
make_function(&raster_symbolizer::get_mode,return_value_policy<copy_const_reference>()),
&raster_symbolizer::set_mode,
"Get/Set merging mode. (deprecated, use comp_op instead)\n"
)
.add_property("comp_op",
&raster_symbolizer::comp_op,
&raster_symbolizer::set_comp_op,
"Set/get the raster comp-op"
)
.add_property("scaling",
&raster_symbolizer::get_scaling_method,
&raster_symbolizer::set_scaling_method,
"Get/Set scaling algorithm.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.scaling = 'mapnik.scaling_method.GAUSSIAN'\n"
)
.add_property("opacity",
&raster_symbolizer::get_opacity,
&raster_symbolizer::set_opacity,
"Get/Set opacity.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.opacity = .5\n"
)
.add_property("colorizer",
&raster_symbolizer::get_colorizer,
&raster_symbolizer::set_colorizer,
"Get/Set the RasterColorizer used to color data rasters.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer, RasterColorizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.colorizer = RasterColorizer()\n"
">>> for value, color in [\n"
"... (0, \"#000000\"),\n"
"... (10, \"#ff0000\"),\n"
"... (40, \"#00ff00\"),\n"
"... ]:\n"
"... r.colorizer.append_band(value, color)\n"
)
.add_property("filter_factor",
&raster_symbolizer::get_filter_factor,
&raster_symbolizer::set_filter_factor,
"Get/Set the filter factor used by the datasource.\n"
"\n"
"This is used by the Raster or Gdal datasources to pre-downscale\n"
"images using overviews.\n"
"Higher numbers can sometimes cause much better scaled image\n"
"output, at the cost of speed.\n"
"\n"
"Examples:\n"
" -1.0 : (Default) A suitable value will be determined from the\n"
" chosen scaling method during rendering.\n"
" 1.0 : The datasource will take care of all the scaling\n"
" (using nearest neighbor interpolation)\n"
" 2.0 : The datasource will scale the datasource to\n"
" 2.0x the desired size, and mapnik will scale the rest\n"
" of the way using the interpolation defined in self.scaling.\n"
)
.add_property("mesh_size",
&raster_symbolizer::get_mesh_size,
&raster_symbolizer::set_mesh_size,
"Get/Set warping mesh size.\n"
"Larger values result in faster warping times but might "
"result in distorted maps.\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.mesh_size = 32\n"
)
.add_property("premultiplied",
&raster_symbolizer::premultiplied,
&raster_symbolizer::set_premultiplied,
"Get/Set premultiplied status of the source image.\n"
"Can be used to override what the source data reports (when in error)\n"
"\n"
"Usage:\n"
"\n"
">>> from mapnik import RasterSymbolizer\n"
">>> r = RasterSymbolizer()\n"
">>> r.premultiplied = False\n"
)
;
}
@ -641,32 +267,9 @@ void export_point_symbolizer()
.value("INTERIOR",mapnik::INTERIOR_POINT_PLACEMENT)
;
class_<point_symbolizer>("PointSymbolizer",
class_<point_symbolizer, bases<symbolizer_base> >("PointSymbolizer",
init<>("Default Point Symbolizer - 4x4 black square"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))
.add_property("filename",
&get_file_impl<point_symbolizer>,
&set_file_impl<point_symbolizer>)
.add_property("allow_overlap",
&point_symbolizer::get_allow_overlap,
&point_symbolizer::set_allow_overlap)
.add_property("opacity",
&point_symbolizer::get_opacity,
&point_symbolizer::set_opacity)
.add_property("ignore_placement",
&point_symbolizer::get_ignore_placement,
&point_symbolizer::set_ignore_placement)
.add_property("placement",
&point_symbolizer::get_point_placement,
&point_symbolizer::set_point_placement,
"Set/get the placement of the point")
.add_property("transform",
mapnik::get_svg_transform<point_symbolizer>,
mapnik::set_svg_transform<point_symbolizer>)
.add_property("comp_op",
&point_symbolizer::comp_op,
&point_symbolizer::set_comp_op,
"Set/get the comp-op")
.def("__hash__",hash_impl_2<point_symbolizer>)
;
}
@ -686,76 +289,9 @@ void export_markers_symbolizer()
.value("LARGEST",mapnik::MARKER_LARGEST_MULTI)
;
class_<markers_symbolizer>("MarkersSymbolizer",
class_<markers_symbolizer, bases<symbolizer_base> >("MarkersSymbolizer",
init<>("Default Markers Symbolizer - circle"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>"))
.add_property("filename",
&get_file_impl<markers_symbolizer>,
&set_file_impl<markers_symbolizer>)
.add_property("marker_type",
&get_file_impl<markers_symbolizer>,
&set_marker_type)
.add_property("allow_overlap",
&markers_symbolizer::get_allow_overlap,
&markers_symbolizer::set_allow_overlap)
.add_property("spacing",
&markers_symbolizer::get_spacing,
&markers_symbolizer::set_spacing)
.add_property("max_error",
&markers_symbolizer::get_max_error,
&markers_symbolizer::set_max_error)
.add_property("opacity",
&markers_symbolizer::get_opacity,
&markers_symbolizer::set_opacity,
"Set/get the overall opacity")
.add_property("fill_opacity",
&markers_symbolizer::get_fill_opacity,
&markers_symbolizer::set_fill_opacity,
"Set/get the fill opacity")
.add_property("ignore_placement",
&markers_symbolizer::get_ignore_placement,
&markers_symbolizer::set_ignore_placement)
.add_property("transform",
&mapnik::get_svg_transform<markers_symbolizer>,
&mapnik::set_svg_transform<markers_symbolizer>)
.add_property("width",
make_function(&markers_symbolizer::get_width,
return_value_policy<copy_const_reference>()),
&markers_symbolizer::set_width,
"Set/get the marker width")
.add_property("height",
make_function(&markers_symbolizer::get_height,
return_value_policy<copy_const_reference>()),
&markers_symbolizer::set_height,
"Set/get the marker height")
.add_property("fill",
&markers_symbolizer::get_fill,
&markers_symbolizer::set_fill,
"Set/get the marker fill color")
.add_property("stroke",
&markers_symbolizer::get_stroke,
&markers_symbolizer::set_stroke,
"Set/get the marker stroke (outline)")
.add_property("placement",
&markers_symbolizer::get_marker_placement,
&markers_symbolizer::set_marker_placement,
"Set/get the marker placement")
.add_property("multi_policy",
&markers_symbolizer::get_marker_multi_policy,
&markers_symbolizer::set_marker_multi_policy,
"Set/get the marker multi geometry rendering policy")
.add_property("comp_op",
&markers_symbolizer::comp_op,
&markers_symbolizer::set_comp_op,
"Set/get the marker comp-op")
.add_property("clip",
&markers_symbolizer::clip,
&markers_symbolizer::set_clip,
"Set/get the marker geometry's clipping status")
.add_property("smooth",
&markers_symbolizer::smooth,
&markers_symbolizer::set_smooth,
"Set/get the marker geometry's smooth value")
.def("__hash__",hash_impl_2<markers_symbolizer>)
;
}
@ -763,43 +299,33 @@ void export_markers_symbolizer()
void export_line_symbolizer()
{
using namespace boost::python;
mapnik::enumeration_<mapnik::line_rasterizer_e>("line_rasterizer")
.value("FULL",mapnik::RASTERIZER_FULL)
.value("FAST",mapnik::RASTERIZER_FAST)
;
class_<line_symbolizer>("LineSymbolizer",
mapnik::enumeration_<mapnik::line_cap_e>("stroke_linecap",
"The possible values for a line cap used when drawing\n"
"with a stroke.\n")
.value("BUTT_CAP",mapnik::BUTT_CAP)
.value("SQUARE_CAP",mapnik::SQUARE_CAP)
.value("ROUND_CAP",mapnik::ROUND_CAP)
;
mapnik::enumeration_<mapnik::line_join_e>("stroke_linejoin",
"The possible values for the line joining mode\n"
"when drawing with a stroke.\n")
.value("MITER_JOIN",mapnik::MITER_JOIN)
.value("MITER_REVERT_JOIN",mapnik::MITER_REVERT_JOIN)
.value("ROUND_JOIN",mapnik::ROUND_JOIN)
.value("BEVEL_JOIN",mapnik::BEVEL_JOIN)
;
class_<line_symbolizer, bases<symbolizer_base> >("LineSymbolizer",
init<>("Default LineSymbolizer - 1px solid black"))
.def(init<mapnik::stroke const&>("TODO"))
.def(init<mapnik::color const& ,float>())
.add_property("rasterizer",
&line_symbolizer::get_rasterizer,
&line_symbolizer::set_rasterizer,
"Set/get the rasterization method of the line of the point")
.add_property("stroke",make_function
(&line_symbolizer::get_stroke,
return_value_policy<reference_existing_object>()),
&line_symbolizer::set_stroke)
.add_property("simplify_tolerance",
&line_symbolizer::simplify_tolerance,
&line_symbolizer::set_simplify_tolerance,
"simplification tolerance measure")
.add_property("offset",
&line_symbolizer::offset,
&line_symbolizer::set_offset,
"offset value")
.add_property("comp_op",
&line_symbolizer::comp_op,
&line_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&line_symbolizer::clip,
&line_symbolizer::set_clip,
"Set/get the line geometry's clipping status")
.add_property("smooth",
&line_symbolizer::smooth,
&line_symbolizer::set_smooth,
"smooth value (0..1.0)")
.def("__hash__", hash_impl)
.def("__hash__",hash_impl_2<line_symbolizer>)
;
}
@ -807,31 +333,9 @@ void export_line_pattern_symbolizer()
{
using namespace boost::python;
class_<line_pattern_symbolizer>("LinePatternSymbolizer",
init<path_expression_ptr>
("<image file expression>"))
.add_property("transform",
mapnik::get_svg_transform<line_pattern_symbolizer>,
mapnik::set_svg_transform<line_pattern_symbolizer>)
.add_property("filename",
&get_file_impl<line_pattern_symbolizer>,
&set_file_impl<line_pattern_symbolizer>)
.add_property("offset",
&line_pattern_symbolizer::offset,
&line_pattern_symbolizer::set_offset,
"Set/get the offset")
.add_property("comp_op",
&line_pattern_symbolizer::comp_op,
&line_pattern_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&line_pattern_symbolizer::clip,
&line_pattern_symbolizer::set_clip,
"Set/get the line pattern geometry's clipping status")
.add_property("smooth",
&line_pattern_symbolizer::smooth,
&line_pattern_symbolizer::set_smooth,
"smooth value (0..1.0)")
class_<line_pattern_symbolizer, bases<symbolizer_base> >("LinePatternSymbolizer",
init<> ("Default LinePatternSymbolizer"))
.def("__hash__",hash_impl_2<line_pattern_symbolizer>)
;
}
@ -844,33 +348,81 @@ void export_debug_symbolizer()
.value("VERTEX",mapnik::DEBUG_SYM_MODE_VERTEX)
;
class_<mapnik::debug_symbolizer>("DebugSymbolizer",
class_<debug_symbolizer, bases<symbolizer_base> >("DebugSymbolizer",
init<>("Default debug Symbolizer"))
.add_property("mode",
&mapnik::debug_symbolizer::get_mode,
&mapnik::debug_symbolizer::set_mode)
.def("__hash__",hash_impl_2<debug_symbolizer>)
;
}
void export_building_symbolizer()
{
using namespace boost::python;
class_<building_symbolizer>("BuildingSymbolizer",
class_<building_symbolizer, bases<symbolizer_base> >("BuildingSymbolizer",
init<>("Default BuildingSymbolizer"))
.add_property("fill",make_function
(&building_symbolizer::get_fill,
return_value_policy<copy_const_reference>()),
&building_symbolizer::set_fill)
.add_property("fill_opacity",
&building_symbolizer::get_opacity,
&building_symbolizer::set_opacity)
.add_property("height",
make_function(&building_symbolizer::height,
return_value_policy<copy_const_reference>()),
&building_symbolizer::set_height,
"Set/get the building height")
.def("__hash__",hash_impl_2<building_symbolizer>)
;
}
namespace {
void group_symbolizer_properties_set_layout_simple(mapnik::group_symbolizer_properties &p,
mapnik::simple_row_layout &s)
{
p.set_layout(s);
}
void group_symbolizer_properties_set_layout_pair(mapnik::group_symbolizer_properties &p,
mapnik::pair_layout &s)
{
p.set_layout(s);
}
std::shared_ptr<mapnik::group_rule> group_rule_construct1(mapnik::expression_ptr p)
{
return std::make_shared<mapnik::group_rule>(p, mapnik::expression_ptr());
}
} // anonymous namespace
void export_group_symbolizer()
{
using namespace boost::python;
using mapnik::group_rule;
using mapnik::simple_row_layout;
using mapnik::pair_layout;
using mapnik::group_symbolizer_properties;
class_<group_rule, std::shared_ptr<group_rule> >("GroupRule",
init<expression_ptr, expression_ptr>())
.def("__init__", boost::python::make_constructor(group_rule_construct1))
.def("append", &group_rule::append)
.def("set_filter", &group_rule::set_filter)
.def("set_repeat_key", &group_rule::set_repeat_key)
;
class_<simple_row_layout>("SimpleRowLayout")
.def("item_margin", &simple_row_layout::get_item_margin)
.def("set_item_margin", &simple_row_layout::set_item_margin)
;
class_<pair_layout>("PairLayout")
.def("item_margin", &simple_row_layout::get_item_margin)
.def("set_item_margin", &simple_row_layout::set_item_margin)
.def("max_difference", &pair_layout::get_max_difference)
.def("set_max_difference", &pair_layout::set_max_difference)
;
class_<group_symbolizer_properties, std::shared_ptr<group_symbolizer_properties> >("GroupSymbolizerProperties")
.def("add_rule", &group_symbolizer_properties::add_rule)
.def("set_layout", &group_symbolizer_properties_set_layout_simple)
.def("set_layout", &group_symbolizer_properties_set_layout_pair)
;
class_<group_symbolizer, bases<symbolizer_base> >("GroupSymbolizer",
init<>("Default GroupSymbolizer"))
.def("__hash__",hash_impl_2<group_symbolizer>)
;
}

View file

@ -33,8 +33,9 @@
#include <mapnik/text/formatting/list.hpp>
#include <mapnik/text/formatting/format.hpp>
#include <mapnik/text/formatting/expression_format.hpp>
#include <mapnik/text/formatting/layout.hpp>
#include <mapnik/text/layout.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/symbolizer.hpp>
#include "mapnik_enumeration.hpp"
#include "mapnik_threads.hpp"
@ -96,12 +97,12 @@ public:
}
};
boost::python::tuple get_displacement(text_symbolizer_properties const& t)
boost::python::tuple get_displacement(text_layout_properties const& t)
{
return boost::python::make_tuple(t.displacement.x, t.displacement.y);
}
void set_displacement(text_symbolizer_properties &t, boost::python::tuple arg)
void set_displacement(text_layout_properties &t, boost::python::tuple arg)
{
if (len(arg) != 2)
{
@ -117,7 +118,6 @@ void set_displacement(text_symbolizer_properties &t, boost::python::tuple arg)
t.displacement.set(x, y);
}
struct NodeWrap: formatting::node, wrapper<formatting::node>
{
NodeWrap() : formatting::node(), wrapper<formatting::node>()
@ -224,6 +224,27 @@ struct ExprFormatWrap: formatting::expression_format, wrapper<formatting::expres
}
};
struct LayoutNodeWrap: formatting::layout_node, wrapper<formatting::layout_node>
{
virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const
{
if(override o = this->get_override("apply"))
{
python_block_auto_unblock b;
o(ptr(&p), ptr(&feature), ptr(&output));
}
else
{
formatting::layout_node::apply(p, feature, output);
}
}
void default_apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const
{
formatting::layout_node::apply(p, feature, output);
}
};
struct ListNodeWrap: formatting::list_node, wrapper<formatting::list_node>
{
//Default constructor
@ -324,6 +345,7 @@ void insert_expression(expression_set *set, expression_ptr p)
set->insert(p);
}
/*
char_properties_ptr get_format(text_symbolizer const& sym)
{
return sym.get_placement_options()->defaults.format;
@ -343,7 +365,7 @@ void set_properties(text_symbolizer const& sym, text_symbolizer_properties & def
{
sym.get_placement_options()->defaults = defaults;
}
*/
}
void export_text_placement()
@ -391,44 +413,13 @@ void export_text_placement()
class_<text_symbolizer>("TextSymbolizer",
init<>())
.def(init<expression_ptr, std::string const&, unsigned, color const&>())
.add_property("placements",
&text_symbolizer::get_placement_options,
&text_symbolizer::set_placement_options)
//TODO: Check return policy, is there a better way to do this?
.add_property("format",
make_function(&get_format),
&set_format,
"Shortcut for placements.defaults.default_format")
.add_property("properties",
make_function(&get_properties, return_value_policy<reference_existing_object>()),
&set_properties,
"Shortcut for placements.defaults")
.add_property("comp_op",
&text_symbolizer::comp_op,
&text_symbolizer::set_comp_op,
"Set/get the comp-op")
.add_property("clip",
&text_symbolizer::clip,
&text_symbolizer::set_clip,
"Set/get the text geometry's clipping status")
.add_property("halo_rasterizer",
&text_symbolizer::get_halo_rasterizer,
&text_symbolizer::set_halo_rasterizer,
"Set/get the halo rasterizer method")
;
class_with_converter<text_symbolizer_properties>
("TextSymbolizerProperties")
.def_readwrite_convert("label_placement", &text_symbolizer_properties::label_placement)
.def_readwrite_convert("horizontal_alignment", &text_symbolizer_properties::halign)
.def_readwrite_convert("justify_alignment", &text_symbolizer_properties::jalign)
.def_readwrite_convert("vertical_alignment", &text_symbolizer_properties::valign)
.def_readwrite("orientation", &text_symbolizer_properties::orientation)
.add_property("displacement",
&get_displacement,
&set_displacement)
.def_readwrite_convert("upright", &text_symbolizer_properties::upright)
.def_readwrite("label_spacing", &text_symbolizer_properties::label_spacing)
.def_readwrite("label_position_tolerance", &text_symbolizer_properties::label_position_tolerance)
.def_readwrite("avoid_edges", &text_symbolizer_properties::avoid_edges)
@ -439,9 +430,7 @@ void export_text_placement()
.def_readwrite("force_odd_labels", &text_symbolizer_properties::force_odd_labels)
.def_readwrite("allow_overlap", &text_symbolizer_properties::allow_overlap)
.def_readwrite("largest_bbox_only", &text_symbolizer_properties::largest_bbox_only)
.def_readwrite("text_ratio", &text_symbolizer_properties::text_ratio)
.def_readwrite("wrap_width", &text_symbolizer_properties::wrap_width)
.def_readwrite("wrap_before", &text_symbolizer_properties::wrap_before)
.def_readwrite("layout_defaults", &text_symbolizer_properties::layout_defaults)
.def_readwrite("format", &text_symbolizer_properties::format)
.add_property ("format_tree",
&text_symbolizer_properties::format_tree,
@ -453,9 +442,19 @@ void export_text_placement()
set_old_style expression is just a compatibility wrapper and doesn't need to be exposed in python. */
;
class_with_converter<text_layout_properties>
("TextLayoutProperties")
.def_readwrite_convert("horizontal_alignment", &text_layout_properties::halign)
.def_readwrite_convert("justify_alignment", &text_layout_properties::jalign)
.def_readwrite_convert("vertical_alignment", &text_layout_properties::valign)
.def_readwrite("text_ratio", &text_layout_properties::text_ratio)
.def_readwrite("wrap_width", &text_layout_properties::wrap_width)
.def_readwrite("wrap_before", &text_layout_properties::wrap_before)
.def_readwrite("orientation", &text_layout_properties::orientation)
.def_readwrite("rotate_displacement", &text_layout_properties::rotate_displacement)
.add_property("displacement", &get_displacement, &set_displacement);
class_with_converter<char_properties,
std::shared_ptr<char_properties> >
class_with_converter<char_properties>
("CharProperties")
.def_readwrite_convert("text_transform", &char_properties::text_transform)
.def_readwrite_convert("fontset", &char_properties::fontset)

View file

@ -38,12 +38,12 @@ namespace boost { namespace python {
return ::PyLong_FromLongLong(val);
}
PyObject * operator() (double val) const
PyObject * operator() (mapnik::value_double val) const
{
return ::PyFloat_FromDouble(val);
}
PyObject * operator() (bool val) const
PyObject * operator() (mapnik::value_bool val) const
{
return ::PyBool_FromLong(val);
}

View file

@ -394,82 +394,6 @@ void render_layer_for_grid(mapnik::Map const& map,
ren.apply(layer,attributes);
}
/* old, original impl - to be removed after further testing
* grid object is created on the fly at potentially reduced size
*/
boost::python::dict render_grid(mapnik::Map const& map,
unsigned layer_idx, // layer
std::string const& key, // key_name
unsigned int step, // resolution
boost::python::list const& fields)
{
std::vector<mapnik::layer> const& layers = map.layers();
std::size_t layer_num = layers.size();
if (layer_idx >= layer_num) {
std::ostringstream s;
s << "Zero-based layer index '" << layer_idx << "' not valid, only '"
<< layer_num << "' layers are in map\n";
throw std::runtime_error(s.str());
}
unsigned int grid_width = map.width()/step;
unsigned int grid_height = map.height()/step;
// TODO - no need to pass step here
mapnik::grid grid(grid_width,grid_height,key,step);
// convert python list to std::set
boost::python::ssize_t num_fields = boost::python::len(fields);
for(boost::python::ssize_t i=0; i<num_fields; i++) {
boost::python::extract<std::string> name(fields[i]);
if (name.check()) {
grid.add_property_name(name());
}
else
{
std::stringstream s;
s << "list of field names must be strings";
throw mapnik::value_error(s.str());
}
}
// copy property names
std::set<std::string> attributes = grid.property_names();
// todo - make this a static constant
std::string known_id_key = "__id__";
if (attributes.find(known_id_key) != attributes.end())
{
attributes.erase(known_id_key);
}
std::string join_field = grid.get_key();
if (known_id_key != join_field &&
attributes.find(join_field) == attributes.end())
{
attributes.insert(join_field);
}
try
{
mapnik::grid_renderer<mapnik::grid> ren(map,grid,1.0,0,0);
mapnik::layer const& layer = layers[layer_idx];
ren.apply(layer,attributes);
}
catch (...)
{
throw;
}
bool add_features = false;
if (num_fields > 0)
add_features = true;
// build dictionary and return to python
boost::python::dict json;
grid_encode_utf(grid,json,add_features,1);
return json;
}
}
#endif

View file

@ -76,14 +76,6 @@ void render_layer_for_grid(const mapnik::Map& map,
unsigned layer_idx, // TODO - layer by name or index
boost::python::list const& fields);
/* old, original impl - to be removed after further testing
* grid object is created on the fly at potentially reduced size
*/
boost::python::dict render_grid(const mapnik::Map& map,
unsigned layer_idx, // layer
std::string const& key, // key_name
unsigned int step, // resolution
boost::python::list const& fields);
}
#endif // MAPNIK_PYTHON_BINDING_GRID_UTILS_INCLUDED

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
* Copyright (C) 2013 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -23,11 +23,9 @@
#include <mapnik/map.hpp>
#include <mapnik/layer.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/feature_type_style.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/text/text_properties.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/agg_renderer.hpp>
@ -45,13 +43,6 @@
int main ( int argc , char** argv)
{
if (argc != 2)
{
std::cout << "usage: ./rundemo <mapnik_install_dir>\nUsually /usr/local\n";
std::cout << "Warning: ./rundemo looks for data in ../data/,\nTherefore must be run from within the demo/c++ folder.\n";
return EXIT_SUCCESS;
}
using namespace mapnik;
const std::string srs_lcc="+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 \
+datum=NAD83 +units=m +no_defs";
@ -60,11 +51,8 @@ int main ( int argc , char** argv)
try {
std::cout << " running demo ... \n";
std::string mapnik_dir(argv[1]);
std::cout << " looking for 'shape.input' plugin in... " << mapnik_dir << "/lib/mapnik/input/" << "\n";
datasource_cache::instance().register_datasources(mapnik_dir + "/lib/mapnik/input/");
std::cout << " looking for DejaVuSans font in... " << mapnik_dir << "/lib/mapnik/fonts/DejaVuSans.ttf" << "\n";
freetype_engine::register_font(mapnik_dir + "/lib/mapnik/fonts/DejaVuSans.ttf");
datasource_cache::instance().register_datasources("plugins/input/");
freetype_engine::register_font("fonts/dejavu-fonts-ttf-2.33/ttf/DejaVuSans.ttf");
Map m(800,600);
m.set_background(parse_color("white"));
@ -73,109 +61,162 @@ int main ( int argc , char** argv)
// Provinces (polygon)
feature_type_style provpoly_style;
rule provpoly_rule_on;
provpoly_rule_on.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));
provpoly_rule_on.append(polygon_symbolizer(color(250, 190, 183)));
provpoly_style.add_rule(provpoly_rule_on);
rule provpoly_rule_qc;
provpoly_rule_qc.set_filter(parse_expression("[NOM_FR] = 'Québec'"));
provpoly_rule_qc.append(polygon_symbolizer(color(217, 235, 203)));
provpoly_style.add_rule(provpoly_rule_qc);
{
rule r;
r.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));
{
polygon_symbolizer poly_sym;
put(poly_sym, keys::fill, color(250, 190, 183));
r.append(std::move(poly_sym));
}
provpoly_style.add_rule(r);
}
{
rule r;
r.set_filter(parse_expression("[NOM_FR] = 'Québec'"));
{
polygon_symbolizer poly_sym;
put(poly_sym, keys::fill, color(217, 235, 203));
r.append(std::move(poly_sym));
}
provpoly_style.add_rule(r);
}
m.insert_style("provinces",provpoly_style);
// Provinces (polyline)
feature_type_style provlines_style;
stroke provlines_stk (color(0,0,0),1.0);
provlines_stk.add_dash(8, 4);
provlines_stk.add_dash(2, 2);
provlines_stk.add_dash(2, 2);
rule provlines_rule;
provlines_rule.append(line_symbolizer(provlines_stk));
provlines_style.add_rule(provlines_rule);
{
rule r;
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(0,0,0));
put(line_sym,keys::stroke_width,1.0);
dash_array dash;
dash.emplace_back(8,4);
dash.emplace_back(2,2);
dash.emplace_back(2,2);
put(line_sym,keys::stroke_dasharray,dash);
r.append(std::move(line_sym));
}
provlines_style.add_rule(r);
}
m.insert_style("provlines",provlines_style);
// Drainage
feature_type_style qcdrain_style;
rule qcdrain_rule;
qcdrain_rule.set_filter(parse_expression("[HYC] = 8"));
qcdrain_rule.append(polygon_symbolizer(color(153, 204, 255)));
qcdrain_style.add_rule(qcdrain_rule);
{
rule r;
r.set_filter(parse_expression("[HYC] = 8"));
{
polygon_symbolizer poly_sym;
put(poly_sym, keys::fill, color(153, 204, 255));
r.append(std::move(poly_sym));
}
qcdrain_style.add_rule(r);
}
m.insert_style("drainage",qcdrain_style);
// Roads 3 and 4 (The "grey" roads)
feature_type_style roads34_style;
rule roads34_rule;
roads34_rule.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
stroke roads34_rule_stk(color(171,158,137),2.0);
roads34_rule_stk.set_line_cap(ROUND_CAP);
roads34_rule_stk.set_line_join(ROUND_JOIN);
roads34_rule.append(line_symbolizer(roads34_rule_stk));
roads34_style.add_rule(roads34_rule);
{
rule r;
r.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(171,158,137));
put(line_sym,keys::stroke_width,2.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads34_style.add_rule(r);
}
m.insert_style("smallroads",roads34_style);
// Roads 2 (The thin yellow ones)
feature_type_style roads2_style_1;
rule roads2_rule_1;
roads2_rule_1.set_filter(parse_expression("[CLASS] = 2"));
stroke roads2_rule_stk_1(color(171,158,137),4.0);
roads2_rule_stk_1.set_line_cap(ROUND_CAP);
roads2_rule_stk_1.set_line_join(ROUND_JOIN);
roads2_rule_1.append(line_symbolizer(roads2_rule_stk_1));
roads2_style_1.add_rule(roads2_rule_1);
{
rule r;
r.set_filter(parse_expression("[CLASS] = 2"));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(171,158,137));
put(line_sym,keys::stroke_width,4.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads2_style_1.add_rule(r);
}
m.insert_style("road-border", roads2_style_1);
feature_type_style roads2_style_2;
rule roads2_rule_2;
roads2_rule_2.set_filter(parse_expression("[CLASS] = 2"));
stroke roads2_rule_stk_2(color(255,250,115),2.0);
roads2_rule_stk_2.set_line_cap(ROUND_CAP);
roads2_rule_stk_2.set_line_join(ROUND_JOIN);
roads2_rule_2.append(line_symbolizer(roads2_rule_stk_2));
roads2_style_2.add_rule(roads2_rule_2);
{
rule r;
r.set_filter(parse_expression("[CLASS] = 2"));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(255,250,115));
put(line_sym,keys::stroke_width,2.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads2_style_2.add_rule(r);
}
m.insert_style("road-fill", roads2_style_2);
// Roads 1 (The big orange ones, the highways)
feature_type_style roads1_style_1;
rule roads1_rule_1;
roads1_rule_1.set_filter(parse_expression("[CLASS] = 1"));
stroke roads1_rule_stk_1(color(188,149,28),7.0);
roads1_rule_stk_1.set_line_cap(ROUND_CAP);
roads1_rule_stk_1.set_line_join(ROUND_JOIN);
roads1_rule_1.append(line_symbolizer(roads1_rule_stk_1));
roads1_style_1.add_rule(roads1_rule_1);
{
rule r;
r.set_filter(parse_expression("[CLASS] = 1"));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(188,149,28));
put(line_sym,keys::stroke_width,7.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads1_style_1.add_rule(r);
}
m.insert_style("highway-border", roads1_style_1);
feature_type_style roads1_style_2;
rule roads1_rule_2;
roads1_rule_2.set_filter(parse_expression("[CLASS] = 1"));
stroke roads1_rule_stk_2(color(242,191,36),5.0);
roads1_rule_stk_2.set_line_cap(ROUND_CAP);
roads1_rule_stk_2.set_line_join(ROUND_JOIN);
roads1_rule_2.append(line_symbolizer(roads1_rule_stk_2));
roads1_style_2.add_rule(roads1_rule_2);
{
rule r;
r.set_filter(parse_expression("[CLASS] = 1"));
{
line_symbolizer line_sym;
put(line_sym,keys::stroke,color(242,191,36));
put(line_sym,keys::stroke_width,5.0);
put(line_sym,keys::stroke_linecap,ROUND_CAP);
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads1_style_2.add_rule(r);
}
m.insert_style("highway-fill", roads1_style_2);
// Populated Places
feature_type_style popplaces_style;
rule popplaces_rule;
text_symbolizer popplaces_text_symbolizer(parse_expression("[GEONAME]"),"DejaVu Sans Book",10,color(0,0,0));
popplaces_text_symbolizer.set_halo_fill(color(255,255,200));
popplaces_text_symbolizer.set_halo_radius(1);
popplaces_rule.append(popplaces_text_symbolizer);
popplaces_style.add_rule(popplaces_rule);
{
rule r;
{
text_symbolizer text_sym;
text_placements_ptr placement_finder = std::make_shared<text_placements_dummy>();
placement_finder->defaults.format->face_name = "DejaVu Sans Book";
placement_finder->defaults.format->text_size = 10;
placement_finder->defaults.format->fill = color(0,0,0);
placement_finder->defaults.format->halo_fill = color(255,255,200);
placement_finder->defaults.format->halo_radius = 1;
placement_finder->defaults.set_old_style_expression(parse_expression("[GEONAME]"));
put<text_placements_ptr>(text_sym, keys::text_placements_, placement_finder);
r.append(std::move(text_sym));
}
popplaces_style.add_rule(r);
}
m.insert_style("popplaces",popplaces_style );
@ -184,7 +225,7 @@ int main ( int argc , char** argv)
{
parameters p;
p["type"]="shape";
p["file"]="../data/boundaries";
p["file"]="demo/data/boundaries";
p["encoding"]="latin1";
layer lyr("Provinces");
@ -198,7 +239,7 @@ int main ( int argc , char** argv)
{
parameters p;
p["type"]="shape";
p["file"]="../data/qcdrainage";
p["file"]="demo/data/qcdrainage";
layer lyr("Quebec Hydrography");
lyr.set_datasource(datasource_cache::instance().create(p));
lyr.set_srs(srs_lcc);
@ -209,7 +250,7 @@ int main ( int argc , char** argv)
{
parameters p;
p["type"]="shape";
p["file"]="../data/ontdrainage";
p["file"]="demo/data/ontdrainage";
layer lyr("Ontario Hydrography");
lyr.set_datasource(datasource_cache::instance().create(p));
lyr.set_srs(srs_lcc);
@ -221,7 +262,7 @@ int main ( int argc , char** argv)
{
parameters p;
p["type"]="shape";
p["file"]="../data/boundaries_l";
p["file"]="demo/data/boundaries_l";
layer lyr("Provincial borders");
lyr.set_srs(srs_lcc);
lyr.set_datasource(datasource_cache::instance().create(p));
@ -233,7 +274,7 @@ int main ( int argc , char** argv)
{
parameters p;
p["type"]="shape";
p["file"]="../data/roads";
p["file"]="demo/data/roads";
layer lyr("Roads");
lyr.set_srs(srs_lcc);
lyr.set_datasource(datasource_cache::instance().create(p));
@ -249,7 +290,7 @@ int main ( int argc , char** argv)
{
parameters p;
p["type"]="shape";
p["file"]="../data/popplaces";
p["file"]="demo/data/popplaces";
p["encoding"] = "latin1";
layer lyr("Populated Places");
lyr.set_srs(srs_lcc);
@ -321,7 +362,7 @@ int main ( int argc , char** argv)
#endif
}
catch ( const std::exception & ex )
catch ( std::exception const& ex )
{
std::cerr << "### std::exception: " << ex.what() << std::endl;
return EXIT_FAILURE;

View file

@ -26,10 +26,6 @@
#include <mapnik/font_engine_freetype.hpp>
#include "mainwindow.hpp"
// boost
#include <boost/algorithm/string.hpp>
int main( int argc, char **argv )
{
using mapnik::datasource_cache;
@ -75,7 +71,8 @@ int main( int argc, char **argv )
}
else
{
window.zoom_all();
std::shared_ptr<mapnik::Map> map = window.get_map();
if (map) map->zoom_all();
}
if (argc == 4)
{

View file

@ -43,6 +43,7 @@
#include <mapnik/load_map.hpp>
#include <mapnik/save_map.hpp>
#include <mapnik/projection.hpp>
#include <mapnik/util/timer.hpp>
#endif
// qt
@ -53,6 +54,9 @@
#include "layerdelegate.hpp"
#include "about_dialog.hpp"
// boost
#include <boost/algorithm/string.hpp>
MainWindow::MainWindow()
: filename_(),
default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428)
@ -189,6 +193,7 @@ void MainWindow::load_map_file(QString const& filename)
mapWidget_->setMap(map);
try
{
mapnik::auto_cpu_timer t(std::clog, "loading map took: ");
mapnik::load_map(*map,filename.toStdString());
}
catch (mapnik::config_error & ex)
@ -441,3 +446,8 @@ void MainWindow::zoom_all()
mapWidget_->zoomToBox(ext);
}
}
std::shared_ptr<mapnik::Map> MainWindow::get_map()
{
return mapWidget_->getMap();
}

View file

@ -46,6 +46,8 @@ class MainWindow : public QMainWindow
virtual ~MainWindow();
void set_default_extent(double x0,double y0,double x1, double y1);
void set_scaling_factor(double scaling_factor);
public :
std::shared_ptr<mapnik::Map> get_map();
protected:
void closeEvent(QCloseEvent* event);
public slots:
@ -70,7 +72,6 @@ private:
void createContextMenu();
void load_map_file(QString const& filename);
QString currentPath;
QString filename_;
QAbstractItemModel *model;

View file

@ -20,11 +20,7 @@
#include <QtGui>
#define BOOST_CHRONO_HEADER_ONLY
#include <boost/chrono/process_cpu_clocks.hpp>
#include <boost/chrono.hpp>
#include <boost/bind.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/graphics.hpp>
#include <mapnik/layer.hpp>
@ -35,6 +31,7 @@
#include <mapnik/feature_kv_iterator.hpp>
#include <mapnik/config_error.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/util/timer.hpp>
#ifdef HAVE_CAIRO
// cairo
@ -504,12 +501,8 @@ void render_agg(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
try
{
{
boost::chrono::process_cpu_clock::time_point start = boost::chrono::process_cpu_clock::now();
mapnik::auto_cpu_timer t(std::clog, "rendering took: ");
ren.apply();
boost::chrono::process_cpu_clock::duration elapsed = boost::chrono::process_cpu_clock::now() - start;
std::clog << "rendering took: " << boost::chrono::duration_cast<boost::chrono::milliseconds>(elapsed) << "\n";
}
QImage image((uchar*)buf.raw_data(),width,height,QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());
}
@ -541,7 +534,10 @@ void render_cairo(mapnik::Map const& map, double scaling_factor, QPixmap & pix)
mapnik::cairo_surface_ptr image_surface(cairo_image_surface_create(CAIRO_FORMAT_ARGB32,map.width(),map.height()),
mapnik::cairo_surface_closer());
mapnik::cairo_renderer<mapnik::cairo_surface_ptr> renderer(map, image_surface, scaling_factor);
{
mapnik::auto_cpu_timer t(std::clog, "rendering took: ");
renderer.apply();
}
image_32 buf(image_surface);
QImage image((uchar*)buf.raw_data(),buf.width(),buf.height(),QImage::Format_ARGB32);
pix = QPixmap::fromImage(image.rgbSwapped());

View file

@ -189,7 +189,7 @@ struct symbolizer_icon : public boost::static_visitor<QIcon>
{
QPixmap pix(16,16);
QPainter painter(&pix);
mapnik::color const& fill = sym.get_fill();
mapnik::color const& fill = mapnik::get<mapnik::color>(sym, mapnik::keys::fill);
QBrush brush(QColor(fill.red(),fill.green(),fill.blue(),fill.alpha()));
painter.fillRect(0, 0, 16, 16, brush);
return QIcon(pix);
@ -215,10 +215,10 @@ struct symbolizer_icon : public boost::static_visitor<QIcon>
QPixmap pix(48,16);
pix.fill();
QPainter painter(&pix);
mapnik::stroke const& strk = sym.get_stroke();
mapnik::color const& col = strk.get_color();
//mapnik::stroke const& strk = sym.get_stroke();
mapnik::color const& col = mapnik::get<mapnik::color>(sym, mapnik::keys::stroke);
QPen pen(QColor(col.red(),col.green(),col.blue(),col.alpha()));
pen.setWidth(strk.get_width());
pen.setWidth(mapnik::get<double>(sym, mapnik::keys::width));
painter.setPen(pen);
painter.drawLine(0,7,47,7);
//painter.drawLine(7,15,12,0);

View file

@ -25,7 +25,7 @@ from glob import glob
Import('env')
base = './mapnik/'
subdirs = ['','svg','wkt','grid','json','util','text','text/placements','text/formatting']
subdirs = ['','svg','wkt','grid','json','util','group','text','text/placements','text/formatting']
if env['SVG_RENDERER']:
subdirs.append('svg/output')

View file

@ -25,7 +25,7 @@
// mapnik
#include <mapnik/gamma_method.hpp>
#include <mapnik/stroke.hpp> // for line_cap_e, line_join_e, etc
#include <mapnik/symbolizer.hpp>
// agg
@ -35,35 +35,35 @@
namespace mapnik {
template <typename T0, typename T1>
void set_gamma_method(T0 const& obj, T1 & ras_ptr)
template <typename T>
void set_gamma_method(T & ras_ptr, double gamma, gamma_method_enum method)
{
switch (obj.get_gamma_method())
switch (method)
{
case GAMMA_POWER:
ras_ptr->gamma(agg::gamma_power(obj.get_gamma()));
ras_ptr->gamma(agg::gamma_power(gamma));
break;
case GAMMA_LINEAR:
ras_ptr->gamma(agg::gamma_linear(0.0, obj.get_gamma()));
ras_ptr->gamma(agg::gamma_linear(0.0, gamma));
break;
case GAMMA_NONE:
ras_ptr->gamma(agg::gamma_none());
break;
case GAMMA_THRESHOLD:
ras_ptr->gamma(agg::gamma_threshold(obj.get_gamma()));
ras_ptr->gamma(agg::gamma_threshold(gamma));
break;
case GAMMA_MULTIPLY:
ras_ptr->gamma(agg::gamma_multiply(obj.get_gamma()));
ras_ptr->gamma(agg::gamma_multiply(gamma));
break;
default:
ras_ptr->gamma(agg::gamma_power(obj.get_gamma()));
ras_ptr->gamma(agg::gamma_power(gamma));
}
}
template <typename Stroke,typename PathType>
void set_join_caps(Stroke const& stroke_, PathType & stroke)
template <typename Symbolizer, typename PathType, typename Feature>
void set_join_caps(Symbolizer const& sym, PathType & stroke, Feature const& feature)
{
line_join_e join=stroke_.get_line_join();
line_join_enum join = get<line_join_enum>(sym, keys::stroke_linejoin, feature, MITER_JOIN);
switch (join)
{
case MITER_JOIN:
@ -79,7 +79,8 @@ void set_join_caps(Stroke const& stroke_, PathType & stroke)
stroke.generator().line_join(agg::bevel_join);
}
line_cap_e cap=stroke_.get_line_cap();
line_cap_enum cap = get<line_cap_enum>(sym, keys::stroke_linecap, feature, BUTT_CAP);
switch (cap)
{
case BUTT_CAP:
@ -94,11 +95,10 @@ void set_join_caps(Stroke const& stroke_, PathType & stroke)
}
template <typename Stroke,typename Rasterizer>
void set_join_caps_aa(Stroke const& stroke_, Rasterizer & ras)
template <typename Symbolizer, typename Rasterizer, typename Feature>
void set_join_caps_aa(Symbolizer const& sym, Rasterizer & ras, Feature & feature)
{
line_join_e join=stroke_.get_line_join();
line_join_enum join = get<line_join_enum>(sym, keys::stroke_linejoin, feature, MITER_JOIN);
switch (join)
{
case MITER_JOIN:
@ -114,7 +114,8 @@ void set_join_caps_aa(Stroke const& stroke_, Rasterizer & ras)
ras.line_join(agg::outline_no_join);
}
line_cap_e cap=stroke_.get_line_cap();
line_cap_enum cap = get<line_cap_enum>(sym, keys::stroke_linecap, feature, BUTT_CAP);
switch (cap)
{
case BUTT_CAP:

View file

@ -35,7 +35,8 @@
#include <mapnik/image_compositing.hpp> // for composite_mode_e
#include <mapnik/pixel_position.hpp>
#include <mapnik/request.hpp>
#include <mapnik/gamma_method.hpp>
#include <mapnik/renderer_common.hpp>
// boost
#include <memory>
@ -57,21 +58,22 @@ namespace mapnik {
namespace mapnik {
template <typename T>
class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T> >,
template <typename T0, typename T1=label_collision_detector4>
class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T0> >,
private mapnik::noncopyable
{
public:
typedef T buffer_type;
typedef agg_renderer<T> processor_impl_type;
typedef T0 buffer_type;
typedef agg_renderer<T0> processor_impl_type;
typedef T1 detector_type;
// create with default, empty placement detector
agg_renderer(Map const& m, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
agg_renderer(Map const& m, buffer_type & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
// create with external placement detector, possibly non-empty
agg_renderer(Map const &m, T & pixmap, std::shared_ptr<label_collision_detector4> detector,
agg_renderer(Map const &m, buffer_type & pixmap, std::shared_ptr<detector_type> detector,
double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
// pass in mapnik::request object to provide the mutable things per render
agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
agg_renderer(Map const& m, request const& req, buffer_type & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0);
~agg_renderer();
void start_map_processing(Map const& map);
void end_map_processing(Map const& map);
@ -114,13 +116,16 @@ public:
void process(markers_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
void process(group_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
void process(debug_symbolizer const& sym,
feature_impl & feature,
proj_transform const& prj_trans);
inline bool process(rule::symbolizers const& /*syms*/,
mapnik::feature_impl & /*feature*/,
proj_transform const& /*prj_trans*/)
inline bool process(rule::symbolizers const&,
mapnik::feature_impl&,
proj_transform const& )
{
// agg renderer doesn't support processing of multiple symbolizers.
return false;
@ -134,22 +139,22 @@ public:
inline double scale_factor() const
{
return scale_factor_;
return common_.scale_factor_;
}
inline box2d<double> clipping_extent() const
{
if (t_.offset() > 0)
if (common_.t_.offset() > 0)
{
box2d<double> box = query_extent_;
double scale = static_cast<double>(query_extent_.width())/static_cast<double>(width_);
box2d<double> box = common_.query_extent_;
double scale = static_cast<double>(common_.query_extent_.width())/static_cast<double>(common_.width_);
// 3 is used here because at least 3 was needed for the 'style-level-compositing-tiled-0,1' visual test to pass
// TODO - add more tests to hone in on a more robust #
scale *= t_.offset()*3;
scale *= common_.t_.offset()*3;
box.pad(scale);
return box;
}
return query_extent_;
return common_.query_extent_;
}
protected:
@ -164,18 +169,11 @@ private:
buffer_type & pixmap_;
std::shared_ptr<buffer_type> internal_buffer_;
mutable buffer_type * current_buffer_;
CoordTransform t_;
mutable bool style_level_compositing_;
unsigned width_;
unsigned height_;
double scale_factor_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
std::shared_ptr<label_collision_detector4> detector_;
const std::unique_ptr<rasterizer> ras_ptr;
box2d<double> query_extent_;
gamma_method_e gamma_method_;
gamma_method_enum gamma_method_;
double gamma_;
renderer_common common_;
void setup(Map const& m);
};
}

View file

@ -53,20 +53,31 @@ struct geometry_type_attribute
V value(F const& f) const
{
mapnik::value_integer type = 0;
geometry_container::const_iterator itr = f.paths().begin();
geometry_container::const_iterator end = f.paths().end();
for ( ; itr != end; ++itr)
for (auto const& geom : f.paths())
{
if (type != 0 && itr->type() != type)
if (type != 0 && geom.type() != type)
{
return value_integer(4); // Collection
}
type = itr->type();
type = geom.type();
}
return type;
}
};
struct global_attribute
{
std::string name;
explicit global_attribute(std::string const& name_)
: name(name_) {}
template <typename V, typename C>
V const& operator() (C const& ctx)
{
return ctx.get(name);
}
};
}
#endif // MAPNIK_ATTRIBUTE_HPP

View file

@ -27,17 +27,7 @@
#include <mapnik/transform_processor.hpp>
#include <mapnik/noncopyable.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/symbolizer.hpp> // for transform_list_ptr
#include <mapnik/building_symbolizer.hpp>
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/line_pattern_symbolizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/polygon_pattern_symbolizer.hpp>
#include <mapnik/point_symbolizer.hpp>
#include <mapnik/raster_symbolizer.hpp>
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/markers_symbolizer.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/rule.hpp> // for rule::symbolizers
#include <mapnik/expression.hpp> // for expression_ptr, etc
#include <mapnik/expression_node_types.hpp>
@ -45,10 +35,15 @@
#include <mapnik/parse_path.hpp> // for path_processor_type
#include <mapnik/path_expression.hpp> // for path_expression_ptr
#include <mapnik/text/placements/base.hpp> // for text_placements
#include <mapnik/image_scaling.hpp>
#include <mapnik/group/group_symbolizer_properties.hpp>
#include <mapnik/group/group_rule.hpp>
// boost
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
// stl
#include <set>
@ -61,15 +56,6 @@ struct expression_attributes : boost::static_visitor<void>
explicit expression_attributes(Container& names)
: names_(names) {}
void operator() (value_type const& /*x*/) const
{
}
void operator() (geometry_type_attribute const& /*type*/) const
{
// do nothing
}
void operator() (attribute const& attr) const
{
names_.insert(attr.name());
@ -80,7 +66,6 @@ struct expression_attributes : boost::static_visitor<void>
{
boost::apply_visitor(*this, x.left);
boost::apply_visitor(*this, x.right);
}
template <typename Tag>
@ -99,142 +84,127 @@ struct expression_attributes : boost::static_visitor<void>
boost::apply_visitor(*this, x.expr);
}
template <typename T>
void operator() (T const& val) const {}
private:
Container& names_;
};
class group_attribute_collector : public mapnik::noncopyable
{
private:
std::set<std::string>& names_;
bool expand_index_columns_;
public:
group_attribute_collector(std::set<std::string>& names,
bool expand_index_columns)
: names_(names),
expand_index_columns_(expand_index_columns) {}
void operator() (group_symbolizer const& sym);
};
template <typename Container>
struct extract_attribute_names : boost::static_visitor<void>
{
explicit extract_attribute_names(Container& names)
: names_(names),
f_attr_(names) {}
void operator() (mapnik::expression_ptr const& expr) const
{
if (expr)
{
boost::apply_visitor(f_attr_, *expr);
}
}
void operator() (mapnik::transform_type const& expr) const
{
if (expr)
{
transform_processor_type::collect_attributes(names_, *expr);
}
}
void operator() (mapnik::text_placements_ptr const& expr) const
{
if (expr)
{
expression_set::const_iterator it;
expression_set expressions;
// TODO - optimize (dane)
expr->add_expressions(expressions);
for (it=expressions.begin(); it != expressions.end(); ++it)
{
if (*it) boost::apply_visitor(f_attr_, **it);
}
}
}
void operator() (mapnik::path_expression_ptr const& expr) const
{
if (expr)
{
path_processor_type::collect_attributes(*expr,names_);
}
}
template <typename T>
void operator() (T const& val) const {}
private:
Container& names_;
expression_attributes<std::set<std::string> > f_attr_;
};
struct symbolizer_attributes : public boost::static_visitor<>
{
symbolizer_attributes(std::set<std::string>& names,
double & filter_factor)
: names_(names),
filter_factor_(filter_factor),
f_attr(names) {}
: filter_factor_(filter_factor),
f_attrs_(names),
g_attrs_(names, true) {}
template <typename T>
void operator () (T const&) const {}
void operator () (text_symbolizer const& sym)
void operator () (T const& sym)
{
expression_set::const_iterator it;
expression_set expressions;
sym.get_placement_options()->add_expressions(expressions);
for (it=expressions.begin(); it != expressions.end(); it++)
for (auto const& prop : sym.properties)
{
if (*it) boost::apply_visitor(f_attr, **it);
boost::apply_visitor(f_attrs_, prop.second);
}
collect_transform(sym.get_transform());
}
void operator () (point_symbolizer const& sym)
{
path_expression_ptr const& filename_expr = sym.get_filename();
if (filename_expr)
{
path_processor_type::collect_attributes(*filename_expr,names_);
}
collect_transform(sym.get_image_transform());
collect_transform(sym.get_transform());
}
void operator () (line_symbolizer const& sym)
{
collect_transform(sym.get_transform());
}
void operator () (line_pattern_symbolizer const& sym)
{
path_expression_ptr const& filename_expr = sym.get_filename();
if (filename_expr)
{
path_processor_type::collect_attributes(*filename_expr,names_);
}
collect_transform(sym.get_image_transform());
collect_transform(sym.get_transform());
}
void operator () (polygon_symbolizer const& sym)
{
collect_transform(sym.get_transform());
}
void operator () (polygon_pattern_symbolizer const& sym)
{
path_expression_ptr const& filename_expr = sym.get_filename();
if (filename_expr)
{
path_processor_type::collect_attributes(*filename_expr,names_);
}
collect_transform(sym.get_image_transform());
collect_transform(sym.get_transform());
}
void operator () (shield_symbolizer const& sym)
{
expression_set::const_iterator it;
expression_set expressions;
sym.get_placement_options()->add_expressions(expressions);
for (it=expressions.begin(); it != expressions.end(); it++)
{
if (*it) boost::apply_visitor(f_attr, **it);
}
path_expression_ptr const& filename_expr = sym.get_filename();
if (filename_expr)
{
path_processor_type::collect_attributes(*filename_expr,names_);
}
collect_transform(sym.get_image_transform());
collect_transform(sym.get_transform());
}
void operator () (markers_symbolizer const& sym)
{
expression_ptr const& height_expr = sym.get_height();
if (height_expr)
{
boost::apply_visitor(f_attr,*height_expr);
}
expression_ptr const& width_expr = sym.get_width();
if (width_expr)
{
boost::apply_visitor(f_attr,*width_expr);
}
path_expression_ptr const& filename_expr = sym.get_filename();
if (filename_expr)
{
path_processor_type::collect_attributes(*filename_expr,names_);
}
collect_transform(sym.get_image_transform());
collect_transform(sym.get_transform());
}
void operator () (building_symbolizer const& sym)
{
expression_ptr const& height_expr = sym.height();
if (height_expr)
{
boost::apply_visitor(f_attr,*height_expr);
}
collect_transform(sym.get_transform());
}
void operator () (raster_symbolizer const& sym)
{
filter_factor_ = sym.calculate_filter_factor();
boost::optional<double> filter_factor = get_optional<double>(sym, keys::filter_factor);
if (filter_factor)
{
filter_factor_ = *filter_factor;
}
else
{
boost::optional<scaling_method_e> scaling_method = get_optional<scaling_method_e>(sym, keys::scaling);
if (scaling_method && *scaling_method != SCALING_NEAR)
{
filter_factor_ = 2;
}
}
for (auto const& prop : sym.properties)
{
boost::apply_visitor(f_attrs_, prop.second);
}
}
void operator () (group_symbolizer const& sym)
{
g_attrs_(sym);
}
private:
std::set<std::string>& names_;
double & filter_factor_;
expression_attributes<std::set<std::string> > f_attr;
void collect_transform(transform_list_ptr const& trans_expr)
{
if (trans_expr)
{
transform_processor_type::collect_attributes(names_, *trans_expr);
}
}
extract_attribute_names<std::set<std::string> > f_attrs_;
group_attribute_collector g_attrs_;
};
@ -254,11 +224,10 @@ public:
void operator() (RuleType const& r)
{
typename RuleType::symbolizers const& symbols = r.get_symbolizers();
typename RuleType::symbolizers::const_iterator symIter=symbols.begin();
symbolizer_attributes s_attr(names_,filter_factor_);
while (symIter != symbols.end())
for (auto symbol : symbols)
{
boost::apply_visitor(s_attr,*symIter++);
boost::apply_visitor(s_attr,symbol);
}
expression_ptr const& expr = r.get_filter();
@ -271,6 +240,67 @@ public:
}
};
inline void group_attribute_collector::operator() (group_symbolizer const& sym)
{
// find all column names referenced in the group symbolizer
std::set<std::string> group_columns;
attribute_collector column_collector(group_columns);
expression_attributes<std::set<std::string> > rk_attr(group_columns);
// get columns from symbolizer repeat key
expression_ptr repeat_key = get<mapnik::expression_ptr>(sym, keys::repeat_key);
if (repeat_key)
{
boost::apply_visitor(rk_attr, *repeat_key);
}
// get columns from child rules and symbolizers
group_symbolizer_properties_ptr props = get<group_symbolizer_properties_ptr>(sym, keys::group_properties);
if (props) {
for (auto const& rule : props->get_rules())
{
// note that this recurses down on to the symbolizer
// internals too, so we get all free variables.
column_collector(*rule);
// still need to collect repeat key columns
if (rule->get_repeat_key())
{
boost::apply_visitor(rk_attr, *(rule->get_repeat_key()));
}
}
}
// get indexed column names
int start = get<value_integer>(sym, keys::start_column);
int end = start + get<value_integer>(sym, keys::num_columns);
for (auto const& col_name : group_columns)
{
if (expand_index_columns_ && col_name.find('%') != std::string::npos)
{
// Note: ignore column name if it is '%' by itself.
// '%' is a special case to access the index value itself,
// rather than acessing indexed columns from data source.
if (col_name.size() > 1)
{
// Indexed column name. add column name for each index value.
for (int col_idx = start; col_idx < end; ++col_idx)
{
std::string col_idx_name = col_name;
boost::replace_all(col_idx_name, "%", boost::lexical_cast<std::string>(col_idx));
names_.insert(col_idx_name);
}
}
}
else
{
// This is not an indexed column, or we are ignoring indexes.
// Insert the name as is.
names_.insert(col_name);
}
}
}
} // namespace mapnik
#endif // MAPNIK_ATTRIBUTE_COLLECTOR_HPP

View file

@ -1,54 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_BUILDING_SYMBOLIZER_HPP
#define MAPNIK_BUILDING_SYMBOLIZER_HPP
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/config.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/expression.hpp>
namespace mapnik
{
struct MAPNIK_DECL building_symbolizer : public symbolizer_base
{
building_symbolizer();
building_symbolizer(color const& fill, expression_ptr const& height);
color const& get_fill() const;
void set_fill(color const& fill);
expression_ptr const& height() const;
void set_height(expression_ptr const& height);
void set_opacity(double opacity);
double get_opacity() const;
private:
color fill_;
expression_ptr height_;
double opacity_;
};
}
#endif // MAPNIK_BUILDING_SYMBOLIZER_HPP

View file

@ -28,7 +28,6 @@
#include <mapnik/debug.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/color.hpp>
#include <mapnik/stroke.hpp>
#include <mapnik/image_data.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/font_engine_freetype.hpp>
@ -38,6 +37,7 @@
#include <mapnik/text/glyph_info.hpp>
#include <mapnik/vertex.hpp>
#include <mapnik/noncopyable.hpp>
#include <mapnik/symbolizer.hpp>
// boost
#include <memory>

View file

@ -37,6 +37,7 @@
#include <mapnik/cairo_context.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/ctrans.hpp> // for CoordTransform
#include <mapnik/renderer_common.hpp>
// cairo
#include <cairo.h>
@ -109,6 +110,12 @@ public:
void process(markers_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
void process(group_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
void process(debug_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
inline bool process(rule::symbolizers const& /*syms*/,
mapnik::feature_impl & /*feature*/,
proj_transform const& /*prj_trans*/)
@ -128,7 +135,7 @@ public:
inline double scale_factor() const
{
return scale_factor_;
return common_.scale_factor_;
}
void render_marker(pixel_position const& pos,
@ -140,15 +147,8 @@ public:
protected:
Map const& m_;
cairo_context context_;
unsigned width_;
unsigned height_;
double scale_factor_;
CoordTransform t_;
std::shared_ptr<freetype_engine> font_engine_;
face_manager<freetype_engine> font_manager_;
renderer_common common_;
cairo_face_manager face_manager_;
std::shared_ptr<label_collision_detector4> detector_;
box2d<double> query_extent_;
void setup(Map const& m);
};

View file

@ -74,16 +74,9 @@ public:
void premultiply();
void demultiply();
color& operator=(color const& rhs)
color& operator=(color rhs)
{
if (this==&rhs)
return *this;
red_ = rhs.red_;
green_ = rhs.green_;
blue_ = rhs.blue_;
alpha_ = rhs.alpha_;
swap(rhs);
return *this;
}
@ -139,6 +132,14 @@ public:
return static_cast<unsigned>((alpha_ << 24) | (blue_ << 16) | (green_ << 8) | (red_)) ;
#endif
}
private:
void swap(color & rhs)
{
std::swap(red_, rhs.red_);
std::swap(green_,rhs.green_);
std::swap(blue_,rhs.blue_);
std::swap(alpha_,rhs.alpha_);
}
};
template <typename charT, typename traits>

View file

@ -54,22 +54,34 @@ public:
: x(),y() {}
coord(T x_,T y_)
: x(x_),y(y_) {}
coord(coord<T,2> const& rhs)
: x(rhs.x),
y(rhs.y) {}
template <typename T2>
coord (const coord<T2,2>& rhs)
coord (coord<T2,2> const& rhs)
: x(type(rhs.x)),
y(type(rhs.y)) {}
coord(coord<T,2> && rhs) noexcept
: x(std::move(rhs.x)),
y(std::move(rhs.y)) {}
coord<T,2>& operator=(coord<T,2> rhs)
{
swap(rhs);
return *this;
}
template <typename T2>
coord<T,2>& operator=(const coord<T2,2>& rhs)
{
if ((void*)this==(void*)&rhs)
{
return *this;
}
x=type(rhs.x);
y=type(rhs.y);
coord<T,2> tmp(rhs);
swap(rhs);
return *this;
}
template <typename T2>
bool operator==(coord<T2,2> const& rhs)
{
@ -116,6 +128,12 @@ public:
y/=t;
return *this;
}
private:
void swap(coord<T,2> & rhs)
{
std::swap(this->x, rhs.x);
std::swap(this->y, rhs.y);
}
};
template <typename T>
@ -130,24 +148,38 @@ public:
: x(),y(),z() {}
coord(T x_,T y_,T z_)
: x(x_),y(y_),z(z_) {}
template <typename T2>
coord (const coord<T2,3>& rhs)
coord (coord<T2,3> const& rhs)
: x(type(rhs.x)),
y(type(rhs.y)),
z(type(rhs.z)) {}
template <typename T2>
coord<T,3>& operator=(const coord<T2,3>& rhs)
{
if ((void*)this==(void*)&rhs)
coord(coord<T,3> && rhs) noexcept
: x(std::move(rhs.x)),
y(std::move(rhs.y)),
z(std::move(rhs.z)) {}
coord<T,3> operator=(coord<T,3> rhs)
{
swap(rhs);
return *this;
}
x=type(rhs.x);
y=type(rhs.y);
z=type(rhs.z);
template <typename T2>
coord<T,3>& operator=(coord<T2,3> const& rhs)
{
coord<T,3> tmp(rhs);
swap(tmp);
return *this;
}
private:
void swap(coord<T,3> & rhs)
{
std::swap(this->x, rhs.x);
std::swap(this->y, rhs.y);
std::swap(this->z, rhs.z);
}
};
typedef coord<double,2> coord2d;

View file

@ -104,11 +104,7 @@ struct alpha_conv_impl
struct hsl_conv_impl
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template<typename T>
#else
template<typename T0,typename T1, typename T2, typename T3>
#endif
struct result
{
typedef void type;

View file

@ -1,53 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_DISTANCE_HPP
#define MAPNIK_DISTANCE_HPP
#include <mapnik/coord.hpp>
namespace mapnik
{
struct ellipsoid;
// great-circle distance
class great_circle_distance
{
public:
double operator() (coord2d const& pt0, coord2d const& pt1) const;
};
// vincenty distance
/*
class vincenty_distance : boost::noncopyble
{
public:
vincenty_distance(ellipsoid const& e);
double operator() (coord2d const& pt0, coord2d const& pt1) const;
private:
ellipsoid & e_;
};
*/
}
#endif // MAPNIK_DISTANCE_HPP

View file

@ -0,0 +1,244 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_EVALUATE_GLOBAL_ATTRIBUTES_HPP
#define MAPNIK_EVALUATE_GLOBAL_ATTRIBUTES_HPP
#include <mapnik/map.hpp>
#include <mapnik/feature_type_style.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/symbolizer_hash.hpp>
#include <mapnik/attribute.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/expression_node.hpp>
#include <mapnik/color_factory.hpp>
// boost
#include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp>
#include <boost/regex.hpp>
#if defined(BOOST_REGEX_HAS_ICU)
#include <boost/regex/icu.hpp>
#endif
namespace mapnik {
namespace {
template <typename T, typename Attributes>
struct evaluate_expression : boost::static_visitor<T>
{
typedef T value_type;
explicit evaluate_expression(Attributes const& attributes)
: attributes_(attributes) {}
value_type operator() (attribute const& attr) const
{
throw std::runtime_error("can't evaluate feature attributes in this context");
}
value_type operator() (global_attribute const& attr) const
{
auto itr = attributes_.find(attr.name);
if (itr != attributes_.end())
{
return itr->second;
}
return value_type();// throw?
}
value_type operator() (geometry_type_attribute const& geom) const
{
throw std::runtime_error("can't evaluate geometry_type attributes in this context");
}
value_type operator() (binary_node<tags::logical_and> const & x) const
{
return (boost::apply_visitor(*this, x.left).to_bool())
&& (boost::apply_visitor(*this, x.right).to_bool());
}
value_type operator() (binary_node<tags::logical_or> const & x) const
{
return (boost::apply_visitor(*this,x.left).to_bool())
|| (boost::apply_visitor(*this,x.right).to_bool());
}
template <typename Tag>
value_type operator() (binary_node<Tag> const& x) const
{
typename make_op<Tag>::type operation;
return operation(boost::apply_visitor(*this, x.left),
boost::apply_visitor(*this, x.right));
}
template <typename Tag>
value_type operator() (unary_node<Tag> const& x) const
{
typename make_op<Tag>::type func;
return func(boost::apply_visitor(*this, x.expr));
}
value_type operator() (unary_node<tags::logical_not> const& x) const
{
return ! (boost::apply_visitor(*this,x.expr).to_bool());
}
value_type operator() (regex_match_node const& x) const
{
value_type v = boost::apply_visitor(*this, x.expr);
#if defined(BOOST_REGEX_HAS_ICU)
return boost::u32regex_match(v.to_unicode(),x.pattern);
#else
return boost::regex_match(v.to_string(),x.pattern);
#endif
}
value_type operator() (regex_replace_node const& x) const
{
value_type v = boost::apply_visitor(*this, x.expr);
#if defined(BOOST_REGEX_HAS_ICU)
return boost::u32regex_replace(v.to_unicode(),x.pattern,x.format);
#else
std::string repl = boost::regex_replace(v.to_string(),x.pattern,x.format);
mapnik::transcoder tr_("utf8");
return tr_.transcode(repl.c_str());
#endif
}
template <typename ValueType>
value_type operator() (ValueType const& val) const
{
return value_type(val);
}
Attributes const& attributes_;
};
template <typename T, typename Attributes>
struct assign_value : boost::static_visitor<> {};
template <typename Attributes>
struct assign_value<expression_ptr,Attributes> : boost::static_visitor<>
{
assign_value(symbolizer_base::value_type & val, expression_ptr const& expr, Attributes const& attributes)
: val_(val),
expr_(expr),
attributes_(attributes) {}
void operator() (color const& default_val) const
{
// evaluate expression as a string then parse as css color
std::string str = boost::apply_visitor(mapnik::evaluate_expression<mapnik::value,
Attributes>(attributes_),*expr_).to_string();
try { val_ = parse_color(str); }
catch (...) { val_ = default_val;}
}
void operator() (value_double default_val) const
{
val_ = boost::apply_visitor(mapnik::evaluate_expression<mapnik::value, Attributes>(attributes_),*expr_).to_double();
}
void operator() (value_integer default_val) const
{
val_ = boost::apply_visitor(mapnik::evaluate_expression<mapnik::value, Attributes>(attributes_),*expr_).to_int();
}
void operator() (value_bool default_val) const
{
val_ = boost::apply_visitor(mapnik::evaluate_expression<mapnik::value, Attributes>(attributes_),*expr_).to_bool();
}
template <typename T>
void operator() (T const& default_val) const
{
// no-op
}
symbolizer_base::value_type & val_;
expression_ptr const& expr_;
Attributes const& attributes_;
};
}
struct evaluate_global_attributes : mapnik::noncopyable
{
template <typename Attributes>
struct evaluator : boost::static_visitor<>
{
evaluator(symbolizer_base::cont_type::value_type & prop, Attributes const& attributes)
: prop_(prop),
attributes_(attributes) {}
void operator() (expression_ptr const& expr) const
{
auto const& meta = get_meta(prop_.first);
boost::apply_visitor(assign_value<expression_ptr,Attributes>(prop_.second, expr, attributes_), std::get<1>(meta));
}
template <typename T>
void operator() (T const& val) const
{
// no-op
}
symbolizer_base::cont_type::value_type & prop_;
Attributes const& attributes_;
};
template <typename Attributes>
struct extract_symbolizer : boost::static_visitor<>
{
extract_symbolizer(Attributes const& attributes)
: attributes_(attributes) {}
template <typename Symbolizer>
void operator() (Symbolizer & sym) const
{
for (auto & prop : sym.properties)
{
boost::apply_visitor(evaluator<Attributes>(prop, attributes_), prop.second);
}
}
Attributes const& attributes_;
};
template <typename Attributes>
static void apply(Map & m, Attributes const& attributes)
{
for ( auto & val : m.styles() )
{
for (auto & rule : val.second.get_rules_nonconst())
{
for (auto & sym : rule)
{
boost::apply_visitor(extract_symbolizer<Attributes>(attributes), sym);
}
}
}
}
};
}
#endif // MAPNIK_EVALUATE_GLOBAL_ATTRIBUTES_HPP

View file

@ -38,6 +38,7 @@
namespace mapnik
{
template <typename T0, typename T1>
struct evaluate : boost::static_visitor<T1>
{
@ -77,6 +78,11 @@ struct evaluate : boost::static_visitor<T1>
return attr.value<value_type,feature_type>(feature_);
}
value_type operator() (global_attribute const& attr) const
{
return value_type();// shouldn't get here
}
value_type operator() (geometry_type_attribute const& geom) const
{
return geom.value<value_type,feature_type>(feature_);
@ -84,22 +90,22 @@ struct evaluate : boost::static_visitor<T1>
value_type operator() (binary_node<tags::logical_and> const & x) const
{
return (boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.left).to_bool())
&& (boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.right).to_bool());
return (boost::apply_visitor(*this, x.left).to_bool())
&& (boost::apply_visitor(*this, x.right).to_bool());
}
value_type operator() (binary_node<tags::logical_or> const & x) const
{
return (boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.left).to_bool())
|| (boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.right).to_bool());
return (boost::apply_visitor(*this,x.left).to_bool())
|| (boost::apply_visitor(*this,x.right).to_bool());
}
template <typename Tag>
value_type operator() (binary_node<Tag> const& x) const
{
typename make_op<Tag>::type operation;
return operation(boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.left),
boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.right));
return operation(boost::apply_visitor(*this, x.left),
boost::apply_visitor(*this, x.right));
}
template <typename Tag>
@ -111,12 +117,12 @@ struct evaluate : boost::static_visitor<T1>
value_type operator() (unary_node<tags::logical_not> const& x) const
{
return ! (boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.expr).to_bool());
return ! (boost::apply_visitor(*this,x.expr).to_bool());
}
value_type operator() (regex_match_node const& x) const
{
value_type v = boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.expr);
value_type v = boost::apply_visitor(*this, x.expr);
#if defined(BOOST_REGEX_HAS_ICU)
return boost::u32regex_match(v.to_unicode(),x.pattern);
#else
@ -127,7 +133,7 @@ struct evaluate : boost::static_visitor<T1>
value_type operator() (regex_replace_node const& x) const
{
value_type v = boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.expr);
value_type v = boost::apply_visitor(*this, x.expr);
#if defined(BOOST_REGEX_HAS_ICU)
return boost::u32regex_replace(v.to_unicode(),x.pattern,x.format);
#else

View file

@ -65,11 +65,7 @@ struct unicode_impl
struct regex_match_impl
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef expr_node type;
@ -87,11 +83,7 @@ struct regex_match_impl
struct regex_replace_impl
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T>
#else
template <typename T0, typename T1, typename T2>
#endif
struct result
{
typedef expr_node type;
@ -155,7 +147,10 @@ struct expression_grammar : qi::grammar<Iterator, expr_node(), space_type>
qi::rule<Iterator, std::string() > regex_match_expr;
qi::rule<Iterator, expr_node(expr_node), qi::locals<std::string,std::string>, space_type> regex_replace_expr;
qi::rule<Iterator, std::string() , space_type> attr;
qi::rule<Iterator, std::string(), qi::locals<char> > ustring;
qi::rule<Iterator, std::string() , space_type> global_attr;
qi::rule<Iterator, std::string(), qi::locals<char> > quoted_ustring;
qi::rule<Iterator, std::string(), space_type> ustring;
qi::symbols<char const, char const> unesc_char;
qi::rule<Iterator, char() > quote_char;
geometry_types geom_type;

View file

@ -70,7 +70,6 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
regex_match_(regex_match_impl(tr)),
regex_replace_(regex_replace_impl(tr))
{
using boost::phoenix::construct;
qi::_1_type _1;
qi::_a_type _a;
qi::_b_type _b;
@ -81,8 +80,11 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
qi::double_type double_;
qi::hex_type hex;
qi::omit_type omit;
qi::alpha_type alpha;
qi::alnum_type alnum;
standard_wide::char_type char_;
standard_wide::no_case_type no_case;
using boost::phoenix::construct;
expr = logical_expr.alias();
@ -110,16 +112,16 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
regex_match_expr = lit(".match")
>> lit('(')
>> ustring [_val = _1]
>> quoted_ustring [_val = _1]
>> lit(')')
;
regex_replace_expr =
lit(".replace")
>> lit('(')
>> ustring [_a = _1]
>> quoted_ustring [_a = _1]
>> lit(',')
>> ustring [_b = _1]
>> quoted_ustring [_b = _1]
>> lit(')') [_val = regex_replace_(_r1,_a,_b)]
;
@ -158,10 +160,13 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
| no_case[lit("false")] [_val = false]
| no_case[lit("null")] [_val = value_null() ]
| no_case[geom_type][_val = _1 ]
| ustring [_val = unicode_(_1) ]
| quoted_ustring [_val = unicode_(_1)]
| lit("[mapnik::geometry_type]")[_val = construct<mapnik::geometry_type_attribute>()]
| attr [_val = construct<mapnik::attribute>( _1 ) ]
| global_attr [_val = construct<mapnik::global_attribute>( _1 )]
| lit("not") >> expr [_val = !_1]
| '(' >> expr [_val = _1 ] >> ')'
| ustring[_val = unicode_(_1)] // if we get here then try parsing as unquoted string
;
unesc_char.add("\\a", '\a')("\\b", '\b')("\\f", '\f')("\\n", '\n')
@ -169,11 +174,13 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
("\\\'", '\'')("\\\"", '\"')
;
ustring %= no_skip[alpha >> *alnum];
quote_char %= char_('\'') | char_('"');
ustring %= omit[quote_char[_a = _1]]
quoted_ustring %= omit[quote_char[_a = _1]]
>> *(unesc_char | "\\x" >> hex | (char_ - lit(_a)))
>> lit(_a);
attr %= '[' >> no_skip[+~char_(']')] >> ']';
global_attr %= '@' >> no_skip[alpha >> * (alnum | char_('-'))];
}

View file

@ -167,13 +167,14 @@ struct regex_replace_node;
typedef mapnik::value value_type;
typedef boost::mpl::vector24<
typedef boost::mpl::vector25<
value_null,
value_bool,
value_integer,
value_double,
value_unicode_string,
attribute,
global_attribute,
geometry_type_attribute,
boost::recursive_wrapper<unary_node<tags::negate> >,
boost::recursive_wrapper<binary_node<tags::plus> >,

View file

@ -1,112 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_FASTMATH_HPP
#define MAPNIK_FASTMATH_HPP
/* Timings:
* fast_sin(not inlined) 8.95s
* fast_sin(inlined) 6.64s
* sin 28.7s
* => 4.3x speedup
* worst case accuracy abs(fast_sin(x)/sin(x) - 1) = 0.000018 (at 0.664, M_PI-0.664, M_PI+0.664; 2*M_PI-0.664)
*/
static inline double fast_sin(double x)
{
bool negative = false;
double result;
while (x > 2*M_PI) x -= 2*M_PI;
while (x < 0) x += 2*M_PI;
if (x > M_PI) {
x -= M_PI;
negative = true;
}
if (x < 0.664 || x > M_PI-0.664) {
//series expansion at x=0: x-x^3/6+x^5/120-x^7/5040+...
if (x > M_PI-0.664) x = M_PI - x;
result = x*(1. + x*x*(-1/6. + x*x/120.));
} else {
//series expansion at x=pi/2
//1-x^2/2+x^4/24-x^6/720+x^8/40320+...
x -= M_PI/2;
result = 1. + x*x*(-1/2.+x*x*(1/24. + x*x*(-1/720.)));
}
return negative?-result:result;
}
static inline double fast_cos(double x)
{
return fast_sin(x + M_PI/2);
}
static inline double atan_helper(double x)
{
//Series expansion at x=0:
// x-x^3/3+x^5/5-x^7/7+...
if (x < 0.30) {
return x * (1 + x*x*(-1/3. + x*x*(1/5.) + x*x*(-1/7. + x*x*(1/9.))));
}
else if (x < 0.71) {
//Series expansion at x=0.5
//atan(1/2)+(4 x)/5-(8 x^2)/25-(16 x^3)/375+(96 x^4)/625 +...
x -= 0.5;
return 0.463647609000806116 /*atan(0.5) */ + x *(4./5. + x *(-8./25. + (-16./375.*x)));
} else {
//series expansion at x=1:
//pi/4+x/2-x^2/4+x^3/12-x^5/40+...
x -= 1;
return (M_PI/4.) + x * (1/2. + x*(-1/4. +x*(1/12. + x * (-1/40.))));
}
}
/*
* fast_atan(not inlined) 6.74s
* fast_atan(everything inlined) 6.78s
* fast_atan(only helper inlined) 6.75
* atan 27.5s
* => 4x speedup
* worst case accuracy abs(fast_atan(x)/atan(x) - 1) = 0.000271 (at 1.411)
*/
double inline fast_atan(double x)
{
double negative = false;
double result;
if (x < 0) {
x = -x;
negative = true;
}
if (x <= 1) result = atan_helper(x); else result = M_PI/2 - atan_helper(1/x);
return negative?-result:result;
}
static inline double fast_atan2(double y, double x)
{
double result = M_PI/2;
if (x == 0 && y == 0) return 0;
if (x != 0) result = fast_atan(y/x);
if (x < 0 && y >= 0) return result + M_PI;
if (x <= 0 && y < 0) return -M_PI + result;
return result;
}
#endif // MAPNIK_FASTMATH_HPP

View file

@ -90,7 +90,7 @@ private:
typedef context<std::map<std::string,std::size_t> > context_type;
typedef std::shared_ptr<context_type> context_ptr;
static const value default_value;
static const value default_feature_value;
class MAPNIK_DECL feature_impl : private mapnik::noncopyable
{
@ -166,14 +166,14 @@ public:
if (itr != ctx_->mapping_.end())
return get(itr->second);
else
return default_value;
return default_feature_value;
}
inline value_type const& get(std::size_t index) const
{
if (index < data_.size())
return data_[index];
return default_value;
return default_feature_value;
}
inline std::size_t size() const

View file

@ -32,6 +32,7 @@
#include <boost/tuple/tuple.hpp>
#include <boost/iterator/iterator_traits.hpp>
#include <boost/iterator/iterator_facade.hpp>
#include <boost/iterator/iterator_adaptor.hpp>
#include <boost/iterator/filter_iterator.hpp>
// stl
@ -79,4 +80,3 @@ typedef boost::filter_iterator<value_not_null, feature_kv_iterator> feature_kv_i
}
#endif // MAPNIK_FEATURE_KV_ITERATOR_HPP

View file

@ -65,10 +65,8 @@ private:
bool image_filters_inflate_;
public:
feature_type_style();
feature_type_style(feature_type_style const& rhs);
feature_type_style& operator=(feature_type_style const& rhs);
feature_type_style& operator=(feature_type_style rhs);
void add_rule(rule const& rule);
rules const& get_rules() const;

View file

@ -35,8 +35,8 @@ class filter_featureset : public Featureset
typedef T filter_type;
public:
filter_featureset(featureset_ptr const& fs, filter_type const& filter)
: fs_(fs), filter_(filter) {}
filter_featureset(featureset_ptr const& fs, filter_type && filter)
: fs_(fs), filter_(std::move(filter)) {}
feature_ptr next()
{

View file

@ -27,7 +27,6 @@
#include <mapnik/config.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/noncopyable.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/pixel_position.hpp>

View file

@ -247,6 +247,46 @@ double path_length(PathType & path)
return length;
}
template <typename PathType>
bool hit_test_first(PathType & path, double x, double y, double tol)
{
bool inside=false;
double x0 = 0;
double y0 = 0;
double x1 = 0;
double y1 = 0;
path.rewind(0);
unsigned command = path.vertex(&x0, &y0);
if (command == SEG_END)
{
return false;
}
unsigned count = 0;
while (SEG_END != (command = path.vertex(&x1, &y1)))
{
if (command == SEG_CLOSE)
{
break;
}
++count;
if (command == SEG_MOVETO)
{
x0 = x1;
y0 = y1;
continue;
}
if ((((y1 <= y) && (y < y0)) ||
((y0 <= y) && (y < y1))) &&
(x < (x0 - x1) * (y - y1)/ (y0 - y1) + x1))
inside=!inside;
x0 = x1;
y0 = y1;
}
return inside;
}
namespace label {
template <typename PathType>

View file

@ -24,7 +24,7 @@
#define MAPNIK_GRID_MARKER_HELPERS_HPP
// mapnik
#include <mapnik/markers_symbolizer.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/markers_placement.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geom_util.hpp>
@ -73,10 +73,23 @@ struct raster_markers_rasterizer_dispatch_grid
//pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op()));
}
raster_markers_rasterizer_dispatch_grid(raster_markers_rasterizer_dispatch_grid &&d)
: buf_(d.buf_), pixf_(d.pixf_), renb_(d.renb_), ras_(d.ras_), src_(d.src_),
marker_trans_(d.marker_trans_), sym_(d.sym_), detector_(d.detector_),
scale_factor_(d.scale_factor_), feature_(d.feature_), pixmap_(d.pixmap_),
placed_(d.placed_)
{
}
template <typename T>
void add_path(T & path)
{
marker_placement_e placement_method = sym_.get_marker_placement();
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, false);
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, false);
double spacing = get<double>(sym_, keys::spacing, 100.0);
double max_error = get<double>(sym_, keys::max_error, 0.2);
box2d<double> bbox_(0,0, src_.width(),src_.height());
if (placement_method != MARKER_LINE_PLACEMENT ||
path.type() == geometry_type::types::Point)
@ -101,11 +114,11 @@ struct raster_markers_rasterizer_dispatch_grid
agg::trans_affine matrix = marker_trans_;
matrix.translate(x,y);
box2d<double> transformed_bbox = bbox_ * matrix;
if (sym_.get_allow_overlap() ||
if (allow_overlap ||
detector_.has_placement(transformed_bbox))
{
render_raster_marker(matrix);
if (!sym_.get_ignore_placement())
if (!ignore_placement)
{
detector_.insert(transformed_bbox);
}
@ -119,11 +132,11 @@ struct raster_markers_rasterizer_dispatch_grid
else
{
markers_placement<T, label_collision_detector4> placement(path, bbox_, marker_trans_, detector_,
sym_.get_spacing() * scale_factor_,
sym_.get_max_error(),
sym_.get_allow_overlap());
spacing * scale_factor_,
max_error,
allow_overlap);
double x, y, angle;
while (placement.get_point(x, y, angle, sym_.get_ignore_placement()))
while (placement.get_point(x, y, angle, ignore_placement))
{
agg::trans_affine matrix = marker_trans_;
matrix.rotate(angle);
@ -181,10 +194,13 @@ template <typename BufferType, typename SvgRenderer, typename Rasterizer, typena
struct vector_markers_rasterizer_dispatch_grid
{
typedef typename SvgRenderer::renderer_base renderer_base;
typedef typename SvgRenderer::vertex_source_type vertex_source_type;
typedef typename SvgRenderer::attribute_source_type attribute_source_type;
typedef typename renderer_base::pixfmt_type pixfmt_type;
vector_markers_rasterizer_dispatch_grid(BufferType & render_buffer,
SvgRenderer & svg_renderer,
vertex_source_type &path,
const attribute_source_type &attrs,
Rasterizer & ras,
box2d<double> const& bbox,
agg::trans_affine const& marker_trans,
@ -196,7 +212,7 @@ struct vector_markers_rasterizer_dispatch_grid
: buf_(render_buffer),
pixf_(buf_),
renb_(pixf_),
svg_renderer_(svg_renderer),
svg_renderer_(path, attrs),
ras_(ras),
bbox_(bbox),
marker_trans_(marker_trans),
@ -211,10 +227,24 @@ struct vector_markers_rasterizer_dispatch_grid
//pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op()));
}
vector_markers_rasterizer_dispatch_grid(vector_markers_rasterizer_dispatch_grid &&d)
: buf_(d.buf_), pixf_(d.pixf_), svg_renderer_(std::move(d.svg_renderer_)), ras_(d.ras_),
bbox_(d.bbox_), marker_trans_(d.marker_trans_), sym_(d.sym_), detector_(d.detector_),
scale_factor_(d.scale_factor_), feature_(d.feature_), pixmap_(d.pixmap_),
placed_(d.placed_)
{
}
template <typename T>
void add_path(T & path)
{
marker_placement_e placement_method = sym_.get_marker_placement();
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, false);
double spacing = get<double>(sym_, keys::spacing, 100.0);
double max_error = get<double>(sym_, keys::max_error, 0.2);
double opacity = get<double>(sym_,keys::opacity, 1.0);
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, false);
if (placement_method != MARKER_LINE_PLACEMENT ||
path.type() == geometry_type::types::Point)
{
@ -238,11 +268,11 @@ struct vector_markers_rasterizer_dispatch_grid
agg::trans_affine matrix = marker_trans_;
matrix.translate(x,y);
box2d<double> transformed_bbox = bbox_ * matrix;
if (sym_.get_allow_overlap() ||
if (allow_overlap ||
detector_.has_placement(transformed_bbox))
{
svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), matrix, sym_.get_opacity(), bbox_);
if (!sym_.get_ignore_placement())
svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), matrix, opacity, bbox_);
if (!ignore_placement)
{
detector_.insert(transformed_bbox);
}
@ -256,16 +286,16 @@ struct vector_markers_rasterizer_dispatch_grid
else
{
markers_placement<T, Detector> placement(path, bbox_, marker_trans_, detector_,
sym_.get_spacing() * scale_factor_,
sym_.get_max_error(),
sym_.get_allow_overlap());
spacing * scale_factor_,
max_error,
allow_overlap);
double x, y, angle;
while (placement.get_point(x, y, angle, sym_.get_ignore_placement()))
while (placement.get_point(x, y, angle, ignore_placement))
{
agg::trans_affine matrix = marker_trans_;
matrix.rotate(angle);
matrix.translate(x, y);
svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), matrix, sym_.get_opacity(), bbox_);
svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), matrix, opacity, bbox_);
if (!placed_)
{
pixmap_.add_feature(feature_);
@ -279,7 +309,7 @@ private:
BufferType & buf_;
pixfmt_type pixf_;
renderer_base renb_;
SvgRenderer & svg_renderer_;
SvgRenderer svg_renderer_;
Rasterizer & ras_;
box2d<double> const& bbox_;
agg::trans_affine const& marker_trans_;

View file

@ -35,6 +35,7 @@
#include <mapnik/ctrans.hpp> // for CoordTransform
#include <mapnik/image_compositing.hpp> // for composite_mode_e
#include <mapnik/pixel_position.hpp>
#include <mapnik/renderer_common.hpp>
// boost
@ -107,6 +108,9 @@ public:
void process(markers_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
void process(group_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
inline bool process(rule::symbolizers const& /*syms*/,
mapnik::feature_impl & /*feature*/,
proj_transform const& /*prj_trans*/)
@ -124,20 +128,13 @@ public:
}
inline double scale_factor() const
{
return scale_factor_;
return common_.scale_factor_;
}
private:
buffer_type & pixmap_;
unsigned width_;
unsigned height_;
double scale_factor_;
CoordTransform t_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
std::shared_ptr<label_collision_detector4> detector_;
const std::unique_ptr<grid_rasterizer> ras_ptr;
box2d<double> query_extent_;
renderer_common common_;
void setup(Map const& m);
};
}

View file

@ -0,0 +1,94 @@
/*****************************************************************************
*
* 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_GROUP_LAYOUT_HPP
#define MAPNIK_GROUP_LAYOUT_HPP
// boost
#include <boost/variant.hpp>
namespace mapnik
{
struct simple_row_layout
{
public:
simple_row_layout(double item_margin = 0.0)
: item_margin_(item_margin)
{
}
double get_item_margin() const
{
return item_margin_;
}
void set_item_margin(double item_margin)
{
item_margin_ = item_margin;
}
private:
double item_margin_;
};
struct pair_layout
{
public:
pair_layout(double item_margin = 1.0, double max_difference = - 1.0)
: item_margin_(item_margin),
max_difference_(max_difference)
{
}
double get_item_margin() const
{
return item_margin_;
}
void set_item_margin(double item_margin)
{
item_margin_ = item_margin;
}
double get_max_difference() const
{
return max_difference_;
}
void set_max_difference(double max_difference)
{
max_difference_ = max_difference;
}
private:
double item_margin_;
double max_difference_;
};
typedef boost::variant<simple_row_layout,
pair_layout> group_layout;
typedef std::shared_ptr<group_layout> group_layout_ptr;
}
#endif // MAPNIK_GROUP_LAYOUT_HPP

View file

@ -0,0 +1,104 @@
/*****************************************************************************
*
* 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_GROUP_LAYOUT_MANAGER_HPP
#define MAPNIK_GROUP_LAYOUT_MANAGER_HPP
// mapnik
#include <mapnik/box2d.hpp>
#include <mapnik/pixel_position.hpp>
#include <mapnik/group/group_layout.hpp>
// stl
#include <vector>
using std::vector;
namespace mapnik
{
typedef box2d<double> bound_box;
struct group_layout_manager
{
group_layout_manager(const group_layout &layout)
: layout_(layout),
input_origin_(0, 0),
member_boxes_(vector<bound_box>()),
member_offsets_(vector<pixel_position>()),
update_layout_(true)
{
}
group_layout_manager(const group_layout &layout, const pixel_position &input_origin)
: layout_(layout),
input_origin_(input_origin),
member_boxes_(vector<bound_box>()),
member_offsets_(vector<pixel_position>()),
update_layout_(true)
{
}
group_layout_manager(const group_layout &layout, const pixel_position &input_origin,
const vector<bound_box> &item_boxes)
: layout_(layout),
input_origin_(input_origin),
member_boxes_(item_boxes),
member_offsets_(vector<pixel_position>()),
update_layout_(true)
{
}
inline void set_layout(const group_layout &layout)
{
layout_ = layout;
update_layout_ = true;
}
inline void add_member_bound_box(const bound_box &member_box)
{
member_boxes_.push_back(member_box);
update_layout_ = true;
}
inline const pixel_position &offset_at(size_t i)
{
handle_update();
return member_offsets_.at(i);
}
bound_box offset_box_at(size_t i);
private:
void handle_update();
group_layout layout_;
pixel_position input_origin_;
vector<bound_box> member_boxes_;
vector<pixel_position> member_offsets_;
bool update_layout_;
};
} // namespace mapnik
#endif // MAPNIK_GROUP_LAYOUT_MANAGER_HPP

View file

@ -0,0 +1,101 @@
/*****************************************************************************
*
* 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_GROUP_RULE_HPP
#define MAPNIK_GROUP_RULE_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/expression.hpp>
namespace mapnik
{
/**
* group rule contains a set of symbolizers which should
* be rendered atomically when the filter attached to
* this rule is matched.
*/
struct group_rule
{
typedef std::vector<symbolizer> symbolizers;
group_rule(const expression_ptr& filter = std::make_shared<mapnik::expr_node>(true),
const expression_ptr& repeat_key = expression_ptr());
group_rule &operator=(const group_rule &rhs);
bool operator==(const group_rule &rhs) const;
void append(const symbolizer &);
const symbolizers &get_symbolizers() const
{
return symbolizers_;
}
inline symbolizers::const_iterator begin() const
{
return symbolizers_.begin();
}
inline symbolizers::const_iterator end() const
{
return symbolizers_.end();
}
inline void set_filter(const expression_ptr& filter)
{
filter_ = filter;
}
inline expression_ptr const& get_filter() const
{
return filter_;
}
inline void set_repeat_key(const expression_ptr& repeat_key)
{
repeat_key_ = repeat_key;
}
inline expression_ptr const& get_repeat_key() const
{
return repeat_key_;
}
private:
// expression filter - when data matches this then
// the symbolizers should be drawn.
expression_ptr filter_;
// expression repeat key - repeat key to be used with minimum distance
expression_ptr repeat_key_;
// the atomic set of symbolizers
symbolizers symbolizers_;
};
}
#endif // MAPNIK_GROUP_RULE_HPP

View file

@ -0,0 +1,105 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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 GROUP_SYMBOLIZER_HELPER_HPP
#define GROUP_SYMBOLIZER_HELPER_HPP
//mapnik
#include <mapnik/text/symbolizer_helpers.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/text/placement_finder.hpp>
#include <mapnik/proj_transform.hpp>
#include <mapnik/ctrans.hpp>
namespace mapnik {
class label_collision_detector4;
typedef label_collision_detector4 DetectorType;
typedef std::list<pixel_position> pixel_position_list;
/** Helper object that does some of the GroupSymbolizer placement finding work. */
class group_symbolizer_helper : public base_symbolizer_helper
{
public:
struct box_element
{
box_element(box2d<double> const& box, value_unicode_string const& repeat_key = "")
: box_(box),
repeat_key_(repeat_key)
{}
box2d<double> box_;
value_unicode_string repeat_key_;
};
group_symbolizer_helper(group_symbolizer const& sym,
feature_impl const& feature,
proj_transform const& prj_trans,
unsigned width,
unsigned height,
double scale_factor,
CoordTransform const &t,
DetectorType &detector,
box2d<double> const& query_extent);
inline void add_box_element(box2d<double> const& box, value_unicode_string const& repeat_key = "")
{
box_elements_.push_back(box_element(box, repeat_key));
}
inline void clear_box_elements()
{
box_elements_.clear();
}
inline text_symbolizer_properties const& get_properties()
{
return placement_->properties;
}
pixel_position_list const& get();
private:
/** Iterate over the given path, placing line-following labels or point labels with respect to label_spacing. */
template <typename T>
bool find_line_placements(T & path);
/** Check if a point placement fits at given position */
bool check_point_placement(pixel_position const& pos);
/** Checks for collision. */
bool collision(box2d<double> const& box, const value_unicode_string &repeat_key = "") const;
double get_spacing(double path_length) const;
DetectorType &detector_;
/** Boxes and repeat keys to take into account when finding placement.
* Boxes are relative to starting point of current placement.
*/
std::list<box_element> box_elements_;
pixel_position_list results_;
};
} //namespace
#endif // GROUP_SYMBOLIZER_HELPER_HPP

View file

@ -0,0 +1,62 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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 GROUP_PROPERTIES_HPP
#define GROUP_PROPERTIES_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/group/group_layout.hpp>
// stl
#include <vector>
namespace mapnik
{
struct group_rule;
typedef std::shared_ptr<group_rule> group_rule_ptr;
typedef std::vector<group_rule_ptr> group_rules;
/** Contains all group symbolizer properties related to building a group layout. */
struct group_symbolizer_properties
{
inline group_symbolizer_properties() : rules_() { }
/** Load all values from XML ptree. */
//void from_xml(xml_node const &sym, fontset_map const & fontsets);
/** Get the layout. */
inline group_layout const& get_layout() const { return layout_; }
/** Get the group rules. */
inline group_rules const& get_rules() const { return rules_; }
/** Set the layout. */
inline void set_layout (group_layout && layout) { layout_ = std::move(layout); }
/** Add add group rule. */
inline void add_rule (group_rule_ptr rule) { rules_.push_back(rule); }
private:
group_layout layout_;
group_rules rules_;
};
typedef std::shared_ptr<group_symbolizer_properties> group_symbolizer_properties_ptr;
} //ns mapnik
#endif // GROUP_PROPERTIES_HPP

View file

@ -31,10 +31,10 @@
#include <cstring>
#include <stdexcept>
namespace mapnik
{
template <class T> class ImageData
template <typename T>
class ImageData
{
public:
typedef T pixel_type;
@ -55,7 +55,7 @@ public:
if (pData_) std::memset(pData_,0,sizeof(T)*width_*height_);
}
ImageData(const ImageData<T>& rhs)
ImageData(ImageData<T> const& rhs)
:width_(rhs.width_),
height_(rhs.height_),
pData_((rhs.width_!=0 && rhs.height_!=0)?
@ -63,6 +63,30 @@ public:
{
if (pData_) std::memcpy(pData_,rhs.pData_,sizeof(T)*rhs.width_* rhs.height_);
}
ImageData(ImageData<T> && rhs) noexcept
: width_(rhs.width_),
height_(rhs.height_),
pData_(rhs.pData_)
{
rhs.width_ = 0;
rhs.height_ = 0;
rhs.pData_ = nullptr;
}
ImageData<T>& operator=(ImageData<T> rhs)
{
swap(rhs);
return *this;
}
void swap(ImageData<T> & rhs)
{
std::swap(width_, rhs.width_);
std::swap(height_, rhs.height_);
std::swap(pData_, rhs.pData_);
}
inline T& operator() (unsigned i,unsigned j)
{
assert(i<width_ && j<height_);
@ -140,8 +164,8 @@ public:
}
private:
const unsigned width_;
const unsigned height_;
unsigned width_;
unsigned height_;
T *pData_;
ImageData& operator=(const ImageData&);
};

View file

@ -63,9 +63,9 @@ void scale_image_agg(Image & target,
scaling_method_e scaling_method,
double image_ratio_x,
double image_ratio_y,
double x_off_f=0,
double y_off_f=0,
double filter_radius=2);
double x_off_f,
double y_off_f,
double filter_factor);
template <typename Image>
void scale_image_bilinear_old(Image & target,

View file

@ -29,9 +29,6 @@
#include <mapnik/noncopyable.hpp>
#include <mapnik/unicode.hpp>
// boost
// stl
#include <vector>

View file

@ -67,7 +67,6 @@ public:
mapnik::transcoder const& tr_;
};
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct put_property
{
typedef void result_type;
@ -90,42 +89,6 @@ struct extract_geometry
return feature.paths();
}
};
#else
struct put_property
{
template <typename T0,typename T1, typename T2>
struct result
{
typedef void type;
};
explicit put_property(mapnik::transcoder const& tr)
: tr_(tr) {}
template <typename T0,typename T1, typename T2>
void operator() (T0 & feature, T1 const& key, T2 const& val) const
{
mapnik::value v = boost::apply_visitor(attribute_value_visitor(tr_),val); // TODO: optimize
feature.put_new(key, v);
}
mapnik::transcoder const& tr_;
};
struct extract_geometry
{
template <typename T>
struct result
{
typedef boost::ptr_vector<mapnik::geometry_type>& type;
};
template <typename T>
boost::ptr_vector<mapnik::geometry_type>& operator() (T & feature) const
{
return feature.paths();
}
};
#endif
template <typename Iterator, typename FeatureType>
struct feature_grammar :

View file

@ -58,7 +58,6 @@ namespace phoenix = boost::phoenix;
namespace {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct get_type
{
typedef int result_type;
@ -117,81 +116,6 @@ struct not_empty
}
};
#else
struct get_type
{
template <typename T>
struct result { typedef int type; };
int operator() (geometry_type const& geom) const
{
return static_cast<int>(geom.type());
}
};
struct get_first
{
template <typename T>
struct result { typedef geometry_type::value_type const type; };
geometry_type::value_type const operator() (geometry_type const& geom) const
{
geometry_type::value_type coord;
std::get<0>(coord) = geom.vertex(0,&std::get<1>(coord),&std::get<2>(coord));
return coord;
}
};
struct multi_geometry_type
{
template <typename T>
struct result { typedef std::tuple<unsigned,bool> type; };
std::tuple<unsigned,bool> operator() (geometry_container const& geom) const
{
unsigned type = 0u;
bool collection = false;
geometry_container::const_iterator itr = geom.begin();
geometry_container::const_iterator end = geom.end();
for ( ; itr != end; ++itr)
{
if (type != 0u && static_cast<unsigned>(itr->type()) != type)
{
collection = true;
break;
}
type = itr->type();
}
if (geom.size() > 1) type +=3;
return std::tuple<unsigned,bool>(type, collection);
}
};
struct not_empty
{
template <typename T>
struct result { typedef bool type; };
bool operator() (geometry_container const& cont) const
{
geometry_container::const_iterator itr = cont.begin();
geometry_container::const_iterator end = cont.end();
for (; itr!=end; ++itr)
{
if (itr->size() > 0) return true;
}
return false;
}
};
#endif
template <typename T>
struct json_coordinate_policy : karma::real_policies<T>
{

View file

@ -37,7 +37,6 @@ namespace qi = boost::spirit::qi;
namespace standard_wide = boost::spirit::standard_wide;
using standard_wide::space_type;
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct push_vertex
{
typedef void result_type;
@ -88,76 +87,6 @@ struct where_message
return str;
}
};
#else
struct push_vertex
{
template <typename T0,typename T1, typename T2, typename T3>
struct result
{
typedef void type;
};
template <typename T0,typename T1, typename T2, typename T3>
void operator() (T0 c, T1 path, T2 x, T3 y) const
{
BOOST_ASSERT( path!=0 );
path->push_vertex(x,y,c);
}
};
struct close_path
{
template <typename T>
struct result
{
typedef void type;
};
template <typename T>
void operator() (T path) const
{
BOOST_ASSERT( path!=0 );
if (path->size() > 2u) // to form a polygon ring we need at least 3 vertices
{
path->close_path();
}
}
};
struct cleanup
{
template <typename T0>
struct result
{
typedef void type;
};
template <typename T0>
void operator() (T0 & path) const
{
if (path) delete path, path=0;
}
};
struct where_message
{
template <typename T0,typename T1,typename T2>
struct result
{
typedef std::string type;
};
template <typename Iterator>
std::string operator() (Iterator first, Iterator last, std::size_t size) const
{
std::string str(first, last);
if (str.length() > size)
return str.substr(0, size) + "..." ;
return str;
}
};
#endif
template <typename Iterator>
struct geometry_grammar :

View file

@ -0,0 +1,218 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_SYMBOLIZER_GRAMMAR_HPP
#define MAPNIK_SYMBOLIZER_GRAMMAR_HPP
// boost
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
// mapnik
#include <mapnik/symbolizer.hpp>
#include <mapnik/symbolizer_utils.hpp>
#include <mapnik/json/generic_json.hpp>
namespace mapnik { namespace json {
namespace qi = boost::spirit::qi;
namespace phoenix = boost::phoenix;
namespace fusion = boost::fusion;
namespace standard_wide = boost::spirit::standard_wide;
using standard_wide::space_type;
template <typename Symbolizer>
struct json_value_visitor : boost::static_visitor<>
{
json_value_visitor(Symbolizer & sym, mapnik::keys key)
: sym_(sym), key_(key) {}
void operator() (value_bool val) const
{
put<value_bool>(sym_, key_, val);
}
void operator() (value_integer val) const
{
put<value_integer>(sym_, key_, val);
}
void operator() (value_double val) const
{
put<value_double>(sym_, key_, val);
}
void operator() (std::string const& val) const
{
set_property(sym_, key_, val);
}
template <typename T>
void operator() (T const& val) const
{
std::cerr << std::get<0>(get_meta(key_)) << ":" << val << std::endl;
//put<T>(sym_, key_, val);
}
Symbolizer & sym_;
keys key_;
};
template <typename T>
struct put_property_visitor : boost::static_visitor<>
{
typedef T value_type;
put_property_visitor(mapnik::keys key, value_type const& val)
: key_(key), val_(val) {}
template <typename Symbolizer>
void operator() (Symbolizer & sym) const
{
boost::apply_visitor(json_value_visitor<Symbolizer>(sym, key_), val_);
}
keys key_;
value_type const& val_;
};
struct put_property
{
typedef void result_type;
template <typename T0,typename T1, typename T2>
result_type operator() (T0 & sym, T1 const& name, T2 const& val) const
{
try
{
boost::apply_visitor(put_property_visitor<T2>(get_key(name),val), sym);
}
catch (std::runtime_error const& err)
{
std::cerr << err.what() << std::endl;
}
}
};
template <typename Iterator>
struct symbolizer_grammar : qi::grammar<Iterator, space_type, symbolizer()>
{
typedef boost::variant<value_null,value_bool,value_integer,value_double, std::string> json_value_type;
symbolizer_grammar(generic_json<Iterator> & json)
: symbolizer_grammar::base_type(sym, "symbolizer"),
json_(json)
{
using qi::lit;
using qi::double_;
using qi::int_;
using qi::no_skip;
using qi::omit;
using qi::_val;
using qi::_a;
using qi::_r1;
using qi::_1;
using qi::_2;
using qi::_3;
using qi::_4;
using qi::fail;
using qi::on_error;
using standard_wide::char_;
using phoenix::construct;
// generic json types
json_.value = json_.object | json_.array | json_.string_
| json_.number
;
json_.pairs = json_.key_value % lit(',')
;
json_.key_value = (json_.string_ >> lit(':') >> json_.value)
;
json_.object = lit('{')
>> *json_.pairs
>> lit('}')
;
json_.array = lit('[')
>> json_.value >> *(lit(',') >> json_.value)
>> lit(']')
;
json_.number %= json_.strict_double
| json_.int__
| lit("true") [_val = true]
| lit ("false") [_val = false]
| lit("null")[_val = construct<value_null>()]
;
json_.unesc_char.add
("\\\"", '\"') // quotation mark
("\\\\", '\\') // reverse solidus
("\\/", '/') // solidus
("\\b", '\b') // backspace
("\\f", '\f') // formfeed
("\\n", '\n') // newline
("\\r", '\r') // carrige return
("\\t", '\t') // tab
;
json_.string_ %= lit('"') >> no_skip[*(json_.unesc_char | "\\u" >> json_.hex4 | (char_ - lit('"')))] >> lit('"')
;
sym = lit('{')
>> lit("\"type\"") >> lit(':')
>> (lit("\"PointSymbolizer\"")[_val = construct<point_symbolizer>()]
|
lit("\"LineSymbolizer\"")[_val = construct<line_symbolizer>()]
|
lit("\"PolygonSymbolizer\"")[_val = construct<polygon_symbolizer>()]
)
>> lit(',')
>> lit("\"properties\"") >> lit(':')
>> ((lit('{') >> *property(_val) >> lit('}')) | lit("null"))
>> lit('}')
;
property = (json_.string_ [_a = _1] >> lit(':') >> property_value [put_property_(_r1,_a,_1)]) % lit(',')
;
property_value %= json.number | json.string_ ;
}
// generic JSON
generic_json<Iterator> & json_;
// symbolizer
qi::rule<Iterator, space_type, mapnik::symbolizer()> sym;
qi::rule<Iterator,qi::locals<std::string>, void(mapnik::symbolizer&),space_type> property;
qi::rule<Iterator, space_type, json_value_type()> property_value;
phoenix::function<put_property> put_property_;
// error
//boost::phoenix::function<where_message> where_message_;
};
}}
#endif // MAPNIK_FEATURE_GRAMMAR_HPP

View file

@ -23,13 +23,15 @@
#ifndef MAPNIK_TOPOJSON_GRAMMAR_HPP
#define MAPNIK_TOPOJSON_GRAMMAR_HPP
#define BOOST_SPIRIT_USE_PHOENIX_V3 1
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
//
// mapnik
#include <mapnik/value.hpp>
#include <mapnik/json/topology.hpp>
//
// boost
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
// stl
#include <string>
namespace mapnik { namespace topojson {

View file

@ -48,7 +48,7 @@ public:
std::string const& srs=MAPNIK_LONGLAT_PROJ);
layer(layer const& l);
layer& operator=(layer const& rhs);
layer& operator=(layer rhs);
bool operator==(layer const& other) const;
/*!
@ -199,7 +199,6 @@ public:
void reset_buffer_size();
~layer();
private:
void swap(layer& other);
std::string name_;
std::string srs_;

View file

@ -1,105 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_LINE_SYMBOLIZER_HPP
#define MAPNIK_LINE_SYMBOLIZER_HPP
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/config.hpp>
#include <mapnik/stroke.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/enumeration.hpp>
namespace mapnik
{
enum line_rasterizer_enum {
RASTERIZER_FULL, // agg::renderer_scanline_aa_solid
RASTERIZER_FAST, // agg::rasterizer_outline_aa, twice as fast but only good for thin lines
line_rasterizer_enum_MAX
};
DEFINE_ENUM( line_rasterizer_e, line_rasterizer_enum );
struct MAPNIK_DECL line_symbolizer : public symbolizer_base
{
explicit line_symbolizer()
: symbolizer_base(),
stroke_(),
offset_(0.0),
rasterizer_p_(RASTERIZER_FULL)
{}
line_symbolizer(stroke const& stroke)
: symbolizer_base(),
stroke_(stroke),
offset_(0.0),
rasterizer_p_(RASTERIZER_FULL)
{}
line_symbolizer(color const& pen,float width=1.0)
: symbolizer_base(),
stroke_(pen,width),
offset_(0.0),
rasterizer_p_(RASTERIZER_FULL)
{}
stroke const& get_stroke() const
{
return stroke_;
}
void set_stroke(stroke const& stk)
{
stroke_ = stk;
}
void set_offset(double val)
{
offset_ = val;
}
double offset() const
{
return offset_;
}
void set_rasterizer(line_rasterizer_e rasterizer_p)
{
rasterizer_p_ = rasterizer_p;
}
line_rasterizer_e get_rasterizer() const
{
return rasterizer_p_;
}
private:
stroke stroke_;
double offset_;
line_rasterizer_e rasterizer_p_;
};
}
#endif // MAPNIK_LINE_SYMBOLIZER_HPP

View file

@ -43,7 +43,7 @@ namespace mapnik
class feature_type_style;
class CoordTransform;
class MAPNIK_DECL Map
class MAPNIK_DECL Map : boost::equality_comparable<Map>
{
public:
@ -123,7 +123,7 @@ public:
* TODO: to be documented
*
*/
Map& operator=(Map const& rhs);
Map& operator=(Map rhs);
/*! \brief Get all styles
* @return Const reference to styles

View file

@ -27,7 +27,7 @@
#include <mapnik/feature.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geom_util.hpp>
#include <mapnik/markers_symbolizer.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/svg/svg_converter.hpp>
@ -62,10 +62,13 @@ template <typename BufferType, typename SvgRenderer, typename Rasterizer, typena
struct vector_markers_rasterizer_dispatch
{
typedef typename SvgRenderer::renderer_base renderer_base;
typedef typename SvgRenderer::vertex_source_type vertex_source_type;
typedef typename SvgRenderer::attribute_source_type attribute_source_type;
typedef typename renderer_base::pixfmt_type pixfmt_type;
vector_markers_rasterizer_dispatch(BufferType & render_buffer,
SvgRenderer & svg_renderer,
vertex_source_type &path,
attribute_source_type const &attrs,
Rasterizer & ras,
box2d<double> const& bbox,
agg::trans_affine const& marker_trans,
@ -76,7 +79,7 @@ struct vector_markers_rasterizer_dispatch
: buf_(render_buffer),
pixf_(buf_),
renb_(pixf_),
svg_renderer_(svg_renderer),
svg_renderer_(path, attrs),
ras_(ras),
bbox_(bbox),
marker_trans_(marker_trans),
@ -85,13 +88,23 @@ struct vector_markers_rasterizer_dispatch
scale_factor_(scale_factor),
snap_to_pixels_(snap_to_pixels)
{
pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op()));
pixf_.comp_op(get<agg::comp_op_e>(sym_, keys::comp_op, agg::comp_op_src_over));
}
vector_markers_rasterizer_dispatch(vector_markers_rasterizer_dispatch &&d)
: buf_(d.buf_), pixf_(d.pixf_), svg_renderer_(std::move(d.svg_renderer_)), ras_(d.ras_),
bbox_(d.bbox_), marker_trans_(d.marker_trans_), sym_(d.sym_), detector_(d.detector_),
scale_factor_(d.scale_factor_), snap_to_pixels_(d.snap_to_pixels_)
{
}
template <typename T>
void add_path(T & path)
{
marker_placement_e placement_method = sym_.get_marker_placement();
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, false);
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, false);
double opacity = get<double>(sym_,keys::opacity, 1.0);
if (placement_method != MARKER_LINE_PLACEMENT ||
path.type() == mapnik::geometry_type::types::Point)
@ -124,11 +137,11 @@ struct vector_markers_rasterizer_dispatch
// TODO https://github.com/mapnik/mapnik/issues/1754
box2d<double> transformed_bbox = bbox_ * matrix;
if (sym_.get_allow_overlap() ||
if (allow_overlap ||
detector_.has_placement(transformed_bbox))
{
svg_renderer_.render(ras_, sl_, renb_, matrix, sym_.get_opacity(), bbox_);
if (!sym_.get_ignore_placement())
svg_renderer_.render(ras_, sl_, renb_, matrix, opacity, bbox_);
if (!ignore_placement)
{
detector_.insert(transformed_bbox);
}
@ -136,19 +149,21 @@ struct vector_markers_rasterizer_dispatch
}
else
{
double spacing = get<double>(sym_, keys::spacing, 100.0);
double max_error = get<double>(sym_, keys::max_error, 0.2);
markers_placement<T, Detector> placement(path, bbox_, marker_trans_, detector_,
sym_.get_spacing() * scale_factor_,
sym_.get_max_error(),
sym_.get_allow_overlap());
spacing * scale_factor_,
max_error,
allow_overlap);
double x = 0;
double y = 0;
double angle = 0;
while (placement.get_point(x, y, angle, sym_.get_ignore_placement()))
while (placement.get_point(x, y, angle, ignore_placement))
{
agg::trans_affine matrix = marker_trans_;
matrix.rotate(angle);
matrix.translate(x, y);
svg_renderer_.render(ras_, sl_, renb_, matrix, sym_.get_opacity(), bbox_);
svg_renderer_.render(ras_, sl_, renb_, matrix, opacity, bbox_);
}
}
}
@ -157,7 +172,7 @@ private:
BufferType & buf_;
pixfmt_type pixf_;
renderer_base renb_;
SvgRenderer & svg_renderer_;
SvgRenderer svg_renderer_;
Rasterizer & ras_;
box2d<double> const& bbox_;
agg::trans_affine const& marker_trans_;
@ -196,14 +211,24 @@ struct raster_markers_rasterizer_dispatch
scale_factor_(scale_factor),
snap_to_pixels_(snap_to_pixels)
{
pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op()));
pixf_.comp_op(get<agg::comp_op_e>(sym_, keys::comp_op, agg::comp_op_src_over));
}
raster_markers_rasterizer_dispatch(raster_markers_rasterizer_dispatch &&d)
: buf_(d.buf_), pixf_(d.pixf_), renb_(d.renb_), ras_(d.ras_), src_(d.src_),
marker_trans_(d.marker_trans_), sym_(d.sym_), detector_(d.detector_),
scale_factor_(d.scale_factor_), snap_to_pixels_(d.snap_to_pixels_)
{
}
template <typename T>
void add_path(T & path)
{
marker_placement_e placement_method = sym_.get_marker_placement();
marker_placement_enum placement_method = get<marker_placement_enum>(sym_, keys::markers_placement_type, MARKER_POINT_PLACEMENT);
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, false);
box2d<double> bbox_(0,0, src_.width(),src_.height());
double opacity = get<double>(sym_, keys::opacity, 1.0);
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, false);
if (placement_method != MARKER_LINE_PLACEMENT ||
path.type() == mapnik::geometry_type::types::Point)
@ -229,11 +254,11 @@ struct raster_markers_rasterizer_dispatch
matrix.translate(x,y);
box2d<double> transformed_bbox = bbox_ * matrix;
if (sym_.get_allow_overlap() ||
if (allow_overlap ||
detector_.has_placement(transformed_bbox))
{
render_raster_marker(matrix, sym_.get_opacity());
if (!sym_.get_ignore_placement())
render_raster_marker(matrix, opacity);
if (!ignore_placement)
{
detector_.insert(transformed_bbox);
}
@ -241,17 +266,19 @@ struct raster_markers_rasterizer_dispatch
}
else
{
double spacing = get<double>(sym_, keys::spacing, 100.0);
double max_error = get<double>(sym_, keys::max_error, 0.2);
markers_placement<T, label_collision_detector4> placement(path, bbox_, marker_trans_, detector_,
sym_.get_spacing() * scale_factor_,
sym_.get_max_error(),
sym_.get_allow_overlap());
spacing * scale_factor_,
max_error,
allow_overlap);
double x, y, angle;
while (placement.get_point(x, y, angle,sym_.get_ignore_placement()))
while (placement.get_point(x, y, angle, ignore_placement))
{
agg::trans_affine matrix = marker_trans_;
matrix.rotate(angle);
matrix.translate(x, y);
render_raster_marker(matrix, sym_.get_opacity());
render_raster_marker(matrix, opacity);
}
}
}
@ -274,7 +301,7 @@ struct raster_markers_rasterizer_dispatch
0,
std::floor(marker_tr.tx + .5),
std::floor(marker_tr.ty + .5),
unsigned(255*sym_.get_opacity()));
unsigned(255*opacity));
}
else
{
@ -339,8 +366,8 @@ private:
template <typename T>
void build_ellipse(T const& sym, mapnik::feature_impl const& feature, svg_storage_type & marker_ellipse, svg::svg_path_adapter & svg_path)
{
expression_ptr const& width_expr = sym.get_width();
expression_ptr const& height_expr = sym.get_height();
auto width_expr = get<expression_ptr>(sym, keys::width);
auto height_expr = get<expression_ptr>(sym, keys::height);
double width = 0;
double height = 0;
if (width_expr && height_expr)
@ -375,10 +402,16 @@ void build_ellipse(T const& sym, mapnik::feature_impl const& feature, svg_storag
template <typename Attr>
bool push_explicit_style(Attr const& src, Attr & dst, markers_symbolizer const& sym)
{
boost::optional<stroke> const& strk = sym.get_stroke();
boost::optional<color> const& fill = sym.get_fill();
boost::optional<float> const& fill_opacity = sym.get_fill_opacity();
if (strk || fill || fill_opacity)
auto fill_color = get_optional<color>(sym, keys::fill);
auto fill_opacity = get_optional<double>(sym, keys::fill_opacity);
auto stroke_color = get_optional<color>(sym, keys::stroke);
auto stroke_width = get_optional<double>(sym, keys::stroke_width);
auto stroke_opacity = get_optional<double>(sym, keys::stroke_opacity);
if (fill_color ||
fill_opacity ||
stroke_color ||
stroke_width ||
stroke_opacity)
{
bool success = false;
for(unsigned i = 0; i < src.size(); ++i)
@ -388,24 +421,28 @@ bool push_explicit_style(Attr const& src, Attr & dst, markers_symbolizer const&
mapnik::svg::path_attributes & attr = dst.last();
if (attr.stroke_flag)
{
// TODO - stroke attributes need to be boost::optional
// for this to work properly
if (strk)
if (stroke_width)
{
attr.stroke_width = strk->get_width();
color const& s_color = strk->get_color();
attr.stroke_width = *stroke_width;
}
if (stroke_color)
{
color const& s_color = *stroke_color;
attr.stroke_color = agg::rgba(s_color.red()/255.0,
s_color.green()/255.0,
s_color.blue()/255.0,
s_color.alpha()/255.0);
attr.stroke_opacity = strk->get_opacity();
}
if (stroke_opacity)
{
attr.stroke_opacity = *stroke_opacity;
}
}
if (attr.fill_flag)
{
if (fill)
if (fill_color)
{
color const& f_color = *fill;
color const& f_color = *fill_color;
attr.fill_color = agg::rgba(f_color.red()/255.0,
f_color.green()/255.0,
f_color.blue()/255.0,
@ -432,11 +469,11 @@ void setup_transform_scaling(agg::trans_affine & tr,
double width = 0;
double height = 0;
expression_ptr const& width_expr = sym.get_width();
expression_ptr width_expr = get<expression_ptr>(sym, keys::width);
if (width_expr)
width = boost::apply_visitor(evaluate<feature_impl,value_type>(feature), *width_expr).to_double();
expression_ptr const& height_expr = sym.get_height();
expression_ptr height_expr = get<expression_ptr>(sym, keys::height);
if (height_expr)
height = boost::apply_visitor(evaluate<feature_impl,value_type>(feature), *height_expr).to_double();
@ -469,8 +506,8 @@ void apply_markers_multi(feature_impl & feature, Converter& converter, markers_s
}
else if (geom_count > 1)
{
marker_multi_policy_e multi_policy = sym.get_marker_multi_policy();
marker_placement_e placement = sym.get_marker_placement();
marker_multi_policy_enum multi_policy = get<marker_multi_policy_enum>(sym, keys::markers_multipolicy, MARKER_EACH_MULTI);
marker_placement_enum placement = get<marker_placement_enum>(sym, keys::markers_placement_type, MARKER_POINT_PLACEMENT);
if (placement == MARKER_POINT_PLACEMENT &&
multi_policy == MARKER_WHOLE_MULTI)
{

View file

@ -1,106 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_MARKERS_SYMBOLIZER_HPP
#define MAPNIK_MARKERS_SYMBOLIZER_HPP
//mapnik
#include <mapnik/color.hpp>
#include <mapnik/config.hpp>
#include <mapnik/stroke.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/path_expression.hpp>
// boost
#include <boost/optional.hpp>
namespace mapnik {
// TODO - consider merging with text_symbolizer label_placement_e
enum marker_placement_enum {
MARKER_POINT_PLACEMENT,
MARKER_INTERIOR_PLACEMENT,
MARKER_LINE_PLACEMENT,
marker_placement_enum_MAX
};
DEFINE_ENUM( marker_placement_e, marker_placement_enum );
enum marker_multi_policy_enum {
MARKER_EACH_MULTI, // each component in a multi gets its marker
MARKER_WHOLE_MULTI, // consider all components of a multi as a whole
MARKER_LARGEST_MULTI, // only the largest component of a multi gets a marker
marker_multi_policy_enum_MAX
};
DEFINE_ENUM( marker_multi_policy_e, marker_multi_policy_enum );
struct MAPNIK_DECL markers_symbolizer :
public symbolizer_with_image, public symbolizer_base
{
public:
markers_symbolizer();
markers_symbolizer(path_expression_ptr const& filename);
markers_symbolizer(markers_symbolizer const& rhs);
void set_width(expression_ptr const& width);
expression_ptr const& get_width() const;
void set_height(expression_ptr const& height);
expression_ptr const& get_height() const;
void set_ignore_placement(bool ignore_placement);
bool get_ignore_placement() const;
void set_allow_overlap(bool overlap);
bool get_allow_overlap() const;
void set_spacing(double spacing);
double get_spacing() const;
void set_max_error(double max_error);
double get_max_error() const;
void set_fill(color const& fill);
boost::optional<color> get_fill() const;
void set_fill_opacity(float opacity);
boost::optional<float> get_fill_opacity() const;
void set_stroke(stroke const& stroke);
boost::optional<stroke> get_stroke() const;
void set_marker_placement(marker_placement_e marker_p);
marker_placement_e get_marker_placement() const;
void set_marker_multi_policy(marker_multi_policy_e marker_p);
marker_multi_policy_e get_marker_multi_policy() const;
private:
expression_ptr width_;
expression_ptr height_;
bool ignore_placement_;
bool allow_overlap_;
double spacing_;
double max_error_;
boost::optional<color> fill_;
boost::optional<float> fill_opacity_;
boost::optional<float> opacity_;
boost::optional<stroke> stroke_;
marker_placement_e marker_p_;
marker_multi_policy_e marker_mp_;
};
}
#endif // MAPNIK_MARKERS_SYMBOLIZER_HPP

View file

@ -33,8 +33,8 @@ class noncopyable
protected:
constexpr noncopyable() = default;
~noncopyable() = default;
noncopyable( const noncopyable& ) = delete;
noncopyable& operator=( const noncopyable& ) = delete;
noncopyable( noncopyable const& ) = delete;
noncopyable& operator=(noncopyable const& ) = delete;
};
}

View file

@ -1,62 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_POINT_SYMBOLIZER_HPP
#define MAPNIK_POINT_SYMBOLIZER_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/enumeration.hpp>
namespace mapnik
{
enum point_placement_enum {
CENTROID_POINT_PLACEMENT,
INTERIOR_POINT_PLACEMENT,
point_placement_enum_MAX
};
DEFINE_ENUM( point_placement_e, point_placement_enum );
struct MAPNIK_DECL point_symbolizer :
public symbolizer_with_image, public symbolizer_base
{
point_symbolizer();
point_symbolizer(path_expression_ptr file);
point_symbolizer(point_symbolizer const& rhs);
void set_allow_overlap(bool overlap);
bool get_allow_overlap() const;
void set_point_placement(point_placement_e point_p);
point_placement_e get_point_placement() const;
void set_ignore_placement(bool ignore_placement);
bool get_ignore_placement() const;
private:
bool overlap_;
point_placement_e point_p_;
bool ignore_placement_;
};
}
#endif // MAPNIK_POINT_SYMBOLIZER_HPP

View file

@ -1,62 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_POLYGON_PATTERN_SYMBOLIZER_HPP
#define MAPNIK_POLYGON_PATTERN_SYMBOLIZER_HPP
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/config.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/enumeration.hpp>
#include <mapnik/gamma_method.hpp>
namespace mapnik
{
enum pattern_alignment_enum {
LOCAL_ALIGNMENT,
GLOBAL_ALIGNMENT,
pattern_alignment_enum_MAX
};
DEFINE_ENUM( pattern_alignment_e, pattern_alignment_enum );
struct MAPNIK_DECL polygon_pattern_symbolizer :
public symbolizer_with_image, public symbolizer_base
{
polygon_pattern_symbolizer(path_expression_ptr file);
polygon_pattern_symbolizer(polygon_pattern_symbolizer const& rhs);
pattern_alignment_e get_alignment() const;
void set_alignment(pattern_alignment_e align);
void set_gamma(double gamma);
double get_gamma() const;
void set_gamma_method(gamma_method_e gamma_method);
gamma_method_e get_gamma_method() const;
private:
pattern_alignment_e alignment_;
double gamma_;
gamma_method_e gamma_method_;
};
}
#endif // MAPNIK_POLYGON_PATTERN_SYMBOLIZER_HPP

View file

@ -1,56 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_POLYGON_SYMBOLIZER_HPP
#define MAPNIK_POLYGON_SYMBOLIZER_HPP
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/config.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/gamma_method.hpp>
namespace mapnik
{
struct MAPNIK_DECL polygon_symbolizer : public symbolizer_base
{
polygon_symbolizer();
explicit polygon_symbolizer(color const& fill);
color const& get_fill() const;
void set_fill(color const& fill);
void set_opacity(double opacity);
double get_opacity() const;
void set_gamma(double gamma);
double get_gamma() const;
void set_gamma_method(gamma_method_e gamma_method);
gamma_method_e get_gamma_method() const;
private:
color fill_;
double opacity_;
double gamma_;
gamma_method_e gamma_method_;
};
}
#endif // MAPNIK_POLYGON_SYMBOLIZER_HPP

View file

@ -37,13 +37,18 @@ class raster : private mapnik::noncopyable
public:
box2d<double> ext_;
image_data_32 data_;
double filter_factor_;
bool premultiplied_alpha_;
boost::optional<double> nodata_;
raster(box2d<double> const& ext, unsigned width, unsigned height, bool premultiplied_alpha = false)
raster(box2d<double> const& ext,
unsigned width,
unsigned height,
double filter_factor,
bool premultiplied_alpha = false)
: ext_(ext),
data_(width,height),
premultiplied_alpha_(premultiplied_alpha)
{}
filter_factor_(filter_factor),
premultiplied_alpha_(premultiplied_alpha) {}
void set_nodata(double nodata)
{
@ -54,6 +59,17 @@ public:
{
return nodata_;
}
double get_filter_factor() const
{
return filter_factor_;
}
void set_filter_factor(double factor)
{
filter_factor_ = factor;
}
};
}

View file

@ -1,4 +1,3 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
@ -68,7 +67,8 @@ enum colorizer_mode_enum
DEFINE_ENUM( colorizer_mode, colorizer_mode_enum );
//! \brief Structure to represent a stop position.
class MAPNIK_DECL colorizer_stop {
class MAPNIK_DECL colorizer_stop
{
public:
//! \brief Constructor

View file

@ -1,73 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_RASTER_SYMBOLIZER_HPP
#define MAPNIK_RASTER_SYMBOLIZER_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/image_scaling.hpp>
// boost
#include <boost/optional.hpp>
//stl
#include <string>
namespace mapnik
{
struct MAPNIK_DECL raster_symbolizer : public symbolizer_base
{
raster_symbolizer();
raster_symbolizer(raster_symbolizer const& rhs);
std::string const& get_mode() const;
void set_mode(std::string const& mode);
scaling_method_e get_scaling_method() const;
void set_scaling_method(scaling_method_e scaling);
void set_opacity(float opacity);
float get_opacity() const;
raster_colorizer_ptr get_colorizer() const;
void set_colorizer(raster_colorizer_ptr const& colorizer);
double get_filter_factor() const;
void set_filter_factor(double filter_factor);
double calculate_filter_factor() const;
unsigned get_mesh_size() const;
void set_mesh_size(unsigned mesh_size);
boost::optional<bool> premultiplied() const;
void set_premultiplied(bool premultiplied);
private:
std::string mode_;
scaling_method_e scaling_;
float opacity_;
raster_colorizer_ptr colorizer_;
double filter_factor_;
unsigned mesh_size_;
boost::optional<bool> premultiplied_;
};
}
#endif // MAPNIK_RASTER_SYMBOLIZER_HPP

View file

@ -0,0 +1,70 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_RENDERER_COMMON_HPP
#define MAPNIK_RENDERER_COMMON_HPP
#include <mapnik/config.hpp> // for MAPNIK_DECL
#include <mapnik/font_engine_freetype.hpp> // for face_manager, etc
#include <mapnik/box2d.hpp> // for box2d
#include <mapnik/ctrans.hpp> // for CoordTransform
// fwd declarations to speed up compile
namespace mapnik {
class label_collision_detector4;
class Map;
class request;
}
namespace mapnik {
struct renderer_common
{
renderer_common(Map const &m, unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height, double scale_factor);
renderer_common(Map const &m, unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height, double scale_factor,
std::shared_ptr<label_collision_detector4> detector);
renderer_common(request const &req, unsigned offset_x, unsigned offset_y,
unsigned width, unsigned height, double scale_factor);
renderer_common(const renderer_common &);
unsigned width_;
unsigned height_;
double scale_factor_;
// TODO: dirty hack for cairo renderer, figure out how to remove this
std::shared_ptr<freetype_engine> shared_font_engine_;
freetype_engine &font_engine_;
face_manager<freetype_engine> font_manager_;
box2d<double> query_extent_;
CoordTransform t_;
std::shared_ptr<label_collision_detector4> detector_;
private:
renderer_common(unsigned width, unsigned height, double scale_factor,
CoordTransform &&t, std::shared_ptr<label_collision_detector4> detector);
};
}
#endif /* MAPNIK_RENDERER_COMMON_HPP */

View file

@ -0,0 +1,109 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP
namespace mapnik {
template <typename F1, typename F2, typename F3>
void render_building_symbolizer(mapnik::feature_impl &feature,
double height,
F1 face_func, F2 frame_func, F3 roof_func)
{
for (auto const& geom : feature.paths())
{
if (geom.size() > 2)
{
const std::unique_ptr<geometry_type> frame(new geometry_type(geometry_type::types::LineString));
const std::unique_ptr<geometry_type> roof(new geometry_type(geometry_type::types::Polygon));
std::deque<segment_t> face_segments;
double x0 = 0;
double y0 = 0;
double x,y;
geom.rewind(0);
for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END;
cm = geom.vertex(&x, &y))
{
if (cm == SEG_MOVETO)
{
frame->move_to(x,y);
}
else if (cm == SEG_LINETO)
{
frame->line_to(x,y);
face_segments.push_back(segment_t(x0,y0,x,y));
}
else if (cm == SEG_CLOSE)
{
frame->close_path();
}
x0 = x;
y0 = y;
}
std::sort(face_segments.begin(),face_segments.end(), y_order);
for (auto const& seg : face_segments)
{
const std::unique_ptr<geometry_type> faces(new geometry_type(geometry_type::types::Polygon));
faces->move_to(std::get<0>(seg),std::get<1>(seg));
faces->line_to(std::get<2>(seg),std::get<3>(seg));
faces->line_to(std::get<2>(seg),std::get<3>(seg) + height);
faces->line_to(std::get<0>(seg),std::get<1>(seg) + height);
face_func(*faces);
//
frame->move_to(std::get<0>(seg),std::get<1>(seg));
frame->line_to(std::get<0>(seg),std::get<1>(seg)+height);
}
geom.rewind(0);
for (unsigned cm = geom.vertex(&x, &y); cm != SEG_END;
cm = geom.vertex(&x, &y))
{
if (cm == SEG_MOVETO)
{
frame->move_to(x,y+height);
roof->move_to(x,y+height);
}
else if (cm == SEG_LINETO)
{
frame->line_to(x,y+height);
roof->line_to(x,y+height);
}
else if (cm == SEG_CLOSE)
{
frame->close_path();
roof->close_path();
}
}
frame_func(*frame);
roof_func(*roof);
}
}
}
} // namespace mapnik
#endif /* MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP */

View file

@ -0,0 +1,344 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP
#include <mapnik/pixel_position.hpp>
#include <mapnik/marker_cache.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/feature_factory.hpp>
#include <mapnik/renderer_common.hpp>
#include <mapnik/label_collision_detector.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/attribute_collector.hpp>
#include <mapnik/group/group_layout.hpp>
#include <mapnik/group/group_layout_manager.hpp>
#include <mapnik/group/group_rule.hpp>
#include <mapnik/group/group_symbolizer_helper.hpp>
#include <mapnik/group/group_symbolizer_properties.hpp>
#include <mapnik/renderer_common/process_point_symbolizer.hpp>
#include <mapnik/text/placements_list.hpp>
#include <agg_trans_affine.h>
namespace mapnik {
class proj_transform;
/* General:
*
* The approach here is to run the normal symbolizers, but in
* a 'virtual' blank environment where the changes that they
* make are recorded (the detector, the render_* calls).
*
* The recorded boxes are then used to lay out the items and
* the offsets from old to new positions can be used to perform
* the actual rendering calls.
*
* This should allow us to re-use as much as possible of the
* existing symbolizer layout and rendering code while still
* being able to interpose our own decisions about whether
* a collision has occured or not.
*/
/**
* Thunk for rendering a particular instance of a point - this
* stores all the arguments necessary to re-render this point
* symbolizer at a later time.
*/
struct point_render_thunk
{
pixel_position pos_;
marker_ptr marker_;
agg::trans_affine tr_;
double opacity_;
composite_mode_e comp_op_;
point_render_thunk(pixel_position const &pos, marker const &m,
agg::trans_affine const &tr, double opacity,
composite_mode_e comp_op);
};
struct text_render_thunk
{
// need to keep these around, annoyingly, as the glyph_position
// struct keeps a pointer to the glyph_info, so we have to
// ensure the lifetime is the same.
placements_list placements_;
std::shared_ptr<std::vector<glyph_info> > glyphs_;
double opacity_;
composite_mode_e comp_op_;
halo_rasterizer_enum halo_rasterizer_;
text_render_thunk(placements_list const &placements,
double opacity, composite_mode_e comp_op,
halo_rasterizer_enum halo_rasterizer);
};
/**
* Variant type for render thunks to allow us to re-render them
* via a static visitor later.
*/
typedef boost::variant<point_render_thunk,
text_render_thunk> render_thunk;
typedef std::shared_ptr<render_thunk> render_thunk_ptr;
typedef std::list<render_thunk_ptr> render_thunk_list;
/**
* Base class for extracting the bounding boxes associated with placing
* a symbolizer at a fake, virtual point - not real geometry.
*
* The bounding boxes can be used for layout, and the thunks are
* used to re-render at locations according to the group layout.
*/
struct render_thunk_extractor : public boost::static_visitor<>
{
render_thunk_extractor(box2d<double> &box,
render_thunk_list &thunks,
mapnik::feature_impl &feature,
proj_transform const &prj_trans,
renderer_common &common,
box2d<double> const &clipping_extent);
void operator()(point_symbolizer const &sym) const;
void operator()(text_symbolizer const &sym) const;
void operator()(shield_symbolizer const &sym) const;
template <typename T>
void operator()(T const &) const
{
// TODO: warning if unimplemented?
}
private:
void extract_text_thunk(text_symbolizer_helper &helper, text_symbolizer const &sym) const;
box2d<double> &box_;
render_thunk_list &thunks_;
mapnik::feature_impl &feature_;
proj_transform const &prj_trans_;
renderer_common &common_;
box2d<double> clipping_extent_;
void update_box() const;
};
geometry_type *origin_point(proj_transform const &prj_trans,
renderer_common const &common);
template <typename F>
void render_offset_placements(placements_list const& placements,
pixel_position const& offset,
F render_text) {
for (glyph_positions_ptr glyphs : placements)
{
// move the glyphs to the correct offset
pixel_position base_point = glyphs->get_base_point();
glyphs->set_base_point(base_point + offset);
// update the position of any marker
marker_info_ptr marker_info = glyphs->marker();
pixel_position marker_pos = glyphs->marker_pos();
if (marker_info)
{
glyphs->set_marker(marker_info, marker_pos + offset);
}
render_text(glyphs);
// Need to put the base_point back how it was in case something else calls this again
// (don't want to add offset twice) or calls with a different offset.
glyphs->set_base_point(base_point);
if (marker_info)
{
glyphs->set_marker(marker_info, marker_pos);
}
}
}
template <typename F>
void render_group_symbolizer(group_symbolizer const &sym,
mapnik::feature_impl &feature,
proj_transform const &prj_trans,
box2d<double> const &clipping_extent,
renderer_common &common,
F render_thunks)
{
// find all column names referenced in the group rules and symbolizers
std::set<std::string> columns;
group_attribute_collector column_collector(columns, false);
column_collector(sym);
group_symbolizer_properties_ptr props = get<group_symbolizer_properties_ptr>(sym, keys::group_properties);
// create a new context for the sub features of this group
context_ptr sub_feature_ctx = std::make_shared<mapnik::context_type>();
// populate new context with column names referenced in the group rules and symbolizers
for (auto const& col_name : columns)
{
sub_feature_ctx->push(col_name);
}
// keep track of the sub features that we'll want to symbolize
// along with the group rules that they matched
std::vector< std::pair<group_rule_ptr, feature_ptr> > matches;
// create a copied 'virtual' common renderer for processing sub feature symbolizers
// create an empty detector for it, so we are sure we won't hit anything
renderer_common virtual_renderer(common);
virtual_renderer.detector_ = std::make_shared<label_collision_detector4>(common.detector_->extent());
// keep track of which lists of render thunks correspond to
// entries in the group_layout_manager.
std::vector<render_thunk_list> layout_thunks;
size_t num_layout_thunks = 0;
// layout manager to store and arrange bboxes of matched features
group_layout_manager layout_manager(props->get_layout(), pixel_position(common.width_ / 2.0, common.height_ / 2.0));
// run feature or sub feature through the group rules & symbolizers
// for each index value in the range
int start = get<value_integer>(sym, keys::start_column);
int end = start + get<value_integer>(sym, keys::num_columns);
for (int col_idx = start; col_idx < end; ++col_idx)
{
// create sub feature with indexed column values
feature_ptr sub_feature = feature_factory::create(sub_feature_ctx, col_idx);
// copy the necessary columns to sub feature
for(auto const& col_name : columns)
{
if (col_name.find('%') != std::string::npos)
{
if (col_name.size() == 1)
{
// column name is '%' by itself, so give the index as the value
sub_feature->put(col_name, (value_integer)col_idx);
}
else
{
// indexed column
std::string col_idx_name = col_name;
boost::replace_all(col_idx_name, "%", boost::lexical_cast<std::string>(col_idx));
sub_feature->put(col_name, feature.get(col_idx_name));
}
}
else
{
// non-indexed column
sub_feature->put(col_name, feature.get(col_name));
}
}
// add a single point geometry at pixel origin
sub_feature->add_geometry(origin_point(prj_trans, common));
// get the layout for this set of properties
for (auto const& rule : props->get_rules())
{
if (boost::apply_visitor(evaluate<Feature,value_type>(*sub_feature),
*(rule->get_filter())).to_bool())
{
// add matched rule and feature to the list of things to draw
matches.push_back(std::make_pair(rule, sub_feature));
// construct a bounding box around all symbolizers for the matched rule
bound_box bounds;
render_thunk_list thunks;
render_thunk_extractor extractor(bounds, thunks, *sub_feature, prj_trans,
virtual_renderer, clipping_extent);
for (auto const& sym : *rule)
{
// TODO: construct layout and obtain bounding box
boost::apply_visitor(extractor, sym);
}
// add the bounding box to the layout manager
layout_manager.add_member_bound_box(bounds);
layout_thunks.emplace_back(std::move(thunks));
++num_layout_thunks;
break;
}
}
}
// create a symbolizer helper
group_symbolizer_helper helper(sym, feature, prj_trans,
common.width_, common.height_,
common.scale_factor_, common.t_,
*common.detector_, clipping_extent);
// determine if we should be tracking repeat distance
bool check_repeat = (helper.get_properties().minimum_distance > 0);
for (size_t i = 0; i < matches.size(); ++i)
{
if (check_repeat)
{
group_rule_ptr match_rule = matches[i].first;
feature_ptr match_feature = matches[i].second;
value_unicode_string rpt_key_value = "";
// get repeat key from matched group rule
expression_ptr rpt_key_expr = match_rule->get_repeat_key();
// if no repeat key was defined, use default from group symbolizer
if (!rpt_key_expr)
{
rpt_key_expr = get<expression_ptr>(sym, keys::repeat_key);
}
// evalute the repeat key with the matched sub feature if we have one
if (rpt_key_expr)
{
rpt_key_value = boost::apply_visitor(evaluate<Feature,value_type>(*match_feature), *rpt_key_expr).to_unicode();
}
helper.add_box_element(layout_manager.offset_box_at(i), rpt_key_value);
}
else
{
helper.add_box_element(layout_manager.offset_box_at(i));
}
}
pixel_position_list positions = helper.get();
for (pixel_position const& pos : positions)
{
for (size_t layout_i = 0; layout_i < num_layout_thunks; ++layout_i)
{
const pixel_position &offset = layout_manager.offset_at(layout_i);
pixel_position render_offset = pos + offset;
render_thunks(layout_thunks[layout_i], render_offset);
}
}
}
} // namespace mapnik
#endif /* MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP */

View file

@ -0,0 +1,176 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP
#include <mapnik/svg/svg_storage.hpp>
#include <mapnik/svg/svg_path_adapter.hpp>
#include <mapnik/svg/svg_path_attributes.hpp>
namespace mapnik {
namespace {
} // anonymous namespace
template <typename F1, typename F2>
void render_markers_symbolizer(markers_symbolizer const &sym,
mapnik::feature_impl &feature,
proj_transform const &prj_trans,
renderer_common &common,
box2d<double> const &clip_box,
F1 make_vector_dispatch,
F2 make_raster_dispatch)
{
using namespace mapnik::svg;
typedef boost::mpl::vector<clip_poly_tag,transform_tag,smooth_tag> conv_types;
typedef agg::pod_bvector<path_attributes> svg_attribute_type;
std::string filename = get<std::string>(sym, keys::file, feature, "shape://ellipse");
bool clip = get<value_bool>(sym, keys::clip, feature, false);
double smooth = get<value_double>(sym, keys::smooth, feature, false);
// https://github.com/mapnik/mapnik/issues/1316
bool snap_pixels = !mapnik::marker_cache::instance().is_uri(filename);
if (!filename.empty())
{
boost::optional<marker_ptr> mark = mapnik::marker_cache::instance().find(filename, true);
if (mark && *mark)
{
agg::trans_affine tr = agg::trans_affine_scaling(common.scale_factor_);
if ((*mark)->is_vector())
{
boost::optional<svg_path_ptr> const& stock_vector_marker = (*mark)->get_vector_data();
auto width_expr = get_optional<expression_ptr>(sym, keys::width);
auto height_expr = get_optional<expression_ptr>(sym, keys::height);
// special case for simple ellipse markers
// to allow for full control over rx/ry dimensions
if (filename == "shape://ellipse"
&& (width_expr || height_expr))
{
svg_storage_type marker_ellipse;
vertex_stl_adapter<svg_path_storage> stl_storage(marker_ellipse.source());
svg_path_adapter svg_path(stl_storage);
build_ellipse(sym, feature, marker_ellipse, svg_path);
svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(tr, feature, *image_transform);
box2d<double> bbox = marker_ellipse.bounding_box();
auto rasterizer_dispatch = make_vector_dispatch(
svg_path, result ? attributes : (*stock_vector_marker)->attributes(),
marker_ellipse, bbox, tr, snap_pixels);
typedef decltype(rasterizer_dispatch) dispatch_type;
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl>
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
//else if (type == LineString)
// converter.template set<clip_line_tag>();
// don't clip if type==Point
}
converter.template set<transform_tag>(); //always transform
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, converter, sym);
}
else
{
box2d<double> const& bbox = (*mark)->bounding_box();
setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, sym);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(tr, feature, *image_transform);
vertex_stl_adapter<svg_path_storage> stl_storage((*stock_vector_marker)->source());
svg_path_adapter svg_path(stl_storage);
svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym);
auto rasterizer_dispatch = make_vector_dispatch(
svg_path, result ? attributes : (*stock_vector_marker)->attributes(),
**stock_vector_marker, bbox, tr, snap_pixels);
typedef decltype(rasterizer_dispatch) dispatch_type;
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl>
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
//else if (type == LineString)
// converter.template set<clip_line_tag>();
// don't clip if type==Point
}
converter.template set<transform_tag>(); //always transform
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, converter, sym);
}
}
else // raster markers
{
setup_transform_scaling(tr, (*mark)->width(), (*mark)->height(), feature, sym);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(tr, feature, *image_transform);
box2d<double> const& bbox = (*mark)->bounding_box();
boost::optional<mapnik::image_ptr> marker = (*mark)->get_bitmap_data();
auto rasterizer_dispatch = make_raster_dispatch(**marker, tr, bbox);
typedef decltype(rasterizer_dispatch) dispatch_type;
vertex_converter<box2d<double>, dispatch_type, markers_symbolizer,
CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl>
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
//else if (type == geometry_type::types::LineString)
// converter.template set<clip_line_tag>();
// don't clip if type==geometry_type::types::Point
}
converter.template set<transform_tag>(); //always transform
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, converter, sym);
}
}
}
}
} // namespace mapnik
#endif /* MAPNIK_RENDERER_COMMON_PROCESS_MARKERS_SYMBOLIZER_HPP */

View file

@ -0,0 +1,106 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_RENDERER_COMMON_PROCESS_POINT_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_POINT_SYMBOLIZER_HPP
#include <mapnik/geom_util.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
namespace mapnik {
template <typename F>
void render_point_symbolizer(point_symbolizer const &sym,
mapnik::feature_impl &feature,
proj_transform const &prj_trans,
renderer_common &common,
F render_marker)
{
std::string filename = get<std::string>(sym, keys::file, feature);
boost::optional<mapnik::marker_ptr> marker;
if ( !filename.empty() )
{
marker = marker_cache::instance().find(filename, true);
}
else
{
marker.reset(std::make_shared<mapnik::marker>());
}
if (marker)
{
double opacity = get<double>(sym,keys::opacity,feature, 1.0);
bool allow_overlap = get<bool>(sym, keys::allow_overlap, feature, false);
bool ignore_placement = get<bool>(sym, keys::ignore_placement, feature, false);
point_placement_enum placement= get<point_placement_enum>(sym, keys::point_placement_type, feature, CENTROID_POINT_PLACEMENT);
box2d<double> const& bbox = (*marker)->bounding_box();
coord2d center = bbox.center();
agg::trans_affine tr;
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(tr, feature, *image_transform);
agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine recenter_tr = recenter * tr;
box2d<double> label_ext = bbox * recenter_tr * agg::trans_affine_scaling(common.scale_factor_);
for (std::size_t i=0; i<feature.num_geometries(); ++i)
{
geometry_type const& geom = feature.get_geometry(i);
double x;
double y;
double z=0;
if (placement == CENTROID_POINT_PLACEMENT)
{
if (!label::centroid(geom, x, y))
return;
}
else
{
if (!label::interior_position(geom ,x, y))
return;
}
prj_trans.backward(x,y,z);
common.t_.forward(&x,&y);
label_ext.re_center(x,y);
if (allow_overlap ||
common.detector_->has_placement(label_ext))
{
render_marker(pixel_position(x, y),
**marker,
tr,
opacity);
if (!ignore_placement)
common.detector_->insert(label_ext);
}
}
}
}
} // namespace mapnik
#endif /* MAPNIK_RENDERER_COMMON_PROCESS_POINT_SYMBOLIZER_HPP */

View file

@ -0,0 +1,69 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_RENDERER_COMMON_PROCESS_POLYGON_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_POLYGON_SYMBOLIZER_HPP
namespace mapnik {
template <typename vertex_converter_type, typename rasterizer_type, typename F>
void render_polygon_symbolizer(polygon_symbolizer const &sym,
mapnik::feature_impl &feature,
proj_transform const &prj_trans,
renderer_common &common,
box2d<double> const &clip_box,
rasterizer_type &ras,
F fill_func)
{
agg::trans_affine tr;
auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
if (transform) evaluate_transform(tr, feature, *transform, common.scale_factor_);
bool clip = get<value_bool>(sym, keys::clip, feature, true);
double simplify_tolerance = get<double>(sym, keys::simplify_tolerance, feature, 0.0);
double smooth = get<value_double>(sym, keys::smooth, feature, 0.0);
double opacity = get<value_double>(sym,keys::fill_opacity,feature, 1.0);
vertex_converter_type converter(clip_box, ras, sym, common.t_, prj_trans, tr,
feature,common.scale_factor_);
if (prj_trans.equal() && clip) converter.template set<clip_poly_tag>(); //optional clip (default: true)
converter.template set<transform_tag>(); //always transform
converter.template set<affine_transform_tag>();
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
for (geometry_type & geom : feature.paths())
{
if (geom.size() > 2)
{
converter.apply(geom);
}
}
color const& fill = get<mapnik::color>(sym, keys::fill, feature, mapnik::color(128,128,128)); // gray
fill_func(fill, opacity);
}
} // namespace mapnik
#endif /* MAPNIK_RENDERER_COMMON_PROCESS_POLYGON_SYMBOLIZER_HPP */

View file

@ -0,0 +1,122 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP
#define MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP
// agg
#include "agg_rendering_buffer.h"
#include "agg_pixfmt_rgba.h"
namespace mapnik {
template <typename F>
void render_raster_symbolizer(raster_symbolizer const &sym,
mapnik::feature_impl &feature,
proj_transform const &prj_trans,
renderer_common &common,
F composite)
{
raster_ptr const& source = feature.get_raster();
if (source)
{
// If there's a colorizer defined, use it to color the raster in-place
raster_colorizer_ptr colorizer = get<raster_colorizer_ptr>(sym, keys::colorizer);
if (colorizer)
colorizer->colorize(source,feature);
box2d<double> target_ext = box2d<double>(source->ext_);
prj_trans.backward(target_ext, PROJ_ENVELOPE_POINTS);
box2d<double> ext = common.t_.forward(target_ext);
int start_x = static_cast<int>(std::floor(ext.minx()+.5));
int start_y = static_cast<int>(std::floor(ext.miny()+.5));
int end_x = static_cast<int>(std::floor(ext.maxx()+.5));
int end_y = static_cast<int>(std::floor(ext.maxy()+.5));
int raster_width = end_x - start_x;
int raster_height = end_y - start_y;
if (raster_width > 0 && raster_height > 0)
{
raster target(target_ext, raster_width, raster_height, source->get_filter_factor());
scaling_method_e scaling_method = get<scaling_method_e>(sym, keys::scaling, feature, SCALING_NEAR);
composite_mode_e comp_op = get<composite_mode_e>(sym, keys::comp_op, feature, src_over);
double opacity = get<double>(sym,keys::opacity,feature, 1.0);
bool premultiply_source = !source->premultiplied_alpha_;
auto is_premultiplied = get_optional<bool>(sym, keys::premultiplied);
if (is_premultiplied)
{
if (*is_premultiplied) premultiply_source = false;
else premultiply_source = true;
}
if (premultiply_source)
{
agg::rendering_buffer buffer(source->data_.getBytes(),
source->data_.width(),
source->data_.height(),
source->data_.width() * 4);
agg::pixfmt_rgba32 pixf(buffer);
pixf.premultiply();
}
if (!prj_trans.equal())
{
double offset_x = ext.minx() - start_x;
double offset_y = ext.miny() - start_y;
unsigned mesh_size = static_cast<unsigned>(get<value_integer>(sym,keys::mesh_size,feature, 16));
reproject_and_scale_raster(target,
*source,
prj_trans,
offset_x,
offset_y,
mesh_size,
scaling_method);
}
else
{
if (scaling_method == SCALING_BILINEAR8)
{
scale_image_bilinear8<image_data_32>(target.data_,
source->data_,
0.0,
0.0);
}
else
{
double image_ratio_x = ext.width() / source->data_.width();
double image_ratio_y = ext.height() / source->data_.height();
scale_image_agg<image_data_32>(target.data_,
source->data_,
scaling_method,
image_ratio_x,
image_ratio_y,
0.0,
0.0,
source->get_filter_factor());
}
}
composite(target, comp_op, opacity, start_x, start_y);
}
}
}
} // namespace mapnik
#endif /* MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP */

View file

@ -24,24 +24,11 @@
#define MAPNIK_RULE_HPP
// mapnik
#include <mapnik/building_symbolizer.hpp>
#include <mapnik/line_symbolizer.hpp>
#include <mapnik/line_pattern_symbolizer.hpp>
#include <mapnik/polygon_symbolizer.hpp>
#include <mapnik/polygon_pattern_symbolizer.hpp>
#include <mapnik/point_symbolizer.hpp>
#include <mapnik/raster_symbolizer.hpp>
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/markers_symbolizer.hpp>
#include <mapnik/debug_symbolizer.hpp>
#include <mapnik/config.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/expression_string.hpp>
#include <mapnik/config.hpp> // MAPNIK_DECL
// boost
#include <boost/variant/variant_fwd.hpp>
// stl
#include <string>
@ -50,82 +37,6 @@
namespace mapnik
{
inline bool operator==(point_symbolizer const& lhs,
point_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(line_symbolizer const& lhs,
line_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(line_pattern_symbolizer const& lhs,
line_pattern_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(polygon_symbolizer const& lhs,
polygon_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(polygon_pattern_symbolizer const& lhs,
polygon_pattern_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(raster_symbolizer const& lhs,
raster_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(text_symbolizer const& lhs,
text_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(shield_symbolizer const& lhs,
shield_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(building_symbolizer const& lhs,
building_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(markers_symbolizer const& lhs,
markers_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
inline bool operator==(debug_symbolizer const& lhs,
debug_symbolizer const& rhs)
{
return (&lhs == &rhs);
}
typedef boost::variant<point_symbolizer,
line_symbolizer,
line_pattern_symbolizer,
polygon_symbolizer,
polygon_pattern_symbolizer,
raster_symbolizer,
shield_symbolizer,
text_symbolizer,
building_symbolizer,
markers_symbolizer,
debug_symbolizer> symbolizer;
class MAPNIK_DECL rule
{
public:
@ -145,9 +56,8 @@ public:
rule(std::string const& name,
double min_scale_denominator = 0,
double max_scale_denominator = std::numeric_limits<double>::infinity());
rule(rule const& rhs);
rule& operator=(rule const& rhs);
rule(const rule& rhs);
rule& operator=(rule rhs);
bool operator==(rule const& other);
void set_max_scale(double scale);
double get_max_scale() const;
@ -155,9 +65,9 @@ public:
double get_min_scale() const;
void set_name(std::string const& name);
std::string const& get_name() const;
void append(symbolizer const& sym);
void append(symbolizer && sym);
void remove_at(size_t index);
const symbolizers& get_symbolizers() const;
symbolizers const& get_symbolizers() const;
symbolizers::const_iterator begin() const;
symbolizers::const_iterator end() const;
symbolizers::iterator begin();

View file

@ -1,65 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_SHIELD_SYMBOLIZER_HPP
#define MAPNIK_SHIELD_SYMBOLIZER_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/color.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/text_symbolizer.hpp>
// boost
#include <boost/tuple/tuple.hpp>
namespace mapnik
{
struct MAPNIK_DECL shield_symbolizer : public text_symbolizer,
public symbolizer_with_image
{
// Note - we do not use std::make_shared below as VC2008 and VC2010 are
// not able to compile make_shared used within a constructor
shield_symbolizer(text_placements_ptr placements = text_placements_ptr(new text_placements_dummy));
shield_symbolizer(expression_ptr name,
std::string const& face_name,
float size,
color const& fill,
path_expression_ptr file);
shield_symbolizer(expression_ptr name,
float size,
color const& fill,
path_expression_ptr file);
bool get_unlock_image() const; // image is not locked to the text placement
void set_unlock_image(bool unlock_image);
void set_shield_displacement(double shield_dx, double shield_dy);
pixel_position const& get_shield_displacement() const;
private:
bool unlock_image_;
pixel_position shield_displacement_;
};
}
#endif // MAPNIK_SHIELD_SYMBOLIZER_HPP

View file

@ -1,119 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_STROKE_HPP
#define MAPNIK_STROKE_HPP
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/color.hpp>
#include <mapnik/gamma_method.hpp>
#include <mapnik/enumeration.hpp>
// stl
#include <vector>
namespace mapnik
{
typedef std::vector<std::pair<double,double> > dash_array;
// if you add new tokens, don't forget to add them to the corresponding
// string array in the cpp file.
enum line_cap_enum
{
BUTT_CAP,
SQUARE_CAP,
ROUND_CAP,
line_cap_enum_MAX
};
DEFINE_ENUM( line_cap_e, line_cap_enum );
// if you add new tokens, don't forget to add them to the corresponding
// string array in the cpp file.
enum line_join_enum
{
MITER_JOIN,
MITER_REVERT_JOIN,
ROUND_JOIN,
BEVEL_JOIN,
line_join_enum_MAX
};
DEFINE_ENUM( line_join_e, line_join_enum );
class MAPNIK_DECL stroke
{
color c_;
double width_;
double opacity_; // 0.0 - 1.0
line_cap_e line_cap_;
line_join_e line_join_;
double gamma_;
gamma_method_e gamma_method_;
dash_array dash_;
double dash_offset_;
double miterlimit_;
public:
stroke();
explicit stroke(color const& c, double width=1.0);
stroke(stroke const& other);
stroke& operator=(const stroke& rhs);
void set_color(const color& c);
color const& get_color() const;
double get_width() const;
void set_width(double w);
void set_opacity(double opacity);
double get_opacity() const;
void set_line_cap(line_cap_e line_cap);
line_cap_e get_line_cap() const;
void set_line_join(line_join_e line_join);
line_join_e get_line_join() const;
void set_gamma(double gamma);
double get_gamma() const;
void set_gamma_method(gamma_method_e gamma_method);
gamma_method_e get_gamma_method() const;
void add_dash(double dash,double gap);
bool has_dash() const;
void set_dash_offset(double offset);
double dash_offset() const;
dash_array const& get_dash_array() const;
void set_miterlimit(double val);
double get_miterlimit() const;
private:
void swap(const stroke& other) throw();
};
}
#endif // MAPNIK_STROKE_HPP

View file

@ -25,7 +25,7 @@
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/stroke.hpp>
#include <mapnik/symbolizer.hpp>
// stl
#include <string>

View file

@ -24,7 +24,7 @@
#define SVG_OUTPUT_GRAMMARS_HPP
// mapnik
#include <mapnik/stroke.hpp>
#include <mapnik/symbolizer.hpp>
// fwd declare
namespace mapnik { namespace svg {

View file

@ -38,6 +38,7 @@
#include <mapnik/image_compositing.hpp> // for composite_mode_e
#include <mapnik/pixel_position.hpp>
#include <mapnik/request.hpp>
#include <mapnik/renderer_common.hpp>
// boost
#include <boost/variant/static_visitor.hpp>
@ -119,6 +120,9 @@ public:
void process(debug_symbolizer const& /*sym*/,
mapnik::feature_impl & /*feature*/,
proj_transform const& /*prj_trans*/) {}
void process(group_symbolizer const& sym,
mapnik::feature_impl & feature,
proj_transform const& prj_trans);
/*!
* @brief Overload that process the whole set of symbolizers of a rule.
@ -140,7 +144,7 @@ public:
inline double scale_factor() const
{
return scale_factor_;
return common_.scale_factor_;
}
inline OutputIterator& get_output_iterator()
@ -155,17 +159,10 @@ public:
private:
OutputIterator& output_iterator_;
const int width_;
const int height_;
double scale_factor_;
CoordTransform t_;
svg::path_output_attributes path_attributes_;
freetype_engine font_engine_;
face_manager<freetype_engine> font_manager_;
std::shared_ptr<label_collision_detector4> detector_;
svg::svg_generator<OutputIterator> generator_;
box2d<double> query_extent_;
bool painted_;
renderer_common common_;
/*!
* @brief Visitor that makes the calls to process each symbolizer when stored in a boost::variant.

View file

@ -46,11 +46,7 @@ template <typename PathType>
struct move_to
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef void type;
@ -71,11 +67,7 @@ struct move_to
template <typename PathType>
struct hline_to
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef void type;
@ -97,11 +89,7 @@ struct hline_to
template <typename PathType>
struct vline_to
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef void type;
@ -122,11 +110,7 @@ struct vline_to
template <typename PathType>
struct line_to
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef void type;
@ -148,11 +132,7 @@ struct line_to
template <typename PathType>
struct curve4
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2, typename T3>
#endif
struct result
{
typedef void type;
@ -177,11 +157,7 @@ struct curve4
template <typename PathType>
struct curve4_smooth
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2>
#endif
struct result
{
typedef void type;
@ -203,11 +179,7 @@ struct curve4_smooth
template <typename PathType>
struct curve3
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2>
#endif
struct result
{
typedef void type;
@ -230,11 +202,7 @@ struct curve3
template <typename PathType>
struct curve3_smooth
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef void type;
@ -256,11 +224,7 @@ struct curve3_smooth
template <typename PathType>
struct arc_to
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
#endif
struct result
{
typedef void type;

View file

@ -27,16 +27,12 @@
#include <mapnik/svg/svg_path_attributes.hpp>
#include <mapnik/gradient.hpp>
#include <mapnik/box2d.hpp>
#include <mapnik/noncopyable.hpp>
#if defined(GRID_RENDERER)
#include <mapnik/grid/grid_pixel.hpp>
#endif
#include <mapnik/noncopyable.hpp>
// boost
// agg
#include "agg_path_storage.h"
#include "agg_conv_transform.h"
@ -111,6 +107,8 @@ public:
typedef agg::conv_transform<curved_type> curved_trans_type;
typedef agg::conv_contour<curved_trans_type> curved_trans_contour_type;
typedef agg::renderer_base<PixelFormat> renderer_base;
typedef VertexSource vertex_source_type;
typedef AttributeSource attribute_source_type;
svg_renderer_agg(VertexSource & source, AttributeSource const& attributes)
: source_(source),
@ -118,6 +116,10 @@ public:
curved_stroked_(curved_),
attributes_(attributes) {}
svg_renderer_agg(svg_renderer_agg &&r)
: source_(r.source_), curved_(source_), curved_stroked_(curved_),
attributes_(r.attributes_) {}
template <typename Rasterizer, typename Scanline, typename Renderer>
void render_gradient(Rasterizer& ras,
Scanline& sl,

View file

@ -50,11 +50,7 @@ namespace mapnik { namespace svg {
template <typename TransformType>
struct process_matrix
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
#endif
struct result
{
typedef void type;
@ -74,11 +70,7 @@ namespace mapnik { namespace svg {
template <typename TransformType>
struct process_rotate
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1, typename T2>
#endif
struct result
{
typedef void type;
@ -109,11 +101,7 @@ namespace mapnik { namespace svg {
template <typename TransformType>
struct process_translate
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef void type;
@ -135,11 +123,7 @@ namespace mapnik { namespace svg {
template <typename TransformType>
struct process_scale
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef void type;
@ -162,11 +146,7 @@ namespace mapnik { namespace svg {
template <typename TransformType>
struct process_skew
{
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result
{
typedef void type;

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 Artem Pavlenko
* Copyright (C) 2013 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -25,16 +25,28 @@
// mapnik
#include <mapnik/config.hpp>
#include <mapnik/path_expression.hpp>
#include <mapnik/value_types.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/simplify.hpp>
// boost
#include <memory>
#include <mapnik/expression.hpp>
#include <mapnik/expression_evaluator.hpp>
#include <mapnik/path_expression.hpp>
#include <mapnik/parse_path.hpp>
#include <mapnik/color.hpp>
#include <mapnik/symbolizer_keys.hpp>
#include <mapnik/text/placements/base.hpp>
#include <mapnik/text/placements/dummy.hpp>
#include <mapnik/raster_colorizer.hpp>
#include <mapnik/group/group_symbolizer_properties.hpp>
// stl
#include <type_traits>
#include <algorithm>
#include <memory>
#include <vector>
#include <string>
#include <functional>
// boost
#include <boost/variant/variant_fwd.hpp>
namespace agg { struct trans_affine; }
@ -49,54 +61,474 @@ typedef std::shared_ptr<transform_list> transform_list_ptr;
typedef transform_list_ptr transform_type;
class feature_impl;
MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr, feature_impl const& feature,
transform_type const& trans_expr, double scale_factor=1.0);
MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr,
feature_impl const& feature,
transform_type const& trans_expr,
double scale_factor=1.0);
class MAPNIK_DECL symbolizer_base
struct enumeration_wrapper
{
public:
symbolizer_base();
symbolizer_base(symbolizer_base const& other);
void set_comp_op(composite_mode_e comp_op);
composite_mode_e comp_op() const;
void set_transform(transform_type const& );
transform_type const& get_transform() const;
std::string get_transform_string() const;
void set_clip(bool clip);
bool clip() const;
void set_simplify_algorithm(simplify_algorithm_e algorithm);
simplify_algorithm_e simplify_algorithm() const;
void set_simplify_tolerance(double simplify_tolerance);
double simplify_tolerance() const;
void set_smooth(double smooth);
double smooth() const;
private:
composite_mode_e comp_op_;
transform_type affine_transform_;
bool clip_;
simplify_algorithm_e simplify_algorithm_value_;
double simplify_tolerance_value_;
double smooth_value_;
int value;
enumeration_wrapper() = delete;
template <typename T>
explicit enumeration_wrapper(T value_)
: value(value_) {}
inline operator int() const
{
return value;
}
};
typedef std::vector<std::pair<double,double> > dash_array;
struct MAPNIK_DECL symbolizer_base
{
typedef boost::variant<value_bool,
value_integer,
enumeration_wrapper,
value_double,
std::string,
color,
expression_ptr,
path_expression_ptr,
transform_type,
text_placements_ptr,
dash_array,
raster_colorizer_ptr,
group_symbolizer_properties_ptr> value_type;
typedef mapnik::keys key_type;
typedef std::map<key_type, value_type> cont_type;
cont_type properties;
};
// symbolizer properties target types
enum class property_types : std::uint8_t
{
target_bool = 1,
target_double,
target_integer,
target_color,
target_comp_op,
target_line_cap,
target_line_join,
target_line_rasterizer,
target_halo_rasterizer,
target_point_placement,
target_pattern_alignment,
target_debug_symbolizer_mode,
target_marker_placement,
target_marker_multi_policy,
target_string,
target_transform,
target_placement,
target_dash_array,
target_colorizer,
target_repeat_key,
target_group_symbolizer_properties
};
inline bool operator==(symbolizer_base const& lhs, symbolizer_base const& rhs)
{
return lhs.properties.size() == rhs.properties.size() &&
std::equal(lhs.properties.begin(), lhs.properties.end(), rhs.properties.begin());
}
template <typename T>
struct evaluate_path_wrapper
{
typedef T result_type;
template <typename T1, typename T2>
result_type operator() (T1 const& expr, T2 const& feature) const
{
return result_type();
}
};
template <>
struct evaluate_path_wrapper<std::string>
{
template <typename T1, typename T2>
std::string operator() (T1 const& expr, T2 const& feature) const
{
return mapnik::path_processor_type::evaluate(expr, feature);
}
};
namespace detail {
// enum
template <typename T, bool is_enum = true>
struct expression_result
{
typedef T result_type;
static result_type convert(value_type const& val)
{
return static_cast<T>(val.convert<value_integer>());
}
};
template <typename T>
struct expression_result<T,false>
{
typedef T result_type;
static result_type convert(value_type const& val)
{
return val.convert<T>();
}
};
// enum
template <typename T, bool is_enum = true>
struct enumeration_result
{
typedef T result_type;
static result_type convert(enumeration_wrapper const& e)
{
return static_cast<result_type>(e.value);
}
};
template <typename T>
struct enumeration_result<T,false>
{
typedef T result_type;
static result_type convert(enumeration_wrapper const& e)
{
return result_type();// FAIL
}
};
// enum
template <typename T, bool is_enum = true >
struct put_impl
{
static void apply(symbolizer_base & sym, keys key, T const& val)
{
auto itr = sym.properties.find(key);
if (itr != sym.properties.end())
{
sym.properties[key] = enumeration_wrapper(val);
}
else
{
// NOTE: we use insert here instead of emplace
// because of lacking std::map emplace support in libstdc++
// http://gcc.gnu.org/bugzilla/show_bug.cgi?id=44436
sym.properties.insert(std::make_pair(key, enumeration_wrapper(val)));
}
}
};
template <typename T>
struct put_impl<T, false>
{
static void apply(symbolizer_base & sym, keys key, T const& val)
{
auto itr = sym.properties.find(key);
if (itr != sym.properties.end())
{
sym.properties[key] = val;
}
else
{
sym.properties.insert(std::make_pair(key, val));
}
}
};
}
template <typename T>
struct evaluate_expression_wrapper
{
typedef T result_type;
template <typename T1, typename T2>
result_type operator() (T1 const& expr, T2 const& feature) const
{
mapnik::value_type result = boost::apply_visitor(mapnik::evaluate<mapnik::feature_impl,mapnik::value_type>(feature), expr);
return detail::expression_result<result_type, std::is_enum<result_type>::value>::convert(result);
}
};
// mapnik::color
template <>
struct evaluate_expression_wrapper<mapnik::color>
{
template <typename T1, typename T2>
mapnik::color operator() (T1 const& expr, T2 const& feature) const
{
mapnik::value_type val = boost::apply_visitor(mapnik::evaluate<mapnik::feature_impl,mapnik::value_type>(feature), expr);
return mapnik::color(val.to_string());
}
};
// enumeration wrapper
template <>
struct evaluate_expression_wrapper<mapnik::enumeration_wrapper>
{
template <typename T1, typename T2>
mapnik::enumeration_wrapper operator() (T1 const& expr, T2 const& feature) const
{
mapnik::value_type val = boost::apply_visitor(mapnik::evaluate<mapnik::feature_impl,mapnik::value_type>(feature), expr);
return mapnik::enumeration_wrapper(val.to_int());
}
};
class MAPNIK_DECL symbolizer_with_image
template <typename T>
struct extract_value : public boost::static_visitor<T>
{
public:
path_expression_ptr const& get_filename() const;
void set_filename(path_expression_ptr const& filename);
void set_opacity(float opacity);
float get_opacity() const;
void set_image_transform(transform_type const& tr);
transform_type const& get_image_transform() const;
std::string get_image_transform_string() const;
protected:
symbolizer_with_image(path_expression_ptr filename = path_expression_ptr());
symbolizer_with_image(symbolizer_with_image const& rhs);
path_expression_ptr image_filename_;
float image_opacity_;
transform_type image_transform_;
typedef T result_type;
extract_value(mapnik::feature_impl const& feature)
: feature_(feature) {}
auto operator() (mapnik::expression_ptr const& expr) const -> result_type
{
return evaluate_expression_wrapper<result_type>()(*expr,feature_);
}
auto operator() (mapnik::path_expression_ptr const& expr) const -> result_type
{
return evaluate_path_wrapper<result_type>()(*expr, feature_);
}
auto operator() (result_type const& val) const -> result_type
{
return val;
}
auto operator() (mapnik::enumeration_wrapper const& e) const -> result_type
{
return detail::enumeration_result<result_type, std::is_enum<result_type>::value>::convert(e);
}
template <typename T1>
auto operator() (T1 const& val) const -> result_type
{
return result_type();
}
mapnik::feature_impl const& feature_;
};
template <typename T1>
struct extract_raw_value : public boost::static_visitor<T1>
{
typedef T1 result_type;
auto operator() (result_type const& val) const -> result_type const&
{
return val;
}
auto operator() (mapnik::enumeration_wrapper const& e) const -> result_type
{
return detail::enumeration_result<result_type, std::is_enum<result_type>::value>::convert(e);
}
template <typename T2>
auto operator() (T2 const& val) const -> result_type
{
return result_type();
}
};
template <typename T>
void put(symbolizer_base & sym, keys key, T const& val)
{
constexpr bool enum_ = std::is_enum<T>::value;
detail::put_impl<T, enum_ >::apply(sym, key, val);
}
template <typename T>
bool has_key(symbolizer_base const& sym, keys key)
{
return (sym.properties.count(key) == 1);
}
template <typename T>
T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, T const& _default_value = T())
{
typedef symbolizer_base::cont_type::const_iterator const_iterator;
const_iterator itr = sym.properties.find(key);
if (itr != sym.properties.end())
{
return boost::apply_visitor(extract_value<T>(feature), itr->second);
}
return _default_value;
}
template <typename T>
boost::optional<T> get_optional(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature)
{
typedef symbolizer_base::cont_type::const_iterator const_iterator;
const_iterator itr = sym.properties.find(key);
if (itr != sym.properties.end())
{
return boost::apply_visitor(extract_value<T>(feature), itr->second);
}
return boost::optional<T>();
}
template <typename T>
T get(symbolizer_base const& sym, keys key, T const& _default_value = T())
{
typedef symbolizer_base::cont_type::const_iterator const_iterator;
const_iterator itr = sym.properties.find(key);
if (itr != sym.properties.end())
{
return boost::apply_visitor(extract_raw_value<T>(), itr->second);
}
return _default_value;
}
template <typename T>
boost::optional<T> get_optional(symbolizer_base const& sym, keys key)
{
typedef symbolizer_base::cont_type::const_iterator const_iterator;
const_iterator itr = sym.properties.find(key);
if (itr != sym.properties.end())
{
return boost::apply_visitor(extract_raw_value<T>(), itr->second);
}
return boost::optional<T>();
}
template<typename Enum>
constexpr auto to_integral(Enum e) -> typename std::underlying_type<Enum>::type
{
return static_cast<typename std::underlying_type<Enum>::type>(e);
}
typedef std::tuple<const char*, mapnik::symbolizer_base::value_type, std::function<std::string(enumeration_wrapper)>, property_types> property_meta_type;
property_meta_type const& get_meta(mapnik::keys key);
mapnik::keys get_key(std::string const& name);
// concrete symbolizer types
struct MAPNIK_DECL point_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL line_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL polygon_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL text_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL shield_symbolizer : public text_symbolizer {};
struct MAPNIK_DECL line_pattern_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL polygon_pattern_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL markers_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL raster_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL building_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL group_symbolizer : public symbolizer_base {};
struct MAPNIK_DECL debug_symbolizer : public symbolizer_base {};
// symbolizer
typedef boost::variant<point_symbolizer,
line_symbolizer,
line_pattern_symbolizer,
polygon_symbolizer,
polygon_pattern_symbolizer,
raster_symbolizer,
shield_symbolizer,
text_symbolizer,
building_symbolizer,
markers_symbolizer,
group_symbolizer,
debug_symbolizer> symbolizer;
typedef std::vector<std::pair<double,double> > dash_array;
enum line_cap_enum
{
BUTT_CAP,
SQUARE_CAP,
ROUND_CAP,
line_cap_enum_MAX
};
DEFINE_ENUM( line_cap_e, line_cap_enum );
enum line_join_enum
{
MITER_JOIN,
MITER_REVERT_JOIN,
ROUND_JOIN,
BEVEL_JOIN,
line_join_enum_MAX
};
DEFINE_ENUM( line_join_e, line_join_enum );
enum line_rasterizer_enum
{
RASTERIZER_FULL, // agg::renderer_scanline_aa_solid
RASTERIZER_FAST, // agg::rasterizer_outline_aa, twice as fast but only good for thin lines
line_rasterizer_enum_MAX
};
DEFINE_ENUM( line_rasterizer_e, line_rasterizer_enum );
enum halo_rasterizer_enum
{
HALO_RASTERIZER_FULL,
HALO_RASTERIZER_FAST,
halo_rasterizer_enum_MAX
};
DEFINE_ENUM(halo_rasterizer_e, halo_rasterizer_enum);
enum point_placement_enum
{
CENTROID_POINT_PLACEMENT,
INTERIOR_POINT_PLACEMENT,
point_placement_enum_MAX
};
DEFINE_ENUM( point_placement_e, point_placement_enum );
enum pattern_alignment_enum
{
LOCAL_ALIGNMENT,
GLOBAL_ALIGNMENT,
pattern_alignment_enum_MAX
};
DEFINE_ENUM( pattern_alignment_e, pattern_alignment_enum );
enum debug_symbolizer_mode_enum
{
DEBUG_SYM_MODE_COLLISION,
DEBUG_SYM_MODE_VERTEX,
debug_symbolizer_mode_enum_MAX
};
DEFINE_ENUM( debug_symbolizer_mode_e, debug_symbolizer_mode_enum );
// markers
// TODO - consider merging with text_symbolizer label_placement_e
enum marker_placement_enum
{
MARKER_POINT_PLACEMENT,
MARKER_INTERIOR_PLACEMENT,
MARKER_LINE_PLACEMENT,
marker_placement_enum_MAX
};
DEFINE_ENUM( marker_placement_e, marker_placement_enum );
enum marker_multi_policy_enum
{
MARKER_EACH_MULTI, // each component in a multi gets its marker
MARKER_WHOLE_MULTI, // consider all components of a multi as a whole
MARKER_LARGEST_MULTI, // only the largest component of a multi gets a marker
marker_multi_policy_enum_MAX
};
DEFINE_ENUM( marker_multi_policy_e, marker_multi_policy_enum );
}
#endif // MAPNIK_SYMBOLIZER_HPP

View file

@ -23,43 +23,82 @@
#ifndef MAPNIK_SYMBOLIZER_HASH_HPP
#define MAPNIK_SYMBOLIZER_HASH_HPP
#include <mapnik/map.hpp>
#include <mapnik/feature_type_style.hpp>
#include <boost/functional/hash.hpp>
// mapnik
#include <mapnik/symbolizer.hpp>
// boost
#include <boost/variant/static_visitor.hpp>
// stl
#include <typeinfo>
#include <typeindex>
#include <functional>
namespace mapnik {
struct property_value_hash_visitor : boost::static_visitor<std::size_t>
{
std::size_t operator() (color val) const
{
return val.rgba();
}
std::size_t operator() (transform_type const& val) const
{
return 0; //FIXME
}
std::size_t operator() (enumeration_wrapper const& val) const
{
return 0; //FIXME
}
std::size_t operator() (dash_array const& val) const
{
return 0; //FIXME
}
template <typename T>
std::size_t operator() (T const& val) const
{
return std::hash<T>()(val);
}
};
struct symbolizer_hash
{
template <typename T>
static std::size_t value(T const& /*sym*/)
static std::size_t value(T const& sym)
{
return 0;
std::size_t seed = std::hash<std::type_index>()(typeid(sym));
for (auto const& prop : sym.properties)
{
seed ^= std::hash<std::size_t>()(static_cast<std::size_t>(prop.first));
seed ^= boost::apply_visitor(property_value_hash_visitor(), prop.second);
}
// specialisation for polygon_symbolizer
static std::size_t value(polygon_symbolizer const& sym)
{
std::size_t seed = geometry_type::types::Polygon;
boost::hash_combine(seed, sym.get_fill().rgba());
boost::hash_combine(seed, sym.get_opacity());
return seed;
}
};
// specialisation for line_symbolizer
static std::size_t value(line_symbolizer const& sym)
struct hash_visitor : boost::static_visitor<std::size_t>
{
std::size_t seed = geometry_type::types::LineString;
boost::hash_combine(seed, sym.get_stroke().get_color().rgba());
boost::hash_combine(seed, sym.get_stroke().get_width());
boost::hash_combine(seed, sym.get_stroke().get_opacity());
boost::hash_combine(seed, static_cast<int>(sym.get_stroke().get_line_cap()));
boost::hash_combine(seed, static_cast<int>(sym.get_stroke().get_line_join()));
return seed;
template <typename Symbolizer>
std::size_t operator() (Symbolizer const& sym) const
{
return symbolizer_hash::value(sym);
}
};
}
namespace std {
template<>
struct hash<mapnik::symbolizer>
{
std::size_t operator()(mapnik::symbolizer const& sym) const
{
return boost::apply_visitor(mapnik::hash_visitor(),sym);
}
};
}
#endif // MAPNIK_SYMBOLIZER_HASH_HPP

View file

@ -0,0 +1,91 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_SYMBOLIZER_KEYS_HPP
#define MAPNIK_SYMBOLIZER_KEYS_HPP
#include <string>
#include <tuple>
namespace mapnik {
enum class keys : std::uint8_t
{
gamma = 0,
gamma_method,
opacity,
alignment,
offset,
comp_op,
clip,
fill,
fill_opacity,
stroke,
stroke_width,
stroke_opacity,
stroke_linejoin,
stroke_linecap,
stroke_gamma,
stroke_gamma_method,
stroke_dashoffset,
stroke_dasharray,
stroke_miterlimit,
geometry_transform,
line_rasterizer,
image_transform,
spacing,
max_error,
allow_overlap,
ignore_placement,
width,
height,
file,
shield_dx,
shield_dy,
unlock_image,
text_opacity,
mode,
scaling,
filter_factor,
mesh_size,
premultiplied,
smooth,
simplify_algorithm,
simplify_tolerance,
halo_rasterizer,
text_placements_,
markers_placement_type,
markers_multipolicy,
point_placement_type,
colorizer,
halo_transform,
num_columns,
start_column,
repeat_key,
group_properties,
MAX_SYMBOLIZER_KEY
};
}
#endif // MAPNIK_SYMBOLIZER_KEYS_HPP

View file

@ -0,0 +1,307 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_SYMBOLIZER_UTILS_HPP
#define MAPNIK_SYMBOLIZER_UTILS_HPP
// mapnik
#include <mapnik/expression_string.hpp>
#include <mapnik/transform_processor.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/symbolizer.hpp>
// boost
#include <boost/variant/apply_visitor.hpp>
namespace mapnik {
template <typename Symbolizer>
struct symbolizer_traits
{
static char const* name() { return "Unknown";}
};
template<>
struct symbolizer_traits<point_symbolizer>
{
static char const* name() { return "PointSymbolizer";}
};
template<>
struct symbolizer_traits<line_symbolizer>
{
static char const* name() { return "LineSymbolizer";}
};
template<>
struct symbolizer_traits<polygon_symbolizer>
{
static char const* name() { return "PolygonSymbolizer";}
};
template<>
struct symbolizer_traits<text_symbolizer>
{
static char const* name() { return "TextSymbolizer";}
};
template<>
struct symbolizer_traits<line_pattern_symbolizer>
{
static char const* name() { return "LinePatternSymbolizer";}
};
template<>
struct symbolizer_traits<polygon_pattern_symbolizer>
{
static char const* name() { return "PolygonPatternSymbolizer";}
};
template<>
struct symbolizer_traits<markers_symbolizer>
{
static char const* name() { return "MarkersSymbolizer";}
};
template<>
struct symbolizer_traits<shield_symbolizer>
{
static char const* name() { return "ShieldSymbolizer";}
};
template<>
struct symbolizer_traits<raster_symbolizer>
{
static char const* name() { return "RasterSymbolizer";}
};
template<>
struct symbolizer_traits<building_symbolizer>
{
static char const* name() { return "BuildingSymbolizer";}
};
template<>
struct symbolizer_traits<debug_symbolizer>
{
static char const* name() { return "DebugSymbolizer";}
};
// symbolizer name impl
namespace detail {
struct symbolizer_name_impl : public boost::static_visitor<std::string>
{
public:
template <typename Symbolizer>
std::string operator () (Symbolizer const& sym) const
{
boost::ignore_unused_variable_warning(sym);
return symbolizer_traits<Symbolizer>::name();
}
};
}
std::string symbolizer_name(symbolizer const& sym)
{
std::string type = boost::apply_visitor( detail::symbolizer_name_impl(), sym);
return type;
}
template <typename Meta>
class symbolizer_property_value_string : public boost::static_visitor<std::string>
{
public:
symbolizer_property_value_string (Meta const& meta)
: meta_(meta) {}
std::string operator() ( mapnik::enumeration_wrapper const& e) const
{
std::stringstream ss;
auto const& convert_fun_ptr(std::get<2>(meta_));
if ( convert_fun_ptr )
{
ss << convert_fun_ptr(e);
}
return ss.str();
}
std::string operator () ( path_expression_ptr const& expr) const
{
std::ostringstream ss;
if (expr)
{
ss << '\"' << path_processor::to_string(*expr) << '\"';
}
return ss.str();
}
std::string operator () (text_placements_ptr const& expr) const
{
return std::string("\"<fixme-text-placement-ptr>\"");
}
std::string operator () (raster_colorizer_ptr const& expr) const
{
return std::string("\"<fixme-raster-colorizer-ptr>\"");
}
std::string operator () (transform_type const& expr) const
{
std::ostringstream ss;
if (expr)
{
ss << '\"' << transform_processor_type::to_string(*expr) << '\"';
}
return ss.str();
}
std::string operator () (expression_ptr const& expr) const
{
std::ostringstream ss;
if (expr)
{
ss << '\"' << "FIXME" /*mapnik::to_expression_string(*expr)*/ << '\"';
}
return ss.str();
}
std::string operator () (color const& c) const
{
std::ostringstream ss;
ss << '\"' << c << '\"';
return ss.str();
}
std::string operator () (dash_array const& dash) const
{
std::ostringstream ss;
for (std::size_t i = 0; i < dash.size(); ++i)
{
ss << dash[i].first << ", " << dash[i].second;
if ( i + 1 < dash.size() ) ss << ',';
}
return ss.str();
}
template <typename T>
std::string operator () ( T const& val ) const
{
std::ostringstream ss;
ss << val;
return ss.str();
}
private:
Meta const& meta_;
};
struct symbolizer_to_json : public boost::static_visitor<std::string>
{
typedef std::string result_type;
template <typename T>
auto operator() (T const& sym) const -> result_type
{
std::stringstream ss;
ss << "{\"type\":\"" << mapnik::symbolizer_traits<T>::name() << "\",";
ss << "\"properties\":{";
bool first = true;
for (auto const& prop : sym.properties)
{
auto const& meta = mapnik::get_meta(prop.first);
if (first) first = false;
else ss << ",";
ss << "\"" << std::get<0>(meta) << "\":";
ss << boost::apply_visitor(symbolizer_property_value_string<property_meta_type>(meta),prop.second);
}
ss << "}}";
return ss.str();
}
};
namespace {
template <typename Symbolizer, typename T>
struct set_property_impl
{
static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
{
std::cerr << "do nothing" << std::endl;
}
};
template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_color> >
{
static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
{
put(sym, key, mapnik::parse_color(val));
}
};
template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_double> >
{
static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
{
std::cerr << " expects double" << std::endl;
}
};
template <typename Symbolizer>
struct set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_bool> >
{
static void apply(Symbolizer & sym, mapnik::keys key, std::string const& val)
{
std::cerr << " expects bool" << std::endl;
}
};
}
template <typename Symbolizer, typename T>
inline void set_property(Symbolizer & sym, mapnik::keys key, T const& val)
{
switch (std::get<3>(get_meta(key)))
{
case property_types::target_bool:
set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_bool> >::apply(sym,key,val);
break;
case property_types::target_integer:
set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_integer> >::apply(sym,key,val);
break;
case property_types::target_double:
set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_double> >::apply(sym,key,val);
break;
case property_types::target_color:
set_property_impl<Symbolizer, std::integral_constant<property_types, property_types::target_color> >::apply(sym,key,val);
break;
default:
break;
}
}
}
#endif // MAPNIK_SYMBOLIZER_UTILS_HPP

View file

@ -0,0 +1,59 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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 FORMATTING_OFFSET_HPP
#define FORMATTING_OFFSET_HPP
#include <mapnik/text/formatting/base.hpp>
#include <mapnik/text/text_properties.hpp>
#include <boost/optional.hpp>
namespace mapnik {
namespace formatting {
class MAPNIK_DECL layout_node: public node {
public:
void to_xml(boost::property_tree::ptree &xml) const;
static node_ptr from_xml(xml_node const& xml);
virtual void apply(char_properties_ptr p, feature_impl const& feature, text_layout &output) const;
virtual void add_expressions(expression_set &output) const;
void set_child(node_ptr child);
node_ptr get_child() const;
boost::optional<double> dx;
boost::optional<double> dy;
boost::optional<horizontal_alignment_e> halign;
boost::optional<vertical_alignment_e> valign;
boost::optional<justify_alignment_e> jalign;
boost::optional<double> text_ratio;
boost::optional<double> wrap_width;
boost::optional<bool> wrap_before;
boost::optional<bool> rotate_displacement;
boost::optional<expression_ptr> orientation;
private:
node_ptr child_;
};
} //ns formatting
} //ns mapnik
#endif // FORMATTING_OFFSET_HPP

View file

@ -30,6 +30,7 @@
#include <mapnik/text/harfbuzz_shaper.hpp>
#include <mapnik/text/icu_shaper.hpp>
#include <mapnik/text/dummy_shaper.hpp>
#include <mapnik/text/rotation.hpp>
//stl
#include <vector>
@ -38,13 +39,17 @@
namespace mapnik
{
typedef std::shared_ptr<text_layout> text_layout_ptr;
typedef std::vector<text_layout_ptr> text_layout_vector;
class text_layout
{
public:
typedef std::vector<text_line> line_vector;
typedef line_vector::const_iterator const_iterator;
typedef text_layout_vector::const_iterator child_iterator;
typedef harfbuzz_shaper shaper_type;
text_layout(face_manager_freetype & font_manager, double scale_factor);
text_layout(face_manager_freetype & font_manager, double scale_factor, text_layout_properties_ptr properties);
/** Adds a new text part. Call this function repeatedly to build the complete text. */
void add_text(mapnik::value_unicode_string const& str, char_properties_ptr format);
@ -53,7 +58,7 @@ public:
mapnik::value_unicode_string const& text() const;
/** Processes the text into a list of glyphs, performing RTL/LTR handling, shaping and line breaking. */
void layout(double wrap_width, unsigned text_ratio, bool wrap_before);
void layout();
/** Clear all data stored in this object. The object's state is the same as directly after construction. */
void clear();
@ -81,11 +86,29 @@ public:
// Returns the number of glyphs so memory can be preallocated.
inline unsigned glyphs_count() const { return glyphs_count_;}
void add_child(text_layout_ptr child_layout);
inline const text_layout_vector &get_child_layouts() const { return child_layout_list_; }
inline face_manager<freetype_engine> &get_font_manager() const { return font_manager_; }
inline double get_scale_factor() const { return scale_factor_; }
inline text_layout_properties_ptr get_layout_properties() const { return properties_; }
inline rotation const& orientation() const { return orientation_; }
inline pixel_position const& displacement() const { return displacement_; }
inline box2d<double> const& bounds() const { return bounds_; }
pixel_position alignment_offset() const;
double jalign_offset(double line_width) const;
void init_orientation(feature_impl const& feature);
private:
void break_line(text_line & line, double wrap_width, unsigned text_ratio, bool wrap_before);
void shape_text(text_line & line);
void add_line(text_line & line);
void clear_cluster_widths(unsigned first, unsigned last);
void init_alignment();
//input
face_manager_freetype &font_manager_;
@ -103,7 +126,60 @@ private:
//output
line_vector lines_;
//text layout properties
text_layout_properties_ptr properties_;
//alignments
vertical_alignment_e valign_;
horizontal_alignment_e halign_;
justify_alignment_e jalign_;
// Precalculated values for maximum performance
rotation orientation_;
pixel_position displacement_;
box2d<double> bounds_;
//children
text_layout_vector child_layout_list_;
};
class layout_container
{
public:
layout_container() : glyphs_count_(0), line_count_(0) {}
void add(text_layout_ptr layout);
void clear();
void layout();
inline size_t size() const { return layouts_.size(); }
inline text_layout_vector::const_iterator begin() const { return layouts_.begin(); }
inline text_layout_vector::const_iterator end() const { return layouts_.end(); }
inline mapnik::value_unicode_string const& text() const { return text_; }
inline unsigned glyphs_count() const { return glyphs_count_; }
inline unsigned line_count() const { return line_count_; }
inline box2d<double> const& bounds() const { return bounds_; }
inline double width() const { return bounds_.width(); }
inline double height() const { return bounds_.height(); }
private:
text_layout_vector layouts_;
mapnik::value_unicode_string text_;
unsigned glyphs_count_;
unsigned line_count_;
box2d<double> bounds_;
};
}
#endif // TEXT_LAYOUT_HPP

View file

@ -29,6 +29,7 @@
#include <mapnik/text/placements/base.hpp>
#include <mapnik/text/placements_list.hpp>
#include <mapnik/text/rotation.hpp>
#include <mapnik/text/vertex_cache.hpp>
#include <mapnik/noncopyable.hpp>
namespace mapnik
@ -62,10 +63,6 @@ public:
void set_marker(marker_info_ptr m, box2d<double> box, bool marker_unlocked, pixel_position const& marker_displacement);
private:
void init_alignment();
pixel_position alignment_offset() const;
double jalign_offset(double line_width) const;
bool single_line_placement(vertex_cache &pp, text_upright_e orientation);
/** Moves dx pixels but makes sure not to fall of the end. */
void path_move_dx(vertex_cache &pp);
@ -80,23 +77,16 @@ private:
/** Maps upright==auto, left_only and right_only to left,right to simplify processing.
angle = angle of at start of line (to estimate best option for upright==auto) */
text_upright_e simplify_upright(text_upright_e upright, double angle) const;
box2d<double> get_bbox(glyph_info const& glyph, pixel_position const& pos, rotation const& rot);
box2d<double> get_bbox(text_layout const& layout, glyph_info const& glyph, pixel_position const& pos, rotation const& rot);
feature_impl const& feature_;
DetectorType &detector_;
box2d<double> const& extent_;
// Precalculated values for maximum performance
rotation orientation_;
text_layout layout_;
text_placement_info_ptr info_;
layout_container layouts_;
bool valid_;
vertical_alignment_e valign_;
/** Horizontal alignment for point placements. */
horizontal_alignment_e halign_point_;
/** Horizontal alignment for line placements. */
horizontal_alignment_e halign_line_;
justify_alignment_e jalign_;
double scale_factor_;
face_manager_freetype &font_manager_;
placements_list placements_;

View file

@ -26,11 +26,10 @@
// mapnik
#include <mapnik/text/placement_finder.hpp>
#include <mapnik/image_compositing.hpp>
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/noncopyable.hpp>
//TODO: Find a better place for halo_rasterizer_e!
//TODO: Halo rasterizer selection should go to text_properties because it might make sense to use a different rasterizer for different fonts
// agg
#include <agg_trans_affine.h>
// freetype2
extern "C"
@ -72,6 +71,8 @@ public:
composite_mode_e comp_op = src_over,
double scale_factor=1.0,
stroker_ptr stroker=stroker_ptr());
void set_transform(agg::trans_affine const& transform);
void set_halo_transform(agg::trans_affine const& halo_transform);
protected:
typedef std::vector<glyph_t> glyph_vector;
void prepare_glyphs(glyph_positions const& positions);
@ -80,6 +81,8 @@ protected:
double scale_factor_;
glyph_vector glyphs_;
stroker_ptr stroker_;
agg::trans_affine transform_;
agg::trans_affine halo_transform_;
};
template <typename T>

View file

@ -15,8 +15,8 @@ struct rotation
void init(double angle) { sin = std::sin(angle); cos = std::cos(angle); }
double sin;
double cos;
rotation operator~() { return rotation(sin, -cos); }
rotation operator!() { return rotation(-sin, cos); }
rotation operator~() const { return rotation(sin, -cos); }
rotation operator!() const { return rotation(-sin, cos); }
};
}

View file

@ -23,8 +23,7 @@
#define SYMBOLIZER_HELPERS_HPP
//mapnik
#include <mapnik/text_symbolizer.hpp>
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/feature.hpp>
#include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp>
@ -34,10 +33,52 @@
namespace mapnik {
class base_symbolizer_helper
{
public:
base_symbolizer_helper(symbolizer_base const& sym,
feature_impl const& feature,
proj_transform const& prj_trans,
unsigned width,
unsigned height,
double scale_factor,
CoordTransform const& t,
box2d<double> const& query_extent);
protected:
void initialize_geometries();
void initialize_points();
//Input
symbolizer_base const& sym_;
feature_impl const& feature_;
proj_transform const& prj_trans_;
CoordTransform const& t_;
box2d<double> dims_;
box2d<double> const& query_extent_;
float scale_factor_;
bool clipped_;
//Processing
/* Using list instead of vector, because we delete random elements and need iterators to stay valid. */
/** Remaining geometries to be processed. */
std::list<geometry_type*> geometries_to_process_;
/** Remaining points to be processed. */
std::list<pixel_position> points_;
/** Geometry currently being processed. */
std::list<geometry_type*>::iterator geo_itr_;
/** Point currently being processed. */
std::list<pixel_position>::iterator point_itr_;
/** Use point placement. Otherwise line placement is used. */
bool point_placement_;
text_placement_info_ptr placement_;
};
/** Helper object that does all the TextSymbolizer placement finding
* work except actually rendering the object. */
class text_symbolizer_helper
class text_symbolizer_helper : public base_symbolizer_helper
{
public:
template <typename FaceManagerT, typename DetectorT>
@ -68,35 +109,13 @@ public:
placements_list const& get();
protected:
bool next_point_placement();
bool next_line_placement();
void initialize_geometries();
void initialize_points();
bool next_line_placement(bool clipped);
placement_finder finder_;
//Input
text_symbolizer const& sym_;
feature_impl const& feature_;
proj_transform const& prj_trans_;
CoordTransform const& t_;
box2d<double> dims_;
box2d<double> const& query_extent_;
//Processing
/* Using list instead of vector, because we delete random elements and need iterators to stay valid. */
/** Remaining geometries to be processed. */
std::list<geometry_type*> geometries_to_process_;
/** Geometry currently being processed. */
std::list<geometry_type*>::iterator geo_itr_;
/** Remaining points to be processed. */
std::list<pixel_position> points_;
/** Point currently being processed. */
std::list<pixel_position>::iterator point_itr_;
/** Use point placement. Otherwise line placement is used. */
bool point_placement_;
/** Place text at points on a line instead of following the line (used for ShieldSymbolizer) .*/
bool points_on_line_;
text_placement_info_ptr placement_;
placement_finder finder_;
//ShieldSymbolizer only
void init_marker();
};

View file

@ -132,13 +132,41 @@ enum text_upright
DEFINE_ENUM(text_upright_e, text_upright);
/** Properties for building the layout of a single text placement */
struct MAPNIK_DECL text_layout_properties
{
text_layout_properties();
/** Load all values from XML ptree. */
void from_xml(xml_node const &sym);
/** Save all values to XML ptree (but does not create a new parent node!). */
void to_xml(boost::property_tree::ptree &node, bool explicit_defaults, text_layout_properties const &dfl=text_layout_properties()) const;
/** Get a list of all expressions used in any placement.
* This function is used to collect attributes. */
void add_expressions(expression_set &output) const;
//Per layout options
expression_ptr orientation;
pixel_position displacement;
horizontal_alignment_e halign;
justify_alignment_e jalign;
vertical_alignment_e valign;
double text_ratio;
double wrap_width;
bool wrap_before;
bool rotate_displacement;
};
typedef std::shared_ptr<text_layout_properties> text_layout_properties_ptr;
class text_layout;
/** Contains all text symbolizer properties which are not directly related to text formatting. */
/** Contains all text symbolizer properties which are not directly related to text formatting and layout. */
struct MAPNIK_DECL text_symbolizer_properties
{
text_symbolizer_properties();
/** Load only placement related values from XML ptree. */
void placement_properties_from_xml(xml_node const &sym);
/** Load all values from XML ptree. */
void from_xml(xml_node const &sym, fontset_map const & fontsets);
/** Save all values to XML ptree (but does not create a new parent node!). */
@ -159,12 +187,7 @@ struct MAPNIK_DECL text_symbolizer_properties
void add_expressions(expression_set &output) const;
//Per symbolizer options
expression_ptr orientation;
pixel_position displacement;
label_placement_e label_placement;
horizontal_alignment_e halign;
justify_alignment_e jalign;
vertical_alignment_e valign;
/** distance between repeated labels on a single geometry */
double label_spacing;
/** distance the label can be moved on the line to fit, if 0 the default is used */
@ -179,11 +202,11 @@ struct MAPNIK_DECL text_symbolizer_properties
bool allow_overlap;
/** Only consider geometry with largest bbox (polygons) */
bool largest_bbox_only;
double text_ratio;
double wrap_width;
bool wrap_before;
bool rotate_displacement;
text_upright_e upright;
/** Default values for text layouts */
text_layout_properties_ptr layout_defaults;
/** Default values for char_properties. */
char_properties_ptr format;
private:

View file

@ -0,0 +1,100 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 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_TOLERANCE_ITERATOR_HPP
#define MAPNIK_TOLERANCE_ITERATOR_HPP
//mapnik
#include <mapnik/debug.hpp>
namespace mapnik
{
class tolerance_iterator
{
public:
tolerance_iterator(double label_position_tolerance, double spacing)
: tolerance_(label_position_tolerance > 0 ?
label_position_tolerance : spacing/2.0),
tolerance_delta_(std::max(1.0, tolerance_/100.0)),
value_(0),
initialized_(false),
values_tried_(0)
{
}
~tolerance_iterator()
{
//std::cout << "values tried:" << values_tried_ << "\n";
}
double get() const
{
return -value_;
}
bool next()
{
++values_tried_;
if (values_tried_ > 255)
{
/* This point should not be reached during normal operation. But I can think of
* cases where very bad spacing and or tolerance values are choosen and the
* placement finder tries an excessive number of placements.
* 255 is an arbitrarily chosen limit.
*/
MAPNIK_LOG_WARN(placement_finder) << "Tried a huge number of placements. Please check "
"'label-position-tolerance' and 'spacing' parameters "
"of your TextSymbolizers.\n";
return false;
}
if (!initialized_)
{
initialized_ = true;
return true; //Always return value 0 as the first value.
}
if (value_ == 0)
{
value_ = tolerance_delta_;
return true;
}
value_ = -value_;
if (value_ > 0)
{
value_ += tolerance_delta_;
}
if (value_ > tolerance_)
{
return false;
}
return true;
}
private:
double tolerance_;
double tolerance_delta_;
double value_;
bool initialized_;
unsigned values_tried_;
};
}//ns mapnik
#endif // MAPNIK_TOLERANCE_ITERATOR_HPP

View file

@ -131,6 +131,8 @@ public:
/** Go back to initial state. */
void reset();
/** position on this line closest to the target position */
double position_closest_to(pixel_position const &target_pos);
private:
void rewind_subpath();

View file

@ -1,149 +0,0 @@
/*****************************************************************************
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2011 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_TEXT_SYMBOLIZER_HPP
#define MAPNIK_TEXT_SYMBOLIZER_HPP
// mapnik
#include <mapnik/color.hpp>
#include <mapnik/font_set.hpp>
#include <mapnik/symbolizer.hpp>
#include <mapnik/text/placements/base.hpp>
#include <mapnik/text/placements/dummy.hpp>
// boost
#include <memory>
// stl
#include <string>
#if (!defined(NO_DEPRECATION_WARNINGS) && __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
#define func_deprecated __attribute__ ((deprecated))
#else
#define func_deprecated
#endif
namespace mapnik
{
enum halo_rasterizer_enum
{
HALO_RASTERIZER_FULL,
HALO_RASTERIZER_FAST,
halo_rasterizer_enum_MAX
};
DEFINE_ENUM(halo_rasterizer_e, halo_rasterizer_enum);
struct MAPNIK_DECL text_symbolizer : public symbolizer_base
{
// Note - we do not use std::make_shared below as VC2008 and VC2010 are
// not able to compile make_shared used within a constructor
text_symbolizer(text_placements_ptr placements = text_placements_ptr(new text_placements_dummy));
text_symbolizer(expression_ptr name, std::string const& face_name,
double size, color const& fill,
text_placements_ptr placements = text_placements_ptr(new text_placements_dummy)
);
text_symbolizer(expression_ptr name, double size, color const& fill,
text_placements_ptr placements = text_placements_ptr(new text_placements_dummy)
);
text_symbolizer(text_symbolizer const& rhs);
text_symbolizer& operator=(text_symbolizer const& rhs);
expression_ptr get_name() const func_deprecated;
void set_name(expression_ptr expr);
expression_ptr get_orientation() const func_deprecated; // orienation (rotation angle atm)
void set_orientation(expression_ptr expr);
double get_text_ratio() const func_deprecated; // target ratio for text bounding box in pixels
void set_text_ratio(double ratio);
double get_wrap_width() const func_deprecated; // width to wrap text at, or trigger ratio
void set_wrap_width(double width);
unsigned char get_wrap_char() const func_deprecated; // character used to wrap lines
std::string get_wrap_char_string() const func_deprecated; // character used to wrap lines as std::string
void set_wrap_char(unsigned char character);
void set_wrap_char_from_string(std::string const& character);
text_transform_e get_text_transform() const func_deprecated; // text conversion on strings before display
void set_text_transform(text_transform_e convert);
double get_line_spacing() const func_deprecated; // spacing between lines of text
void set_line_spacing(double spacing);
double get_character_spacing() const func_deprecated; // spacing between characters in text
void set_character_spacing(double spacing);
double get_label_spacing() const func_deprecated; // spacing between repeated labels on lines
void set_label_spacing(double spacing);
unsigned get_label_position_tolerance() const func_deprecated; //distance the label can be moved on the line to fit, if 0 the default is used
void set_label_position_tolerance(unsigned tolerance);
bool get_force_odd_labels() const func_deprecated; // try render an odd amount of labels
void set_force_odd_labels(bool force);
double get_max_char_angle_delta() const func_deprecated; // maximum change in angle between adjacent characters
void set_max_char_angle_delta(double angle);
double get_text_size() const func_deprecated;
void set_text_size(double size);
std::string const& get_face_name() const func_deprecated;
void set_face_name(std::string face_name);
boost::optional<font_set> const& get_fontset() const func_deprecated;
void set_fontset(font_set const& fset);
color const& get_fill() const func_deprecated;
void set_fill(color const& fill);
void set_halo_fill(color const& fill);
color const& get_halo_fill() const func_deprecated;
void set_halo_radius(double radius);
double get_halo_radius() const func_deprecated;
void set_halo_rasterizer(halo_rasterizer_e rasterizer_p);
halo_rasterizer_e get_halo_rasterizer() const;
void set_label_placement(label_placement_e label_p);
label_placement_e get_label_placement() const func_deprecated;
void set_vertical_alignment(vertical_alignment_e valign);
vertical_alignment_e get_vertical_alignment() const func_deprecated;
void set_displacement(double x, double y);
void set_displacement(pixel_position const& p);
pixel_position const& get_displacement() const func_deprecated;
void set_avoid_edges(bool avoid);
bool get_avoid_edges() const func_deprecated;
void set_minimum_distance(double distance);
double get_minimum_distance() const func_deprecated;
void set_minimum_padding(double distance);
double get_minimum_padding() const func_deprecated;
void set_minimum_path_length(double size);
double get_minimum_path_length() const;
void set_allow_overlap(bool overlap);
bool get_allow_overlap() const func_deprecated;
void set_text_opacity(double opacity);
double get_text_opacity() const func_deprecated;
void set_wrap_before(bool wrap_before);
bool get_wrap_before() const func_deprecated; // wrap text at wrap_char immediately before current work
void set_horizontal_alignment(horizontal_alignment_e valign);
horizontal_alignment_e get_horizontal_alignment() const func_deprecated;
void set_justify_alignment(justify_alignment_e valign);
justify_alignment_e get_justify_alignment() const func_deprecated;
text_placements_ptr get_placement_options() const;
void set_placement_options(text_placements_ptr placement_options);
void set_largest_bbox_only(bool val);
bool largest_bbox_only() const;
private:
text_placements_ptr placement_options_;
halo_rasterizer_e halo_rasterizer_;
};
}
#endif // MAPNIK_TEXT_SYMBOLIZER_HPP

Some files were not shown because too many files have changed in this diff Show more