Compare commits
7 commits
master
...
marker-ref
Author | SHA1 | Date | |
---|---|---|---|
|
99071d1253 | ||
|
8aae463c10 | ||
|
6b33feceab | ||
|
006aadcb89 | ||
|
a50051bded | ||
|
8abda7c7ae | ||
|
3a44fecf6f |
16 changed files with 651 additions and 233 deletions
99
bindings/python/mapnik_marker_cache.cpp
Normal file
99
bindings/python/mapnik_marker_cache.cpp
Normal file
|
@ -0,0 +1,99 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* 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 <mapnik/utils.hpp>
|
||||||
|
#include <mapnik/marker.hpp>
|
||||||
|
#include <mapnik/marker_cache.hpp>
|
||||||
|
#include <mapnik/graphics.hpp>
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
#include <boost/noncopyable.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
bool add_marker_from_image(mapnik::marker_cache & cache, std::string const& uri, mapnik::image_32 const& im)
|
||||||
|
{
|
||||||
|
boost::optional<mapnik::image_ptr> imagep(boost::make_shared<mapnik::image_data_32>(im.data()));
|
||||||
|
return cache.insert_marker(uri,boost::make_shared<mapnik::marker>(imagep),true);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool add_marker_from_svg(mapnik::marker_cache & cache, std::string const& uri, mapnik::svg_storage_type const& svg)
|
||||||
|
{
|
||||||
|
mapnik::svg_path_ptr marker_path(boost::make_shared<mapnik::svg_storage_type>(svg));
|
||||||
|
return cache.insert_marker(uri,boost::make_shared<mapnik::marker>(marker_path),true);
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::python::object get_marker(boost::shared_ptr<mapnik::marker_cache> const& cache, std::string const& uri)
|
||||||
|
{
|
||||||
|
mapnik::marker_cache::iterator_type itr = cache->search(uri);
|
||||||
|
mapnik::marker_cache::iterator_type end = cache->end();
|
||||||
|
if (itr != end)
|
||||||
|
{
|
||||||
|
if (itr->second->is_bitmap())
|
||||||
|
{
|
||||||
|
mapnik::image_data_32 const& im = *itr->second->get_bitmap_data()->get();
|
||||||
|
return boost::python::object(boost::make_shared<mapnik::image_32>(im));
|
||||||
|
}
|
||||||
|
return boost::python::object(*(itr->second->get_vector_data()));
|
||||||
|
}
|
||||||
|
return boost::python::object();
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::python::list get_keys(boost::shared_ptr<mapnik::marker_cache> const& cache)
|
||||||
|
{
|
||||||
|
boost::python::list l;
|
||||||
|
mapnik::marker_cache::iterator_type itr = cache->begin();
|
||||||
|
mapnik::marker_cache::iterator_type end = cache->end();
|
||||||
|
for (;itr != end; ++itr)
|
||||||
|
{
|
||||||
|
l.append(itr->first);
|
||||||
|
}
|
||||||
|
return l;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void export_marker_cache()
|
||||||
|
{
|
||||||
|
using mapnik::marker_cache;
|
||||||
|
using mapnik::singleton;
|
||||||
|
using mapnik::CreateUsingNew;
|
||||||
|
using namespace boost::python;
|
||||||
|
class_<singleton<marker_cache,CreateUsingNew>,boost::noncopyable>("Singleton",no_init)
|
||||||
|
.def("instance",&singleton<marker_cache,CreateUsingNew>::instance,
|
||||||
|
return_value_policy<reference_existing_object>())
|
||||||
|
.staticmethod("instance")
|
||||||
|
;
|
||||||
|
|
||||||
|
class_<marker_cache,bases<singleton<marker_cache,CreateUsingNew> >,
|
||||||
|
boost::noncopyable>("MarkerCache",no_init)
|
||||||
|
.def("clear",&marker_cache::clear)
|
||||||
|
.def("remove",&marker_cache::remove)
|
||||||
|
.def("size",&marker_cache::size)
|
||||||
|
.def("put",&add_marker_from_image)
|
||||||
|
.def("put",&add_marker_from_svg)
|
||||||
|
.def("get",&get_marker)
|
||||||
|
.def("keys",&get_keys)
|
||||||
|
;
|
||||||
|
}
|
|
@ -34,6 +34,7 @@ void export_envelope();
|
||||||
void export_query();
|
void export_query();
|
||||||
void export_geometry();
|
void export_geometry();
|
||||||
void export_palette();
|
void export_palette();
|
||||||
|
void export_svg();
|
||||||
void export_image();
|
void export_image();
|
||||||
void export_image_view();
|
void export_image_view();
|
||||||
void export_gamma_method();
|
void export_gamma_method();
|
||||||
|
@ -64,6 +65,7 @@ void export_text_placement();
|
||||||
void export_shield_symbolizer();
|
void export_shield_symbolizer();
|
||||||
void export_debug_symbolizer();
|
void export_debug_symbolizer();
|
||||||
void export_font_engine();
|
void export_font_engine();
|
||||||
|
void export_marker_cache();
|
||||||
void export_projection();
|
void export_projection();
|
||||||
void export_proj_transform();
|
void export_proj_transform();
|
||||||
void export_view_transform();
|
void export_view_transform();
|
||||||
|
@ -441,6 +443,7 @@ BOOST_PYTHON_MODULE(_mapnik)
|
||||||
export_color();
|
export_color();
|
||||||
export_envelope();
|
export_envelope();
|
||||||
export_palette();
|
export_palette();
|
||||||
|
export_svg();
|
||||||
export_image();
|
export_image();
|
||||||
export_image_view();
|
export_image_view();
|
||||||
export_gamma_method();
|
export_gamma_method();
|
||||||
|
@ -466,6 +469,7 @@ BOOST_PYTHON_MODULE(_mapnik)
|
||||||
export_shield_symbolizer();
|
export_shield_symbolizer();
|
||||||
export_debug_symbolizer();
|
export_debug_symbolizer();
|
||||||
export_font_engine();
|
export_font_engine();
|
||||||
|
export_marker_cache();
|
||||||
export_projection();
|
export_projection();
|
||||||
export_proj_transform();
|
export_proj_transform();
|
||||||
export_view_transform();
|
export_view_transform();
|
||||||
|
|
62
bindings/python/mapnik_svg.cpp
Normal file
62
bindings/python/mapnik_svg.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/python.hpp>
|
||||||
|
#include <boost/python/module.hpp>
|
||||||
|
#include <boost/python/def.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/marker.hpp>
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
mapnik::svg_path_ptr open_from_file(std::string const& filename)
|
||||||
|
{
|
||||||
|
return mapnik::read_svg_marker(filename);
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::svg_path_ptr fromstring(std::string const& svg)
|
||||||
|
{
|
||||||
|
return mapnik::read_svg_marker(svg,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void export_svg()
|
||||||
|
{
|
||||||
|
using namespace boost::python;
|
||||||
|
using mapnik::svg_storage_type;
|
||||||
|
|
||||||
|
class_<svg_storage_type,boost::shared_ptr<svg_storage_type> >("SVG","This class represents an svg object.",no_init)
|
||||||
|
.def("width",&svg_storage_type::width)
|
||||||
|
.def("height",&svg_storage_type::height)
|
||||||
|
.def("extent",make_function(&svg_storage_type::bounding_box,
|
||||||
|
return_value_policy<copy_const_reference>()))
|
||||||
|
.def("open",&open_from_file)
|
||||||
|
.staticmethod("open")
|
||||||
|
.def("fromstring",&fromstring)
|
||||||
|
.staticmethod("fromstring")
|
||||||
|
;
|
||||||
|
|
||||||
|
}
|
|
@ -57,6 +57,7 @@ private:
|
||||||
public:
|
public:
|
||||||
image_32(int width,int height);
|
image_32(int width,int height);
|
||||||
image_32(image_32 const& rhs);
|
image_32(image_32 const& rhs);
|
||||||
|
explicit image_32(image_data_32 const& rhs);
|
||||||
#ifdef HAVE_CAIRO
|
#ifdef HAVE_CAIRO
|
||||||
explicit image_32(cairo_surface_ptr const& surface);
|
explicit image_32(cairo_surface_ptr const& surface);
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -62,6 +62,19 @@ struct MAPNIK_DECL image_reader : private mapnik::noncopyable
|
||||||
virtual ~image_reader() {}
|
virtual ~image_reader() {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct image_reader_guard
|
||||||
|
{
|
||||||
|
image_reader_guard(image_reader * reader)
|
||||||
|
: r_(reader) {}
|
||||||
|
|
||||||
|
~image_reader_guard()
|
||||||
|
{
|
||||||
|
if (r_) delete r_;
|
||||||
|
}
|
||||||
|
image_reader * r_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
bool register_image_reader(std::string const& type,image_reader* (*)(std::string const&));
|
bool register_image_reader(std::string const& type,image_reader* (*)(std::string const&));
|
||||||
bool register_image_reader(std::string const& type,image_reader* (*)(char const*, std::size_t));
|
bool register_image_reader(std::string const& type,image_reader* (*)(char const*, std::size_t));
|
||||||
|
|
||||||
|
|
|
@ -27,18 +27,13 @@
|
||||||
#include <mapnik/global.hpp>
|
#include <mapnik/global.hpp>
|
||||||
#include <mapnik/image_data.hpp>
|
#include <mapnik/image_data.hpp>
|
||||||
#include <mapnik/svg/svg_path_attributes.hpp>
|
#include <mapnik/svg/svg_path_attributes.hpp>
|
||||||
#include <mapnik/svg/svg_storage.hpp>
|
|
||||||
#include <mapnik/svg/svg_path_adapter.hpp>
|
#include <mapnik/svg/svg_path_adapter.hpp>
|
||||||
|
#include <mapnik/svg/svg_storage.hpp>
|
||||||
#include <mapnik/noncopyable.hpp>
|
#include <mapnik/noncopyable.hpp>
|
||||||
|
|
||||||
// agg
|
|
||||||
#include "agg_path_storage.h"
|
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
#include <boost/unordered_map.hpp>
|
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <boost/optional.hpp>
|
#include <boost/optional.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
|
||||||
|
|
||||||
// stl
|
// stl
|
||||||
#include <cassert>
|
#include <cassert>
|
||||||
|
@ -51,6 +46,14 @@ typedef agg::pod_bvector<mapnik::svg::path_attributes> attr_storage;
|
||||||
typedef mapnik::svg::svg_storage<mapnik::svg::svg_path_storage,attr_storage> svg_storage_type;
|
typedef mapnik::svg::svg_storage<mapnik::svg::svg_path_storage,attr_storage> svg_storage_type;
|
||||||
typedef boost::shared_ptr<svg_storage_type> svg_path_ptr;
|
typedef boost::shared_ptr<svg_storage_type> svg_path_ptr;
|
||||||
typedef boost::shared_ptr<image_data_32> image_ptr;
|
typedef boost::shared_ptr<image_data_32> image_ptr;
|
||||||
|
|
||||||
|
class marker;
|
||||||
|
|
||||||
|
typedef boost::shared_ptr<marker> marker_ptr;
|
||||||
|
|
||||||
|
mapnik::svg_path_ptr read_svg_marker(std::string const& uri, bool from_string=false);
|
||||||
|
mapnik::image_ptr read_bitmap_marker(std::string const& uri, bool from_string=false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A class to hold either vector or bitmap marker data. This allows these to be treated equally
|
* A class to hold either vector or bitmap marker data. This allows these to be treated equally
|
||||||
* in the image caches and most of the render paths.
|
* in the image caches and most of the render paths.
|
||||||
|
@ -58,96 +61,24 @@ typedef boost::shared_ptr<image_data_32> image_ptr;
|
||||||
class marker: private mapnik::noncopyable
|
class marker: private mapnik::noncopyable
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
marker()
|
marker();
|
||||||
{
|
marker(boost::optional<mapnik::image_ptr> const& data);
|
||||||
// create default OGC 4x4 black pixel
|
marker(boost::optional<mapnik::svg_path_ptr> const& data);
|
||||||
bitmap_data_ = boost::optional<mapnik::image_ptr>(boost::make_shared<image_data_32>(4,4));
|
marker(marker const& rhs);
|
||||||
(*bitmap_data_)->set(0xff000000);
|
box2d<double> bounding_box() const;
|
||||||
}
|
double width() const;
|
||||||
|
double height() const;
|
||||||
marker(boost::optional<mapnik::image_ptr> const& data)
|
bool is_bitmap() const;
|
||||||
: bitmap_data_(data)
|
bool is_vector() const;
|
||||||
{
|
boost::optional<mapnik::image_ptr> get_bitmap_data() const;
|
||||||
|
boost::optional<mapnik::svg_path_ptr> get_vector_data() const;
|
||||||
}
|
|
||||||
|
|
||||||
marker(boost::optional<mapnik::svg_path_ptr> const& data)
|
|
||||||
: vector_data_(data)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
marker(marker const& rhs)
|
|
||||||
: bitmap_data_(rhs.bitmap_data_),
|
|
||||||
vector_data_(rhs.vector_data_)
|
|
||||||
{}
|
|
||||||
|
|
||||||
box2d<double> bounding_box() const
|
|
||||||
{
|
|
||||||
if (is_vector())
|
|
||||||
{
|
|
||||||
return (*vector_data_)->bounding_box();
|
|
||||||
}
|
|
||||||
if (is_bitmap())
|
|
||||||
{
|
|
||||||
double width = (*bitmap_data_)->width();
|
|
||||||
double height = (*bitmap_data_)->height();
|
|
||||||
return box2d<double>(0, 0, width, height);
|
|
||||||
}
|
|
||||||
return box2d<double>();
|
|
||||||
}
|
|
||||||
|
|
||||||
inline double width() const
|
|
||||||
{
|
|
||||||
if (is_bitmap())
|
|
||||||
{
|
|
||||||
return (*bitmap_data_)->width();
|
|
||||||
}
|
|
||||||
else if (is_vector())
|
|
||||||
{
|
|
||||||
return (*vector_data_)->bounding_box().width();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
inline double height() const
|
|
||||||
{
|
|
||||||
if (is_bitmap())
|
|
||||||
{
|
|
||||||
return (*bitmap_data_)->height();
|
|
||||||
}
|
|
||||||
else if (is_vector())
|
|
||||||
{
|
|
||||||
return (*vector_data_)->bounding_box().height();
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool is_bitmap() const
|
|
||||||
{
|
|
||||||
return bitmap_data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline bool is_vector() const
|
|
||||||
{
|
|
||||||
return vector_data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<mapnik::image_ptr> get_bitmap_data() const
|
|
||||||
{
|
|
||||||
return bitmap_data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
boost::optional<mapnik::svg_path_ptr> get_vector_data() const
|
|
||||||
{
|
|
||||||
return vector_data_;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
boost::optional<mapnik::image_ptr> bitmap_data_;
|
boost::optional<mapnik::image_ptr> bitmap_data_;
|
||||||
boost::optional<mapnik::svg_path_ptr> vector_data_;
|
boost::optional<mapnik::svg_path_ptr> vector_data_;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // MAPNIK_MARKER_HPP
|
#endif // MAPNIK_MARKER_HPP
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#define MAPNIK_MARKER_CACHE_HPP
|
#define MAPNIK_MARKER_CACHE_HPP
|
||||||
|
|
||||||
// mapnik
|
// mapnik
|
||||||
|
#include <mapnik/marker.hpp>
|
||||||
#include <mapnik/utils.hpp>
|
#include <mapnik/utils.hpp>
|
||||||
#include <mapnik/config.hpp>
|
#include <mapnik/config.hpp>
|
||||||
#include <mapnik/noncopyable.hpp>
|
#include <mapnik/noncopyable.hpp>
|
||||||
|
@ -36,11 +37,6 @@
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
|
||||||
class marker;
|
|
||||||
|
|
||||||
typedef boost::shared_ptr<marker> marker_ptr;
|
|
||||||
|
|
||||||
|
|
||||||
class MAPNIK_DECL marker_cache :
|
class MAPNIK_DECL marker_cache :
|
||||||
public singleton <marker_cache, CreateUsingNew>,
|
public singleton <marker_cache, CreateUsingNew>,
|
||||||
private mapnik::noncopyable
|
private mapnik::noncopyable
|
||||||
|
@ -49,15 +45,24 @@ class MAPNIK_DECL marker_cache :
|
||||||
private:
|
private:
|
||||||
marker_cache();
|
marker_cache();
|
||||||
~marker_cache();
|
~marker_cache();
|
||||||
bool insert_marker(std::string const& key, marker_ptr path);
|
|
||||||
boost::unordered_map<std::string,marker_ptr> marker_cache_;
|
boost::unordered_map<std::string,marker_ptr> marker_cache_;
|
||||||
bool insert_svg(std::string const& name, std::string const& svg_string);
|
|
||||||
boost::unordered_map<std::string,std::string> svg_cache_;
|
|
||||||
public:
|
public:
|
||||||
|
typedef boost::unordered_map<std::string, marker_ptr>::const_iterator iterator_type;
|
||||||
|
typedef boost::unordered_map<std::string, marker_ptr>::size_type size_type;
|
||||||
|
bool insert_marker(std::string const& key, marker_ptr path, bool override=false);
|
||||||
std::string known_svg_prefix_;
|
std::string known_svg_prefix_;
|
||||||
|
std::string known_image_prefix_;
|
||||||
|
void init();
|
||||||
bool is_uri(std::string const& path);
|
bool is_uri(std::string const& path);
|
||||||
boost::optional<marker_ptr> find(std::string const& key, bool update_cache = false);
|
bool is_svg_uri(std::string const& path);
|
||||||
|
bool is_image_uri(std::string const& path);
|
||||||
|
boost::optional<marker_ptr> find(std::string const& uri, bool update_cache = false);
|
||||||
|
iterator_type search(std::string const& uri) const { return marker_cache_.find(uri); }
|
||||||
void clear();
|
void clear();
|
||||||
|
bool remove(std::string const& uri);
|
||||||
|
size_type size() const { return marker_cache_.size(); }
|
||||||
|
iterator_type begin() const { return marker_cache_.begin(); }
|
||||||
|
iterator_type end() const { return marker_cache_.end(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,9 +24,7 @@
|
||||||
#define MAPNIK_SVG_PARSER_HPP
|
#define MAPNIK_SVG_PARSER_HPP
|
||||||
|
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/svg/svg_path_attributes.hpp>
|
|
||||||
#include <mapnik/svg/svg_converter.hpp>
|
#include <mapnik/svg/svg_converter.hpp>
|
||||||
#include <mapnik/svg/svg_path_adapter.hpp>
|
|
||||||
#include <mapnik/gradient.hpp>
|
#include <mapnik/gradient.hpp>
|
||||||
#include <mapnik/noncopyable.hpp>
|
#include <mapnik/noncopyable.hpp>
|
||||||
|
|
||||||
|
|
|
@ -25,19 +25,28 @@
|
||||||
|
|
||||||
// mapnik
|
// mapnik
|
||||||
#include <mapnik/box2d.hpp>
|
#include <mapnik/box2d.hpp>
|
||||||
#include <mapnik/noncopyable.hpp>
|
|
||||||
|
|
||||||
namespace mapnik {
|
namespace mapnik {
|
||||||
namespace svg {
|
namespace svg {
|
||||||
|
|
||||||
template <typename VertexSource ,typename AttributeSource>
|
template <typename VertexSource,typename AttributeSource>
|
||||||
class svg_storage : mapnik::noncopyable
|
class svg_storage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
svg_storage() :
|
svg_storage() :
|
||||||
|
source_(),
|
||||||
|
attributes_(),
|
||||||
|
bounding_box_(),
|
||||||
svg_width_(0),
|
svg_width_(0),
|
||||||
svg_height_(0) {}
|
svg_height_(0) {}
|
||||||
|
|
||||||
|
svg_storage(svg_storage const& rhs)
|
||||||
|
: source_(rhs.source_),
|
||||||
|
attributes_(rhs.attributes_),
|
||||||
|
bounding_box_(rhs.bounding_box_),
|
||||||
|
svg_width_(rhs.svg_width_),
|
||||||
|
svg_height_(rhs.svg_height_) {}
|
||||||
|
|
||||||
VertexSource & source() // FIXME!! make const
|
VertexSource & source() // FIXME!! make const
|
||||||
{
|
{
|
||||||
return source_;
|
return source_;
|
||||||
|
|
|
@ -109,6 +109,7 @@ else: # unix, non-macos
|
||||||
|
|
||||||
source = Split(
|
source = Split(
|
||||||
"""
|
"""
|
||||||
|
marker.cpp
|
||||||
debug_symbolizer.cpp
|
debug_symbolizer.cpp
|
||||||
request.cpp
|
request.cpp
|
||||||
well_known_srs.cpp
|
well_known_srs.cpp
|
||||||
|
|
|
@ -53,6 +53,12 @@ image_32::image_32(const image_32& rhs)
|
||||||
data_(rhs.data_),
|
data_(rhs.data_),
|
||||||
painted_(rhs.painted_) {}
|
painted_(rhs.painted_) {}
|
||||||
|
|
||||||
|
image_32::image_32(const image_data_32& rhs)
|
||||||
|
:width_(rhs.width()),
|
||||||
|
height_(rhs.height()),
|
||||||
|
data_(rhs),
|
||||||
|
painted_(false) {}
|
||||||
|
|
||||||
#ifdef HAVE_CAIRO
|
#ifdef HAVE_CAIRO
|
||||||
image_32::image_32(cairo_surface_ptr const& surface)
|
image_32::image_32(cairo_surface_ptr const& surface)
|
||||||
:width_(cairo_image_surface_get_width(&*surface)),
|
:width_(cairo_image_surface_get_width(&*surface)),
|
||||||
|
|
168
src/marker.cpp
Normal file
168
src/marker.cpp
Normal file
|
@ -0,0 +1,168 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* 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
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/marker.hpp>
|
||||||
|
#include <mapnik/svg/svg_converter.hpp>
|
||||||
|
#include <mapnik/svg/svg_path_adapter.hpp>
|
||||||
|
#include <mapnik/svg/svg_parser.hpp>
|
||||||
|
#include <mapnik/image_util.hpp>
|
||||||
|
#include <mapnik/image_reader.hpp>
|
||||||
|
|
||||||
|
// agg
|
||||||
|
#include "agg_rendering_buffer.h"
|
||||||
|
#include "agg_pixfmt_rgba.h"
|
||||||
|
|
||||||
|
// boost
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
|
namespace mapnik
|
||||||
|
{
|
||||||
|
|
||||||
|
mapnik::svg_path_ptr read_svg_marker(std::string const& uri, bool from_string)
|
||||||
|
{
|
||||||
|
using namespace mapnik::svg;
|
||||||
|
svg_path_ptr marker_path(boost::make_shared<svg_storage_type>());
|
||||||
|
vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
|
||||||
|
svg_path_adapter svg_path(stl_storage);
|
||||||
|
svg_converter_type svg(svg_path, marker_path->attributes());
|
||||||
|
svg_parser p(svg);
|
||||||
|
if (from_string)
|
||||||
|
{
|
||||||
|
p.parse_from_string(uri);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
p.parse(uri);
|
||||||
|
}
|
||||||
|
double lox,loy,hix,hiy;
|
||||||
|
svg.bounding_rect(&lox, &loy, &hix, &hiy);
|
||||||
|
marker_path->set_bounding_box(lox,loy,hix,hiy);
|
||||||
|
marker_path->set_dimensions(svg.width(),svg.height());
|
||||||
|
return marker_path;
|
||||||
|
}
|
||||||
|
|
||||||
|
mapnik::image_ptr read_bitmap_marker(std::string const& uri, bool from_string)
|
||||||
|
{
|
||||||
|
mapnik::image_reader * reader = NULL;
|
||||||
|
mapnik::image_reader_guard guard(reader);
|
||||||
|
if (from_string)
|
||||||
|
{
|
||||||
|
reader = mapnik::get_image_reader(uri.data(),uri.size());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
reader = mapnik::get_image_reader(uri);
|
||||||
|
}
|
||||||
|
if (!reader) throw std::runtime_error("could not intialize reader for: '" + uri + "'");
|
||||||
|
unsigned width = reader->width();
|
||||||
|
unsigned height = reader->height();
|
||||||
|
BOOST_ASSERT(width > 0 && height > 0);
|
||||||
|
mapnik::image_ptr image(boost::make_shared<mapnik::image_data_32>(width,height));
|
||||||
|
reader->read(0,0,*image);
|
||||||
|
if (!reader->premultiplied_alpha())
|
||||||
|
{
|
||||||
|
agg::rendering_buffer buffer(image->getBytes(),image->width(),image->height(),image->width() * 4);
|
||||||
|
agg::pixfmt_rgba32 pixf(buffer);
|
||||||
|
pixf.premultiply();
|
||||||
|
}
|
||||||
|
return image;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
marker::marker()
|
||||||
|
{
|
||||||
|
// create default OGC 4x4 black pixel
|
||||||
|
bitmap_data_ = boost::optional<mapnik::image_ptr>(boost::make_shared<image_data_32>(4,4));
|
||||||
|
(*bitmap_data_)->set(0xff000000);
|
||||||
|
}
|
||||||
|
|
||||||
|
marker::marker(boost::optional<mapnik::image_ptr> const& data)
|
||||||
|
: bitmap_data_(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
marker::marker(boost::optional<mapnik::svg_path_ptr> const& data)
|
||||||
|
: vector_data_(data)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
marker::marker(marker const& rhs)
|
||||||
|
: bitmap_data_(rhs.bitmap_data_),
|
||||||
|
vector_data_(rhs.vector_data_)
|
||||||
|
{}
|
||||||
|
|
||||||
|
box2d<double> marker::bounding_box() const
|
||||||
|
{
|
||||||
|
if (is_vector())
|
||||||
|
{
|
||||||
|
return (*vector_data_)->bounding_box();
|
||||||
|
}
|
||||||
|
if (is_bitmap())
|
||||||
|
{
|
||||||
|
double width = (*bitmap_data_)->width();
|
||||||
|
double height = (*bitmap_data_)->height();
|
||||||
|
return box2d<double>(0, 0, width, height);
|
||||||
|
}
|
||||||
|
return box2d<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
double marker::width() const
|
||||||
|
{
|
||||||
|
if (is_bitmap())
|
||||||
|
return (*bitmap_data_)->width();
|
||||||
|
else if (is_vector())
|
||||||
|
return (*vector_data_)->bounding_box().width();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
double marker::height() const
|
||||||
|
{
|
||||||
|
if (is_bitmap())
|
||||||
|
return (*bitmap_data_)->height();
|
||||||
|
else if (is_vector())
|
||||||
|
return (*vector_data_)->bounding_box().height();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool marker::is_bitmap() const
|
||||||
|
{
|
||||||
|
return bitmap_data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool marker::is_vector() const
|
||||||
|
{
|
||||||
|
return vector_data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<mapnik::image_ptr> marker::get_bitmap_data() const
|
||||||
|
{
|
||||||
|
return bitmap_data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::optional<mapnik::svg_path_ptr> marker::get_vector_data() const
|
||||||
|
{
|
||||||
|
return vector_data_;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -24,13 +24,7 @@
|
||||||
#include <mapnik/debug.hpp>
|
#include <mapnik/debug.hpp>
|
||||||
#include <mapnik/marker.hpp>
|
#include <mapnik/marker.hpp>
|
||||||
#include <mapnik/marker_cache.hpp>
|
#include <mapnik/marker_cache.hpp>
|
||||||
#include <mapnik/svg/svg_parser.hpp>
|
|
||||||
#include <mapnik/svg/svg_storage.hpp>
|
|
||||||
#include <mapnik/svg/svg_converter.hpp>
|
|
||||||
#include <mapnik/svg/svg_path_adapter.hpp>
|
|
||||||
#include <mapnik/svg/svg_path_attributes.hpp>
|
|
||||||
#include <mapnik/image_util.hpp>
|
#include <mapnik/image_util.hpp>
|
||||||
#include <mapnik/image_reader.hpp>
|
|
||||||
|
|
||||||
// boost
|
// boost
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
@ -38,36 +32,39 @@
|
||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/make_shared.hpp>
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
// agg
|
|
||||||
#include "agg_rendering_buffer.h"
|
|
||||||
#include "agg_pixfmt_rgba.h"
|
|
||||||
|
|
||||||
namespace mapnik
|
namespace mapnik
|
||||||
{
|
{
|
||||||
|
|
||||||
marker_cache::marker_cache()
|
marker_cache::marker_cache()
|
||||||
: known_svg_prefix_("shape://")
|
: known_svg_prefix_("shape://"),
|
||||||
|
known_image_prefix_("image://")
|
||||||
{
|
{
|
||||||
insert_svg("ellipse",
|
init();
|
||||||
"<?xml version='1.0' standalone='no'?>"
|
|
||||||
"<svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>"
|
|
||||||
"<ellipse rx='5' ry='5' fill='#0000FF' stroke='black' stroke-width='.5'/>"
|
|
||||||
"</svg>");
|
|
||||||
insert_svg("arrow",
|
|
||||||
"<?xml version='1.0' standalone='no'?>"
|
|
||||||
"<svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>"
|
|
||||||
"<path fill='#0000FF' stroke='black' stroke-width='.5' d='m 31.698405,7.5302648 -8.910967,-6.0263712 0.594993,4.8210971 -18.9822542,0 0,2.4105482 18.9822542,0 -0.594993,4.8210971 z'/>"
|
|
||||||
"</svg>");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
marker_cache::~marker_cache() {}
|
marker_cache::~marker_cache() {}
|
||||||
|
|
||||||
|
void marker_cache::init()
|
||||||
|
{
|
||||||
|
std::string ellipse =
|
||||||
|
"<?xml version='1.0' standalone='no'?>"
|
||||||
|
"<svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>"
|
||||||
|
"<ellipse rx='5' ry='5' fill='#0000FF' stroke='black' stroke-width='.5'/>"
|
||||||
|
"</svg>";
|
||||||
|
marker_cache_.insert(std::make_pair("shape://ellipse",boost::make_shared<marker>(read_svg_marker(ellipse,true))));
|
||||||
|
std::string arrow =
|
||||||
|
"<?xml version='1.0' standalone='no'?>"
|
||||||
|
"<svg width='100%' height='100%' version='1.1' xmlns='http://www.w3.org/2000/svg'>"
|
||||||
|
"<path fill='#0000FF' stroke='black' stroke-width='.5' d='m 31.698405,7.5302648 -8.910967,-6.0263712 0.594993,4.8210971 -18.9822542,0 0,2.4105482 18.9822542,0 -0.594993,4.8210971 z'/>"
|
||||||
|
"</svg>";
|
||||||
|
marker_cache_.insert(std::make_pair("shape://arrow",boost::make_shared<marker>(read_svg_marker(arrow,true))));
|
||||||
|
}
|
||||||
|
|
||||||
void marker_cache::clear()
|
void marker_cache::clear()
|
||||||
{
|
{
|
||||||
#ifdef MAPNIK_THREADSAFE
|
#ifdef MAPNIK_THREADSAFE
|
||||||
mutex::scoped_lock lock(mutex_);
|
mutex::scoped_lock lock(mutex_);
|
||||||
#endif
|
#endif
|
||||||
typedef boost::unordered_map<std::string, marker_ptr>::const_iterator iterator_type;
|
|
||||||
iterator_type itr = marker_cache_.begin();
|
iterator_type itr = marker_cache_.begin();
|
||||||
while(itr != marker_cache_.end())
|
while(itr != marker_cache_.end())
|
||||||
{
|
{
|
||||||
|
@ -82,147 +79,103 @@ void marker_cache::clear()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool marker_cache::is_uri(std::string const& path)
|
bool marker_cache::remove(std::string const& uri)
|
||||||
{
|
|
||||||
return boost::algorithm::starts_with(path,known_svg_prefix_);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool marker_cache::insert_svg(std::string const& name, std::string const& svg_string)
|
|
||||||
{
|
|
||||||
std::string key = known_svg_prefix_ + name;
|
|
||||||
typedef boost::unordered_map<std::string, std::string>::const_iterator iterator_type;
|
|
||||||
iterator_type itr = svg_cache_.find(key);
|
|
||||||
if (itr == svg_cache_.end())
|
|
||||||
{
|
|
||||||
return svg_cache_.insert(std::make_pair(key,svg_string)).second;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool marker_cache::insert_marker(std::string const& uri, marker_ptr path)
|
|
||||||
{
|
{
|
||||||
#ifdef MAPNIK_THREADSAFE
|
#ifdef MAPNIK_THREADSAFE
|
||||||
mutex::scoped_lock lock(mutex_);
|
mutex::scoped_lock lock(mutex_);
|
||||||
#endif
|
#endif
|
||||||
|
iterator_type itr = marker_cache_.find(uri);
|
||||||
|
if (itr != marker_cache_.end())
|
||||||
|
{
|
||||||
|
marker_cache_.erase(itr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool marker_cache::is_uri(std::string const& uri)
|
||||||
|
{
|
||||||
|
return is_svg_uri(uri) || is_image_uri(uri);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool marker_cache::is_svg_uri(std::string const& uri)
|
||||||
|
{
|
||||||
|
return boost::algorithm::starts_with(uri,known_svg_prefix_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool marker_cache::is_image_uri(std::string const& uri)
|
||||||
|
{
|
||||||
|
return boost::algorithm::starts_with(uri,known_image_prefix_);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool marker_cache::insert_marker(std::string const& uri, marker_ptr path, bool override)
|
||||||
|
{
|
||||||
|
#ifdef MAPNIK_THREADSAFE
|
||||||
|
mutex::scoped_lock lock(mutex_);
|
||||||
|
#endif
|
||||||
|
if (!override)
|
||||||
|
{
|
||||||
return marker_cache_.insert(std::make_pair(uri,path)).second;
|
return marker_cache_.insert(std::make_pair(uri,path)).second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
typedef boost::unordered_map<std::string, marker_ptr>::iterator non_const_iterator_type;
|
||||||
|
std::pair<non_const_iterator_type,bool> result = marker_cache_.insert(std::make_pair(uri,path));
|
||||||
|
if (!result.second)
|
||||||
|
{
|
||||||
|
result.first->second = path;
|
||||||
|
}
|
||||||
|
return result.second;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
boost::optional<marker_ptr> marker_cache::find(std::string const& uri,
|
boost::optional<marker_ptr> marker_cache::find(std::string const& uri,
|
||||||
bool update_cache)
|
bool update_cache)
|
||||||
{
|
{
|
||||||
|
|
||||||
boost::optional<marker_ptr> result;
|
boost::optional<marker_ptr> result;
|
||||||
if (uri.empty())
|
if (uri.empty())
|
||||||
{
|
{
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef MAPNIK_THREADSAFE
|
#ifdef MAPNIK_THREADSAFE
|
||||||
mutex::scoped_lock lock(mutex_);
|
mutex::scoped_lock lock(mutex_);
|
||||||
#endif
|
#endif
|
||||||
typedef boost::unordered_map<std::string, marker_ptr>::const_iterator iterator_type;
|
|
||||||
iterator_type itr = marker_cache_.find(uri);
|
iterator_type itr = marker_cache_.find(uri);
|
||||||
if (itr != marker_cache_.end())
|
if (itr != marker_cache_.end())
|
||||||
{
|
{
|
||||||
result.reset(itr->second);
|
result.reset(itr->second);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// if uri references a built-in marker
|
if (boost::filesystem::exists(boost::filesystem::path(uri)))
|
||||||
if (is_uri(uri))
|
|
||||||
{
|
{
|
||||||
boost::unordered_map<std::string, std::string>::const_iterator mark_itr = svg_cache_.find(uri);
|
|
||||||
if (mark_itr == svg_cache_.end())
|
|
||||||
{
|
|
||||||
MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
std::string known_svg_string = mark_itr->second;
|
|
||||||
using namespace mapnik::svg;
|
|
||||||
svg_path_ptr marker_path(boost::make_shared<svg_storage_type>());
|
|
||||||
vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
|
|
||||||
svg_path_adapter svg_path(stl_storage);
|
|
||||||
svg_converter_type svg(svg_path, marker_path->attributes());
|
|
||||||
svg_parser p(svg);
|
|
||||||
p.parse_from_string(known_svg_string);
|
|
||||||
//svg.arrange_orientations();
|
|
||||||
double lox,loy,hix,hiy;
|
|
||||||
svg.bounding_rect(&lox, &loy, &hix, &hiy);
|
|
||||||
marker_path->set_bounding_box(lox,loy,hix,hiy);
|
|
||||||
marker_path->set_dimensions(svg.width(),svg.height());
|
|
||||||
marker_ptr mark(boost::make_shared<marker>(marker_path));
|
|
||||||
result.reset(mark);
|
|
||||||
if (update_cache)
|
|
||||||
{
|
|
||||||
marker_cache_.insert(std::make_pair(uri,*result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// otherwise assume file-based
|
|
||||||
else
|
|
||||||
{
|
|
||||||
boost::filesystem::path path(uri);
|
|
||||||
if (!exists(path))
|
|
||||||
{
|
|
||||||
MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri;
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
if (is_svg(uri))
|
if (is_svg(uri))
|
||||||
{
|
{
|
||||||
using namespace mapnik::svg;
|
result.reset(boost::make_shared<marker>(read_svg_marker(uri)));
|
||||||
svg_path_ptr marker_path(boost::make_shared<svg_storage_type>());
|
}
|
||||||
vertex_stl_adapter<svg_path_storage> stl_storage(marker_path->source());
|
else
|
||||||
svg_path_adapter svg_path(stl_storage);
|
{
|
||||||
svg_converter_type svg(svg_path, marker_path->attributes());
|
result.reset(boost::make_shared<marker>(read_bitmap_marker(uri)));
|
||||||
svg_parser p(svg);
|
}
|
||||||
p.parse(uri);
|
}
|
||||||
//svg.arrange_orientations();
|
if (result)
|
||||||
double lox,loy,hix,hiy;
|
{
|
||||||
svg.bounding_rect(&lox, &loy, &hix, &hiy);
|
|
||||||
marker_path->set_bounding_box(lox,loy,hix,hiy);
|
|
||||||
marker_path->set_dimensions(svg.width(),svg.height());
|
|
||||||
marker_ptr mark(boost::make_shared<marker>(marker_path));
|
|
||||||
result.reset(mark);
|
|
||||||
if (update_cache)
|
if (update_cache)
|
||||||
{
|
{
|
||||||
marker_cache_.insert(std::make_pair(uri,*result));
|
marker_cache_.insert(std::make_pair(uri,*result));
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// TODO - support reading images from string
|
MAPNIK_LOG_ERROR(marker_cache) << "Marker does not exist: " << uri;
|
||||||
std::auto_ptr<mapnik::image_reader> reader(mapnik::get_image_reader(uri));
|
return result;
|
||||||
if (reader.get())
|
|
||||||
{
|
|
||||||
unsigned width = reader->width();
|
|
||||||
unsigned height = reader->height();
|
|
||||||
BOOST_ASSERT(width > 0 && height > 0);
|
|
||||||
mapnik::image_ptr image(boost::make_shared<mapnik::image_data_32>(width,height));
|
|
||||||
reader->read(0,0,*image);
|
|
||||||
if (!reader->premultiplied_alpha())
|
|
||||||
{
|
|
||||||
agg::rendering_buffer buffer(image->getBytes(),image->width(),image->height(),image->width() * 4);
|
|
||||||
agg::pixfmt_rgba32 pixf(buffer);
|
|
||||||
pixf.premultiply();
|
|
||||||
}
|
|
||||||
marker_ptr mark(boost::make_shared<marker>(image));
|
|
||||||
result.reset(mark);
|
|
||||||
if (update_cache)
|
|
||||||
{
|
|
||||||
marker_cache_.insert(std::make_pair(uri,*result));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
MAPNIK_LOG_ERROR(marker_cache) << "could not intialize reader for: '" << uri << "'";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (std::exception const& ex)
|
catch (std::exception const& ex)
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_ERROR(marker_cache) << "Exception caught while loading: '" << uri << "' (" << ex.what() << ")";
|
MAPNIK_LOG_ERROR(marker_cache) << ex.what();
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1060,11 +1060,11 @@ void svg_parser::parse(std::string const& filename)
|
||||||
xmlTextReaderPtr reader = xmlNewTextReaderFilename(filename.c_str());
|
xmlTextReaderPtr reader = xmlNewTextReaderFilename(filename.c_str());
|
||||||
if (reader == NULL)
|
if (reader == NULL)
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_ERROR(svg_parser) << "Unable to open '" << filename << "'";
|
throw std::runtime_error("Unable to open '" + filename + "'");
|
||||||
}
|
}
|
||||||
else if (!parse_reader(*this,reader))
|
else if (!parse_reader(*this,reader))
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_ERROR(svg_parser) << "Unable to parse '" << filename << "'";
|
throw std::runtime_error("Unable to parse '" + filename + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1074,11 +1074,11 @@ void svg_parser::parse_from_string(std::string const& svg)
|
||||||
(XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING));
|
(XML_PARSE_NOBLANKS | XML_PARSE_NOCDATA | XML_PARSE_NOERROR | XML_PARSE_NOWARNING));
|
||||||
if (reader == NULL)
|
if (reader == NULL)
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_ERROR(svg_parser) << "Unable to parse '" << svg << "'";
|
throw std::runtime_error("Unable to parse '" + svg + "'");
|
||||||
}
|
}
|
||||||
else if (!parse_reader(*this,reader))
|
else if (!parse_reader(*this,reader))
|
||||||
{
|
{
|
||||||
MAPNIK_LOG_ERROR(svg_parser) << "Unable to parse '" << svg << "'";
|
throw std::runtime_error("Unable to parse '" + svg + "'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
125
tests/python_tests/marker_cache_test.py
Normal file
125
tests/python_tests/marker_cache_test.py
Normal file
|
@ -0,0 +1,125 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
from utilities import execution_path
|
||||||
|
from nose.tools import *
|
||||||
|
import mapnik
|
||||||
|
import threading
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
# All of the paths used are relative, if we run the tests
|
||||||
|
# from another directory we need to chdir()
|
||||||
|
os.chdir(execution_path('.'))
|
||||||
|
|
||||||
|
def test_svg_put_to_marker_cache():
|
||||||
|
cache = mapnik.MarkerCache.instance()
|
||||||
|
cache.clear()
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
svg_file = '../data/svg/octocat.svg'
|
||||||
|
svg = mapnik.SVG.open(svg_file)
|
||||||
|
cache.put(svg_file,svg)
|
||||||
|
eq_(cache.size(),3)
|
||||||
|
eq_(svg_file in cache.keys(),True)
|
||||||
|
|
||||||
|
def test_svg_put_and_clear_marker_cache():
|
||||||
|
cache = mapnik.MarkerCache.instance()
|
||||||
|
cache.clear()
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
svg_file = '../data/svg/octocat.svg'
|
||||||
|
svg = mapnik.SVG.open(svg_file)
|
||||||
|
cache.put(svg_file,svg)
|
||||||
|
eq_(cache.size(),3)
|
||||||
|
eq_(svg_file in cache.keys(),True)
|
||||||
|
cache.clear()
|
||||||
|
eq_(svg_file in cache.keys(),False)
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
|
||||||
|
def test_svg_put_and_remove_marker_cache():
|
||||||
|
cache = mapnik.MarkerCache.instance()
|
||||||
|
cache.clear()
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
svg_file = '../data/svg/octocat.svg'
|
||||||
|
svg = mapnik.SVG.open(svg_file)
|
||||||
|
cache.put(svg_file,svg)
|
||||||
|
eq_(cache.size(),3)
|
||||||
|
eq_(svg_file in cache.keys(),True)
|
||||||
|
cache.remove(svg_file)
|
||||||
|
eq_(svg_file in cache.keys(),False)
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
|
||||||
|
def test_image_put_and_clear_marker_cache():
|
||||||
|
cache = mapnik.MarkerCache.instance()
|
||||||
|
cache.clear()
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
image_file = '../data/images/marker.png'
|
||||||
|
image = mapnik.Image.open(image_file)
|
||||||
|
cache.put(image_file,image)
|
||||||
|
eq_(cache.size(),3)
|
||||||
|
eq_(image_file in cache.keys(),True)
|
||||||
|
cache.clear()
|
||||||
|
eq_(image_file in cache.keys(),False)
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
|
||||||
|
def test_image_put_and_clear_marker_cache():
|
||||||
|
cache = mapnik.MarkerCache.instance()
|
||||||
|
cache.clear()
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
image_file = '../data/images/marker.png'
|
||||||
|
image = mapnik.Image.open(image_file)
|
||||||
|
cache.put(image_file,image)
|
||||||
|
eq_(cache.size(),3)
|
||||||
|
eq_(image_file in cache.keys(),True)
|
||||||
|
eq_(cache.remove(image_file),True)
|
||||||
|
# removing twice should return False for no successful removal
|
||||||
|
eq_(cache.remove(image_file),False)
|
||||||
|
eq_(image_file in cache.keys(),False)
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
|
||||||
|
def test_image_put_and_get_image_in_marker_cache():
|
||||||
|
cache = mapnik.MarkerCache.instance()
|
||||||
|
cache.clear()
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
image_file = '../data/images/marker.png'
|
||||||
|
image = mapnik.Image.open(image_file)
|
||||||
|
cache.put(image_file,image)
|
||||||
|
new_im = cache.get(image_file)
|
||||||
|
eq_(image.tostring(),new_im.tostring())
|
||||||
|
|
||||||
|
def test_image_put_and_get_svg_in_marker_cache():
|
||||||
|
cache = mapnik.MarkerCache.instance()
|
||||||
|
cache.clear()
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
image_file = '../data/svg/rect.svg'
|
||||||
|
image = mapnik.SVG.open(image_file)
|
||||||
|
cache.put(image_file,image)
|
||||||
|
new_im = cache.get(image_file)
|
||||||
|
eq_(image.width(),new_im.width())
|
||||||
|
|
||||||
|
def test_marker_cache_override():
|
||||||
|
cache = mapnik.MarkerCache.instance()
|
||||||
|
cache.clear()
|
||||||
|
eq_(cache.size(),2)
|
||||||
|
image_file = '../data/images/marker.png'
|
||||||
|
image = mapnik.Image.open(image_file)
|
||||||
|
cache.put(image_file,image)
|
||||||
|
alt_im = mapnik.Image(4,4)
|
||||||
|
result = cache.put(image_file,alt_im)
|
||||||
|
# putting a item for which a key already exists should return False
|
||||||
|
eq_(result,False)
|
||||||
|
alt_im_copy = cache.get(image_file)
|
||||||
|
eq_(alt_im.tostring(),alt_im_copy.tostring())
|
||||||
|
|
||||||
|
|
||||||
|
def test_threaded_reads_and_writes():
|
||||||
|
threads = []
|
||||||
|
for i in range(100):
|
||||||
|
t = threading.Thread(target=test_image_put_and_clear_marker_cache)
|
||||||
|
t.start()
|
||||||
|
threads.append(t)
|
||||||
|
for t in threads:
|
||||||
|
t.join()
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
setup()
|
||||||
|
[eval(run)() for run in dir() if 'test_' in run]
|
43
tests/python_tests/svg_test.py
Normal file
43
tests/python_tests/svg_test.py
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#!/usr/bin/env python
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
|
||||||
|
import os
|
||||||
|
from utilities import execution_path
|
||||||
|
from nose.tools import *
|
||||||
|
import mapnik
|
||||||
|
import threading
|
||||||
|
|
||||||
|
def setup():
|
||||||
|
# All of the paths used are relative, if we run the tests
|
||||||
|
# from another directory we need to chdir()
|
||||||
|
os.chdir(execution_path('.'))
|
||||||
|
|
||||||
|
def test_svg_loading_from_file():
|
||||||
|
svg_file = '../data/svg/octocat.svg'
|
||||||
|
svg = mapnik.SVG.open(svg_file)
|
||||||
|
# TODO - invalid numbers
|
||||||
|
eq_(svg.width(),0)
|
||||||
|
eq_(svg.height(),0)
|
||||||
|
expected = mapnik.Box2d(0.00700000000001,-4.339,378.46,332.606)
|
||||||
|
actual = svg.extent()
|
||||||
|
assert_almost_equal(expected.minx,actual.minx, places=7)
|
||||||
|
assert_almost_equal(expected.miny,actual.miny, places=7)
|
||||||
|
assert_almost_equal(expected.maxx,actual.maxx, places=7)
|
||||||
|
assert_almost_equal(expected.maxy,actual.maxy, places=7)
|
||||||
|
|
||||||
|
def test_svg_loading_from_string():
|
||||||
|
svg_file = '../data/svg/octocat.svg'
|
||||||
|
svg = mapnik.SVG.fromstring(open(svg_file,'rb').read())
|
||||||
|
# TODO - invalid numbers
|
||||||
|
eq_(svg.width(),0)
|
||||||
|
eq_(svg.height(),0)
|
||||||
|
expected = mapnik.Box2d(0.00700000000001,-4.339,378.46,332.606)
|
||||||
|
actual = svg.extent()
|
||||||
|
assert_almost_equal(expected.minx,actual.minx, places=7)
|
||||||
|
assert_almost_equal(expected.miny,actual.miny, places=7)
|
||||||
|
assert_almost_equal(expected.maxx,actual.maxx, places=7)
|
||||||
|
assert_almost_equal(expected.maxy,actual.maxy, places=7)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
setup()
|
||||||
|
[eval(run)() for run in dir() if 'test_' in run]
|
Loading…
Reference in a new issue