Merge remote-tracking branch 'origin/master'

This commit is contained in:
artemp 2012-11-29 10:36:18 +00:00
commit 85e00d6596
26 changed files with 270 additions and 234 deletions

View file

@ -8,6 +8,8 @@ For a complete change history, see the git log.
## Future
- Added serialization of `line-offset` to save_map (#1562)
- Enabled default input plugin directory and fonts path to be set inherited from environment settings in
python bindings to make it easier to run tests locally (#1594). New environment settings are:
- MAPNIK_INPUT_PLUGINS_DIRECTORY

View file

@ -29,6 +29,7 @@ namespace agg
void rewind(unsigned) {}
unsigned vertex(double*, double*) { return path_cmd_stop; }
unsigned type() const { return 0; }
};
@ -64,6 +65,7 @@ namespace agg
}
unsigned vertex(double* x, double* y);
unsigned type() const { return m_source->type(); }
private:
// Prohibit copying

View file

@ -33,6 +33,7 @@ namespace agg
void rewind(unsigned path_id);
unsigned vertex(double* x, double* y);
unsigned type() const { return m_source->type(); }
private:
conv_adaptor_vpgen(const conv_adaptor_vpgen<VertexSource, VPGen>&);

View file

@ -51,6 +51,7 @@ namespace agg
double y1() const { return base_type::vpgen().y1(); }
double x2() const { return base_type::vpgen().x2(); }
double y2() const { return base_type::vpgen().y2(); }
unsigned type() const { return base_type::type(); }
private:
conv_clip_polygon(const conv_clip_polygon<VertexSource>&);

View file

@ -51,6 +51,7 @@ namespace agg
double y1() const { return base_type::vpgen().y1(); }
double x2() const { return base_type::vpgen().x2(); }
double y2() const { return base_type::vpgen().y2(); }
unsigned type() const { return base_type::type(); }
private:
conv_clip_polyline(const conv_clip_polyline<VertexSource>&);

View file

@ -42,6 +42,7 @@ namespace agg
void smooth_value(double v) { base_type::generator().smooth_value(v); }
double smooth_value() const { return base_type::generator().smooth_value(); }
unsigned type() const { return base_type::type(); }
private:
conv_smooth_poly1(const conv_smooth_poly1<VertexSource>&);
@ -64,6 +65,7 @@ namespace agg
void smooth_value(double v) { m_smooth.generator().smooth_value(v); }
double smooth_value() const { return m_smooth.generator().smooth_value(); }
unsigned type() const { return m_smooth.type(); }
private:
conv_smooth_poly1_curve(const conv_smooth_poly1_curve<VertexSource>&);

View file

@ -6,8 +6,8 @@ Import('env')
base = './mapnik/'
subdirs = ['','svg','wkt','grid','json','util','text_placements','formatting']
#if env['SVG_RENDERER']:
# subdirs.append('svg/output')
if env['SVG_RENDERER']:
subdirs.append('svg/output')
if 'install' in COMMAND_LINE_TARGETS:
for subdir in subdirs:

View file

