diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index f56e992b6..2126cd88e 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -70,8 +70,8 @@ public: // create with external placement detector, possibly non-empty agg_renderer(Map const &m, T & pixmap, boost::shared_ptr detector, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); - // create with mapnik.request object that holds request-specific stuff - agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor=1.0); + // pass in mapnik::request object to provide the mutable things per render + agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor=1.0, unsigned offset_x=0, unsigned offset_y=0); ~agg_renderer(); void start_map_processing(Map const& map); void end_map_processing(Map const& map); diff --git a/include/mapnik/request.hpp b/include/mapnik/request.hpp index 8d95a600a..9a4b99cf0 100644 --- a/include/mapnik/request.hpp +++ b/include/mapnik/request.hpp @@ -24,7 +24,6 @@ #define MAPNIK_REQUEST_HPP // mapnik -//#include #include #include @@ -36,91 +35,24 @@ namespace mapnik class MAPNIK_DECL request { - -private: - static const unsigned MIN_MAPSIZE=16; - static const unsigned MAX_MAPSIZE=MIN_MAPSIZE<<10; - unsigned width_; - unsigned height_; - int buffer_size_; - box2d current_extent_; - boost::optional > maximum_extent_; - public: - - /*! \brief Constructor - * @param width Initial map width. - * @param height Initial map height. - * @param srs Initial map projection. - */ - request(int width, int height); - - /*! \brief Get map width. - */ + request(unsigned width, + unsigned height, + box2d const& extent); unsigned width() const; - - /*! \brief Get map height. - */ unsigned height() const; - - /*! \brief Set map width. - */ - void set_width(unsigned width); - - /*! \brief Set map height. - */ - void set_height(unsigned height); - - /*! \brief Resize the map. - */ - void resize(unsigned width,unsigned height); - - /*! \brief Set buffer size - * @param buffer_size Buffer size in pixels. - */ - void set_buffer_size(int buffer_size); - - /*! \brief Get the map buffer size - * @return Buffer size as int - */ int buffer_size() const; - - /*! \brief Set the map maximum extent. - * @param box The bounding box for the maximum extent. - */ - void set_maximum_extent(box2d const& box); - - /*! \brief Get the map maximum extent as box2d - */ - boost::optional > const& maximum_extent() const; - - void reset_maximum_extent(); - - /*! \brief Zoom the map to a bounding box. - * - * Aspect is handled automatic if not fitting to width/height. - * @param box The bounding box where to zoom. - */ - void zoom_to_box(const box2d& box); - - /*! \brief Get current bounding box. - * @return The current bounding box. - */ - const box2d& get_current_extent() const; - - /*! \brief Get current buffered bounding box. - * @return The current buffered bounding box. - */ + box2d const& extent() const; + void set_extent(box2d const& box); box2d get_buffered_extent() const; - - /*! - * @return The Map Scale. - */ double scale() const; - ~request(); private: + unsigned width_; + unsigned height_; + box2d extent_; + int buffer_size_; }; } diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index fadc509de..e538a9256 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -85,7 +85,7 @@ agg_renderer::agg_renderer(Map const& m, T & pixmap, double scale_factor, uns } template -agg_renderer::agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor) +agg_renderer::agg_renderer(Map const& m, request const& req, T & pixmap, double scale_factor, unsigned offset_x, unsigned offset_y) : feature_style_processor(m, scale_factor), pixmap_(pixmap), internal_buffer_(), @@ -94,7 +94,7 @@ agg_renderer::agg_renderer(Map const& m, request const& req, T & pixmap, doub width_(pixmap_.width()), height_(pixmap_.height()), scale_factor_(scale_factor), - t_(req.width(),req.height(),req.get_current_extent(),0.0,0.0), + t_(req.width(),req.height(),req.extent(),offset_x,offset_y), font_engine_(), font_manager_(font_engine_), detector_(boost::make_shared(box2d(-req.buffer_size(), -req.buffer_size(), req.width() + req.buffer_size() ,req.height() + req.buffer_size()))), diff --git a/src/request.cpp b/src/request.cpp index 6bef9b455..b99f533de 100644 --- a/src/request.cpp +++ b/src/request.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2013 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -26,10 +26,12 @@ namespace mapnik { - -request::request(int width,int height) +request::request(unsigned width, + unsigned height, + box2d const& extent) : width_(width), height_(height), + extent_(extent), buffer_size_(0) {} request::~request() {} @@ -44,41 +46,7 @@ unsigned request::height() const return height_; } -void request::set_width(unsigned width) -{ - if (width != width_ && - width >= MIN_MAPSIZE && - width <= MAX_MAPSIZE) - { - width_=width; - } -} - -void request::set_height(unsigned height) -{ - if (height != height_ && - height >= MIN_MAPSIZE && - height <= MAX_MAPSIZE) - { - height_=height; - } -} - -void request::resize(unsigned width,unsigned height) -{ - if (width != width_ && - height != height_ && - width >= MIN_MAPSIZE && - width <= MAX_MAPSIZE && - height >= MIN_MAPSIZE && - height <= MAX_MAPSIZE) - { - width_=width; - height_=height; - } -} - -void request::set_buffer_size( int buffer_size) +void request::set_buffer_size(int buffer_size) { buffer_size_ = buffer_size; } @@ -88,45 +56,30 @@ int request::buffer_size() const return buffer_size_; } -void request::set_maximum_extent(box2d const& box) +void request::set_extent(box2d const& box) { - maximum_extent_.reset(box); + extent_ = box; } -boost::optional > const& request::maximum_extent() const +box2d const& request::extent() const { - return maximum_extent_; -} - -void request::reset_maximum_extent() -{ - maximum_extent_.reset(); -} - -void request::zoom_to_box(const box2d &box) -{ - current_extent_=box; -} - -const box2d& request::get_current_extent() const -{ - return current_extent_; + return extent_; } box2d request::get_buffered_extent() const { double extra = 2.0 * scale() * buffer_size_; - box2d ext(current_extent_); - ext.width(current_extent_.width() + extra); - ext.height(current_extent_.height() + extra); + box2d ext(extent_); + ext.width(extent_.width() + extra); + ext.height(extent_.height() + extra); return ext; } double request::scale() const { if (width_>0) - return current_extent_.width()/width_; - return current_extent_.width(); + return extent_.width()/width_; + return extent_.width(); } } diff --git a/tests/cpp_tests/map_request_test.cpp b/tests/cpp_tests/map_request_test.cpp new file mode 100644 index 000000000..eb69d1910 --- /dev/null +++ b/tests/cpp_tests/map_request_test.cpp @@ -0,0 +1,132 @@ +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +bool compare_images(std::string const& src_fn,std::string const& dest_fn) +{ + using namespace mapnik; + std::auto_ptr reader1(mapnik::get_image_reader(dest_fn,"png")); + if (!reader1.get()) + { + throw mapnik::image_reader_exception("Failed to load: " + dest_fn); + } + boost::shared_ptr image_ptr1 = boost::make_shared(reader1->width(),reader1->height()); + reader1->read(0,0,image_ptr1->data()); + + std::auto_ptr reader2(mapnik::get_image_reader(src_fn,"png")); + if (!reader2.get()) + { + throw mapnik::image_reader_exception("Failed to load: " + src_fn); + } + boost::shared_ptr image_ptr2 = boost::make_shared(reader2->width(),reader2->height()); + reader2->read(0,0,image_ptr2->data()); + + image_data_32 const& dest = image_ptr1->data(); + image_data_32 const& src = image_ptr2->data(); + + unsigned int width = src.width(); + unsigned int height = src.height(); + if ((width != dest.width()) || height != dest.height()) return false; + for (unsigned int y = 0; y < height; ++y) + { + const unsigned int* row_from = src.getRow(y); + const unsigned int* row_to = dest.getRow(y); + for (unsigned int x = 0; x < width; ++x) + { + if (row_from[x] != row_to[x]) return false; + } + } + return true; +} + +int main( int, char*[] ) +{ + try { + mapnik::datasource_cache::instance().register_datasources("./plugins/input/"); + mapnik::freetype_engine::register_fonts("./fonts", true ); + mapnik::Map m(256,256); + mapnik::load_map(m,"./tests/data/good_maps/marker-text-line.xml",false); + m.zoom_all(); + mapnik::image_32 im(m.width(),m.height()); + double scale_factor = 1.2; + std::string expected("./tests/cpp_tests/support/map-request-marker-text-line-expected.png"); + + // render normally with apply() and just map and image + mapnik::agg_renderer renderer1(m,im,scale_factor); + renderer1.apply(); + std::string actual1("/tmp/map-request-marker-text-line-actual1.png"); + //mapnik::save_to_file(im,expected); + mapnik::save_to_file(im,actual1); + BOOST_TEST(compare_images(actual1,expected)); + + // reset image + im.clear(); + + // set up a mapnik::request object + mapnik::request req(m.width(),m.height(),m.get_current_extent()); + req.set_buffer_size(m.buffer_size()); + + // render using apply() and mapnik::request + mapnik::agg_renderer renderer2(m,req,im,scale_factor); + renderer2.apply(); + std::string actual2("/tmp/map-request-marker-text-line-actual2.png"); + mapnik::save_to_file(im,actual2); + BOOST_TEST(compare_images(actual2,expected)); + + // reset image + im.clear(); + + // render with apply_to_layer api and mapnik::request params passed to apply_to_layer + mapnik::agg_renderer renderer3(m,req,im,scale_factor); + renderer3.start_map_processing(m); + mapnik::projection map_proj(m.srs(),true); + double scale_denom = mapnik::scale_denominator(req.scale(),map_proj.is_geographic()); + scale_denom *= scale_factor; + BOOST_FOREACH ( mapnik::layer const& lyr, m.layers() ) + { + if (lyr.visible(scale_denom)) + { + std::set names; + renderer3.apply_to_layer(lyr, + renderer3, + map_proj, + req.scale(), + scale_denom, + req.width(), + req.height(), + req.extent(), + req.buffer_size(), + names); + + } + } + renderer3.end_map_processing(m); + std::string actual3("/tmp/map-request-marker-text-line-actual3.png"); + mapnik::save_to_file(im,actual3); + BOOST_TEST(compare_images(actual3,expected)); + + } catch (std::exception const& ex) { + std::clog << ex.what() << "\n"; + } + if (!::boost::detail::test_errors()) { + std::clog << "C++ Map Request rendering hook: \x1b[1;32m✓ \x1b[0m\n"; +#if BOOST_VERSION >= 104600 + ::boost::detail::report_errors_remind().called_report_errors_function = true; +#endif + } else { + return ::boost::report_errors(); + } +} diff --git a/tests/cpp_tests/support/map-request-marker-text-line-expected.png b/tests/cpp_tests/support/map-request-marker-text-line-expected.png new file mode 100644 index 000000000..2a7be3ddc Binary files /dev/null and b/tests/cpp_tests/support/map-request-marker-text-line-expected.png differ diff --git a/tests/data/good_maps/marker-text-line.xml b/tests/data/good_maps/marker-text-line.xml index 6c43cf53c..776a87341 100644 --- a/tests/data/good_maps/marker-text-line.xml +++ b/tests/data/good_maps/marker-text-line.xml @@ -1,4 +1,4 @@ - +