From a7b8ca28882dc6de2680fa6ac7ea0cbc85ad25f8 Mon Sep 17 00:00:00 2001 From: Blake Thompson Date: Fri, 16 Jan 2015 15:36:53 -0600 Subject: [PATCH] Moved set_rectangle out of image_32 into image_util. Ref #2633 --- include/mapnik/graphics.hpp | 24 ---------- include/mapnik/image_util.hpp | 3 ++ src/image_util.cpp | 84 +++++++++++++++++++++++++++++++++++ 3 files changed, 87 insertions(+), 24 deletions(-) diff --git a/include/mapnik/graphics.hpp b/include/mapnik/graphics.hpp index dccbdaeea..6faae9927 100644 --- a/include/mapnik/graphics.hpp +++ b/include/mapnik/graphics.hpp @@ -117,30 +117,6 @@ public: return data_.height(); } - inline void set_rectangle(int x0,int y0,image_data_rgba8 const& data) - { - box2d ext0(0,0,data_.width(),data_.height()); - box2d ext1(x0,y0,x0+data.width(),y0+data.height()); - - if (ext0.intersects(ext1)) - { - box2d box = ext0.intersect(ext1); - for (int y = box.miny(); y < box.maxy(); ++y) - { - unsigned int* row_to = data_.getRow(y); - unsigned int const * row_from = data.getRow(y-y0); - - for (int x = box.minx(); x < box.maxx(); ++x) - { - if (row_from[x-x0] & 0xff000000) - { - row_to[x] = row_from[x-x0]; - } - } - } - } - } - template inline void merge_rectangle(image_data_rgba8 const& data, unsigned x0, unsigned y0, float opacity) { diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp index c96e879cc..8b7f1e0c2 100644 --- a/include/mapnik/image_util.hpp +++ b/include/mapnik/image_util.hpp @@ -135,6 +135,9 @@ MAPNIK_DECL void set_color_to_alpha (T & image, color const& c); template MAPNIK_DECL void fill (T1 & data, T2 const& c); +template +MAPNIK_DECL void set_rectangle (T & dst, T const& src, int x = 0, int y = 0); + inline bool is_png(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".png")); diff --git a/src/image_util.cpp b/src/image_util.cpp index 3da3c7fc2..761d2f2cf 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -863,4 +863,88 @@ MAPNIK_DECL void fill (image_data_rgba8 & data , int3 visitor(data); } +namespace detail { + +struct visitor_set_rectangle +{ + visitor_set_rectangle(image_data_any const & src, int x0, int y0) + : src_(src), x0_(x0), y0_(y0) {} + + template + void operator() (T & dst) + { + using pixel_type = typename T::pixel_type; + T src = util::get(src_); + box2d ext0(0,0,dst.width(),dst.height()); + box2d ext1(x0_,y0_,x0_+src.width(),y0_+src.height()); + + if (ext0.intersects(ext1)) + { + box2d box = ext0.intersect(ext1); + for (std::size_t y = box.miny(); y < box.maxy(); ++y) + { + pixel_type* row_to = dst.getRow(y); + pixel_type const * row_from = src.getRow(y-y0_); + + for (std::size_t x = box.minx(); x < box.maxx(); ++x) + { + row_to[x] = row_from[x-x0_]; + } + } + } + } + private: + image_data_any const& src_; + int x0_; + int y0_; +}; + +template <> +void visitor_set_rectangle::operator() (image_data_rgba8 & dst) +{ + using pixel_type = typename image_data_rgba8::pixel_type; + image_data_rgba8 src = util::get(src_); + box2d ext0(0,0,dst.width(),dst.height()); + box2d ext1(x0_,y0_,x0_+src.width(),y0_+src.height()); + + if (ext0.intersects(ext1)) + { + box2d box = ext0.intersect(ext1); + for (std::size_t y = box.miny(); y < box.maxy(); ++y) + { + pixel_type* row_to = dst.getRow(y); + pixel_type const * row_from = src.getRow(y-y0_); + + for (std::size_t x = box.minx(); x < box.maxx(); ++x) + { + if (row_from[x-x0_] & 0xff000000) // Don't change if alpha == 0 + { + row_to[x] = row_from[x-x0_]; + } + } + } + } +} + +template<> +void visitor_set_rectangle::operator() (image_data_null &) +{ + throw std::runtime_error("Set rectangle not support for null images"); +} + +} // end detail ns + +template +void set_rectangle (T & dst, T const& src, int x, int y) +{ + detail::visitor_set_rectangle visit(src, x, y); + visit(dst); +} + +template <> +void set_rectangle (image_data_any & dst, image_data_any const& src, int x, int y) +{ + util::apply_visitor(detail::visitor_set_rectangle(src, x, y), dst); +} + } // end ns