@ -100,6 +100,11 @@ struct MAPNIK_DECL coord_transform
geom_.rewind(pos);
}
unsigned type() const
{
return static_cast<unsigned>(geom_.type());
}
Geometry const& geom() const
{
return geom_;

View file

@ -427,7 +427,7 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
featureset_ptr features = ds->features(q);
if (features) {
// Cache all features into the memory_datasource before rendering.
memory_datasource cache;
memory_datasource cache(ds->type(),false);
feature_ptr feature, prev;
while ((feature = features->next()))
@ -458,7 +458,7 @@ void feature_style_processor<Processor>::apply_to_layer(layer const& lay, Proces
}
else if (cache_features)
{
memory_datasource cache(ds->type());
memory_datasource cache(ds->type(),false);
featureset_ptr features = ds->features(q);
if (features) {
// Cache all features into the memory_datasource before rendering.

View file

@ -91,7 +91,12 @@ struct vector_markers_rasterizer_dispatch
{
double x = 0;
double y = 0;
if (placement_method == MARKER_INTERIOR_PLACEMENT)
if (path.type() == LineString)
{
if (!label::middle_point(path, x, y))
return;
}
else if (placement_method == MARKER_INTERIOR_PLACEMENT)
{
if (!label::interior_position(path, x, y))
return;
@ -187,7 +192,12 @@ struct raster_markers_rasterizer_dispatch
{
double x = 0;
double y = 0;
if (placement_method == MARKER_INTERIOR_PLACEMENT)
if (path.type() == LineString)
{
if (!label::middle_point(path, x, y))
return;
}
else if (placement_method == MARKER_INTERIOR_PLACEMENT)
{
if (!label::interior_position(path, x, y))
return;

View file

@ -36,7 +36,7 @@ class MAPNIK_DECL memory_datasource : public datasource
{
friend class memory_featureset;
public:
memory_datasource(datasource::datasource_t type=datasource::Vector);
memory_datasource(datasource::datasource_t type=datasource::Vector, bool bbox_check=true);
virtual ~memory_datasource();
void push(feature_ptr feature);
datasource::datasource_t type() const;
@ -51,6 +51,7 @@ private:
std::vector<feature_ptr> features_;
mapnik::layer_descriptor desc_;
datasource::datasource_t type_;
bool bbox_check_;
};
}

View file

@ -34,18 +34,20 @@ namespace mapnik {
class memory_featureset : public Featureset
{
public:
memory_featureset(box2d<double> const& bbox, memory_datasource const& ds)
memory_featureset(box2d<double> const& bbox, memory_datasource const& ds, bool bbox_check = true)
: bbox_(bbox),
pos_(ds.features_.begin()),
end_(ds.features_.end()),
type_(ds.type())
type_(ds.type()),
bbox_check_(bbox_check)
{}
memory_featureset(box2d<double> const& bbox, std::vector<feature_ptr> const& features)
memory_featureset(box2d<double> const& bbox, std::vector<feature_ptr> const& features, bool bbox_check = true)
: bbox_(bbox),
pos_(features.begin()),
end_(features.end()),
type_(datasource::Vector)
type_(datasource::Vector),
bbox_check_(bbox_check)
{}
virtual ~memory_featureset() {}
@ -54,22 +56,33 @@ public:
{
while (pos_ != end_)
{
if (type_ == datasource::Raster)
if (!bbox_check_)
{
return *pos_++;
}
else
{
for (unsigned i=0; i<(*pos_)->num_geometries();++i)
if (type_ == datasource::Raster)
{
geometry_type & geom = (*pos_)->get_geometry(i);
if (bbox_.intersects(geom.envelope()))
raster_ptr const& source = (*pos_)->get_raster();
if (source && bbox_.intersects(source->ext_))
{
return *pos_++;
}
}
else
{
for (unsigned i=0; i<(*pos_)->num_geometries();++i)
{
geometry_type & geom = (*pos_)->get_geometry(i);
if (bbox_.intersects(geom.envelope()))
{
return *pos_++;
}
}
}
++pos_;
}
++pos_;
}
return feature_ptr();
}
@ -79,6 +92,7 @@ private:
std::vector<feature_ptr>::const_iterator pos_;
std::vector<feature_ptr>::const_iterator end_;
datasource::datasource_t type_;
bool bbox_check_;
};
}

View file

@ -27,6 +27,7 @@
#include <mapnik/ctrans.hpp>
#include <mapnik/color.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/util/geometry_svg_generator.hpp>
#include <mapnik/svg/output/svg_output_grammars.hpp>
#include <mapnik/svg/output/svg_output_attributes.hpp>
@ -44,11 +45,8 @@ namespace mapnik { namespace svg {
template <typename OutputIterator>
class svg_generator : private boost::noncopyable
{
typedef coord_transform<CoordTransform, geometry_type> path_type;
typedef svg::svg_root_attributes_grammar<OutputIterator> root_attributes_grammar;
typedef svg::svg_rect_attributes_grammar<OutputIterator> rect_attributes_grammar;
//typedef svg::svg_path_data_grammar<OutputIterator, path_type> path_data_grammar;
typedef svg::svg_path_attributes_grammar<OutputIterator> path_attributes_grammar;
typedef svg::svg_path_dash_array_grammar<OutputIterator> path_dash_array_grammar;
@ -60,7 +58,16 @@ namespace mapnik { namespace svg {
void generate_opening_root(root_output_attributes const& root_attributes);
void generate_closing_root();
void generate_rect(rect_output_attributes const& rect_attributes);
//void generate_path(path_type const& path, path_output_attributes const& path_attributes);
template <typename PathType>
void generate_path(PathType const& path, path_output_attributes const& path_attributes)
{
util::svg_generator<OutputIterator,PathType> svg_path_grammer;
karma::generate(output_iterator_, lit("<path ") << svg_path_grammer, path);
path_attributes_grammar attributes_grammar;
path_dash_array_grammar dash_array_grammar;
karma::generate(output_iterator_, lit(" ") << dash_array_grammar, path_attributes.stroke_dasharray());
karma::generate(output_iterator_, lit(" ") << attributes_grammar << lit("/>\n"), path_attributes);
}
private:
OutputIterator& output_iterator_;

View file

@ -87,88 +87,11 @@ BOOST_FUSION_ADAPT_STRUCT(
(std::string, svg_namespace_url_)
)
/*!
* mapnik::geometry_type is adapted to conform to the concepts
* required by Karma to be recognized as a container of
* attributes for output generation.
*/
/*
namespace boost { namespace spirit { namespace traits {
typedef mapnik::coord_transform<mapnik::CoordTransform, mapnik::geometry_type> path_type;
template <>
struct is_container<path_type const>
: mpl::true_ {};
template <>
struct container_iterator<path_type const>
{
typedef mapnik::svg::path_iterator_type type;
};
template <>
struct begin_container<path_type const>
{
static mapnik::svg::path_iterator_type
call(path_type const& path)
{
return mapnik::svg::path_iterator_type(0, path);
}
};
template <>
struct end_container<path_type const>
{
static mapnik::svg::path_iterator_type
call(path_type const& path)
{
return mapnik::svg::path_iterator_type(path);
}
};
}}}
*/
namespace mapnik { namespace svg {
using namespace boost::spirit;
using namespace boost::phoenix;
/*
template <typename OutputIterator, typename PathType>
struct svg_path_data_grammar : karma::grammar<OutputIterator, PathType&()>
{
typedef path_iterator_type::value_type vertex_type;
explicit svg_path_data_grammar(PathType const& path_type)
: svg_path_data_grammar::base_type(svg_path),
path_type_(path_type)
{
using karma::int_;
using karma::double_;
using repository::confix;
svg_path =
lit("d=")
<< confix('"', '"')[
-(path_vertex % lit(' '))];
path_vertex =
path_vertex_command
<< double_
<< lit(' ')
<< double_;
path_vertex_command = &int_(1) << lit('M') | lit('L');
}
karma::rule<OutputIterator, PathType&()> svg_path;
karma::rule<OutputIterator, vertex_type()> path_vertex;
karma::rule<OutputIterator, int()> path_vertex_command;
PathType const& path_type_;
};
*/
template <typename OutputIterator>
struct svg_path_attributes_grammar : karma::grammar<OutputIterator, mapnik::svg::path_output_attributes()>

View file

@ -25,7 +25,8 @@
// mapnik
#include <mapnik/global.hpp>
#include <mapnik/geometry.hpp>
#include <mapnik/geometry.hpp> // for container stuff
#include <mapnik/ctrans.hpp> // for container stuff
#include <mapnik/util/path_iterator.hpp>
#include <mapnik/util/container_adapter.hpp>
@ -38,35 +39,84 @@
#include <boost/spirit/include/phoenix_function.hpp>
#include <boost/spirit/home/phoenix/statement/if.hpp>
#include <boost/fusion/include/boost_tuple.hpp>
#include <boost/type_traits/remove_pointer.hpp>
//#define BOOST_SPIRIT_USE_PHOENIX_V3 1
/*!
* adapted to conform to the concepts
* required by Karma to be recognized as a container of
* attributes for output generation.
*/
namespace boost { namespace spirit { namespace traits {
// TODO - this needs to be made generic to any path type
typedef mapnik::coord_transform<mapnik::CoordTransform, mapnik::geometry_type> path_type;
template <>
struct is_container<path_type const> : mpl::true_ {} ;
template <>
struct container_iterator<path_type const>
{
typedef mapnik::util::path_iterator<path_type> type;
};
template <>
struct begin_container<path_type const>
{
static mapnik::util::path_iterator<path_type>
call (path_type const& g)
{
return mapnik::util::path_iterator<path_type>(g);
}
};
template <>
struct end_container<path_type const>
{
static mapnik::util::path_iterator<path_type>
call (path_type const& g)
{
return mapnik::util::path_iterator<path_type>();
}
};
}}}
namespace mapnik { namespace util {
namespace karma = boost::spirit::karma;
namespace phoenix = boost::phoenix;
namespace svg_detail {
template <typename Geometry>
struct get_type
{
template <typename T>
struct result { typedef int type; };
int operator() (geometry_type const& geom) const
int operator() (Geometry const& geom) const
{
return (int)geom.type();
return static_cast<int>(geom.type());
}
};
template <typename T>
struct get_first
{
template <typename T>
struct result { typedef geometry_type::value_type const type; };
typedef T geometry_type;
geometry_type::value_type const operator() (geometry_type const& geom) const
template <typename U>
struct result { typedef typename geometry_type::value_type const type; };
typename geometry_type::value_type const operator() (geometry_type const& geom) const
{
geometry_type::value_type coord;
boost::get<0>(coord) = geom.vertex(0,&boost::get<1>(coord),&boost::get<2>(coord));
typename geometry_type::value_type coord;
geom.rewind(0);
boost::get<0>(coord) = geom.vertex(&boost::get<1>(coord),&boost::get<2>(coord));
return coord;
}
};
@ -80,11 +130,14 @@ namespace mapnik { namespace util {
};
}
template <typename OutputIterator>
template <typename OutputIterator, typename Geometry>
struct svg_generator :
karma::grammar<OutputIterator, geometry_type const& ()>
karma::grammar<OutputIterator, Geometry const& ()>
{
typedef Geometry geometry_type;
typedef typename boost::remove_pointer<typename geometry_type::value_type>::type coord_type;
svg_generator()
: svg_generator::base_type(svg)
{
@ -102,22 +155,22 @@ namespace mapnik { namespace util {
;
svg_point = &uint_
<< lit("cx=\"") << coord_type
<< lit("\" cy=\"") << coord_type
<< lit("cx=\"") << coordinate
<< lit("\" cy=\"") << coordinate
<< lit('\"')
;
linestring = &uint_(mapnik::LineString)[_1 = _type(_val)]
<< svg_path
<< svg_path << lit('\"')
;
polygon = &uint_(mapnik::Polygon)[_1 = _type(_val)]
<< svg_path
<< svg_path << lit('\"')
;
svg_path %= ((&uint_(mapnik::SEG_MOVETO) << lit('M')
svg_path %= ((&uint_(mapnik::SEG_MOVETO) << lit("d=\"") << lit('M')
| &uint_(mapnik::SEG_LINETO) [_a +=1] << karma::string [if_(_a == 1) [_1 = "L" ] ])
<< lit(' ') << coord_type << lit(' ') << coord_type) % lit(' ')
<< lit(' ') << coordinate << lit(' ') << coordinate) % lit(' ')
;
@ -129,14 +182,14 @@ namespace mapnik { namespace util {
karma::rule<OutputIterator, geometry_type const& ()> linestring;
karma::rule<OutputIterator, geometry_type const& ()> polygon;
karma::rule<OutputIterator, geometry_type::value_type ()> svg_point;
karma::rule<OutputIterator, coord_type ()> svg_point;
karma::rule<OutputIterator, karma::locals<unsigned>, geometry_type const& ()> svg_path;
// phoenix functions
phoenix::function<svg_detail::get_type > _type;
phoenix::function<svg_detail::get_first> _first;
phoenix::function<svg_detail::get_type<geometry_type> > _type;
phoenix::function<svg_detail::get_first<geometry_type> > _first;
//
karma::real_generator<double, svg_detail::coordinate_policy<double> > coord_type;
karma::real_generator<double, svg_detail::coordinate_policy<double> > coordinate;
};

View file

@ -39,7 +39,7 @@ bool to_svg(std::string & svg, mapnik::geometry_type const& geom)
{
typedef std::back_insert_iterator<std::string> sink_type;
sink_type sink(svg);
svg_generator<sink_type> generator;
svg_generator<sink_type, mapnik::geometry_type> generator;
bool result = karma::generate(sink, generator, geom);
return result;
}

View file

@ -33,10 +33,6 @@
#include <boost/shared_ptr.hpp>
#include <boost/make_shared.hpp>
#include <boost/optional.hpp>
#ifdef MAPNIK_THREADSAFE
#include <boost/thread/mutex.hpp>
//using boost::mutex;
#endif
// stl
#include <string>
@ -115,9 +111,6 @@ public:
bool registerPool(const ConnectionCreator<Connection>& creator,unsigned initialSize,unsigned maxSize)
{
#ifdef MAPNIK_THREADSAFE
//mutex::scoped_lock lock(mutex_);
#endif
ContType::const_iterator itr = pools_.find(creator.id());
if (itr != pools_.end())
@ -137,9 +130,6 @@ public:
boost::shared_ptr<PoolType> getPool(std::string const& key)
{
#ifdef MAPNIK_THREADSAFE
//mutex::scoped_lock lock(mutex_);
#endif
ContType::const_iterator itr=pools_.find(key);
if (itr!=pools_.end())
{
@ -149,19 +139,6 @@ public:
return emptyPool;
}
HolderType get(std::string const& key)
{
#ifdef MAPNIK_THREADSAFE
//mutex::scoped_lock lock(mutex_);
#endif
ContType::const_iterator itr=pools_.find(key);
if (itr!=pools_.end())
{
boost::shared_ptr<PoolType> pool=itr->second;
return pool->borrowObject();
}
return HolderType();
}
ConnectionManager() {}
private:
ConnectionManager(const ConnectionManager&);

View file

@ -160,46 +160,49 @@ void postgis_datasource::bind() const
#ifdef MAPNIK_STATS
mapnik::progress_timer __stats2__(std::clog, "postgis_datasource::bind(get_srid_and_geometry_column)");
#endif
std::ostringstream s;
s << "SELECT f_geometry_column, srid FROM "
<< GEOMETRY_COLUMNS <<" WHERE f_table_name='"
<< mapnik::sql_utils::unquote_double(geometry_table_)
<< "'";
if (! schema_.empty())
try
{
s << " AND f_table_schema='"
<< mapnik::sql_utils::unquote_double(schema_)
s << "SELECT f_geometry_column, srid FROM "
<< GEOMETRY_COLUMNS <<" WHERE f_table_name='"
<< mapnik::sql_utils::unquote_double(geometry_table_)
<< "'";
}
if (! geometry_field_.empty())
{
s << " AND f_geometry_column='"
<< mapnik::sql_utils::unquote_double(geometry_field_)
<< "'";
}
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
if (rs->next())
{
geometryColumn_ = rs->getValue("f_geometry_column");
if (srid_ == 0)
if (! schema_.empty())
{
const char* srid_c = rs->getValue("srid");
if (srid_c != NULL)
s << " AND f_table_schema='"
<< mapnik::sql_utils::unquote_double(schema_)
<< "'";
}
if (! geometry_field_.empty())
{
s << " AND f_geometry_column='"
<< mapnik::sql_utils::unquote_double(geometry_field_)
<< "'";
}
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
if (rs->next())
{
geometryColumn_ = rs->getValue("f_geometry_column");
if (srid_ == 0)
{
int result = 0;
if (mapnik::util::string2int(srid_c, result))
const char* srid_c = rs->getValue("srid");
if (srid_c != NULL)
{
srid_ = result;
int result = 0;
if (mapnik::util::string2int(srid_c, result))
{
srid_ = result;
}
}
}
}
rs->close();
}
catch (mapnik::datasource_exception const& ex) {
// let this pass on query error and use the fallback below
MAPNIK_LOG_WARN(postgis) << "postgis_datasource: metadata query failed: " << ex.what();
}
rs->close();
// If we still do not know the srid then we can try to fetch
// it from the 'table_' parameter, which should work even if it is
@ -711,7 +714,7 @@ featureset_ptr postgis_datasource::features(const query& q) const
}
else
{
err_msg += "Null connection";
err_msg += " Null connection";
}
throw mapnik::datasource_exception(err_msg);
}
@ -929,50 +932,53 @@ boost::optional<mapnik::datasource::geometry_t> postgis_datasource::get_geometry
std::ostringstream s;
std::string g_type;
s << "SELECT lower(type) as type FROM "
<< GEOMETRY_COLUMNS <<" WHERE f_table_name='"
<< mapnik::sql_utils::unquote_double(geometry_table_)
<< "'";
if (! schema_.empty())
try
{
s << " AND f_table_schema='"
<< mapnik::sql_utils::unquote_double(schema_)
s << "SELECT lower(type) as type FROM "
<< GEOMETRY_COLUMNS <<" WHERE f_table_name='"
<< mapnik::sql_utils::unquote_double(geometry_table_)
<< "'";
if (! schema_.empty())
{
s << " AND f_table_schema='"
<< mapnik::sql_utils::unquote_double(schema_)
<< "'";
}
if (! geometry_field_.empty())
{
s << " AND f_geometry_column='"
<< mapnik::sql_utils::unquote_double(geometry_field_)
<< "'";
}
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
if (rs->next())
{
g_type = rs->getValue("type");
if (boost::algorithm::contains(g_type, "line"))
{
result.reset(mapnik::datasource::LineString);
return result;
}
else if (boost::algorithm::contains(g_type, "point"))
{
result.reset(mapnik::datasource::Point);
return result;
}
else if (boost::algorithm::contains(g_type, "polygon"))
{
result.reset(mapnik::datasource::Polygon);
return result;
}
else // geometry
{
result.reset(mapnik::datasource::Collection);
return result;
}
}
}
if (! geometry_field_.empty())
{
s << " AND f_geometry_column='"
<< mapnik::sql_utils::unquote_double(geometry_field_)
<< "'";
}
shared_ptr<ResultSet> rs = conn->executeQuery(s.str());
if (rs->next())
{
g_type = rs->getValue("type");
if (boost::algorithm::contains(g_type, "line"))
{
result.reset(mapnik::datasource::LineString);
return result;
}
else if (boost::algorithm::contains(g_type, "point"))
{
result.reset(mapnik::datasource::Point);
return result;
}
else if (boost::algorithm::contains(g_type, "polygon"))
{
result.reset(mapnik::datasource::Polygon);
return result;
}
else // geometry
{
result.reset(mapnik::datasource::Collection);
return result;
}
catch (mapnik::datasource_exception const& ex) {
// let this pass on query error and use the fallback below
MAPNIK_LOG_WARN(postgis) << "postgis_datasource: metadata query failed: " << ex.what();
}
// fallback to querying first several features

View file

@ -57,7 +57,7 @@ shape_featureset<filterT>::shape_featureset(filterT const& filter,
template <typename filterT>
feature_ptr shape_featureset<filterT>::next()
{
if (row_limit_ && count_ > row_limit_)
if (row_limit_ && count_ >= row_limit_)
{
return feature_ptr();
}

View file

@ -75,7 +75,7 @@ shape_index_featureset<filterT>::shape_index_featureset(filterT const& filter,
template <typename filterT>
feature_ptr shape_index_featureset<filterT>::next()
{
if (row_limit_ && count_ > row_limit_)
if (row_limit_ && count_ >= row_limit_)
{
return feature_ptr();
}

View file

@ -62,10 +62,11 @@ struct accumulate_extent
bool first_;
};
memory_datasource::memory_datasource(datasource::datasource_t type)
memory_datasource::memory_datasource(datasource::datasource_t type, bool bbox_check)
: datasource(parameters()),
desc_("in-memory datasource","utf-8"),
type_(type) {}
type_(type),
bbox_check_(bbox_check) {}
memory_datasource::~memory_datasource() {}
@ -83,7 +84,7 @@ datasource::datasource_t memory_datasource::type() const
featureset_ptr memory_datasource::features(const query& q) const
{
return boost::make_shared<memory_featureset>(q.get_bbox(),*this);
return boost::make_shared<memory_featureset>(q.get_bbox(),*this,bbox_check_);
}

View file

@ -98,6 +98,10 @@ public:
{
set_attr( sym_node, "rasterizer", sym.get_rasterizer() );
}
if ( sym.offset() != dfl.offset() || explicit_defaults_ )
{
set_attr( sym_node, "offset", sym.offset() );
}
serialize_symbolizer_base(sym_node, sym);
}

View file

@ -44,11 +44,11 @@ bool svg_renderer<OutputIterator>::process(rule::symbolizers const& syms,
// generate path output for each geometry of the current feature.
for(unsigned i=0; i<feature.num_geometries(); ++i)
{
geometry_type const& geom = feature.get_geometry(i);
if(geom.size() > 1)
geometry_type & geom = feature.get_geometry(i);
if(geom.size() > 0)
{
//path_type path(t_, geom, prj_trans);
//generator_.generate_path(path, path_attributes_);
path_type path(t_, geom, prj_trans);
generator_.generate_path(path, path_attributes_);
}
}

View file

@ -65,17 +65,5 @@ namespace mapnik { namespace svg {
karma::generate(output_iterator_, lit("<rect ") << attributes_grammar << lit("/>\n"), rect_attributes);
}
/*template <typename OutputIterator>
void svg_generator<OutputIterator>::generate_path(path_type const& path, path_output_attributes const& path_attributes)
{
path_data_grammar data_grammar(path);
path_attributes_grammar attributes_grammar;
path_dash_array_grammar dash_array_grammar;
karma::generate(output_iterator_, lit("<path ") << data_grammar, path);
karma::generate(output_iterator_, lit(" ") << dash_array_grammar, path_attributes.stroke_dasharray());
karma::generate(output_iterator_, lit(" ") << attributes_grammar << lit("/>\n"), path_attributes);
}*/
template class svg_generator<std::ostream_iterator<char> >;
}}

View file

@ -89,9 +89,13 @@ transform_type const& symbolizer_base::get_transform() const
std::string symbolizer_base::get_transform_string() const
{
if (affine_transform_)
{
return transform_processor_type::to_string(*affine_transform_);
}
else
{
return std::string();
}
}
void symbolizer_base::set_clip(bool clip)
@ -189,9 +193,13 @@ transform_type const& symbolizer_with_image::get_image_transform() const
std::string symbolizer_with_image::get_image_transform_string() const
{
if (image_transform_)
{
return transform_processor_type::to_string(*image_transform_);
}
else
{
return std::string();
}
}
} // end of namespace mapnik

View file

@ -6,6 +6,9 @@ import time
from utilities import execution_path
from subprocess import Popen, PIPE
import os, mapnik
from Queue import Queue
import threading
MAPNIK_TEST_DBNAME = 'mapnik-tmp-postgis-test-db'
POSTGIS_TEMPLATE_DBNAME = 'template_postgis'
@ -443,9 +446,36 @@ if 'postgis' in mapnik.DatasourceCache.plugin_names() \
fs = ds.featureset()
eq_(fs.next()['gid'],1)
def create_ds():
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,
table='test',
max_size=20)
fs = ds.all_features()
def test_threaded_create(NUM_THREADS=100):
for i in range(NUM_THREADS):
t = threading.Thread(target=create_ds)
t.start()
t.join()
def create_ds_and_error():
try:
ds = mapnik.PostGIS(dbname=MAPNIK_TEST_DBNAME,
table='asdfasdfasdfasdfasdf',
max_size=20)
fs = ds.all_features()
except: pass
def test_threaded_create2(NUM_THREADS=10):
for i in range(NUM_THREADS):
t = threading.Thread(target=create_ds_and_error)
t.start()
t.join()
atexit.register(postgis_takedown)
if __name__ == "__main__":
setup()
#test_auto_detection_and_subquery()
[eval(run)() for run in dir() if 'test_' in run]