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('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('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('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('COLOR_PRINT', 'Print build status information in color', 'True'),
BoolVariable('SAMPLE_INPUT_PLUGINS', 'Compile and install sample plugins', 'False'), BoolVariable('SAMPLE_INPUT_PLUGINS', 'Compile and install sample plugins', 'False'),
BoolVariable('BIGINT', 'Compile support for 64-bit integers in mapnik::value', 'True'), 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 = env.Clone()
temp_env['LIBS'] = [] temp_env['LIBS'] = []
try: try:
# TODO - freetype-config accepts --static as of v2.5.3
temp_env.ParseConfig('%s --libs' % env['FREETYPE_CONFIG']) temp_env.ParseConfig('%s --libs' % env['FREETYPE_CONFIG'])
if 'bz2' in temp_env['LIBS']: if 'bz2' in temp_env['LIBS']:
env['EXTRA_FREETYPE_LIBS'].append('bz2') env['EXTRA_FREETYPE_LIBS'].append('bz2')
@ -1981,6 +1983,8 @@ if not HELP_REQUESTED:
SConscript('utils/pgsql2sqlite/build.py') SConscript('utils/pgsql2sqlite/build.py')
if env['SVG2PNG']: if env['SVG2PNG']:
SConscript('utils/svg2png/build.py') SConscript('utils/svg2png/build.py')
if env['NIK2IMG']:
SConscript('utils/nik2img/build.py')
# devtools not ready for public # devtools not ready for public
#SConscript('utils/ogrindex/build.py') #SConscript('utils/ogrindex/build.py')
env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND']) env['LIBS'].remove('boost_program_options%s' % env['BOOST_APPEND'])

View file

@ -285,11 +285,15 @@ class _Color(Color,_injector):
def __repr__(self): def __repr__(self):
return "Color(R=%d,G=%d,B=%d,A=%d)" % (self.r,self.g,self.b,self.a) 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): @filename.setter
sym = Symbolizers._c___getitem__(self, idx) def filename(self, val):
return sym.symbol() self['file'] = val
def _add_symbol_method_to_symbolizers(vars=globals()): def _add_symbol_method_to_symbolizers(vars=globals()):

View file

@ -2,7 +2,7 @@
* *
* This file is part of Mapnik (c++ mapping toolkit) * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * 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 // mapnik
#include <mapnik/line_symbolizer.hpp> #include <mapnik/symbolizer.hpp>
#include <mapnik/enumeration.hpp>
namespace mapnik // boost
{ #include <boost/python.hpp>
static const char * line_rasterizer_strings[] = {
"full",
"fast",
""
};
IMPLEMENT_ENUM( line_rasterizer_e, line_rasterizer_strings )
} namespace boost { namespace python {
struct mapnik_enumeration_wrapper_to_python
{
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" #include "boost_std_shared_shim.hpp"
// boost // 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/iterator.hpp>
#include <boost/python/call_method.hpp> #include <boost/python/call_method.hpp>
#include <boost/python/tuple.hpp> #include <boost/python/tuple.hpp>

View file

@ -58,7 +58,6 @@ void export_python();
void export_expression(); void export_expression();
void export_rule(); void export_rule();
void export_style(); void export_style();
void export_stroke();
void export_feature(); void export_feature();
void export_featureset(); void export_featureset();
void export_fontset(); void export_fontset();
@ -76,6 +75,7 @@ void export_raster_symbolizer();
void export_text_placement(); void export_text_placement();
void export_shield_symbolizer(); void export_shield_symbolizer();
void export_debug_symbolizer(); void export_debug_symbolizer();
void export_group_symbolizer();
void export_font_engine(); void export_font_engine();
void export_projection(); void export_projection();
void export_proj_transform(); void export_proj_transform();
@ -99,6 +99,7 @@ void export_wkt_reader();
#include "python_grid_utils.hpp" #include "python_grid_utils.hpp"
#endif #endif
#include "mapnik_value_converter.hpp" #include "mapnik_value_converter.hpp"
#include "mapnik_enumeration_wrapper_converter.hpp"
#include "mapnik_threads.hpp" #include "mapnik_threads.hpp"
#include "python_optional.hpp" #include "python_optional.hpp"
#include <mapnik/marker_cache.hpp> #include <mapnik/marker_cache.hpp>
@ -108,7 +109,6 @@ void export_wkt_reader();
namespace mapnik { namespace mapnik {
class font_set; class font_set;
class stroke;
class layer; class layer;
class color; class color;
class label_collision_detector4; class label_collision_detector4;
@ -565,7 +565,6 @@ BOOST_PYTHON_MODULE(_mapnik)
export_rule(); export_rule();
export_style(); export_style();
export_layer(); export_layer();
export_stroke();
export_datasource_cache(); export_datasource_cache();
export_symbolizer(); export_symbolizer();
export_markers_symbolizer(); export_markers_symbolizer();
@ -579,6 +578,7 @@ BOOST_PYTHON_MODULE(_mapnik)
export_text_placement(); export_text_placement();
export_shield_symbolizer(); export_shield_symbolizer();
export_debug_symbolizer(); export_debug_symbolizer();
export_group_symbolizer();
export_font_engine(); export_font_engine();
export_projection(); export_projection();
export_proj_transform(); export_proj_transform();
@ -599,17 +599,6 @@ BOOST_PYTHON_MODULE(_mapnik)
">>> clear_cache()\n" ">>> 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, def("render_to_file",&render_to_file1,
"\n" "\n"
"Render Map to file using explicit image type.\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_png", &has_png, "Get png read/write support status");
def("has_tiff", &has_tiff, "Get tiff 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_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_grid_renderer", &has_grid_renderer, "Get grid_renderer status");
def("has_cairo", &has_cairo, "Get cairo library status"); def("has_cairo", &has_cairo, "Get cairo library status");
def("has_pycairo", &has_pycairo, "Get pycairo module status"); def("has_pycairo", &has_pycairo, "Get pycairo module status");
python_optional<mapnik::stroke>();
python_optional<mapnik::font_set>(); python_optional<mapnik::font_set>();
python_optional<mapnik::color>(); python_optional<mapnik::color>();
python_optional<mapnik::box2d<double> >(); python_optional<mapnik::box2d<double> >();
@ -882,4 +869,5 @@ BOOST_PYTHON_MODULE(_mapnik)
register_ptr_to_python<mapnik::path_expression_ptr>(); register_ptr_to_python<mapnik::path_expression_ptr>();
to_python_converter<mapnik::value_holder,mapnik_param_to_python>(); to_python_converter<mapnik::value_holder,mapnik_param_to_python>();
to_python_converter<mapnik::value,mapnik_value_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 // mapnik
#include <mapnik/raster_colorizer.hpp> #include <mapnik/raster_colorizer.hpp>
#include <mapnik/symbolizer.hpp>
using mapnik::raster_colorizer; using mapnik::raster_colorizer;
using mapnik::raster_colorizer_ptr; using mapnik::raster_colorizer_ptr;
using mapnik::symbolizer_base;
using mapnik::colorizer_stop; using mapnik::colorizer_stop;
using mapnik::colorizer_stops; using mapnik::colorizer_stops;
using mapnik::colorizer_mode_enum; using mapnik::colorizer_mode_enum;
@ -81,6 +83,8 @@ void export_raster_colorizer()
{ {
using namespace boost::python; using namespace boost::python;
implicitly_convertible<raster_colorizer_ptr, mapnik::symbolizer_base::value_type>();
class_<raster_colorizer,raster_colorizer_ptr>("RasterColorizer", class_<raster_colorizer,raster_colorizer_ptr>("RasterColorizer",
"A Raster Colorizer object.", "A Raster Colorizer object.",
init<colorizer_mode_enum, color>(args("default_mode","default_color")) 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::text_symbolizer;
using mapnik::building_symbolizer; using mapnik::building_symbolizer;
using mapnik::markers_symbolizer; using mapnik::markers_symbolizer;
using mapnik::group_symbolizer;
using mapnik::symbolizer; using mapnik::symbolizer;
using mapnik::to_expression_string; using mapnik::to_expression_string;
@ -61,6 +62,7 @@ void export_rule()
implicitly_convertible<shield_symbolizer,symbolizer>(); implicitly_convertible<shield_symbolizer,symbolizer>();
implicitly_convertible<text_symbolizer,symbolizer>(); implicitly_convertible<text_symbolizer,symbolizer>();
implicitly_convertible<markers_symbolizer,symbolizer>(); implicitly_convertible<markers_symbolizer,symbolizer>();
implicitly_convertible<group_symbolizer,symbolizer>();
class_<rule::symbolizers>("Symbolizers",init<>("TODO")) class_<rule::symbolizers>("Symbolizers",init<>("TODO"))
.def(vector_indexing_suite<rule::symbolizers>()) .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" #include "boost_std_shared_shim.hpp" // FIXME - do we need it?
/* The functions in this file produce deprecation warnings. // The functions in this file produce deprecation warnings.
* But as shield symbolizer doesn't fully support more than one // But as shield symbolizer doesn't fully support more than one
* placement from python yet these functions are actually the // placement from python yet these functions are actually the
* correct ones. // correct ones.
*/
#define NO_DEPRECATION_WARNINGS #define NO_DEPRECATION_WARNINGS
// boost // boost
#include <boost/python.hpp> #include <boost/python.hpp>
#include <boost/variant.hpp> #include <boost/variant.hpp>
#include <boost/python/suite/indexing/map_indexing_suite.hpp>
// mapnik // mapnik
//symbolizer typdef here rather than mapnik/symbolizer.hpp #include <mapnik/symbolizer.hpp>
#include <mapnik/rule.hpp>
#include <mapnik/symbolizer_hash.hpp> #include <mapnik/symbolizer_hash.hpp>
#include <mapnik/symbolizer_utils.hpp>
#include <mapnik/symbolizer_keys.hpp>
#include <mapnik/image_util.hpp> #include <mapnik/image_util.hpp>
#include <mapnik/parse_path.hpp> #include <mapnik/parse_path.hpp>
#include <mapnik/path_expression.hpp> #include <mapnik/path_expression.hpp>
@ -46,10 +46,14 @@
#include <mapnik/expression_node.hpp> #include <mapnik/expression_node.hpp>
#include <mapnik/value_error.hpp> #include <mapnik/value_error.hpp>
#include <mapnik/marker_cache.hpp> // for known_svg_prefix_ #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::symbolizer;
using mapnik::rule;
using mapnik::point_symbolizer; using mapnik::point_symbolizer;
using mapnik::line_symbolizer; using mapnik::line_symbolizer;
using mapnik::line_pattern_symbolizer; using mapnik::line_pattern_symbolizer;
@ -60,6 +64,9 @@ using mapnik::shield_symbolizer;
using mapnik::text_symbolizer; using mapnik::text_symbolizer;
using mapnik::building_symbolizer; using mapnik::building_symbolizer;
using mapnik::markers_symbolizer; using mapnik::markers_symbolizer;
using mapnik::debug_symbolizer;
using mapnik::group_symbolizer;
using mapnik::symbolizer_base;
using mapnik::color; using mapnik::color;
using mapnik::path_processor_type; using mapnik::path_processor_type;
using mapnik::path_expression_ptr; using mapnik::path_expression_ptr;
@ -67,176 +74,68 @@ using mapnik::guess_type;
using mapnik::expression_ptr; using mapnik::expression_ptr;
using mapnik::parse_path; using mapnik::parse_path;
namespace { namespace {
using namespace boost::python; using namespace boost::python;
void __setitem__(mapnik::symbolizer_base & sym, std::string const& name, mapnik::symbolizer_base::value_type const& val)
tuple get_shield_displacement(const shield_symbolizer& s)
{ {
mapnik::pixel_position const& pos = s.get_shield_displacement(); put(sym, mapnik::get_key(name), val);
return boost::python::make_tuple(pos.x, pos.y);
} }
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]); std::shared_ptr<mapnik::symbolizer_base::value_type> result;
s.get_placement_options()->defaults.displacement.y = extract<double>(arg[1]); if (PyBool_Check(arg.ptr()))
}
tuple get_text_displacement(const shield_symbolizer& t)
{
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"; mapnik::value_bool val = extract<mapnik::value_bool>(arg);
result.reset(new mapnik::symbolizer_base::value_type(val));
} }
else if (marker_type == "arrow") else if (PyFloat_Check(arg.ptr()))
{ {
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 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>
struct get_symbolizer_type : public boost::static_visitor<std::string>
{ {
public: typedef boost::python::object result_type;
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 template <typename T>
auto operator() (T const& val) const -> result_type
{ {
boost::ignore_unused_variable_warning(sym); return result_type(val); // wrap into python object
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");
} }
}; };
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); typedef symbolizer_base::cont_type::const_iterator const_iterator;
return type; 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); return mapnik::symbolizer_name(sym); // FIXME - do we need this ?
}
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);
} }
struct symbolizer_hash_visitor : public boost::static_visitor<std::size_t> 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> 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> struct extract_underlying_type_visitor : boost::static_visitor<boost::python::object>
void set_file_impl(T & sym, std::string const& file_expr)
{ {
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; 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) class_<symbolizer>("Symbolizer",no_init)
.def("type",get_symbolizer_type)
.def("type",get_symbol_type)
.def("__hash__",hash_impl) .def("__hash__",hash_impl)
.def("extract", extract_underlying_type)
;
.def("point",point_, class_<symbolizer_base::value_type>("NumericWrapper")
return_value_policy<copy_const_reference>()) .def("__init__", make_constructor(numeric_wrapper))
;
.def("line",line_, class_<symbolizer_base>("SymbolizerBase",no_init)
return_value_policy<copy_const_reference>()) .def("__setitem__",&__setitem__)
.def("__setattr__",&__setitem__)
.def("line_pattern",line_pattern_, .def("__getitem__",&__getitem__)
return_value_policy<copy_const_reference>()) .def("__getattr__",&__getitem__)
.def("__str__", &__str__)
.def("polygon",polygon_, .def(self == self) // __eq__
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>())
; ;
} }
@ -314,169 +217,19 @@ void export_shield_symbolizer()
{ {
using namespace boost::python; using namespace boost::python;
class_< shield_symbolizer, bases<text_symbolizer> >("ShieldSymbolizer", class_< shield_symbolizer, bases<text_symbolizer> >("ShieldSymbolizer",
init<expression_ptr, init<>("Default ctor"))
std::string const&, .def("__hash__",hash_impl_2<shield_symbolizer>)
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")
; ;
} }
void export_polygon_symbolizer() void export_polygon_symbolizer()
{ {
using namespace boost::python; using namespace boost::python;
class_<polygon_symbolizer>("PolygonSymbolizer", class_<polygon_symbolizer, bases<symbolizer_base> >("PolygonSymbolizer",
init<>("Default PolygonSymbolizer - solid fill grey")) init<>("Default ctor"))
.def(init<color const&>("TODO")) .def("__hash__",hash_impl_2<polygon_symbolizer>)
.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)
; ;
} }
@ -491,144 +244,17 @@ void export_polygon_pattern_symbolizer()
; ;
class_<polygon_pattern_symbolizer>("PolygonPatternSymbolizer", class_<polygon_pattern_symbolizer>("PolygonPatternSymbolizer",
init<path_expression_ptr>("<path_expression_ptr>")) init<>("Default ctor"))
.add_property("alignment", .def("__hash__",hash_impl_2<polygon_pattern_symbolizer>)
&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")
; ;
} }
void export_raster_symbolizer() void export_raster_symbolizer()
{ {
using namespace boost::python; using namespace boost::python;
class_<raster_symbolizer>("RasterSymbolizer", class_<raster_symbolizer, bases<symbolizer_base> >("RasterSymbolizer",
init<>("Default ctor")) 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) .value("INTERIOR",mapnik::INTERIOR_POINT_PLACEMENT)
; ;
class_<point_symbolizer>("PointSymbolizer", class_<point_symbolizer, bases<symbolizer_base> >("PointSymbolizer",
init<>("Default Point Symbolizer - 4x4 black square")) init<>("Default Point Symbolizer - 4x4 black square"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>")) .def("__hash__",hash_impl_2<point_symbolizer>)
.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")
; ;
} }
@ -686,76 +289,9 @@ void export_markers_symbolizer()
.value("LARGEST",mapnik::MARKER_LARGEST_MULTI) .value("LARGEST",mapnik::MARKER_LARGEST_MULTI)
; ;
class_<markers_symbolizer>("MarkersSymbolizer", class_<markers_symbolizer, bases<symbolizer_base> >("MarkersSymbolizer",
init<>("Default Markers Symbolizer - circle")) init<>("Default Markers Symbolizer - circle"))
.def (init<mapnik::path_expression_ptr>("<path expression ptr>")) .def("__hash__",hash_impl_2<markers_symbolizer>)
.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")
; ;
} }
@ -763,43 +299,33 @@ void export_markers_symbolizer()
void export_line_symbolizer() void export_line_symbolizer()
{ {
using namespace boost::python; using namespace boost::python;
mapnik::enumeration_<mapnik::line_rasterizer_e>("line_rasterizer") mapnik::enumeration_<mapnik::line_rasterizer_e>("line_rasterizer")
.value("FULL",mapnik::RASTERIZER_FULL) .value("FULL",mapnik::RASTERIZER_FULL)
.value("FAST",mapnik::RASTERIZER_FAST) .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")) init<>("Default LineSymbolizer - 1px solid black"))
.def(init<mapnik::stroke const&>("TODO")) .def("__hash__",hash_impl_2<line_symbolizer>)
.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)
; ;
} }
@ -807,31 +333,9 @@ void export_line_pattern_symbolizer()
{ {
using namespace boost::python; using namespace boost::python;
class_<line_pattern_symbolizer>("LinePatternSymbolizer", class_<line_pattern_symbolizer, bases<symbolizer_base> >("LinePatternSymbolizer",
init<path_expression_ptr> init<> ("Default LinePatternSymbolizer"))
("<image file expression>")) .def("__hash__",hash_impl_2<line_pattern_symbolizer>)
.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)")
; ;
} }
@ -844,33 +348,81 @@ void export_debug_symbolizer()
.value("VERTEX",mapnik::DEBUG_SYM_MODE_VERTEX) .value("VERTEX",mapnik::DEBUG_SYM_MODE_VERTEX)
; ;
class_<mapnik::debug_symbolizer>("DebugSymbolizer", class_<debug_symbolizer, bases<symbolizer_base> >("DebugSymbolizer",
init<>("Default debug Symbolizer")) init<>("Default debug Symbolizer"))
.add_property("mode", .def("__hash__",hash_impl_2<debug_symbolizer>)
&mapnik::debug_symbolizer::get_mode,
&mapnik::debug_symbolizer::set_mode)
; ;
} }
void export_building_symbolizer() void export_building_symbolizer()
{ {
using namespace boost::python; using namespace boost::python;
class_<building_symbolizer>("BuildingSymbolizer", class_<building_symbolizer, bases<symbolizer_base> >("BuildingSymbolizer",
init<>("Default BuildingSymbolizer")) init<>("Default BuildingSymbolizer"))
.add_property("fill",make_function .def("__hash__",hash_impl_2<building_symbolizer>)
(&building_symbolizer::get_fill, ;
return_value_policy<copy_const_reference>()),
&building_symbolizer::set_fill) }
.add_property("fill_opacity",
&building_symbolizer::get_opacity, namespace {
&building_symbolizer::set_opacity)
.add_property("height", void group_symbolizer_properties_set_layout_simple(mapnik::group_symbolizer_properties &p,
make_function(&building_symbolizer::height, mapnik::simple_row_layout &s)
return_value_policy<copy_const_reference>()), {
&building_symbolizer::set_height, p.set_layout(s);
"Set/get the building height") }
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/list.hpp>
#include <mapnik/text/formatting/format.hpp> #include <mapnik/text/formatting/format.hpp>
#include <mapnik/text/formatting/expression_format.hpp> #include <mapnik/text/formatting/expression_format.hpp>
#include <mapnik/text/formatting/layout.hpp>
#include <mapnik/text/layout.hpp> #include <mapnik/text/layout.hpp>
#include <mapnik/text_symbolizer.hpp> #include <mapnik/symbolizer.hpp>
#include "mapnik_enumeration.hpp" #include "mapnik_enumeration.hpp"
#include "mapnik_threads.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); 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) if (len(arg) != 2)
{ {
@ -117,7 +118,6 @@ void set_displacement(text_symbolizer_properties &t, boost::python::tuple arg)
t.displacement.set(x, y); t.displacement.set(x, y);
} }
struct NodeWrap: formatting::node, wrapper<formatting::node> struct NodeWrap: formatting::node, wrapper<formatting::node>
{ {
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> struct ListNodeWrap: formatting::list_node, wrapper<formatting::list_node>
{ {
//Default constructor //Default constructor
@ -324,6 +345,7 @@ void insert_expression(expression_set *set, expression_ptr p)
set->insert(p); set->insert(p);
} }
/*
char_properties_ptr get_format(text_symbolizer const& sym) char_properties_ptr get_format(text_symbolizer const& sym)
{ {
return sym.get_placement_options()->defaults.format; 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; sym.get_placement_options()->defaults = defaults;
} }
*/
} }
void export_text_placement() void export_text_placement()
@ -391,44 +413,13 @@ void export_text_placement()
class_<text_symbolizer>("TextSymbolizer", class_<text_symbolizer>("TextSymbolizer",
init<>()) 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> class_with_converter<text_symbolizer_properties>
("TextSymbolizerProperties") ("TextSymbolizerProperties")
.def_readwrite_convert("label_placement", &text_symbolizer_properties::label_placement) .def_readwrite_convert("label_placement", &text_symbolizer_properties::label_placement)
.def_readwrite_convert("horizontal_alignment", &text_symbolizer_properties::halign) .def_readwrite_convert("upright", &text_symbolizer_properties::upright)
.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("label_spacing", &text_symbolizer_properties::label_spacing) .def_readwrite("label_spacing", &text_symbolizer_properties::label_spacing)
.def_readwrite("label_position_tolerance", &text_symbolizer_properties::label_position_tolerance) .def_readwrite("label_position_tolerance", &text_symbolizer_properties::label_position_tolerance)
.def_readwrite("avoid_edges", &text_symbolizer_properties::avoid_edges) .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("force_odd_labels", &text_symbolizer_properties::force_odd_labels)
.def_readwrite("allow_overlap", &text_symbolizer_properties::allow_overlap) .def_readwrite("allow_overlap", &text_symbolizer_properties::allow_overlap)
.def_readwrite("largest_bbox_only", &text_symbolizer_properties::largest_bbox_only) .def_readwrite("largest_bbox_only", &text_symbolizer_properties::largest_bbox_only)
.def_readwrite("text_ratio", &text_symbolizer_properties::text_ratio) .def_readwrite("layout_defaults", &text_symbolizer_properties::layout_defaults)
.def_readwrite("wrap_width", &text_symbolizer_properties::wrap_width)
.def_readwrite("wrap_before", &text_symbolizer_properties::wrap_before)
.def_readwrite("format", &text_symbolizer_properties::format) .def_readwrite("format", &text_symbolizer_properties::format)
.add_property ("format_tree", .add_property ("format_tree",
&text_symbolizer_properties::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. */ 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, class_with_converter<char_properties>
std::shared_ptr<char_properties> >
("CharProperties") ("CharProperties")
.def_readwrite_convert("text_transform", &char_properties::text_transform) .def_readwrite_convert("text_transform", &char_properties::text_transform)
.def_readwrite_convert("fontset", &char_properties::fontset) .def_readwrite_convert("fontset", &char_properties::fontset)

View file

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

View file

@ -394,82 +394,6 @@ void render_layer_for_grid(mapnik::Map const& map,
ren.apply(layer,attributes); 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 #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 unsigned layer_idx, // TODO - layer by name or index
boost::python::list const& fields); 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 #endif // MAPNIK_PYTHON_BINDING_GRID_UTILS_INCLUDED

View file

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

View file

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

View file

@ -43,6 +43,7 @@
#include <mapnik/load_map.hpp> #include <mapnik/load_map.hpp>
#include <mapnik/save_map.hpp> #include <mapnik/save_map.hpp>
#include <mapnik/projection.hpp> #include <mapnik/projection.hpp>
#include <mapnik/util/timer.hpp>
#endif #endif
// qt // qt
@ -53,6 +54,9 @@
#include "layerdelegate.hpp" #include "layerdelegate.hpp"
#include "about_dialog.hpp" #include "about_dialog.hpp"
// boost
#include <boost/algorithm/string.hpp>
MainWindow::MainWindow() MainWindow::MainWindow()
: filename_(), : filename_(),
default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428) default_extent_(-20037508.3428,-20037508.3428,20037508.3428,20037508.3428)
@ -182,13 +186,14 @@ void MainWindow::save()
void MainWindow::load_map_file(QString const& filename) void MainWindow::load_map_file(QString const& filename)
{ {
std::cout<<"loading "<< filename.toStdString() << std::endl; std::cout << "loading "<< filename.toStdString() << std::endl;
unsigned width = mapWidget_->width(); unsigned width = mapWidget_->width();
unsigned height = mapWidget_->height(); unsigned height = mapWidget_->height();
std::shared_ptr<mapnik::Map> map(new mapnik::Map(width,height)); std::shared_ptr<mapnik::Map> map(new mapnik::Map(width,height));
mapWidget_->setMap(map); mapWidget_->setMap(map);
try try
{ {
mapnik::auto_cpu_timer t(std::clog, "loading map took: ");
mapnik::load_map(*map,filename.toStdString()); mapnik::load_map(*map,filename.toStdString());
} }
catch (mapnik::config_error & ex) catch (mapnik::config_error & ex)
@ -441,3 +446,8 @@ void MainWindow::zoom_all()
mapWidget_->zoomToBox(ext); 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(); virtual ~MainWindow();
void set_default_extent(double x0,double y0,double x1, double y1); void set_default_extent(double x0,double y0,double x1, double y1);
void set_scaling_factor(double scaling_factor); void set_scaling_factor(double scaling_factor);
public :
std::shared_ptr<mapnik::Map> get_map();
protected: protected:
void closeEvent(QCloseEvent* event); void closeEvent(QCloseEvent* event);
public slots: public slots:
@ -70,7 +72,6 @@ private:
void createContextMenu(); void createContextMenu();
void load_map_file(QString const& filename); void load_map_file(QString const& filename);
QString currentPath; QString currentPath;
QString filename_; QString filename_;
QAbstractItemModel *model; QAbstractItemModel *model;

View file

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

View file

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

View file

@ -25,7 +25,7 @@ from glob import glob
Import('env') Import('env')
base = './mapnik/' 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']: if env['SVG_RENDERER']:
subdirs.append('svg/output') subdirs.append('svg/output')

View file

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

View file

@ -35,7 +35,8 @@
#include <mapnik/image_compositing.hpp> // for composite_mode_e #include <mapnik/image_compositing.hpp> // for composite_mode_e
#include <mapnik/pixel_position.hpp> #include <mapnik/pixel_position.hpp>
#include <mapnik/request.hpp> #include <mapnik/request.hpp>
#include <mapnik/gamma_method.hpp>
#include <mapnik/renderer_common.hpp>
// boost // boost
#include <memory> #include <memory>
@ -57,21 +58,22 @@ namespace mapnik {
namespace mapnik { namespace mapnik {
template <typename T> template <typename T0, typename T1=label_collision_detector4>
class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T> >, class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T0> >,
private mapnik::noncopyable private mapnik::noncopyable
{ {
public: public:
typedef T buffer_type; typedef T0 buffer_type;
typedef agg_renderer<T> processor_impl_type; typedef agg_renderer<T0> processor_impl_type;
typedef T1 detector_type;
// create with default, empty placement detector // 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 // 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); 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 // 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(); ~agg_renderer();
void start_map_processing(Map const& map); void start_map_processing(Map const& map);
void end_map_processing(Map const& map); void end_map_processing(Map const& map);
@ -114,13 +116,16 @@ public:
void process(markers_symbolizer const& sym, void process(markers_symbolizer const& sym,
mapnik::feature_impl & feature, mapnik::feature_impl & feature,
proj_transform const& prj_trans); 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, void process(debug_symbolizer const& sym,
feature_impl & feature, feature_impl & feature,
proj_transform const& prj_trans); proj_transform const& prj_trans);
inline bool process(rule::symbolizers const& /*syms*/, inline bool process(rule::symbolizers const&,
mapnik::feature_impl & /*feature*/, mapnik::feature_impl&,
proj_transform const& /*prj_trans*/) proj_transform const& )
{ {
// agg renderer doesn't support processing of multiple symbolizers. // agg renderer doesn't support processing of multiple symbolizers.
return false; return false;
@ -134,22 +139,22 @@ public:
inline double scale_factor() const inline double scale_factor() const
{ {
return scale_factor_; return common_.scale_factor_;
} }
inline box2d<double> clipping_extent() const inline box2d<double> clipping_extent() const
{ {
if (t_.offset() > 0) if (common_.t_.offset() > 0)
{ {
box2d<double> box = query_extent_; box2d<double> box = common_.query_extent_;
double scale = static_cast<double>(query_extent_.width())/static_cast<double>(width_); 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 // 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 # // TODO - add more tests to hone in on a more robust #
scale *= t_.offset()*3; scale *= common_.t_.offset()*3;
box.pad(scale); box.pad(scale);
return box; return box;
} }
return query_extent_; return common_.query_extent_;
} }
protected: protected:
@ -164,18 +169,11 @@ private:
buffer_type & pixmap_; buffer_type & pixmap_;
std::shared_ptr<buffer_type> internal_buffer_; std::shared_ptr<buffer_type> internal_buffer_;
mutable buffer_type * current_buffer_; mutable buffer_type * current_buffer_;
CoordTransform t_;
mutable bool style_level_compositing_; 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; const std::unique_ptr<rasterizer> ras_ptr;
box2d<double> query_extent_; gamma_method_enum gamma_method_;
gamma_method_e gamma_method_;
double gamma_; double gamma_;
renderer_common common_;
void setup(Map const& m); void setup(Map const& m);
}; };
} }

View file

@ -53,20 +53,31 @@ struct geometry_type_attribute
V value(F const& f) const V value(F const& f) const
{ {
mapnik::value_integer type = 0; mapnik::value_integer type = 0;
geometry_container::const_iterator itr = f.paths().begin(); for (auto const& geom : f.paths())
geometry_container::const_iterator end = f.paths().end();
for ( ; itr != end; ++itr)
{ {
if (type != 0 && itr->type() != type) if (type != 0 && geom.type() != type)
{ {
return value_integer(4); // Collection return value_integer(4); // Collection
} }
type = itr->type(); type = geom.type();
} }
return 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 #endif // MAPNIK_ATTRIBUTE_HPP

View file

@ -27,17 +27,7 @@
#include <mapnik/transform_processor.hpp> #include <mapnik/transform_processor.hpp>
#include <mapnik/noncopyable.hpp> #include <mapnik/noncopyable.hpp>
#include <mapnik/attribute.hpp> #include <mapnik/attribute.hpp>
#include <mapnik/symbolizer.hpp> // for transform_list_ptr #include <mapnik/symbolizer.hpp>
#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/rule.hpp> // for rule::symbolizers #include <mapnik/rule.hpp> // for rule::symbolizers
#include <mapnik/expression.hpp> // for expression_ptr, etc #include <mapnik/expression.hpp> // for expression_ptr, etc
#include <mapnik/expression_node_types.hpp> #include <mapnik/expression_node_types.hpp>
@ -45,10 +35,15 @@
#include <mapnik/parse_path.hpp> // for path_processor_type #include <mapnik/parse_path.hpp> // for path_processor_type
#include <mapnik/path_expression.hpp> // for path_expression_ptr #include <mapnik/path_expression.hpp> // for path_expression_ptr
#include <mapnik/text/placements/base.hpp> // for text_placements #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 // boost
#include <boost/variant/static_visitor.hpp> #include <boost/variant/static_visitor.hpp>
#include <boost/variant/apply_visitor.hpp> #include <boost/variant/apply_visitor.hpp>
#include <boost/algorithm/string.hpp>
#include <boost/lexical_cast.hpp>
// stl // stl
#include <set> #include <set>
@ -61,15 +56,6 @@ struct expression_attributes : boost::static_visitor<void>
explicit expression_attributes(Container& names) explicit expression_attributes(Container& names)
: names_(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 void operator() (attribute const& attr) const
{ {
names_.insert(attr.name()); 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.left);
boost::apply_visitor(*this, x.right); boost::apply_visitor(*this, x.right);
} }
template <typename Tag> template <typename Tag>
@ -99,142 +84,127 @@ struct expression_attributes : boost::static_visitor<void>
boost::apply_visitor(*this, x.expr); boost::apply_visitor(*this, x.expr);
} }
template <typename T>
void operator() (T const& val) const {}
private: private:
Container& names_; 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<> struct symbolizer_attributes : public boost::static_visitor<>
{ {
symbolizer_attributes(std::set<std::string>& names, symbolizer_attributes(std::set<std::string>& names,
double & filter_factor) double & filter_factor)
: names_(names), : filter_factor_(filter_factor),
filter_factor_(filter_factor), f_attrs_(names),
f_attr(names) {} g_attrs_(names, true) {}
template <typename T> template <typename T>
void operator () (T const&) const {} void operator () (T const& sym)
void operator () (text_symbolizer const& sym)
{ {
expression_set::const_iterator it; for (auto const& prop : sym.properties)
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); 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) 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: private:
std::set<std::string>& names_;
double & filter_factor_; double & filter_factor_;
expression_attributes<std::set<std::string> > f_attr; extract_attribute_names<std::set<std::string> > f_attrs_;
void collect_transform(transform_list_ptr const& trans_expr) group_attribute_collector g_attrs_;
{
if (trans_expr)
{
transform_processor_type::collect_attributes(names_, *trans_expr);
}
}
}; };
@ -254,11 +224,10 @@ public:
void operator() (RuleType const& r) void operator() (RuleType const& r)
{ {
typename RuleType::symbolizers const& symbols = r.get_symbolizers(); typename RuleType::symbolizers const& symbols = r.get_symbolizers();
typename RuleType::symbolizers::const_iterator symIter=symbols.begin();
symbolizer_attributes s_attr(names_,filter_factor_); 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(); 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 } // namespace mapnik
#endif // MAPNIK_ATTRIBUTE_COLLECTOR_HPP #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/debug.hpp>
#include <mapnik/box2d.hpp> #include <mapnik/box2d.hpp>
#include <mapnik/color.hpp> #include <mapnik/color.hpp>
#include <mapnik/stroke.hpp>
#include <mapnik/image_data.hpp> #include <mapnik/image_data.hpp>
#include <mapnik/image_compositing.hpp> #include <mapnik/image_compositing.hpp>
#include <mapnik/font_engine_freetype.hpp> #include <mapnik/font_engine_freetype.hpp>
@ -38,6 +37,7 @@
#include <mapnik/text/glyph_info.hpp> #include <mapnik/text/glyph_info.hpp>
#include <mapnik/vertex.hpp> #include <mapnik/vertex.hpp>
#include <mapnik/noncopyable.hpp> #include <mapnik/noncopyable.hpp>
#include <mapnik/symbolizer.hpp>
// boost // boost
#include <memory> #include <memory>

View file

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

View file

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

View file

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

View file

@ -104,11 +104,7 @@ struct alpha_conv_impl
struct hsl_conv_impl struct hsl_conv_impl
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template<typename T> template<typename T>
#else
template<typename T0,typename T1, typename T2, typename T3>
#endif
struct result struct result
{ {
typedef void type; 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 namespace mapnik
{ {
template <typename T0, typename T1> template <typename T0, typename T1>
struct evaluate : boost::static_visitor<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_); 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 value_type operator() (geometry_type_attribute const& geom) const
{ {
return geom.value<value_type,feature_type>(feature_); 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 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()) return (boost::apply_visitor(*this, x.left).to_bool())
&& (boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.right).to_bool()); && (boost::apply_visitor(*this, x.right).to_bool());
} }
value_type operator() (binary_node<tags::logical_or> const & x) const 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()) return (boost::apply_visitor(*this,x.left).to_bool())
|| (boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.right).to_bool()); || (boost::apply_visitor(*this,x.right).to_bool());
} }
template <typename Tag> template <typename Tag>
value_type operator() (binary_node<Tag> const& x) const value_type operator() (binary_node<Tag> const& x) const
{ {
typename make_op<Tag>::type operation; typename make_op<Tag>::type operation;
return operation(boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.left), return operation(boost::apply_visitor(*this, x.left),
boost::apply_visitor(evaluate<feature_type,value_type>(feature_),x.right)); boost::apply_visitor(*this, x.right));
} }
template <typename Tag> template <typename Tag>
@ -111,12 +117,12 @@ struct evaluate : boost::static_visitor<T1>
value_type operator() (unary_node<tags::logical_not> const& x) const 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 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) #if defined(BOOST_REGEX_HAS_ICU)
return boost::u32regex_match(v.to_unicode(),x.pattern); return boost::u32regex_match(v.to_unicode(),x.pattern);
#else #else
@ -127,7 +133,7 @@ struct evaluate : boost::static_visitor<T1>
value_type operator() (regex_replace_node const& x) const 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) #if defined(BOOST_REGEX_HAS_ICU)
return boost::u32regex_replace(v.to_unicode(),x.pattern,x.format); return boost::u32regex_replace(v.to_unicode(),x.pattern,x.format);
#else #else

View file

@ -65,11 +65,7 @@ struct unicode_impl
struct regex_match_impl struct regex_match_impl
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T> template <typename T>
#else
template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef expr_node type; typedef expr_node type;
@ -87,11 +83,7 @@ struct regex_match_impl
struct regex_replace_impl struct regex_replace_impl
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T> template <typename T>
#else
template <typename T0, typename T1, typename T2>
#endif
struct result struct result
{ {
typedef expr_node type; 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, 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, 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() , 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::symbols<char const, char const> unesc_char;
qi::rule<Iterator, char() > quote_char; qi::rule<Iterator, char() > quote_char;
geometry_types geom_type; 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_match_(regex_match_impl(tr)),
regex_replace_(regex_replace_impl(tr)) regex_replace_(regex_replace_impl(tr))
{ {
using boost::phoenix::construct;
qi::_1_type _1; qi::_1_type _1;
qi::_a_type _a; qi::_a_type _a;
qi::_b_type _b; qi::_b_type _b;
@ -81,8 +80,11 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
qi::double_type double_; qi::double_type double_;
qi::hex_type hex; qi::hex_type hex;
qi::omit_type omit; qi::omit_type omit;
qi::alpha_type alpha;
qi::alnum_type alnum;
standard_wide::char_type char_; standard_wide::char_type char_;
standard_wide::no_case_type no_case; standard_wide::no_case_type no_case;
using boost::phoenix::construct;
expr = logical_expr.alias(); expr = logical_expr.alias();
@ -110,16 +112,16 @@ expression_grammar<Iterator>::expression_grammar(mapnik::transcoder const& tr)
regex_match_expr = lit(".match") regex_match_expr = lit(".match")
>> lit('(') >> lit('(')
>> ustring [_val = _1] >> quoted_ustring [_val = _1]
>> lit(')') >> lit(')')
; ;
regex_replace_expr = regex_replace_expr =
lit(".replace") lit(".replace")
>> lit('(') >> lit('(')
>> ustring [_a = _1] >> quoted_ustring [_a = _1]
>> lit(',') >> lit(',')
>> ustring [_b = _1] >> quoted_ustring [_b = _1]
>> lit(')') [_val = regex_replace_(_r1,_a,_b)] >> 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("false")] [_val = false]
| no_case[lit("null")] [_val = value_null() ] | no_case[lit("null")] [_val = value_null() ]
| no_case[geom_type][_val = _1 ] | 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>()] | lit("[mapnik::geometry_type]")[_val = construct<mapnik::geometry_type_attribute>()]
| attr [_val = construct<mapnik::attribute>( _1 ) ] | attr [_val = construct<mapnik::attribute>( _1 ) ]
| global_attr [_val = construct<mapnik::global_attribute>( _1 )]
| lit("not") >> expr [_val = !_1]
| '(' >> 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') 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_('"'); quote_char %= char_('\'') | char_('"');
ustring %= omit[quote_char[_a = _1]] quoted_ustring %= omit[quote_char[_a = _1]]
>> *(unesc_char | "\\x" >> hex | (char_ - lit(_a))) >> *(unesc_char | "\\x" >> hex | (char_ - lit(_a)))
>> lit(_a); >> lit(_a);
attr %= '[' >> no_skip[+~char_(']')] >> ']'; 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 mapnik::value value_type;
typedef boost::mpl::vector24< typedef boost::mpl::vector25<
value_null, value_null,
value_bool, value_bool,
value_integer, value_integer,
value_double, value_double,
value_unicode_string, value_unicode_string,
attribute, attribute,
global_attribute,
geometry_type_attribute, geometry_type_attribute,
boost::recursive_wrapper<unary_node<tags::negate> >, boost::recursive_wrapper<unary_node<tags::negate> >,
boost::recursive_wrapper<binary_node<tags::plus> >, 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 context<std::map<std::string,std::size_t> > context_type;
typedef std::shared_ptr<context_type> context_ptr; 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 class MAPNIK_DECL feature_impl : private mapnik::noncopyable
{ {
@ -166,14 +166,14 @@ public:
if (itr != ctx_->mapping_.end()) if (itr != ctx_->mapping_.end())
return get(itr->second); return get(itr->second);
else else
return default_value; return default_feature_value;
} }
inline value_type const& get(std::size_t index) const inline value_type const& get(std::size_t index) const
{ {
if (index < data_.size()) if (index < data_.size())
return data_[index]; return data_[index];
return default_value; return default_feature_value;
} }
inline std::size_t size() const inline std::size_t size() const

View file

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

View file

@ -65,15 +65,13 @@ private:
bool image_filters_inflate_; bool image_filters_inflate_;
public: public:
feature_type_style(); feature_type_style();
feature_type_style(feature_type_style const& rhs); feature_type_style(feature_type_style const& rhs);
feature_type_style& operator=(feature_type_style rhs);
feature_type_style& operator=(feature_type_style const& rhs);
void add_rule(rule const& rule); void add_rule(rule const& rule);
rules const& get_rules() const; rules const& get_rules() const;
rules& get_rules_nonconst(); rules& get_rules_nonconst();
bool active(double scale_denom) const; bool active(double scale_denom) const;
void set_filter_mode(filter_mode_e mode); void set_filter_mode(filter_mode_e mode);
@ -81,12 +79,12 @@ public:
// filters // filters
std::vector<filter::filter_type> const& image_filters() const; std::vector<filter::filter_type> const& image_filters() const;
std::vector<filter::filter_type> & image_filters(); std::vector<filter::filter_type> & image_filters();
std::vector<filter::filter_type> const& direct_image_filters() const; std::vector<filter::filter_type> const& direct_image_filters() const;
std::vector<filter::filter_type> & direct_image_filters(); std::vector<filter::filter_type> & direct_image_filters();
// compositing // compositing
void set_comp_op(composite_mode_e comp_op); void set_comp_op(composite_mode_e comp_op);
boost::optional<composite_mode_e> comp_op() const; boost::optional<composite_mode_e> comp_op() const;
void set_opacity(float opacity); void set_opacity(float opacity);
float get_opacity() const; float get_opacity() const;
void set_image_filters_inflate(bool inflate); void set_image_filters_inflate(bool inflate);

View file

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

View file

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

View file

@ -247,6 +247,46 @@ double path_length(PathType & path)
return length; 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 { namespace label {
template <typename PathType> template <typename PathType>

View file

@ -24,7 +24,7 @@
#define MAPNIK_GRID_MARKER_HELPERS_HPP #define MAPNIK_GRID_MARKER_HELPERS_HPP
// mapnik // mapnik
#include <mapnik/markers_symbolizer.hpp> #include <mapnik/symbolizer.hpp>
#include <mapnik/markers_placement.hpp> #include <mapnik/markers_placement.hpp>
#include <mapnik/geometry.hpp> #include <mapnik/geometry.hpp>
#include <mapnik/geom_util.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())); //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> template <typename T>
void add_path(T & path) 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()); box2d<double> bbox_(0,0, src_.width(),src_.height());
if (placement_method != MARKER_LINE_PLACEMENT || if (placement_method != MARKER_LINE_PLACEMENT ||
path.type() == geometry_type::types::Point) path.type() == geometry_type::types::Point)
@ -101,11 +114,11 @@ struct raster_markers_rasterizer_dispatch_grid
agg::trans_affine matrix = marker_trans_; agg::trans_affine matrix = marker_trans_;
matrix.translate(x,y); matrix.translate(x,y);
box2d<double> transformed_bbox = bbox_ * matrix; box2d<double> transformed_bbox = bbox_ * matrix;
if (sym_.get_allow_overlap() || if (allow_overlap ||
detector_.has_placement(transformed_bbox)) detector_.has_placement(transformed_bbox))
{ {
render_raster_marker(matrix); render_raster_marker(matrix);
if (!sym_.get_ignore_placement()) if (!ignore_placement)
{ {
detector_.insert(transformed_bbox); detector_.insert(transformed_bbox);
} }
@ -119,11 +132,11 @@ struct raster_markers_rasterizer_dispatch_grid
else else
{ {
markers_placement<T, label_collision_detector4> placement(path, bbox_, marker_trans_, detector_, markers_placement<T, label_collision_detector4> placement(path, bbox_, marker_trans_, detector_,
sym_.get_spacing() * scale_factor_, spacing * scale_factor_,
sym_.get_max_error(), max_error,
sym_.get_allow_overlap()); allow_overlap);
double x, y, angle; 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_; agg::trans_affine matrix = marker_trans_;
matrix.rotate(angle); matrix.rotate(angle);
@ -180,23 +193,26 @@ private:
template <typename BufferType, typename SvgRenderer, typename Rasterizer, typename Detector, typename PixMapType> template <typename BufferType, typename SvgRenderer, typename Rasterizer, typename Detector, typename PixMapType>
struct vector_markers_rasterizer_dispatch_grid struct vector_markers_rasterizer_dispatch_grid
{ {
typedef typename SvgRenderer::renderer_base renderer_base; typedef typename SvgRenderer::renderer_base renderer_base;
typedef typename renderer_base::pixfmt_type pixfmt_type; 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, vector_markers_rasterizer_dispatch_grid(BufferType & render_buffer,
SvgRenderer & svg_renderer, vertex_source_type &path,
Rasterizer & ras, const attribute_source_type &attrs,
box2d<double> const& bbox, Rasterizer & ras,
agg::trans_affine const& marker_trans, box2d<double> const& bbox,
markers_symbolizer const& sym, agg::trans_affine const& marker_trans,
Detector & detector, markers_symbolizer const& sym,
double scale_factor, Detector & detector,
mapnik::feature_impl & feature, double scale_factor,
PixMapType & pixmap) mapnik::feature_impl & feature,
PixMapType & pixmap)
: buf_(render_buffer), : buf_(render_buffer),
pixf_(buf_), pixf_(buf_),
renb_(pixf_), renb_(pixf_),
svg_renderer_(svg_renderer), svg_renderer_(path, attrs),
ras_(ras), ras_(ras),
bbox_(bbox), bbox_(bbox),
marker_trans_(marker_trans), 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())); //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> template <typename T>
void add_path(T & path) 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 || if (placement_method != MARKER_LINE_PLACEMENT ||
path.type() == geometry_type::types::Point) path.type() == geometry_type::types::Point)
{ {
@ -238,11 +268,11 @@ struct vector_markers_rasterizer_dispatch_grid
agg::trans_affine matrix = marker_trans_; agg::trans_affine matrix = marker_trans_;
matrix.translate(x,y); matrix.translate(x,y);
box2d<double> transformed_bbox = bbox_ * matrix; box2d<double> transformed_bbox = bbox_ * matrix;
if (sym_.get_allow_overlap() || if (allow_overlap ||
detector_.has_placement(transformed_bbox)) detector_.has_placement(transformed_bbox))
{ {
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 (!sym_.get_ignore_placement()) if (!ignore_placement)
{ {
detector_.insert(transformed_bbox); detector_.insert(transformed_bbox);
} }
@ -256,16 +286,16 @@ struct vector_markers_rasterizer_dispatch_grid
else else
{ {
markers_placement<T, Detector> placement(path, bbox_, marker_trans_, detector_, markers_placement<T, Detector> placement(path, bbox_, marker_trans_, detector_,
sym_.get_spacing() * scale_factor_, spacing * scale_factor_,
sym_.get_max_error(), max_error,
sym_.get_allow_overlap()); allow_overlap);
double x, y, angle; 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_; agg::trans_affine matrix = marker_trans_;
matrix.rotate(angle); matrix.rotate(angle);
matrix.translate(x, y); 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_) if (!placed_)
{ {
pixmap_.add_feature(feature_); pixmap_.add_feature(feature_);
@ -279,7 +309,7 @@ private:
BufferType & buf_; BufferType & buf_;
pixfmt_type pixf_; pixfmt_type pixf_;
renderer_base renb_; renderer_base renb_;
SvgRenderer & svg_renderer_; SvgRenderer svg_renderer_;
Rasterizer & ras_; Rasterizer & ras_;
box2d<double> const& bbox_; box2d<double> const& bbox_;
agg::trans_affine const& marker_trans_; agg::trans_affine const& marker_trans_;

View file

@ -35,6 +35,7 @@
#include <mapnik/ctrans.hpp> // for CoordTransform #include <mapnik/ctrans.hpp> // for CoordTransform
#include <mapnik/image_compositing.hpp> // for composite_mode_e #include <mapnik/image_compositing.hpp> // for composite_mode_e
#include <mapnik/pixel_position.hpp> #include <mapnik/pixel_position.hpp>
#include <mapnik/renderer_common.hpp>
// boost // boost
@ -107,6 +108,9 @@ public:
void process(markers_symbolizer const& sym, void process(markers_symbolizer const& sym,
mapnik::feature_impl & feature, mapnik::feature_impl & feature,
proj_transform const& prj_trans); 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*/, inline bool process(rule::symbolizers const& /*syms*/,
mapnik::feature_impl & /*feature*/, mapnik::feature_impl & /*feature*/,
proj_transform const& /*prj_trans*/) proj_transform const& /*prj_trans*/)
@ -124,20 +128,13 @@ public:
} }
inline double scale_factor() const inline double scale_factor() const
{ {
return scale_factor_; return common_.scale_factor_;
} }
private: private:
buffer_type & pixmap_; 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; const std::unique_ptr<grid_rasterizer> ras_ptr;
box2d<double> query_extent_; renderer_common common_;
void setup(Map const& m); 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 <cstring>
#include <stdexcept> #include <stdexcept>
namespace mapnik namespace mapnik
{ {
template <class T> class ImageData template <typename T>
class ImageData
{ {
public: public:
typedef T pixel_type; typedef T pixel_type;
@ -55,7 +55,7 @@ public:
if (pData_) std::memset(pData_,0,sizeof(T)*width_*height_); if (pData_) std::memset(pData_,0,sizeof(T)*width_*height_);
} }
ImageData(const ImageData<T>& rhs) ImageData(ImageData<T> const& rhs)
:width_(rhs.width_), :width_(rhs.width_),
height_(rhs.height_), height_(rhs.height_),
pData_((rhs.width_!=0 && rhs.height_!=0)? 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_); 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) inline T& operator() (unsigned i,unsigned j)
{ {
assert(i<width_ && j<height_); assert(i<width_ && j<height_);
@ -140,8 +164,8 @@ public:
} }
private: private:
const unsigned width_; unsigned width_;
const unsigned height_; unsigned height_;
T *pData_; T *pData_;
ImageData& operator=(const ImageData&); ImageData& operator=(const ImageData&);
}; };

View file

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

View file

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

View file

@ -67,7 +67,6 @@ public:
mapnik::transcoder const& tr_; mapnik::transcoder const& tr_;
}; };
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct put_property struct put_property
{ {
typedef void result_type; typedef void result_type;
@ -90,42 +89,6 @@ struct extract_geometry
return feature.paths(); 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> template <typename Iterator, typename FeatureType>
struct feature_grammar : struct feature_grammar :

View file

@ -58,7 +58,6 @@ namespace phoenix = boost::phoenix;
namespace { namespace {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct get_type struct get_type
{ {
typedef int result_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> template <typename T>
struct json_coordinate_policy : karma::real_policies<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; namespace standard_wide = boost::spirit::standard_wide;
using standard_wide::space_type; using standard_wide::space_type;
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
struct push_vertex struct push_vertex
{ {
typedef void result_type; typedef void result_type;
@ -88,76 +87,6 @@ struct where_message
return str; 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> template <typename Iterator>
struct geometry_grammar : 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 #ifndef MAPNIK_TOPOJSON_GRAMMAR_HPP
#define MAPNIK_TOPOJSON_GRAMMAR_HPP #define MAPNIK_TOPOJSON_GRAMMAR_HPP
#define BOOST_SPIRIT_USE_PHOENIX_V3 1 // mapnik
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
//
#include <mapnik/value.hpp> #include <mapnik/value.hpp>
#include <mapnik/json/topology.hpp> #include <mapnik/json/topology.hpp>
//
// boost
#include <boost/spirit/include/qi.hpp>
#include <boost/spirit/include/phoenix.hpp>
// stl
#include <string> #include <string>
namespace mapnik { namespace topojson { namespace mapnik { namespace topojson {

View file

@ -48,7 +48,7 @@ public:
std::string const& srs=MAPNIK_LONGLAT_PROJ); std::string const& srs=MAPNIK_LONGLAT_PROJ);
layer(layer const& l); layer(layer const& l);
layer& operator=(layer const& rhs); layer& operator=(layer rhs);
bool operator==(layer const& other) const; bool operator==(layer const& other) const;
/*! /*!
@ -199,7 +199,6 @@ public:
void reset_buffer_size(); void reset_buffer_size();
~layer(); ~layer();
private: private:
void swap(layer& other);
std::string name_; std::string name_;
std::string srs_; 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 feature_type_style;
class CoordTransform; class CoordTransform;
class MAPNIK_DECL Map class MAPNIK_DECL Map : boost::equality_comparable<Map>
{ {
public: public:
@ -123,7 +123,7 @@ public:
* TODO: to be documented * TODO: to be documented
* *
*/ */
Map& operator=(Map const& rhs); Map& operator=(Map rhs);
/*! \brief Get all styles /*! \brief Get all styles
* @return Const reference to styles * @return Const reference to styles

View file

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

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: protected:
constexpr noncopyable() = default; constexpr noncopyable() = default;
~noncopyable() = default; ~noncopyable() = default;
noncopyable( const noncopyable& ) = delete; noncopyable( noncopyable const& ) = delete;
noncopyable& operator=( const noncopyable& ) = 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: public:
box2d<double> ext_; box2d<double> ext_;
image_data_32 data_; image_data_32 data_;
double filter_factor_;
bool premultiplied_alpha_; bool premultiplied_alpha_;
boost::optional<double> nodata_; 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), : ext_(ext),
data_(width,height), data_(width,height),
premultiplied_alpha_(premultiplied_alpha) filter_factor_(filter_factor),
{} premultiplied_alpha_(premultiplied_alpha) {}
void set_nodata(double nodata) void set_nodata(double nodata)
{ {
@ -54,6 +59,17 @@ public:
{ {
return nodata_; 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) * This file is part of Mapnik (c++ mapping toolkit)
@ -68,7 +67,8 @@ enum colorizer_mode_enum
DEFINE_ENUM( colorizer_mode, colorizer_mode_enum ); DEFINE_ENUM( colorizer_mode, colorizer_mode_enum );
//! \brief Structure to represent a stop position. //! \brief Structure to represent a stop position.
class MAPNIK_DECL colorizer_stop { class MAPNIK_DECL colorizer_stop
{
public: public:
//! \brief Constructor //! \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 #define MAPNIK_RULE_HPP
// mapnik // mapnik
#include <mapnik/building_symbolizer.hpp> #include <mapnik/config.hpp>
#include <mapnik/line_symbolizer.hpp> #include <mapnik/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/feature.hpp> #include <mapnik/feature.hpp>
#include <mapnik/expression.hpp> #include <mapnik/expression.hpp>
#include <mapnik/expression_string.hpp> #include <mapnik/expression_string.hpp>
#include <mapnik/config.hpp> // MAPNIK_DECL
// boost
#include <boost/variant/variant_fwd.hpp>
// stl // stl
#include <string> #include <string>
@ -50,82 +37,6 @@
namespace mapnik 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 class MAPNIK_DECL rule
{ {
public: public:
@ -145,9 +56,8 @@ public:
rule(std::string const& name, rule(std::string const& name,
double min_scale_denominator = 0, double min_scale_denominator = 0,
double max_scale_denominator = std::numeric_limits<double>::infinity()); double max_scale_denominator = std::numeric_limits<double>::infinity());
rule(rule const& rhs); rule(const rule& rhs);
rule& operator=(rule rhs);
rule& operator=(rule const& rhs);
bool operator==(rule const& other); bool operator==(rule const& other);
void set_max_scale(double scale); void set_max_scale(double scale);
double get_max_scale() const; double get_max_scale() const;
@ -155,9 +65,9 @@ public:
double get_min_scale() const; double get_min_scale() const;
void set_name(std::string const& name); void set_name(std::string const& name);
std::string const& get_name() const; std::string const& get_name() const;
void append(symbolizer const& sym); void append(symbolizer && sym);
void remove_at(size_t index); void remove_at(size_t index);
const symbolizers& get_symbolizers() const; symbolizers const& get_symbolizers() const;
symbolizers::const_iterator begin() const; symbolizers::const_iterator begin() const;
symbolizers::const_iterator end() const; symbolizers::const_iterator end() const;
symbolizers::iterator begin(); 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 // mapnik
#include <mapnik/color.hpp> #include <mapnik/color.hpp>
#include <mapnik/stroke.hpp> #include <mapnik/symbolizer.hpp>
// stl // stl
#include <string> #include <string>

View file

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

View file

@ -38,6 +38,7 @@
#include <mapnik/image_compositing.hpp> // for composite_mode_e #include <mapnik/image_compositing.hpp> // for composite_mode_e
#include <mapnik/pixel_position.hpp> #include <mapnik/pixel_position.hpp>
#include <mapnik/request.hpp> #include <mapnik/request.hpp>
#include <mapnik/renderer_common.hpp>
// boost // boost
#include <boost/variant/static_visitor.hpp> #include <boost/variant/static_visitor.hpp>
@ -119,6 +120,9 @@ public:
void process(debug_symbolizer const& /*sym*/, void process(debug_symbolizer const& /*sym*/,
mapnik::feature_impl & /*feature*/, mapnik::feature_impl & /*feature*/,
proj_transform const& /*prj_trans*/) {} 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. * @brief Overload that process the whole set of symbolizers of a rule.
@ -140,7 +144,7 @@ public:
inline double scale_factor() const inline double scale_factor() const
{ {
return scale_factor_; return common_.scale_factor_;
} }
inline OutputIterator& get_output_iterator() inline OutputIterator& get_output_iterator()
@ -155,17 +159,10 @@ public:
private: private:
OutputIterator& output_iterator_; OutputIterator& output_iterator_;
const int width_;
const int height_;
double scale_factor_;
CoordTransform t_;
svg::path_output_attributes path_attributes_; 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_; svg::svg_generator<OutputIterator> generator_;
box2d<double> query_extent_;
bool painted_; bool painted_;
renderer_common common_;
/*! /*!
* @brief Visitor that makes the calls to process each symbolizer when stored in a boost::variant. * @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 struct move_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -71,11 +67,7 @@ struct move_to
template <typename PathType> template <typename PathType>
struct hline_to struct hline_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -97,11 +89,7 @@ struct hline_to
template <typename PathType> template <typename PathType>
struct vline_to struct vline_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -122,11 +110,7 @@ struct vline_to
template <typename PathType> template <typename PathType>
struct line_to struct line_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -148,11 +132,7 @@ struct line_to
template <typename PathType> template <typename PathType>
struct curve4 struct curve4
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1, typename T2, typename T3>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -177,11 +157,7 @@ struct curve4
template <typename PathType> template <typename PathType>
struct curve4_smooth struct curve4_smooth
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1, typename T2>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -203,11 +179,7 @@ struct curve4_smooth
template <typename PathType> template <typename PathType>
struct curve3 struct curve3
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1, typename T2>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -230,11 +202,7 @@ struct curve3
template <typename PathType> template <typename PathType>
struct curve3_smooth struct curve3_smooth
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1>
#endif
struct result struct result
{ {
typedef void type; typedef void type;
@ -256,11 +224,7 @@ struct curve3_smooth
template <typename PathType> template <typename PathType>
struct arc_to struct arc_to
{ {
#ifdef BOOST_SPIRIT_USE_PHOENIX_V3
template <typename T0> template <typename T0>
#else
template <typename T0, typename T1, typename T2, typename T3, typename T4, typename T5>
#endif
struct result struct result
{ {
typedef void type; typedef void type;

View file

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

View file

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

View file

@ -2,7 +2,7 @@
* *
* This file is part of Mapnik (c++ mapping toolkit) * 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 * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -25,16 +25,28 @@
// mapnik // mapnik
#include <mapnik/config.hpp> #include <mapnik/config.hpp>
#include <mapnik/path_expression.hpp> #include <mapnik/value_types.hpp>
#include <mapnik/image_compositing.hpp> #include <mapnik/image_compositing.hpp>
#include <mapnik/simplify.hpp> #include <mapnik/simplify.hpp>
#include <mapnik/expression.hpp>
// boost #include <mapnik/expression_evaluator.hpp>
#include <memory> #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 // stl
#include <type_traits>
#include <algorithm>
#include <memory>
#include <vector> #include <vector>
#include <string> #include <string>
#include <functional>
// boost
#include <boost/variant/variant_fwd.hpp>
namespace agg { struct trans_affine; } namespace agg { struct trans_affine; }
@ -44,59 +56,479 @@ namespace mapnik
// fwd declares // fwd declares
// TODO - move these transform declares to own header // TODO - move these transform declares to own header
namespace detail { struct transform_node; } namespace detail { struct transform_node; }
typedef std::vector<detail::transform_node> transform_list; typedef std::vector<detail::transform_node> transform_list;
typedef std::shared_ptr<transform_list> transform_list_ptr; typedef std::shared_ptr<transform_list> transform_list_ptr;
typedef transform_list_ptr transform_type; typedef transform_list_ptr transform_type;
class feature_impl; class feature_impl;
MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr, feature_impl const& feature, MAPNIK_DECL void evaluate_transform(agg::trans_affine& tr,
transform_type const& trans_expr, double scale_factor=1.0); feature_impl const& feature,
transform_type const& trans_expr,
double scale_factor=1.0);
class MAPNIK_DECL symbolizer_base struct enumeration_wrapper
{ {
public: int value;
symbolizer_base(); enumeration_wrapper() = delete;
symbolizer_base(symbolizer_base const& other); template <typename T>
void set_comp_op(composite_mode_e comp_op); explicit enumeration_wrapper(T value_)
composite_mode_e comp_op() const; : value(value_) {}
void set_transform(transform_type const& );
transform_type const& get_transform() const; inline operator int() const
std::string get_transform_string() const; {
void set_clip(bool clip); return value;
bool clip() const; }
void set_simplify_algorithm(simplify_algorithm_e algorithm); };
simplify_algorithm_e simplify_algorithm() const;
void set_simplify_tolerance(double simplify_tolerance); typedef std::vector<std::pair<double,double> > dash_array;
double simplify_tolerance() const;
void set_smooth(double smooth); struct MAPNIK_DECL symbolizer_base
double smooth() const; {
private: typedef boost::variant<value_bool,
composite_mode_e comp_op_; value_integer,
transform_type affine_transform_; enumeration_wrapper,
bool clip_; value_double,
simplify_algorithm_e simplify_algorithm_value_; std::string,
double simplify_tolerance_value_; color,
double smooth_value_; 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: typedef T result_type;
path_expression_ptr const& get_filename() const;
void set_filename(path_expression_ptr const& filename); extract_value(mapnik::feature_impl const& feature)
void set_opacity(float opacity); : feature_(feature) {}
float get_opacity() const;
void set_image_transform(transform_type const& tr); auto operator() (mapnik::expression_ptr const& expr) const -> result_type
transform_type const& get_image_transform() const; {
std::string get_image_transform_string() const; return evaluate_expression_wrapper<result_type>()(*expr,feature_);
protected: }
symbolizer_with_image(path_expression_ptr filename = path_expression_ptr());
symbolizer_with_image(symbolizer_with_image const& rhs); auto operator() (mapnik::path_expression_ptr const& expr) const -> result_type
path_expression_ptr image_filename_; {
float image_opacity_; return evaluate_path_wrapper<result_type>()(*expr, feature_);
transform_type image_transform_; }
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 #endif // MAPNIK_SYMBOLIZER_HPP

View file

@ -23,43 +23,82 @@
#ifndef MAPNIK_SYMBOLIZER_HASH_HPP #ifndef MAPNIK_SYMBOLIZER_HASH_HPP
#define MAPNIK_SYMBOLIZER_HASH_HPP #define MAPNIK_SYMBOLIZER_HASH_HPP
#include <mapnik/map.hpp> // mapnik
#include <mapnik/feature_type_style.hpp> #include <mapnik/symbolizer.hpp>
// boost
#include <boost/functional/hash.hpp>
#include <boost/variant/static_visitor.hpp> #include <boost/variant/static_visitor.hpp>
// stl
#include <typeinfo>
#include <typeindex>
#include <functional>
namespace mapnik { 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 struct symbolizer_hash
{ {
template <typename T> 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)
// specialisation for polygon_symbolizer {
static std::size_t value(polygon_symbolizer const& sym) seed ^= std::hash<std::size_t>()(static_cast<std::size_t>(prop.first));
{ seed ^= boost::apply_visitor(property_value_hash_visitor(), prop.second);
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; return seed;
} }
};
// specialisation for line_symbolizer struct hash_visitor : boost::static_visitor<std::size_t>
static std::size_t value(line_symbolizer const& sym) {
template <typename Symbolizer>
std::size_t operator() (Symbolizer const& sym) const
{ {
std::size_t seed = geometry_type::types::LineString; return symbolizer_hash::value(sym);
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;
} }
}; };
} }
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 #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/harfbuzz_shaper.hpp>
#include <mapnik/text/icu_shaper.hpp> #include <mapnik/text/icu_shaper.hpp>
#include <mapnik/text/dummy_shaper.hpp> #include <mapnik/text/dummy_shaper.hpp>
#include <mapnik/text/rotation.hpp>
//stl //stl
#include <vector> #include <vector>
@ -38,13 +39,17 @@
namespace mapnik namespace mapnik
{ {
typedef std::shared_ptr<text_layout> text_layout_ptr;
typedef std::vector<text_layout_ptr> text_layout_vector;
class text_layout class text_layout
{ {
public: public:
typedef std::vector<text_line> line_vector; typedef std::vector<text_line> line_vector;
typedef line_vector::const_iterator const_iterator; typedef line_vector::const_iterator const_iterator;
typedef text_layout_vector::const_iterator child_iterator;
typedef harfbuzz_shaper shaper_type; 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. */ /** 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); 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; mapnik::value_unicode_string const& text() const;
/** Processes the text into a list of glyphs, performing RTL/LTR handling, shaping and line breaking. */ /** 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. */ /** Clear all data stored in this object. The object's state is the same as directly after construction. */
void clear(); void clear();
@ -81,11 +86,29 @@ public:
// Returns the number of glyphs so memory can be preallocated. // Returns the number of glyphs so memory can be preallocated.
inline unsigned glyphs_count() const { return glyphs_count_;} 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: private:
void break_line(text_line & line, double wrap_width, unsigned text_ratio, bool wrap_before); void break_line(text_line & line, double wrap_width, unsigned text_ratio, bool wrap_before);
void shape_text(text_line & line); void shape_text(text_line & line);
void add_line(text_line & line); void add_line(text_line & line);
void clear_cluster_widths(unsigned first, unsigned last); void clear_cluster_widths(unsigned first, unsigned last);
void init_alignment();
//input //input
face_manager_freetype &font_manager_; face_manager_freetype &font_manager_;
@ -103,7 +126,60 @@ private:
//output //output
line_vector lines_; 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 #endif // TEXT_LAYOUT_HPP

View file

@ -29,6 +29,7 @@
#include <mapnik/text/placements/base.hpp> #include <mapnik/text/placements/base.hpp>
#include <mapnik/text/placements_list.hpp> #include <mapnik/text/placements_list.hpp>
#include <mapnik/text/rotation.hpp> #include <mapnik/text/rotation.hpp>
#include <mapnik/text/vertex_cache.hpp>
#include <mapnik/noncopyable.hpp> #include <mapnik/noncopyable.hpp>
namespace mapnik 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); void set_marker(marker_info_ptr m, box2d<double> box, bool marker_unlocked, pixel_position const& marker_displacement);
private: 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); bool single_line_placement(vertex_cache &pp, text_upright_e orientation);
/** Moves dx pixels but makes sure not to fall of the end. */ /** Moves dx pixels but makes sure not to fall of the end. */
void path_move_dx(vertex_cache &pp); 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. /** 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) */ 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; 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_; feature_impl const& feature_;
DetectorType &detector_; DetectorType &detector_;
box2d<double> const& extent_; box2d<double> const& extent_;
// Precalculated values for maximum performance
rotation orientation_;
text_layout layout_;
text_placement_info_ptr info_; text_placement_info_ptr info_;
layout_container layouts_;
bool valid_; 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_; double scale_factor_;
face_manager_freetype &font_manager_;
placements_list placements_; placements_list placements_;

View file

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

View file

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

View file

@ -23,8 +23,7 @@
#define SYMBOLIZER_HELPERS_HPP #define SYMBOLIZER_HELPERS_HPP
//mapnik //mapnik
#include <mapnik/text_symbolizer.hpp> #include <mapnik/symbolizer.hpp>
#include <mapnik/shield_symbolizer.hpp>
#include <mapnik/feature.hpp> #include <mapnik/feature.hpp>
#include <mapnik/marker.hpp> #include <mapnik/marker.hpp>
#include <mapnik/marker_cache.hpp> #include <mapnik/marker_cache.hpp>
@ -34,10 +33,52 @@
namespace mapnik { 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 /** Helper object that does all the TextSymbolizer placement finding
* work except actually rendering the object. */ * work except actually rendering the object. */
class text_symbolizer_helper class text_symbolizer_helper : public base_symbolizer_helper
{ {
public: public:
template <typename FaceManagerT, typename DetectorT> template <typename FaceManagerT, typename DetectorT>
@ -68,35 +109,13 @@ public:
placements_list const& get(); placements_list const& get();
protected: protected:
bool next_point_placement(); bool next_point_placement();
bool next_line_placement(); bool next_line_placement(bool clipped);
void initialize_geometries();
void initialize_points(); 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) .*/ /** Place text at points on a line instead of following the line (used for ShieldSymbolizer) .*/
bool points_on_line_; bool points_on_line_;
text_placement_info_ptr placement_;
placement_finder finder_;
//ShieldSymbolizer only //ShieldSymbolizer only
void init_marker(); void init_marker();
}; };

View file

@ -132,13 +132,41 @@ enum text_upright
DEFINE_ENUM(text_upright_e, 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; class text_layout;
/** Contains all text symbolizer properties which are not directly related to text formatting and layout. */
/** Contains all text symbolizer properties which are not directly related to text formatting. */
struct MAPNIK_DECL text_symbolizer_properties struct MAPNIK_DECL text_symbolizer_properties
{ {
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. */ /** Load all values from XML ptree. */
void from_xml(xml_node const &sym, fontset_map const & fontsets); 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!). */ /** 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; void add_expressions(expression_set &output) const;
//Per symbolizer options //Per symbolizer options
expression_ptr orientation;
pixel_position displacement;
label_placement_e label_placement; 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 */ /** distance between repeated labels on a single geometry */
double label_spacing; double label_spacing;
/** distance the label can be moved on the line to fit, if 0 the default is used */ /** 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; bool allow_overlap;
/** Only consider geometry with largest bbox (polygons) */ /** Only consider geometry with largest bbox (polygons) */
bool largest_bbox_only; bool largest_bbox_only;
double text_ratio;
double wrap_width;
bool wrap_before;
bool rotate_displacement;
text_upright_e upright; text_upright_e upright;
/** Default values for text layouts */
text_layout_properties_ptr layout_defaults;
/** Default values for char_properties. */ /** Default values for char_properties. */
char_properties_ptr format; char_properties_ptr format;
private: 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. */ /** Go back to initial state. */
void reset(); void reset();
/** position on this line closest to the target position */
double position_closest_to(pixel_position const &target_pos);
private: private:
void rewind_subpath(); 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