From 532c03552dbc3741da7526f412903154b5506c6e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 3 Aug 2014 20:59:15 -0700 Subject: [PATCH 01/92] remove invalid csv line --- tests/visual_tests/styles/formatting-expr-alignment.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/visual_tests/styles/formatting-expr-alignment.xml b/tests/visual_tests/styles/formatting-expr-alignment.xml index 4a223b622..46ec4bfe7 100644 --- a/tests/visual_tests/styles/formatting-expr-alignment.xml +++ b/tests/visual_tests/styles/formatting-expr-alignment.xml @@ -20,7 +20,6 @@ lat,long,horizontal_alignment,vertical_alignment,dy,text -0.25,-0.35,left,bottom,0 -0.25,-0.12,middle,bottom,0 -0.25, 0.11,right,bottom,0 -# right column: auto vertical alignment 0.25, 0.35,right,auto,-0.0001 0 , 0.35,middle,auto,0 -0.25, 0.35,left,auto,0.0001 From 9f05389754a15ffe47cfd1de7cbce9669a933019 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 3 Aug 2014 21:28:19 -0700 Subject: [PATCH 02/92] fix handling of all sym enums as expressions - fixes tests from #2328 --- bindings/python/mapnik_gamma_method.cpp | 2 +- include/mapnik/agg_helpers.hpp | 2 +- include/mapnik/agg_renderer.hpp | 2 +- include/mapnik/gamma_method.hpp | 43 ---------------------- include/mapnik/symbolizer.hpp | 35 +++++++++++------- include/mapnik/symbolizer_enumerations.hpp | 11 ++++++ src/build.py | 1 - src/gamma_method.cpp | 41 --------------------- src/load_map.cpp | 1 - src/symbolizer_enumerations.cpp | 11 ++++++ src/symbolizer_keys.cpp | 1 - src/xml_tree.cpp | 2 - 12 files changed, 47 insertions(+), 105 deletions(-) delete mode 100644 include/mapnik/gamma_method.hpp delete mode 100644 src/gamma_method.cpp diff --git a/bindings/python/mapnik_gamma_method.cpp b/bindings/python/mapnik_gamma_method.cpp index 23b832d6d..f3f777453 100644 --- a/bindings/python/mapnik_gamma_method.cpp +++ b/bindings/python/mapnik_gamma_method.cpp @@ -22,7 +22,7 @@ #include -#include +#include #include "mapnik_enumeration.hpp" void export_gamma_method() diff --git a/include/mapnik/agg_helpers.hpp b/include/mapnik/agg_helpers.hpp index 78127d2df..c3bc759d2 100644 --- a/include/mapnik/agg_helpers.hpp +++ b/include/mapnik/agg_helpers.hpp @@ -24,7 +24,7 @@ #define MAPNIK_AGG_HELPERS_HPP // mapnik -#include +#include // agg #include "agg_gamma_functions.h" diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index cd6e30c8b..d01c00685 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -34,7 +34,7 @@ #include // for composite_mode_e #include #include -#include +#include #include #include // boost diff --git a/include/mapnik/gamma_method.hpp b/include/mapnik/gamma_method.hpp deleted file mode 100644 index b8a7bd189..000000000 --- a/include/mapnik/gamma_method.hpp +++ /dev/null @@ -1,43 +0,0 @@ -/***************************************************************************** - * - * 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_GAMMA_METHOD_HPP -#define MAPNIK_GAMMA_METHOD_HPP - -#include - -namespace mapnik { - -enum gamma_method_enum { - GAMMA_POWER, //agg::gamma_power - GAMMA_LINEAR, //agg::gamma_linear - GAMMA_NONE, //agg::gamma_none - GAMMA_THRESHOLD, //agg::gamma_threshold - GAMMA_MULTIPLY, //agg::gamma_multiply - gamma_method_enum_MAX -}; - -DEFINE_ENUM (gamma_method_e, gamma_method_enum ); - -} - -#endif // MAPNIK_GAMMA_METHOD_HPP diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 1a77ca768..56a55e852 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -26,6 +26,7 @@ // mapnik #include #include +#include #include #include #include @@ -38,7 +39,6 @@ #include #include #include -#include #include #include @@ -185,14 +185,7 @@ struct evaluate_path_wrapper namespace detail { template -struct enum_traits -{ - using result_type = boost::optional; - static result_type from_string(std::string const& str) - { - return result_type(); - } -}; +struct enum_traits {}; template <> struct enum_traits @@ -204,6 +197,16 @@ struct enum_traits } }; +template <> +struct enum_traits +{ + using result_type = boost::optional; + static result_type from_string(std::string const& str) + { + return scaling_method_from_string(str); + } +}; + template <> struct enum_traits { @@ -232,16 +235,22 @@ template <> struct enum_traits { \ } \ };\ -ENUM_FROM_STRING( pattern_alignment_enum ) -ENUM_FROM_STRING( line_join_enum ) ENUM_FROM_STRING( line_cap_enum ) +ENUM_FROM_STRING( line_join_enum ) ENUM_FROM_STRING( point_placement_enum ) -ENUM_FROM_STRING( marker_placement_enum ) -ENUM_FROM_STRING( gamma_method_enum ) ENUM_FROM_STRING( line_rasterizer_enum ) +ENUM_FROM_STRING( marker_placement_enum ) ENUM_FROM_STRING( marker_multi_policy_enum ) +ENUM_FROM_STRING( debug_symbolizer_mode_enum ) +ENUM_FROM_STRING( pattern_alignment_enum ) ENUM_FROM_STRING( halo_rasterizer_enum ) +ENUM_FROM_STRING( label_placement_enum ) +ENUM_FROM_STRING( vertical_alignment_enum ) +ENUM_FROM_STRING( horizontal_alignment_enum ) +ENUM_FROM_STRING( justify_alignment_enum ) ENUM_FROM_STRING( text_transform_enum ) +ENUM_FROM_STRING( text_upright_enum ) +ENUM_FROM_STRING( gamma_method_enum ) // enum template diff --git a/include/mapnik/symbolizer_enumerations.hpp b/include/mapnik/symbolizer_enumerations.hpp index 11ec98df4..0b3179815 100644 --- a/include/mapnik/symbolizer_enumerations.hpp +++ b/include/mapnik/symbolizer_enumerations.hpp @@ -184,6 +184,17 @@ enum text_upright_enum DEFINE_ENUM(text_upright_e, text_upright_enum); +enum gamma_method_enum { + GAMMA_POWER, //agg::gamma_power + GAMMA_LINEAR, //agg::gamma_linear + GAMMA_NONE, //agg::gamma_none + GAMMA_THRESHOLD, //agg::gamma_threshold + GAMMA_MULTIPLY, //agg::gamma_multiply + gamma_method_enum_MAX +}; + +DEFINE_ENUM (gamma_method_e, gamma_method_enum ); + } diff --git a/src/build.py b/src/build.py index 709a357f3..1d9617671 100644 --- a/src/build.py +++ b/src/build.py @@ -168,7 +168,6 @@ source = Split( feature_type_style.cpp font_engine_freetype.cpp font_set.cpp - gamma_method.cpp gradient.cpp graphics.cpp parse_path.cpp diff --git a/src/gamma_method.cpp b/src/gamma_method.cpp deleted file mode 100644 index f1adf99e2..000000000 --- a/src/gamma_method.cpp +++ /dev/null @@ -1,41 +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 - * - *****************************************************************************/ - -// mapnik -#include -#include - -namespace mapnik -{ - -static const char * gamma_method_strings[] = { - "power", //agg::gamma_power - "linear", //agg::gamma_linear - "none", //agg::gamma_none - "threshold", //agg::gamma_threshold - "multiply", //agg::gamma_multiply", - "" -}; - -IMPLEMENT_ENUM( gamma_method_e, gamma_method_strings ) - -} diff --git a/src/load_map.cpp b/src/load_map.cpp index 0d4931d9d..195c25366 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -31,7 +31,6 @@ #include #include #include -#include #include #include #include diff --git a/src/symbolizer_enumerations.cpp b/src/symbolizer_enumerations.cpp index e56df9290..27e3f9b14 100644 --- a/src/symbolizer_enumerations.cpp +++ b/src/symbolizer_enumerations.cpp @@ -172,4 +172,15 @@ static const char * text_upright_strings[] = { }; IMPLEMENT_ENUM(text_upright_e, text_upright_strings) +static const char * gamma_method_strings[] = { + "power", //agg::gamma_power + "linear", //agg::gamma_linear + "none", //agg::gamma_none + "threshold", //agg::gamma_threshold + "multiply", //agg::gamma_multiply", + "" +}; + +IMPLEMENT_ENUM( gamma_method_e, gamma_method_strings ) + } // namespace mapnik diff --git a/src/symbolizer_keys.cpp b/src/symbolizer_keys.cpp index 6756c5052..b802c453e 100644 --- a/src/symbolizer_keys.cpp +++ b/src/symbolizer_keys.cpp @@ -22,7 +22,6 @@ #include #include -#include #include // boost diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index 96786834b..1c7ee10b9 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -27,13 +27,11 @@ #include #include #include -#include #include #include #include #include #include - #include // stl From c1c5421fb683b5b1b42ff33b7806edc0656c885e Mon Sep 17 00:00:00 2001 From: artemp Date: Mon, 4 Aug 2014 12:33:37 +0100 Subject: [PATCH 03/92] add divide, linear-dodge and linear-burn blending modes (needs testing) --- deps/agg/include/agg_pixfmt_rgba.h | 5809 +++++++++++++------------- include/mapnik/image_compositing.hpp | 5 +- src/cairo/cairo_context.cpp | 3 + src/image_compositing.cpp | 3 + 4 files changed, 2975 insertions(+), 2845 deletions(-) diff --git a/deps/agg/include/agg_pixfmt_rgba.h b/deps/agg/include/agg_pixfmt_rgba.h index 8400c5c43..9d5535128 100644 --- a/deps/agg/include/agg_pixfmt_rgba.h +++ b/deps/agg/include/agg_pixfmt_rgba.h @@ -1,4 +1,3 @@ - //---------------------------------------------------------------------------- // Anti-Grain Geometry - Version 2.4 // Copyright (C) 2002-2005 Maxim Shemanarev (http://www.antigrain.com) @@ -34,1849 +33,2000 @@ namespace agg { - //=========================================================multiplier_rgba - template struct multiplier_rgba +//=========================================================multiplier_rgba +template struct multiplier_rgba +{ + typedef typename ColorT::value_type value_type; + typedef typename ColorT::calc_type calc_type; + + //-------------------------------------------------------------------- + static AGG_INLINE void premultiply(value_type* p) { - typedef typename ColorT::value_type value_type; - typedef typename ColorT::calc_type calc_type; - - //-------------------------------------------------------------------- - static AGG_INLINE void premultiply(value_type* p) + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) { - calc_type a = p[Order::A]; - if(a < ColorT::base_mask) + if(a == 0) { - if(a == 0) - { - p[Order::R] = p[Order::G] = p[Order::B] = 0; - return; - } - p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); - p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); - p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; } + p[Order::R] = value_type((p[Order::R] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::G] = value_type((p[Order::G] * a + ColorT::base_mask) >> ColorT::base_shift); + p[Order::B] = value_type((p[Order::B] * a + ColorT::base_mask) >> ColorT::base_shift); } + } - //-------------------------------------------------------------------- - static AGG_INLINE void demultiply(value_type* p) + //-------------------------------------------------------------------- + static AGG_INLINE void demultiply(value_type* p) + { + calc_type a = p[Order::A]; + if(a < ColorT::base_mask) { - calc_type a = p[Order::A]; - if(a < ColorT::base_mask) + if(a == 0) { - if(a == 0) - { - p[Order::R] = p[Order::G] = p[Order::B] = 0; - return; - } - calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; - calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; - calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; - p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); - p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); - p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); + p[Order::R] = p[Order::G] = p[Order::B] = 0; + return; } + calc_type r = (calc_type(p[Order::R]) * ColorT::base_mask) / a; + calc_type g = (calc_type(p[Order::G]) * ColorT::base_mask) / a; + calc_type b = (calc_type(p[Order::B]) * ColorT::base_mask) / a; + p[Order::R] = value_type((r > ColorT::base_mask) ? ColorT::base_mask : r); + p[Order::G] = value_type((g > ColorT::base_mask) ? ColorT::base_mask : g); + p[Order::B] = value_type((b > ColorT::base_mask) ? ColorT::base_mask : b); } + } +}; + +//=====================================================apply_gamma_dir_rgba +template class apply_gamma_dir_rgba +{ +public: + typedef typename ColorT::value_type value_type; + + apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.dir(p[Order::R]); + p[Order::G] = m_gamma.dir(p[Order::G]); + p[Order::B] = m_gamma.dir(p[Order::B]); + } + +private: + const GammaLut& m_gamma; +}; + +//=====================================================apply_gamma_inv_rgba +template class apply_gamma_inv_rgba +{ +public: + typedef typename ColorT::value_type value_type; + + apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + + AGG_INLINE void operator () (value_type* p) + { + p[Order::R] = m_gamma.inv(p[Order::R]); + p[Order::G] = m_gamma.inv(p[Order::G]); + p[Order::B] = m_gamma.inv(p[Order::B]); + } + +private: + const GammaLut& m_gamma; +}; + +//=============================================================blender_rgba +template struct blender_rgba +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //=====================================================apply_gamma_dir_rgba - template class apply_gamma_dir_rgba + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned /*cover*/=0) { - public: - typedef typename ColorT::value_type value_type; + calc_type r = p[Order::R]; + calc_type g = p[Order::G]; + calc_type b = p[Order::B]; + calc_type a = p[Order::A]; + p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); + p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); + p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); + p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); + } +}; - apply_gamma_dir_rgba(const GammaLut& gamma) : m_gamma(gamma) {} - - AGG_INLINE void operator () (value_type* p) - { - p[Order::R] = m_gamma.dir(p[Order::R]); - p[Order::G] = m_gamma.dir(p[Order::G]); - p[Order::B] = m_gamma.dir(p[Order::B]); - } - - private: - const GammaLut& m_gamma; +//=========================================================blender_rgba_pre +template struct blender_rgba_pre +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //=====================================================apply_gamma_inv_rgba - template class apply_gamma_inv_rgba + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) { - public: - typedef typename ColorT::value_type value_type; + alpha = color_type::base_mask - alpha; + cover = (cover + 1) << (base_shift - 8); + p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } - apply_gamma_inv_rgba(const GammaLut& gamma) : m_gamma(gamma) {} + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + alpha = color_type::base_mask - alpha; + p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); + p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); + p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); + p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + } +}; - AGG_INLINE void operator () (value_type* p) - { - p[Order::R] = m_gamma.inv(p[Order::R]); - p[Order::G] = m_gamma.inv(p[Order::G]); - p[Order::B] = m_gamma.inv(p[Order::B]); - } +//======================================================blender_rgba_plain +template struct blender_rgba_plain +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e { base_shift = color_type::base_shift }; - private: - const GammaLut& m_gamma; + //-------------------------------------------------------------------- + static AGG_INLINE void blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned /*cover*/=0) + { + if(alpha == 0) return; + calc_type a = p[Order::A]; + calc_type r = p[Order::R] * a; + calc_type g = p[Order::G] * a; + calc_type b = p[Order::B] * a; + a = ((alpha + a) << base_shift) - alpha * a; + p[Order::A] = (value_type)(a >> base_shift); + p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); + p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); + p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); + } +}; + + + + + + + + + + + +//=========================================================comp_op_rgba_clear +template struct comp_op_rgba_clear +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //=============================================================blender_rgba - template struct blender_rgba + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, unsigned, + unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e + if(cover < 255) { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned /*cover*/=0) - { - calc_type r = p[Order::R]; - calc_type g = p[Order::G]; - calc_type b = p[Order::B]; - calc_type a = p[Order::A]; - p[Order::R] = (value_type)(((cr - r) * alpha + (r << base_shift)) >> base_shift); - p[Order::G] = (value_type)(((cg - g) * alpha + (g << base_shift)) >> base_shift); - p[Order::B] = (value_type)(((cb - b) * alpha + (b << base_shift)) >> base_shift); - p[Order::A] = (value_type)((alpha + a) - ((alpha * a + base_mask) >> base_shift)); + cover = 255 - cover; + p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); + p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); + p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); + p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); } + else + { + p[0] = p[1] = p[2] = p[3] = 0; + } + } +}; + +//===========================================================comp_op_rgba_src +template struct comp_op_rgba_src +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + } + else + { + p[Order::R] = sr; + p[Order::G] = sg; + p[Order::B] = sb; + p[Order::A] = sa; + } + } +}; + +//===========================================================comp_op_rgba_dst +template struct comp_op_rgba_dst +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + + static AGG_INLINE void blend_pix(value_type*, + unsigned, unsigned, unsigned, + unsigned, unsigned) + { + } +}; + +//======================================================comp_op_rgba_src_over +template struct comp_op_rgba_src_over +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //=========================================================blender_rgba_pre - template struct blender_rgba_pre + // Dca' = Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e + if(cover < 255) { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned cover) - { - alpha = color_type::base_mask - alpha; - cover = (cover + 1) << (base_shift - 8); - p[Order::R] = (value_type)((p[Order::R] * alpha + cr * cover) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * alpha + cg * cover) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * alpha + cb * cover) >> base_shift); - p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; } + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + ((p[Order::A] * s1a + base_mask) >> base_shift)); + } +}; - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha) - { - alpha = color_type::base_mask - alpha; - p[Order::R] = (value_type)(((p[Order::R] * alpha) >> base_shift) + cr); - p[Order::G] = (value_type)(((p[Order::G] * alpha) >> base_shift) + cg); - p[Order::B] = (value_type)(((p[Order::B] * alpha) >> base_shift) + cb); - p[Order::A] = (value_type)(base_mask - ((alpha * (base_mask - p[Order::A])) >> base_shift)); - } +//======================================================comp_op_rgba_dst_over +template struct comp_op_rgba_dst_over +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //======================================================blender_rgba_plain - template struct blender_rgba_plain + // Dca' = Dca + Sca.(1 - Da) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e { base_shift = color_type::base_shift }; - - //-------------------------------------------------------------------- - static AGG_INLINE void blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned /*cover*/=0) + if(cover < 255) { - if(alpha == 0) return; - calc_type a = p[Order::A]; - calc_type r = p[Order::R] * a; - calc_type g = p[Order::G] * a; - calc_type b = p[Order::B] * a; - a = ((alpha + a) << base_shift) - alpha * a; - p[Order::A] = (value_type)(a >> base_shift); - p[Order::R] = (value_type)((((cr << base_shift) - r) * alpha + (r << base_shift)) / a); - p[Order::G] = (value_type)((((cg << base_shift) - g) * alpha + (g << base_shift)) / a); - p[Order::B] = (value_type)((((cb << base_shift) - b) * alpha + (b << base_shift)) / a); + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; } + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(p[Order::A] + ((sa * d1a + base_mask) >> base_shift)); + } +}; + +//======================================================comp_op_rgba_src_in +template struct comp_op_rgba_src_in +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - - - - - - - - - - - //=========================================================comp_op_rgba_clear - template struct comp_op_rgba_clear + // Dca' = Sca.Da + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - enum base_scale_e + calc_type da = p[Order::A]; + if(cover < 255) { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, unsigned, - unsigned cover) - { - if(cover < 255) - { - cover = 255 - cover; - p[Order::R] = (value_type)((p[Order::R] * cover + 255) >> 8); - p[Order::G] = (value_type)((p[Order::G] * cover + 255) >> 8); - p[Order::B] = (value_type)((p[Order::B] * cover + 255) >> 8); - p[Order::A] = (value_type)((p[Order::A] * cover + 255) >> 8); - } - else - { - p[0] = p[1] = p[2] = p[3] = 0; - } + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } +}; + +//======================================================comp_op_rgba_dst_in +template struct comp_op_rgba_dst_in +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //===========================================================comp_op_rgba_src - template struct comp_op_rgba_src + // Dca' = Dca.Sa + // Da' = Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) + if(cover < 255) { - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); - } - else - { - p[Order::R] = sr; - p[Order::G] = sg; - p[Order::B] = sb; - p[Order::A] = sa; - } + sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); } + p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); + } +}; + +//======================================================comp_op_rgba_src_out +template struct comp_op_rgba_src_out +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //===========================================================comp_op_rgba_dst - template struct comp_op_rgba_dst + // Dca' = Sca.(1 - Da) + // Da' = Sa.(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - - static AGG_INLINE void blend_pix(value_type*, - unsigned, unsigned, unsigned, - unsigned, unsigned) + calc_type da = base_mask - p[Order::A]; + if(cover < 255) { + unsigned alpha = 255 - cover; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); } + else + { + p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); + } + } +}; + +//======================================================comp_op_rgba_dst_out +template struct comp_op_rgba_dst_out +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //======================================================comp_op_rgba_src_over - template struct comp_op_rgba_src_over + // Dca' = Dca.(1 - Sa) + // Da' = Da.(1 - Sa) + static AGG_INLINE void blend_pix(value_type* p, + unsigned, unsigned, unsigned, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Sca + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(sr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + ((p[Order::A] * s1a + base_mask) >> base_shift)); - } - }; - - //======================================================comp_op_rgba_dst_over - template struct comp_op_rgba_dst_over - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Dca + Sca.(1 - Da) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type d1a = base_mask - p[Order::A]; - p[Order::R] = (value_type)(p[Order::R] + ((sr * d1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(p[Order::G] + ((sg * d1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(p[Order::B] + ((sb * d1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(p[Order::A] + ((sa * d1a + base_mask) >> base_shift)); - } - }; - - //======================================================comp_op_rgba_src_in - template struct comp_op_rgba_src_in - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Sca.Da - // Da' = Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); - } - else - { - p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); - } - } - }; - - //======================================================comp_op_rgba_dst_in - template struct comp_op_rgba_dst_in - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Dca.Sa - // Da' = Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sa = base_mask - ((cover * (base_mask - sa) + 255) >> 8); - } - p[Order::R] = (value_type)((p[Order::R] * sa + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + base_mask) >> base_shift); - p[Order::A] = (value_type)((p[Order::A] * sa + base_mask) >> base_shift); - } - }; - - //======================================================comp_op_rgba_src_out - template struct comp_op_rgba_src_out - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Sca.(1 - Da) - // Da' = Sa.(1 - Da) - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = base_mask - p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((((sr * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((((sg * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((((sb * da + base_mask) >> base_shift) * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((((sa * da + base_mask) >> base_shift) * cover + 255) >> 8)); - } - else - { - p[Order::R] = (value_type)((sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)((sa * da + base_mask) >> base_shift); - } - } - }; - - //======================================================comp_op_rgba_dst_out - template struct comp_op_rgba_dst_out - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Dca.(1 - Sa) - // Da' = Da.(1 - Sa) - static AGG_INLINE void blend_pix(value_type* p, - unsigned, unsigned, unsigned, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sa = (sa * cover + 255) >> 8; - } - sa = base_mask - sa; - p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); - p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); - } - }; - - //=====================================================comp_op_rgba_src_atop - template struct comp_op_rgba_src_atop - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Sca.Da + Dca.(1 - Sa) - // Da' = Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - calc_type da = p[Order::A]; - sa = base_mask - sa; - p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); - } - }; - - //=====================================================comp_op_rgba_dst_atop - template struct comp_op_rgba_dst_atop - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Dca.Sa + Sca.(1 - Da) - // Da' = Sa - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - calc_type da = base_mask - p[Order::A]; - if(cover < 255) - { - unsigned alpha = 255 - cover; - sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; - sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; - sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; - p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); - p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); - p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); - p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); - - } - else - { - p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); - p[Order::A] = (value_type)sa; - } - } - }; - - //=========================================================comp_op_rgba_xor - template struct comp_op_rgba_xor - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - 2.Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type s1a = base_mask - sa; - calc_type d1a = base_mask - p[Order::A]; - p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); - } - } - }; - - //=========================================================comp_op_rgba_plus - template struct comp_op_rgba_plus - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Sca + Dca - // Da' = Sa + Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R] + sr; - calc_type dg = p[Order::G] + sg; - calc_type db = p[Order::B] + sb; - calc_type da = p[Order::A] + sa; - p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; - p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; - p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; - p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; - } - } - }; - - //========================================================comp_op_rgba_minus - template struct comp_op_rgba_minus - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Dca - Sca - // Da' = 1 - (1 - Sa).(1 - Da) - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = (sr > p[Order::R]) ? 0 : p[Order::R] - sr; - calc_type dg = (sg > p[Order::G]) ? 0 : p[Order::G] - sg; - calc_type db = (sb > p[Order::B]) ? 0 : p[Order::B] - sb; - p[Order::R] = (dr > base_mask) ? 0 : dr; - p[Order::G] = (dg > base_mask) ? 0 : dg; - p[Order::B] = (db > base_mask) ? 0 : db; - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_multiply - template struct comp_op_rgba_multiply - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type s1a = base_mask - sa; - calc_type d1a = base_mask - p[Order::A]; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_screen - template struct comp_op_rgba_screen - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = Sca + Dca - Sca.Dca - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_overlay - template struct comp_op_rgba_overlay - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // if 2.Dca < Da - // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - calc_type sada = sa * p[Order::A]; - - p[Order::R] = (value_type)(((2*dr < da) ? - 2*sr*dr + sr*d1a + dr*s1a : - sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); - - p[Order::G] = (value_type)(((2*dg < da) ? - 2*sg*dg + sg*d1a + dg*s1a : - sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); - - p[Order::B] = (value_type)(((2*db < da) ? - 2*sb*db + sb*d1a + db*s1a : - sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); - - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - - template inline T sd_min(T a, T b) { return (a < b) ? a : b; } - template inline T sd_max(T a, T b) { return (a > b) ? a : b; } - - //=====================================================comp_op_rgba_darken - template struct comp_op_rgba_darken - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - - p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_lighten - template struct comp_op_rgba_lighten - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - - p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_color_dodge - template struct comp_op_rgba_color_dodge - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // if Sca.Da + Dca.Sa >= Sa.Da - // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - long_type drsa = dr * sa; - long_type dgsa = dg * sa; - long_type dbsa = db * sa; - long_type srda = sr * da; - long_type sgda = sg * da; - long_type sbda = sb * da; - long_type sada = sa * da; - - p[Order::R] = (value_type)((srda + drsa >= sada) ? - (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : - drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); - - p[Order::G] = (value_type)((sgda + dgsa >= sada) ? - (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : - dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); - - p[Order::B] = (value_type)((sbda + dbsa >= sada) ? - (sada + sb * d1a + db * s1a + base_mask) >> base_shift : - dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); - - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_color_burn - template struct comp_op_rgba_color_burn - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // if Sca.Da + Dca.Sa <= Sa.Da - // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - - - // http://www.w3.org/TR/SVGCompositing/ - // if Sca == 0 and Dca == Da - // Dca' = Sa × Da + Sca × (1 - Da) + Dca × (1 - Sa) - // = Sa × Da + Dca × (1 - Sa) - // = Da = Dca - // otherwise if Sca == 0 - // Dca' = Sca × (1 - Da) + Dca × (1 - Sa) - // = Dca × (1 - Sa) - // otherwise if Sca > 0 - // Dca' = Sa × Da - Sa × Da × min(1, (1 - Dca/Da) × Sa/Sca) + Sca × (1 - Da) + Dca × (1 - Sa) - // = Sa × Da × (1 - min(1, (1 - Dca/Da) × Sa/Sca)) + Sca × (1 - Da) + Dca × (1 - Sa) - - // sa * da * (255 - std::min(255, (255 - p[0]/da)*(sa/(sc*sa)) + - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if (cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - - if (sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - long_type drsa = dr * sa; - long_type dgsa = dg * sa; - long_type dbsa = db * sa; - long_type srda = sr * da; - long_type sgda = sg * da; - long_type sbda = sb * da; - long_type sada = sa * da; - - p[Order::R] = (value_type)(((srda + drsa <= sada) ? - sr * d1a + dr * s1a : - (sr > 0 ? sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask : 0)) >> base_shift); - - p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? - sg * d1a + dg * s1a : - (sg > 0 ? sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask : 0)) >> base_shift); - - p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? - sb * d1a + db * s1a : - (sb > 0 ? sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask : 0)) >> base_shift); - - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_hard_light - template struct comp_op_rgba_hard_light - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // if 2.Sca < Sa - // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - calc_type sada = sa * da; - - p[Order::R] = (value_type)(((2*sr < sa) ? - 2*sr*dr + sr*d1a + dr*s1a : - sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); - - p[Order::G] = (value_type)(((2*sg < sa) ? - 2*sg*dg + sg*d1a + dg*s1a : - sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); - - p[Order::B] = (value_type)(((2*sb < sa) ? - 2*sb*db + sb*d1a + db*s1a : - sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); - - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_soft_light - template struct comp_op_rgba_soft_light - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // if 2.Sca < Sa - // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise if 8.Dca <= Da - // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) - // otherwise - // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) - // - // Da' = Sa + Da - Sa.Da - - static AGG_INLINE void blend_pix(value_type* p, - unsigned r, unsigned g, unsigned b, - unsigned a, unsigned cover) - { - double sr = double(r * cover) / (base_mask * 255); - double sg = double(g * cover) / (base_mask * 255); - double sb = double(b * cover) / (base_mask * 255); - double sa = double(a * cover) / (base_mask * 255); - if(sa > 0) - { - double dr = double(p[Order::R]) / base_mask; - double dg = double(p[Order::G]) / base_mask; - double db = double(p[Order::B]) / base_mask; - double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; - if(cover < 255) - { - a = (a * cover + 255) >> 8; - } - - if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); - else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); - else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); - - if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); - else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); - else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); - - if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); - else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); - else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); - - p[Order::R] = (value_type)uround(dr * base_mask); - p[Order::G] = (value_type)uround(dg * base_mask); - p[Order::B] = (value_type)uround(db * base_mask); - p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_difference - template struct comp_op_rgba_difference - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask - }; - - // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); - p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); - p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_exclusion - template struct comp_op_rgba_exclusion - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type d1a = base_mask - p[Order::A]; - calc_type s1a = base_mask - sa; - calc_type dr = p[Order::R]; - calc_type dg = p[Order::G]; - calc_type db = p[Order::B]; - calc_type da = p[Order::A]; - p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); - p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); - p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } - } - }; - - //=====================================================comp_op_rgba_contrast - template struct comp_op_rgba_contrast - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - if(cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - long_type dr = p[Order::R]; - long_type dg = p[Order::G]; - long_type db = p[Order::B]; - int da = p[Order::A]; - long_type d2a = da >> 1; - unsigned s2a = sa >> 1; - - int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); - int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); - int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); - - r = (r < 0) ? 0 : r; - g = (g < 0) ? 0 : g; - b = (b < 0) ? 0 : b; - - p[Order::R] = (value_type)((r > da) ? da : r); - p[Order::G] = (value_type)((g > da) ? da : g); - p[Order::B] = (value_type)((b > da) ? da : b); - } - }; - - //=====================================================comp_op_rgba_invert - template struct comp_op_rgba_invert - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned /*sr*/, unsigned /*sg*/, unsigned /*sb*/, - unsigned sa, unsigned cover) + if(cover < 255) { sa = (sa * cover + 255) >> 8; - if(sa) - { - calc_type da = p[Order::A]; - calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; - calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; - calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } } + sa = base_mask - sa; + p[Order::R] = (value_type)((p[Order::R] * sa + base_shift) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + base_shift) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + base_shift) >> base_shift); + p[Order::A] = (value_type)((p[Order::A] * sa + base_shift) >> base_shift); + } +}; + +//=====================================================comp_op_rgba_src_atop +template struct comp_op_rgba_src_atop +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - //=================================================comp_op_rgba_invert_rgb - template struct comp_op_rgba_invert_rgb + // Dca' = Sca.Da + Dca.(1 - Sa) + // Da' = Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e + if(cover < 255) { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + calc_type da = p[Order::A]; + sa = base_mask - sa; + p[Order::R] = (value_type)((sr * da + p[Order::R] * sa + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * da + p[Order::G] * sa + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * da + p[Order::B] * sa + base_mask) >> base_shift); + } +}; - // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) - // Da' = Sa + Da - Sa.Da - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) +//=====================================================comp_op_rgba_dst_atop +template struct comp_op_rgba_dst_atop +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca.Sa + Sca.(1 - Da) + // Da' = Sa + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = base_mask - p[Order::A]; + if(cover < 255) { + unsigned alpha = 255 - cover; + sr = (p[Order::R] * sa + sr * da + base_mask) >> base_shift; + sg = (p[Order::G] * sa + sg * da + base_mask) >> base_shift; + sb = (p[Order::B] * sa + sb * da + base_mask) >> base_shift; + p[Order::R] = (value_type)(((p[Order::R] * alpha + 255) >> 8) + ((sr * cover + 255) >> 8)); + p[Order::G] = (value_type)(((p[Order::G] * alpha + 255) >> 8) + ((sg * cover + 255) >> 8)); + p[Order::B] = (value_type)(((p[Order::B] * alpha + 255) >> 8) + ((sb * cover + 255) >> 8)); + p[Order::A] = (value_type)(((p[Order::A] * alpha + 255) >> 8) + ((sa * cover + 255) >> 8)); + + } + else + { + p[Order::R] = (value_type)((p[Order::R] * sa + sr * da + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * sa + sg * da + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * sa + sb * da + base_mask) >> base_shift); + p[Order::A] = (value_type)sa; + } + } +}; + +//=========================================================comp_op_rgba_xor +template struct comp_op_rgba_xor +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - 2.Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + p[Order::R] = (value_type)((p[Order::R] * s1a + sr * d1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((p[Order::G] * s1a + sg * d1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((p[Order::B] * s1a + sb * d1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask/2) >> (base_shift - 1))); + } + } +}; + +//=========================================================comp_op_rgba_plus +template struct comp_op_rgba_plus +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca + // Da' = Sa + Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R] + sr; + calc_type dg = p[Order::G] + sg; + calc_type db = p[Order::B] + sb; + calc_type da = p[Order::A] + sa; + p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; + p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; + p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; + p[Order::A] = (da > base_mask) ? (value_type)base_mask : da; + } + } +}; + +//========================================================comp_op_rgba_minus +template struct comp_op_rgba_minus +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Dca - Sca + // Da' = 1 - (1 - Sa).(1 - Da) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = (sr > p[Order::R]) ? 0 : p[Order::R] - sr; + calc_type dg = (sg > p[Order::G]) ? 0 : p[Order::G] - sg; + calc_type db = (sb > p[Order::B]) ? 0 : p[Order::B] - sb; + p[Order::R] = (dr > base_mask) ? 0 : dr; + p[Order::G] = (dg > base_mask) ? 0 : dg; + p[Order::B] = (db > base_mask) ? 0 : db; + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + //p[Order::A] = (value_type)(base_mask - (((base_mask - sa) * (base_mask - p[Order::A]) + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_multiply +template struct comp_op_rgba_multiply +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type s1a = base_mask - sa; + calc_type d1a = base_mask - p[Order::A]; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + p[Order::R] = (value_type)((sr * dr + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg * dg + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb * db + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + p[Order::A] - ((sa * p[Order::A] + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_screen +template struct comp_op_rgba_screen +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca - Sca.Dca + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)(sr + dr - ((sr * dr + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((sg * dg + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((sb * db + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_overlay +template struct comp_op_rgba_overlay +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if 2.Dca < Da + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + calc_type sada = sa * p[Order::A]; + + p[Order::R] = (value_type)(((2*dr < da) ? + 2*sr*dr + sr*d1a + dr*s1a : + sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); + + p[Order::G] = (value_type)(((2*dg < da) ? + 2*sg*dg + sg*d1a + dg*s1a : + sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); + + p[Order::B] = (value_type)(((2*db < da) ? + 2*sb*db + sb*d1a + db*s1a : + sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + + +template inline T sd_min(T a, T b) { return (a < b) ? a : b; } +template inline T sd_max(T a, T b) { return (a > b) ? a : b; } + +//=====================================================comp_op_rgba_darken +template struct comp_op_rgba_darken +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = min(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + + p[Order::R] = (value_type)((sd_min(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sd_min(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_min(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_lighten +template struct comp_op_rgba_lighten +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = max(Sca.Da, Dca.Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + + p[Order::R] = (value_type)((sd_max(sr * da, dr * sa) + sr * d1a + dr * s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sd_max(sg * da, dg * sa) + sg * d1a + dg * s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sd_max(sb * da, db * sa) + sb * d1a + db * s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_color_dodge +template struct comp_op_rgba_color_dodge +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if Sca.Da + Dca.Sa >= Sa.Da + // Dca' = Sa.Da + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Dca.Sa/(1-Sca/Sa) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; + + p[Order::R] = (value_type)((srda + drsa >= sada) ? + (sada + sr * d1a + dr * s1a + base_mask) >> base_shift : + drsa / (base_mask - (sr << base_shift) / sa) + ((sr * d1a + dr * s1a + base_mask) >> base_shift)); + + p[Order::G] = (value_type)((sgda + dgsa >= sada) ? + (sada + sg * d1a + dg * s1a + base_mask) >> base_shift : + dgsa / (base_mask - (sg << base_shift) / sa) + ((sg * d1a + dg * s1a + base_mask) >> base_shift)); + + p[Order::B] = (value_type)((sbda + dbsa >= sada) ? + (sada + sb * d1a + db * s1a + base_mask) >> base_shift : + dbsa / (base_mask - (sb << base_shift) / sa) + ((sb * d1a + db * s1a + base_mask) >> base_shift)); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_color_burn +template struct comp_op_rgba_color_burn +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if Sca.Da + Dca.Sa <= Sa.Da + // Dca' = Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.(Sca.Da + Dca.Sa - Sa.Da)/Sca + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + + + // http://www.w3.org/TR/SVGCompositing/ + // if Sca == 0 and Dca == Da + // Dca' = Sa × Da + Sca × (1 - Da) + Dca × (1 - Sa) + // = Sa × Da + Dca × (1 - Sa) + // = Da = Dca + // otherwise if Sca == 0 + // Dca' = Sca × (1 - Da) + Dca × (1 - Sa) + // = Dca × (1 - Sa) + // otherwise if Sca > 0 + // Dca' = Sa × Da - Sa × Da × min(1, (1 - Dca/Da) × Sa/Sca) + Sca × (1 - Da) + Dca × (1 - Sa) + // = Sa × Da × (1 - min(1, (1 - Dca/Da) × Sa/Sca)) + Sca × (1 - Da) + Dca × (1 - Sa) + + // sa * da * (255 - std::min(255, (255 - p[0]/da)*(sa/(sc*sa)) + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + + if (sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + long_type drsa = dr * sa; + long_type dgsa = dg * sa; + long_type dbsa = db * sa; + long_type srda = sr * da; + long_type sgda = sg * da; + long_type sbda = sb * da; + long_type sada = sa * da; + + p[Order::R] = (value_type)(((srda + drsa <= sada) ? + sr * d1a + dr * s1a : + (sr > 0 ? sa * (srda + drsa - sada) / sr + sr * d1a + dr * s1a + base_mask : 0)) >> base_shift); + + p[Order::G] = (value_type)(((sgda + dgsa <= sada) ? + sg * d1a + dg * s1a : + (sg > 0 ? sa * (sgda + dgsa - sada) / sg + sg * d1a + dg * s1a + base_mask : 0)) >> base_shift); + + p[Order::B] = (value_type)(((sbda + dbsa <= sada) ? + sb * d1a + db * s1a : + (sb > 0 ? sa * (sbda + dbsa - sada) / sb + sb * d1a + db * s1a + base_mask : 0)) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_hard_light +template struct comp_op_rgba_hard_light +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if 2.Sca < Sa + // Dca' = 2.Sca.Dca + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = Sa.Da - 2.(Da - Dca).(Sa - Sca) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + calc_type sada = sa * da; + + p[Order::R] = (value_type)(((2*sr < sa) ? + 2*sr*dr + sr*d1a + dr*s1a : + sada - 2*(da - dr)*(sa - sr) + sr*d1a + dr*s1a + base_mask) >> base_shift); + + p[Order::G] = (value_type)(((2*sg < sa) ? + 2*sg*dg + sg*d1a + dg*s1a : + sada - 2*(da - dg)*(sa - sg) + sg*d1a + dg*s1a + base_mask) >> base_shift); + + p[Order::B] = (value_type)(((2*sb < sa) ? + 2*sb*db + sb*d1a + db*s1a : + sada - 2*(da - db)*(sa - sb) + sb*d1a + db*s1a + base_mask) >> base_shift); + + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_soft_light +template struct comp_op_rgba_soft_light +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // if 2.Sca < Sa + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise if 8.Dca <= Da + // Dca' = Dca.(Sa + (1 - Dca/Da).(2.Sca - Sa).(3 - 8.Dca/Da)) + Sca.(1 - Da) + Dca.(1 - Sa) + // otherwise + // Dca' = (Dca.Sa + ((Dca/Da)^(0.5).Da - Dca).(2.Sca - Sa)) + Sca.(1 - Da) + Dca.(1 - Sa) + // + // Da' = Sa + Da - Sa.Da + + static AGG_INLINE void blend_pix(value_type* p, + unsigned r, unsigned g, unsigned b, + unsigned a, unsigned cover) + { + double sr = double(r * cover) / (base_mask * 255); + double sg = double(g * cover) / (base_mask * 255); + double sb = double(b * cover) / (base_mask * 255); + double sa = double(a * cover) / (base_mask * 255); + if(sa > 0) + { + double dr = double(p[Order::R]) / base_mask; + double dg = double(p[Order::G]) / base_mask; + double db = double(p[Order::B]) / base_mask; + double da = double(p[Order::A] ? p[Order::A] : 1) / base_mask; if(cover < 255) { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if(sa) - { - calc_type da = p[Order::A]; - calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; - calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; - calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; - calc_type s1a = base_mask - sa; - p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); - p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); - p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + a = (a * cover + 255) >> 8; } + + if(2*sr < sa) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + else if(8*dr <= da) dr = dr*(sa + (1 - dr/da)*(2*sr - sa)*(3 - 8*dr/da)) + sr*(1 - da) + dr*(1 - sa); + else dr = (dr*sa + (sqrt(dr/da)*da - dr)*(2*sr - sa)) + sr*(1 - da) + dr*(1 - sa); + + if(2*sg < sa) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + else if(8*dg <= da) dg = dg*(sa + (1 - dg/da)*(2*sg - sa)*(3 - 8*dg/da)) + sg*(1 - da) + dg*(1 - sa); + else dg = (dg*sa + (sqrt(dg/da)*da - dg)*(2*sg - sa)) + sg*(1 - da) + dg*(1 - sa); + + if(2*sb < sa) db = db*(sa + (1 - db/da)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + else if(8*db <= da) db = db*(sa + (1 - db/da)*(2*sb - sa)*(3 - 8*db/da)) + sb*(1 - da) + db*(1 - sa); + else db = (db*sa + (sqrt(db/da)*da - db)*(2*sb - sa)) + sb*(1 - da) + db*(1 - sa); + + p[Order::R] = (value_type)uround(dr * base_mask); + p[Order::G] = (value_type)uround(dg * base_mask); + p[Order::B] = (value_type)uround(db * base_mask); + p[Order::A] = (value_type)(a + p[Order::A] - ((a * p[Order::A] + base_mask) >> base_shift)); } + } +}; + +//=====================================================comp_op_rgba_difference +template struct comp_op_rgba_difference +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; + + // Dca' = Sca + Dca - 2.min(Sca.Da, Dca.Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)(sr + dr - ((2 * sd_min(sr*da, dr*sa) + base_mask) >> base_shift)); + p[Order::G] = (value_type)(sg + dg - ((2 * sd_min(sg*da, dg*sa) + base_mask) >> base_shift)); + p[Order::B] = (value_type)(sb + db - ((2 * sd_min(sb*da, db*sa) + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_exclusion +template struct comp_op_rgba_exclusion +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Sca.Da + Dca.Sa - 2.Sca.Dca) + Sca.(1 - Da) + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type d1a = base_mask - p[Order::A]; + calc_type s1a = base_mask - sa; + calc_type dr = p[Order::R]; + calc_type dg = p[Order::G]; + calc_type db = p[Order::B]; + calc_type da = p[Order::A]; + p[Order::R] = (value_type)((sr*da + dr*sa - 2*sr*dr + sr*d1a + dr*s1a + base_mask) >> base_shift); + p[Order::G] = (value_type)((sg*da + dg*sa - 2*sg*dg + sg*d1a + dg*s1a + base_mask) >> base_shift); + p[Order::B] = (value_type)((sb*da + db*sa - 2*sb*db + sb*d1a + db*s1a + base_mask) >> base_shift); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +//=====================================================comp_op_rgba_contrast +template struct comp_op_rgba_contrast +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - // merge grain (GIMP) - // E = I + M - 128 - - template - struct comp_op_rgba_grain_merge + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e + if(cover < 255) { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) - { - - if (cover < 255) - { - sr = (sr * cover + 255) >> 8; - sg = (sg * cover + 255) >> 8; - sb = (sb * cover + 255) >> 8; - sa = (sa * cover + 255) >> 8; - } - if (sa > 0) - { - calc_type da = p[Order::A]; - int dr = sr + p[Order::R] - 128; - int dg = sg + p[Order::G] - 128; - int db = sb + p[Order::B] - 128; - p[Order::R] = dr < 0 ? 0 : (dr > 255 ? 255 : dr); - p[Order::G] = dg < 0 ? 0 : (dg > 255 ? 255 : dg); - p[Order::B] = db < 0 ? 0 : (db > 255 ? 255 : db); - p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); - } + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; } + long_type dr = p[Order::R]; + long_type dg = p[Order::G]; + long_type db = p[Order::B]; + int da = p[Order::A]; + long_type d2a = da >> 1; + unsigned s2a = sa >> 1; + + int r = (int)((((dr - d2a) * int((sr - s2a)*2 + base_mask)) >> base_shift) + d2a); + int g = (int)((((dg - d2a) * int((sg - s2a)*2 + base_mask)) >> base_shift) + d2a); + int b = (int)((((db - d2a) * int((sb - s2a)*2 + base_mask)) >> base_shift) + d2a); + + r = (r < 0) ? 0 : r; + g = (g < 0) ? 0 : g; + b = (b < 0) ? 0 : b; + + p[Order::R] = (value_type)((r > da) ? da : r); + p[Order::G] = (value_type)((g > da) ? da : g); + p[Order::B] = (value_type)((b > da) ? da : b); + } +}; + +//=====================================================comp_op_rgba_invert +template struct comp_op_rgba_invert +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask }; - // grain extract (GIMP) - // E = I - M + 128 - template - struct comp_op_rgba_grain_extract + // Dca' = (Da - Dca) * Sa + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned /*sr*/, unsigned /*sg*/, unsigned /*sb*/, + unsigned sa, unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e + sa = (sa * cover + 255) >> 8; + if(sa) { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sa + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sa + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sa + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; - static AGG_INLINE void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover) +//=================================================comp_op_rgba_invert_rgb +template struct comp_op_rgba_invert_rgb +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + // Dca' = (Da - Dca) * Sca + Dca.(1 - Sa) + // Da' = Sa + Da - Sa.Da + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if(cover < 255) { - calc_type da = (p[Order::A] * sa + 255) >> 8; + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if(sa) + { + calc_type da = p[Order::A]; + calc_type dr = ((da - p[Order::R]) * sr + base_mask) >> base_shift; + calc_type dg = ((da - p[Order::G]) * sg + base_mask) >> base_shift; + calc_type db = ((da - p[Order::B]) * sb + base_mask) >> base_shift; + calc_type s1a = base_mask - sa; + p[Order::R] = (value_type)(dr + ((p[Order::R] * s1a + base_mask) >> base_shift)); + p[Order::G] = (value_type)(dg + ((p[Order::G] * s1a + base_mask) >> base_shift)); + p[Order::B] = (value_type)(db + ((p[Order::B] * s1a + base_mask) >> base_shift)); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; - int dr = p[Order::R] - sr + 128; - int dg = p[Order::G] - sg + 128; - int db = p[Order::B] - sb + 128; - dr = dr < 0 ? 0 : (dr > 255 ? 255 : dr); - dg = dg < 0 ? 0 : (dg > 255 ? 255 : dg); - db = db < 0 ? 0 : (db > 255 ? 255 : db); +// merge grain (GIMP) +// E = I + M - 128 - p[Order::A] = da; +template +struct comp_op_rgba_grain_merge +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; - if (da < 255) + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + if (sa > 0) + { + calc_type da = p[Order::A]; + int dr = sr + p[Order::R] - 128; + int dg = sg + p[Order::G] - 128; + int db = sb + p[Order::B] - 128; + p[Order::R] = dr < 0 ? 0 : (dr > 255 ? 255 : dr); + p[Order::G] = dg < 0 ? 0 : (dg > 255 ? 255 : dg); + p[Order::B] = db < 0 ? 0 : (db > 255 ? 255 : db); + p[Order::A] = (value_type)(sa + da - ((sa * da + base_mask) >> base_shift)); + } + } +}; + +// grain extract (GIMP) +// E = I - M + 128 +template +struct comp_op_rgba_grain_extract +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + calc_type da = (p[Order::A] * sa + 255) >> 8; + + int dr = p[Order::R] - sr + 128; + int dg = p[Order::G] - sg + 128; + int db = p[Order::B] - sb + 128; + + dr = dr < 0 ? 0 : (dr > 255 ? 255 : dr); + dg = dg < 0 ? 0 : (dg > 255 ? 255 : dg); + db = db < 0 ? 0 : (db > 255 ? 255 : db); + + p[Order::A] = da; + + if (da < 255) + { + p[Order::R] = (dr * da + 255) >> 8; + p[Order::G] = (dg * da + 255) >> 8; + p[Order::B] = (db * da + 255) >> 8; + } + else + { + p[Order::R] = dr; + p[Order::G] = dg; + p[Order::B] = db; + } + } +}; + +template +struct comp_op_rgba_hue +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover); +}; + +template +struct comp_op_rgba_saturation +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover); +}; + +template +struct comp_op_rgba_color +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover); +}; + + +template +struct comp_op_rgba_value +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover); +}; + +// Linear dodge: Target + Blend +template +struct comp_op_rgba_linear_dodge +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + + calc_type dr = p[Order::R] + sr; + calc_type dg = p[Order::G] + sg; + calc_type db = p[Order::B] + sb; + p[Order::R] = (dr > base_mask) ? (value_type)base_mask : dr; + p[Order::G] = (dg > base_mask) ? (value_type)base_mask : dg; + p[Order::B] = (db > base_mask) ? (value_type)base_mask : db; + p[Order::A] = (value_type)(sa + ((p[Order::A] * (base_mask - sa) + base_mask) >> base_shift)); + } +}; + +// Linear burn: Target + Blend - 1 +template +struct comp_op_rgba_linear_burn +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + + long_type dr = p[Order::R] + sr - base_mask; + long_type dg = p[Order::G] + sg - base_mask; + long_type db = p[Order::B] + sb - base_mask; + p[Order::R] = (dr < 0) ? 0 : dr; + p[Order::G] = (dg < 0) ? 0 : dg; + p[Order::B] = (db < 0) ? 0 : db; + p[Order::A] = (value_type)(sa + ((p[Order::A] * (base_mask - sa) + base_mask) >> base_shift)); + } +}; + +// Divide +template +struct comp_op_rgba_divide +{ + typedef ColorT color_type; + typedef Order order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::long_type long_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(value_type* p, + unsigned sr, unsigned sg, unsigned sb, + unsigned sa, unsigned cover) + { + if (cover < 255) + { + sr = (sr * cover + 255) >> 8; + sg = (sg * cover + 255) >> 8; + sb = (sb * cover + 255) >> 8; + sa = (sa * cover + 255) >> 8; + } + + float fr = (sr > 0) ? sr : 0.001; + float fg = (sg > 0) ? sg : 0.001; + float fb = (sb > 0) ? sb : 0.001; + + long_type dr = long_type(p[Order::R]/((fr + 1) / 256)); + long_type dg = long_type(p[Order::G]/((fg + 1) / 256)); + long_type db = long_type(p[Order::B]/((fb + 1) / 256)); + + p[Order::R] = (dr > 255) ? 255 : dr; + p[Order::G] = (dg > 255) ? 255 : dg; + p[Order::B] = (db > 255) ? 255 : db; + + p[Order::A] = (value_type)(sa + ((p[Order::A] * (base_mask - sa) + base_mask) >> base_shift)); + } +}; + + +//======================================================comp_op_table_rgba +template struct comp_op_table_rgba +{ + typedef typename ColorT::value_type value_type; + typedef void (*comp_op_func_type)(value_type* p, + unsigned cr, + unsigned cg, + unsigned cb, + unsigned ca, + unsigned cover); + static comp_op_func_type g_comp_op_func[]; +}; + +//==========================================================g_comp_op_func +template +typename comp_op_table_rgba::comp_op_func_type +comp_op_table_rgba::g_comp_op_func[] = +{ + comp_op_rgba_clear ::blend_pix, + comp_op_rgba_src ::blend_pix, + comp_op_rgba_dst ::blend_pix, + comp_op_rgba_src_over ::blend_pix, + comp_op_rgba_dst_over ::blend_pix, + comp_op_rgba_src_in ::blend_pix, + comp_op_rgba_dst_in ::blend_pix, + comp_op_rgba_src_out ::blend_pix, + comp_op_rgba_dst_out ::blend_pix, + comp_op_rgba_src_atop ::blend_pix, + comp_op_rgba_dst_atop ::blend_pix, + comp_op_rgba_xor ::blend_pix, + comp_op_rgba_plus ::blend_pix, + comp_op_rgba_minus ::blend_pix, + comp_op_rgba_multiply ::blend_pix, + comp_op_rgba_screen ::blend_pix, + comp_op_rgba_overlay ::blend_pix, + comp_op_rgba_darken ::blend_pix, + comp_op_rgba_lighten ::blend_pix, + comp_op_rgba_color_dodge::blend_pix, + comp_op_rgba_color_burn ::blend_pix, + comp_op_rgba_hard_light ::blend_pix, + comp_op_rgba_soft_light ::blend_pix, + comp_op_rgba_difference ::blend_pix, + comp_op_rgba_exclusion ::blend_pix, + comp_op_rgba_contrast ::blend_pix, + comp_op_rgba_invert ::blend_pix, + comp_op_rgba_invert_rgb ::blend_pix, + comp_op_rgba_grain_merge::blend_pix, + comp_op_rgba_grain_extract::blend_pix, + comp_op_rgba_hue::blend_pix, + comp_op_rgba_saturation::blend_pix, + comp_op_rgba_color::blend_pix, + comp_op_rgba_value::blend_pix, + comp_op_rgba_linear_dodge::blend_pix, + comp_op_rgba_linear_burn::blend_pix, + comp_op_rgba_divide::blend_pix, + //comp_op_rgba_colorize_alpha::blend_pix, + 0 +}; + + +//==============================================================comp_op_e +enum comp_op_e +{ + comp_op_clear, //----comp_op_clear + comp_op_src, //----comp_op_src + comp_op_dst, //----comp_op_dst + comp_op_src_over, //----comp_op_src_over + comp_op_dst_over, //----comp_op_dst_over + comp_op_src_in, //----comp_op_src_in + comp_op_dst_in, //----comp_op_dst_in + comp_op_src_out, //----comp_op_src_out + comp_op_dst_out, //----comp_op_dst_out + comp_op_src_atop, //----comp_op_src_atop + comp_op_dst_atop, //----comp_op_dst_atop + comp_op_xor, //----comp_op_xor + comp_op_plus, //----comp_op_plus + comp_op_minus, //----comp_op_minus + comp_op_multiply, //----comp_op_multiply + comp_op_screen, //----comp_op_screen + comp_op_overlay, //----comp_op_overlay + comp_op_darken, //----comp_op_darken + comp_op_lighten, //----comp_op_lighten + comp_op_color_dodge, //----comp_op_color_dodge + comp_op_color_burn, //----comp_op_color_burn + comp_op_hard_light, //----comp_op_hard_light + comp_op_soft_light, //----comp_op_soft_light + comp_op_difference, //----comp_op_difference + comp_op_exclusion, //----comp_op_exclusion + comp_op_contrast, //----comp_op_contrast + comp_op_invert, //----comp_op_invert + comp_op_invert_rgb, //----comp_op_invert_rgb + comp_op_grain_merge, //----comp_op_grain_merge_rgb + comp_op_grain_extract, //----comp_op_grain_extract_rgb + comp_op_hue, //----comp_op_hue + comp_op_saturation, //----comp_op_saturation + comp_op_color, //----comp_op_color + comp_op_value, //----comp_op_value + //comp_op_colorize_alpha,//----comp_op_colorize_alpha + comp_op_linear_dodge, // comp_op_linear_dodge + comp_op_linear_burn, // comp_op_linear_burn + comp_op_divide, // comp_op_divide + end_of_comp_op_e +}; + +//====================================================comp_op_adaptor_rgba +template struct comp_op_adaptor_rgba +{ + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } +}; + +//=========================================comp_op_adaptor_clip_to_dst_rgba +template struct comp_op_adaptor_clip_to_dst_rgba +{ + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } +}; + +//================================================comp_op_adaptor_rgba_pre +template struct comp_op_adaptor_rgba_pre +{ + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + comp_op_table_rgba::g_comp_op_func[op](p, cr, cg, cb, ca, cover); + } +}; + +//=====================================comp_op_adaptor_clip_to_dst_rgba_pre +template struct comp_op_adaptor_clip_to_dst_rgba_pre +{ + typedef Order order_type; + typedef ColorT color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned op, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[Order::A]; + comp_op_table_rgba::g_comp_op_func[op] + (p, (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } +}; + +//=======================================================comp_adaptor_rgba +template struct comp_adaptor_rgba +{ + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + BlenderPre::blend_pix(p, + (cr * ca + base_mask) >> base_shift, + (cg * ca + base_mask) >> base_shift, + (cb * ca + base_mask) >> base_shift, + ca, cover); + } +}; + +//==========================================comp_adaptor_clip_to_dst_rgba +template struct comp_adaptor_clip_to_dst_rgba +{ + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + cr = (cr * ca + base_mask) >> base_shift; + cg = (cg * ca + base_mask) >> base_shift; + cb = (cb * ca + base_mask) >> base_shift; + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } +}; + +//======================================comp_adaptor_clip_to_dst_rgba_pre +template struct comp_adaptor_clip_to_dst_rgba_pre +{ + typedef typename BlenderPre::order_type order_type; + typedef typename BlenderPre::color_type color_type; + typedef typename color_type::value_type value_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_mask = color_type::base_mask + }; + + static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned ca, + unsigned cover) + { + unsigned da = p[order_type::A]; + BlenderPre::blend_pix(p, + (cr * da + base_mask) >> base_shift, + (cg * da + base_mask) >> base_shift, + (cb * da + base_mask) >> base_shift, + (ca * da + base_mask) >> base_shift, + cover); + } +}; + + + + + + +//===============================================copy_or_blend_rgba_wrapper +template struct copy_or_blend_rgba_wrapper +{ + typedef typename Blender::color_type color_type; + typedef typename Blender::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask + }; + + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha) + { + if(alpha) + { + if(alpha == base_mask) { - p[Order::R] = (dr * da + 255) >> 8; - p[Order::G] = (dg * da + 255) >> 8; - p[Order::B] = (db * da + 255) >> 8; + p[order_type::R] = cr; + p[order_type::G] = cg; + p[order_type::B] = cb; + p[order_type::A] = base_mask; } else { - p[Order::R] = dr; - p[Order::G] = dg; - p[Order::B] = db; + Blender::blend_pix(p, cr, cg, cb, alpha); } } - }; + } - template - struct comp_op_rgba_hue + //-------------------------------------------------------------------- + static AGG_INLINE void copy_or_blend_pix(value_type* p, + unsigned cr, unsigned cg, unsigned cb, + unsigned alpha, + unsigned cover) { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e + if(cover == 255) { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover); - }; - - template - struct comp_op_rgba_saturation - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover); - }; - - template - struct comp_op_rgba_color - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover); - }; - - - template - struct comp_op_rgba_value - { - typedef ColorT color_type; - typedef Order order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef typename color_type::long_type long_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static void blend_pix(value_type* p, - unsigned sr, unsigned sg, unsigned sb, - unsigned sa, unsigned cover); - }; - - //======================================================comp_op_table_rgba - template struct comp_op_table_rgba - { - typedef typename ColorT::value_type value_type; - typedef void (*comp_op_func_type)(value_type* p, - unsigned cr, - unsigned cg, - unsigned cb, - unsigned ca, - unsigned cover); - static comp_op_func_type g_comp_op_func[]; - }; - - //==========================================================g_comp_op_func - template - typename comp_op_table_rgba::comp_op_func_type - comp_op_table_rgba::g_comp_op_func[] = - { - comp_op_rgba_clear ::blend_pix, - comp_op_rgba_src ::blend_pix, - comp_op_rgba_dst ::blend_pix, - comp_op_rgba_src_over ::blend_pix, - comp_op_rgba_dst_over ::blend_pix, - comp_op_rgba_src_in ::blend_pix, - comp_op_rgba_dst_in ::blend_pix, - comp_op_rgba_src_out ::blend_pix, - comp_op_rgba_dst_out ::blend_pix, - comp_op_rgba_src_atop ::blend_pix, - comp_op_rgba_dst_atop ::blend_pix, - comp_op_rgba_xor ::blend_pix, - comp_op_rgba_plus ::blend_pix, - comp_op_rgba_minus ::blend_pix, - comp_op_rgba_multiply ::blend_pix, - comp_op_rgba_screen ::blend_pix, - comp_op_rgba_overlay ::blend_pix, - comp_op_rgba_darken ::blend_pix, - comp_op_rgba_lighten ::blend_pix, - comp_op_rgba_color_dodge::blend_pix, - comp_op_rgba_color_burn ::blend_pix, - comp_op_rgba_hard_light ::blend_pix, - comp_op_rgba_soft_light ::blend_pix, - comp_op_rgba_difference ::blend_pix, - comp_op_rgba_exclusion ::blend_pix, - comp_op_rgba_contrast ::blend_pix, - comp_op_rgba_invert ::blend_pix, - comp_op_rgba_invert_rgb ::blend_pix, - comp_op_rgba_grain_merge::blend_pix, - comp_op_rgba_grain_extract::blend_pix, - comp_op_rgba_hue::blend_pix, - comp_op_rgba_saturation::blend_pix, - comp_op_rgba_color::blend_pix, - comp_op_rgba_value::blend_pix, - //comp_op_rgba_colorize_alpha::blend_pix, - 0 - }; - - - //==============================================================comp_op_e - enum comp_op_e - { - comp_op_clear, //----comp_op_clear - comp_op_src, //----comp_op_src - comp_op_dst, //----comp_op_dst - comp_op_src_over, //----comp_op_src_over - comp_op_dst_over, //----comp_op_dst_over - comp_op_src_in, //----comp_op_src_in - comp_op_dst_in, //----comp_op_dst_in - comp_op_src_out, //----comp_op_src_out - comp_op_dst_out, //----comp_op_dst_out - comp_op_src_atop, //----comp_op_src_atop - comp_op_dst_atop, //----comp_op_dst_atop - comp_op_xor, //----comp_op_xor - comp_op_plus, //----comp_op_plus - comp_op_minus, //----comp_op_minus - comp_op_multiply, //----comp_op_multiply - comp_op_screen, //----comp_op_screen - comp_op_overlay, //----comp_op_overlay - comp_op_darken, //----comp_op_darken - comp_op_lighten, //----comp_op_lighten - comp_op_color_dodge, //----comp_op_color_dodge - comp_op_color_burn, //----comp_op_color_burn - comp_op_hard_light, //----comp_op_hard_light - comp_op_soft_light, //----comp_op_soft_light - comp_op_difference, //----comp_op_difference - comp_op_exclusion, //----comp_op_exclusion - comp_op_contrast, //----comp_op_contrast - comp_op_invert, //----comp_op_invert - comp_op_invert_rgb, //----comp_op_invert_rgb - comp_op_grain_merge, //----comp_op_grain_merge_rgb - comp_op_grain_extract, //----comp_op_grain_extract_rgb - comp_op_hue, //----comp_op_hue - comp_op_saturation, //----comp_op_saturation - comp_op_color, //----comp_op_color - comp_op_value, //----comp_op_value - //comp_op_colorize_alpha,//----comp_op_colorize_alpha - end_of_comp_op_e - }; - - //====================================================comp_op_adaptor_rgba - template struct comp_op_adaptor_rgba - { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * ca + base_mask) >> base_shift, - (cg * ca + base_mask) >> base_shift, - (cb * ca + base_mask) >> base_shift, - ca, cover); + copy_or_blend_pix(p, cr, cg, cb, alpha); } - }; - - //=========================================comp_op_adaptor_clip_to_dst_rgba - template struct comp_op_adaptor_clip_to_dst_rgba - { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - cr = (cr * ca + base_mask) >> base_shift; - cg = (cg * ca + base_mask) >> base_shift; - cb = (cb * ca + base_mask) >> base_shift; - unsigned da = p[Order::A]; - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } - }; - - //================================================comp_op_adaptor_rgba_pre - template struct comp_op_adaptor_rgba_pre - { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - comp_op_table_rgba::g_comp_op_func[op](p, cr, cg, cb, ca, cover); - } - }; - - //=====================================comp_op_adaptor_clip_to_dst_rgba_pre - template struct comp_op_adaptor_clip_to_dst_rgba_pre - { - typedef Order order_type; - typedef ColorT color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(unsigned op, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - unsigned da = p[Order::A]; - comp_op_table_rgba::g_comp_op_func[op] - (p, (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } - }; - - //=======================================================comp_adaptor_rgba - template struct comp_adaptor_rgba - { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - BlenderPre::blend_pix(p, - (cr * ca + base_mask) >> base_shift, - (cg * ca + base_mask) >> base_shift, - (cb * ca + base_mask) >> base_shift, - ca, cover); - } - }; - - //==========================================comp_adaptor_clip_to_dst_rgba - template struct comp_adaptor_clip_to_dst_rgba - { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - cr = (cr * ca + base_mask) >> base_shift; - cg = (cg * ca + base_mask) >> base_shift; - cb = (cb * ca + base_mask) >> base_shift; - unsigned da = p[order_type::A]; - BlenderPre::blend_pix(p, - (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } - }; - - //======================================comp_adaptor_clip_to_dst_rgba_pre - template struct comp_adaptor_clip_to_dst_rgba_pre - { - typedef typename BlenderPre::order_type order_type; - typedef typename BlenderPre::color_type color_type; - typedef typename color_type::value_type value_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_mask = color_type::base_mask - }; - - static AGG_INLINE void blend_pix(unsigned /*op*/, value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned ca, - unsigned cover) - { - unsigned da = p[order_type::A]; - BlenderPre::blend_pix(p, - (cr * da + base_mask) >> base_shift, - (cg * da + base_mask) >> base_shift, - (cb * da + base_mask) >> base_shift, - (ca * da + base_mask) >> base_shift, - cover); - } - }; - - - - - - - //===============================================copy_or_blend_rgba_wrapper - template struct copy_or_blend_rgba_wrapper - { - typedef typename Blender::color_type color_type; - typedef typename Blender::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask - }; - - //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha) + else { if(alpha) { + alpha = (alpha * (cover + 1)) >> 8; if(alpha == base_mask) { p[order_type::R] = cr; @@ -1886,412 +2036,188 @@ namespace agg } else { - Blender::blend_pix(p, cr, cg, cb, alpha); + Blender::blend_pix(p, cr, cg, cb, alpha, cover); } } } + } +}; - //-------------------------------------------------------------------- - static AGG_INLINE void copy_or_blend_pix(value_type* p, - unsigned cr, unsigned cg, unsigned cb, - unsigned alpha, - unsigned cover) - { - if(cover == 255) - { - copy_or_blend_pix(p, cr, cg, cb, alpha); - } - else - { - if(alpha) - { - alpha = (alpha * (cover + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = cr; - p[order_type::G] = cg; - p[order_type::B] = cb; - p[order_type::A] = base_mask; - } - else - { - Blender::blend_pix(p, cr, cg, cb, alpha, cover); - } - } - } - } + + + + + +//=================================================pixfmt_alpha_blend_rgba +template +class pixfmt_alpha_blend_rgba +{ +public: + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef PixelT pixel_type; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + typedef copy_or_blend_rgba_wrapper cob_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(pixel_type) }; + //-------------------------------------------------------------------- + pixfmt_alpha_blend_rgba() : m_rbuf(0) {} + explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } - - - - - //=================================================pixfmt_alpha_blend_rgba - template - class pixfmt_alpha_blend_rgba + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) { - public: - typedef RenBuf rbuf_type; - typedef typename rbuf_type::row_data row_data; - typedef PixelT pixel_type; - typedef Blender blender_type; - typedef typename blender_type::color_type color_type; - typedef typename blender_type::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - typedef copy_or_blend_rgba_wrapper cob_type; - enum base_scale_e + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask, - pix_width = sizeof(pixel_type) - }; - - //-------------------------------------------------------------------- - pixfmt_alpha_blend_rgba() : m_rbuf(0) {} - explicit pixfmt_alpha_blend_rgba(rbuf_type& rb) : m_rbuf(&rb) {} - void attach(rbuf_type& rb) { m_rbuf = &rb; } - - //-------------------------------------------------------------------- - template - bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) - { - rect_i r(x1, y1, x2, y2); - if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) - { - int stride = pixf.stride(); - m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), - (r.x2 - r.x1) + 1, - (r.y2 - r.y1) + 1, - stride); - return true; - } - return false; + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; } + return false; + } - //-------------------------------------------------------------------- - AGG_INLINE unsigned width() const { return m_rbuf->width(); } - AGG_INLINE unsigned height() const { return m_rbuf->height(); } - AGG_INLINE int stride() const { return m_rbuf->stride(); } + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } - AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } - AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } - //-------------------------------------------------------------------- - AGG_INLINE int8u* pix_ptr(int x, int y) + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } + + //-------------------------------------------------------------------- + AGG_INLINE color_type pixel(int x, int y) const + { + const value_type* p = (const value_type*)m_rbuf->row_ptr(y); + if(p) { - return m_rbuf->row_ptr(y) + x * pix_width; + p += x << 2; + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); } + return color_type::no_color(); + } - AGG_INLINE const int8u* pix_ptr(int x, int y) const + //-------------------------------------------------------------------- + AGG_INLINE void copy_pixel(int x, int y, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = c.a; + } + + //-------------------------------------------------------------------- + AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + cob_type::copy_or_blend_pix( + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } + + + //-------------------------------------------------------------------- + AGG_INLINE void copy_hline(int x, int y, + unsigned len, + const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do { - return m_rbuf->row_ptr(y) + x * pix_width; + *(pixel_type*)p = v; + p += 4; } + while(--len); + } - //-------------------------------------------------------------------- - AGG_INLINE static void make_pix(int8u* p, const color_type& c) + //-------------------------------------------------------------------- + AGG_INLINE void copy_vline(int x, int y, + unsigned len, + const color_type& c) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do { - ((value_type*)p)[order_type::R] = c.r; - ((value_type*)p)[order_type::G] = c.g; - ((value_type*)p)[order_type::B] = c.b; - ((value_type*)p)[order_type::A] = c.a; - } - - //-------------------------------------------------------------------- - AGG_INLINE color_type pixel(int x, int y) const - { - const value_type* p = (const value_type*)m_rbuf->row_ptr(y); - if(p) - { - p += x << 2; - return color_type(p[order_type::R], - p[order_type::G], - p[order_type::B], - p[order_type::A]); - } - return color_type::no_color(); - } - - //-------------------------------------------------------------------- - AGG_INLINE void copy_pixel(int x, int y, const color_type& c) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2); - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = c.a; - } - - //-------------------------------------------------------------------- - AGG_INLINE void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - cob_type::copy_or_blend_pix( - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; } + while(--len); + } - //-------------------------------------------------------------------- - AGG_INLINE void copy_hline(int x, int y, - unsigned len, - const color_type& c) + //-------------------------------------------------------------------- + void blend_hline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) { value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) { - *(pixel_type*)p = v; - p += 4; - } - while(--len); - } - - - //-------------------------------------------------------------------- - AGG_INLINE void copy_vline(int x, int y, - unsigned len, - const color_type& c) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - *(pixel_type*)p = v; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - if (c.a) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - *(pixel_type*)p = v; - p += 4; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha); - p += 4; - } - while(--len); - } - else - { - do - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - p += 4; - } - while(--len); - } - } - } - } - - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, - unsigned len, - const color_type& c, - int8u cover) - { - if (c.a) - { - value_type* p; - calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; - if(alpha == base_mask) - { - pixel_type v; - ((value_type*)&v)[order_type::R] = c.r; - ((value_type*)&v)[order_type::G] = c.g; - ((value_type*)&v)[order_type::B] = c.b; - ((value_type*)&v)[order_type::A] = c.a; - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - *(pixel_type*)p = v; - } - while(--len); - } - else - { - if(cover == 255) - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - blender_type::blend_pix(p, c.r, c.g, c.b, alpha); - } - while(--len); - } - else - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); - } - while(--len); - } - } - } - } - - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - if (c.a) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; do { - calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = base_mask; - } - else - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); - } + *(pixel_type*)p = v; p += 4; - ++covers; - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, - unsigned len, - const color_type& c, - const int8u* covers) - { - if (c.a) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; - if(alpha == base_mask) - { - p[order_type::R] = c.r; - p[order_type::G] = c.g; - p[order_type::B] = c.b; - p[order_type::A] = base_mask; - } - else - { - blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); - } - ++covers; - } - while(--len); - } - } - - - //-------------------------------------------------------------------- - void copy_color_hspan(int x, int y, - unsigned len, - const color_type* colors) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - p += 4; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void copy_color_vspan(int x, int y, - unsigned len, - const color_type* colors) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - if(covers) - { - do - { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - *covers++); - p += 4; - ++colors; } while(--len); } @@ -2301,13 +2227,8 @@ namespace agg { do { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); p += 4; - ++colors; } while(--len); } @@ -2315,31 +2236,262 @@ namespace agg { do { - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - cover); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); p += 4; - ++colors; } while(--len); } } } + } - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, - unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) + //-------------------------------------------------------------------- + void blend_vline(int x, int y, + unsigned len, + const color_type& c, + int8u cover) + { + if (c.a) { value_type* p; - if(covers) + calc_type alpha = (calc_type(c.a) * (cover + 1)) >> 8; + if(alpha == base_mask) + { + pixel_type v; + ((value_type*)&v)[order_type::R] = c.r; + ((value_type*)&v)[order_type::G] = c.g; + ((value_type*)&v)[order_type::B] = c.b; + ((value_type*)&v)[order_type::A] = c.a; + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + *(pixel_type*)p = v; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha); + } + while(--len); + } + else + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, cover); + } + while(--len); + } + } + } + } + + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + p += 4; + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, + unsigned len, + const color_type& c, + const int8u* covers) + { + if (c.a) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + calc_type alpha = (calc_type(c.a) * (calc_type(*covers) + 1)) >> 8; + if(alpha == base_mask) + { + p[order_type::R] = c.r; + p[order_type::G] = c.g; + p[order_type::B] = c.b; + p[order_type::A] = base_mask; + } + else + { + blender_type::blend_pix(p, c.r, c.g, c.b, alpha, *covers); + } + ++covers; + } + while(--len); + } + } + + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + p += 4; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + } + while(--len); + } + + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + if(covers) + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + p += 4; + ++colors; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); + p += 4; + ++colors; + } + while(--len); + } + else + { + do + { + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + cover); + p += 4; + ++colors; + } + while(--len); + } + } + } + + + + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, + unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p; + if(covers) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a, + *covers++); + ++colors; + } + while(--len); + } + else + { + if(cover == 255) + { + do + { + p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + cob_type::copy_or_blend_pix(p, + colors->r, + colors->g, + colors->b, + colors->a); + ++colors; + } + while(--len); + } + else { do { @@ -2349,756 +2501,725 @@ namespace agg colors->g, colors->b, colors->a, - *covers++); + cover); ++colors; } while(--len); } + } + } + + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); + } + } + } + + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } + + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } + + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + + if(cover == 255) + { + do + { + cob_type::copy_or_blend_pix(pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A]); + psrc += incp; + pdst += incp; + } + while(--len); + } else { - if(cover == 255) - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a); - ++colors; - } - while(--len); - } - else - { - do - { - p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - cob_type::copy_or_blend_pix(p, - colors->r, - colors->g, - colors->b, - colors->a, - cover); - ++colors; - } - while(--len); - } - } - } - - //-------------------------------------------------------------------- - template void for_each_pixel(Function f) - { - unsigned y; - for(y = 0; y < height(); ++y) - { - row_data r = m_rbuf->row(y); - if(r.ptr) - { - unsigned len = r.x2 - r.x1 + 1; - value_type* p = - (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); - do - { - f(p); - p += 4; - } - while(--len); - } - } - } - - //-------------------------------------------------------------------- - void premultiply() - { - for_each_pixel(multiplier_rgba::premultiply); - } - - //-------------------------------------------------------------------- - void demultiply() - { - for_each_pixel(multiplier_rgba::demultiply); - } - - //-------------------------------------------------------------------- - template void apply_gamma_dir(const GammaLut& g) - { - for_each_pixel(apply_gamma_dir_rgba(g)); - } - - //-------------------------------------------------------------------- - template void apply_gamma_inv(const GammaLut& g) - { - for_each_pixel(apply_gamma_inv_rgba(g)); - } - - //-------------------------------------------------------------------- - template void copy_from(const RenBuf2& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - const int8u* p = from.row_ptr(ysrc); - if(p) - { - memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, - p + xsrc * pix_width, - len * pix_width); - } - } - - //-------------------------------------------------------------------- - template - void blend_from(const SrcPixelFormatRenderer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::order_type src_order; - const value_type* psrc = (value_type*)from.row_ptr(ysrc); - if(psrc) - { - psrc += xsrc << 2; - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - int incp = 4; - if(xdst > xsrc) - { - psrc += (len-1) << 2; - pdst += (len-1) << 2; - incp = -4; - } - - if(cover == 255) - { - do - { - cob_type::copy_or_blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A]); - psrc += incp; - pdst += incp; - } - while(--len); - } - else - { - do - { - cob_type::copy_or_blend_pix(pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A], - cover); - psrc += incp; - pdst += incp; - } - while(--len); - } - } - } - - //-------------------------------------------------------------------- - template - void blend_from_color(const SrcPixelFormatRenderer& from, - const color_type& color, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); do { cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a, - (*psrc * cover + base_mask) >> base_shift); - ++psrc; - pdst += 4; - } - while(--len); - } - } - - //-------------------------------------------------------------------- - template - void blend_from_lut(const SrcPixelFormatRenderer& from, - const color_type* color_lut, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) - { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - - if(cover == 255) - { - do - { - const color_type& color = color_lut[*psrc]; - cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a); - ++psrc; - pdst += 4; - } - while(--len); - } - else - { - do - { - const color_type& color = color_lut[*psrc]; - cob_type::copy_or_blend_pix(pdst, - color.r, color.g, color.b, color.a, - cover); - ++psrc; - pdst += 4; - } - while(--len); - } - } - } - - private: - rbuf_type* m_rbuf; - }; - - - - - //================================================pixfmt_custom_blend_rgba - template class pixfmt_custom_blend_rgba - { - public: - typedef RenBuf rbuf_type; - typedef typename rbuf_type::row_data row_data; - typedef Blender blender_type; - typedef typename blender_type::color_type color_type; - typedef typename blender_type::order_type order_type; - typedef typename color_type::value_type value_type; - typedef typename color_type::calc_type calc_type; - enum base_scale_e - { - base_shift = color_type::base_shift, - base_scale = color_type::base_scale, - base_mask = color_type::base_mask, - pix_width = sizeof(value_type) * 4 - }; - - - //-------------------------------------------------------------------- - pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} - explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : - m_rbuf(&rb), - m_comp_op(comp_op) - {} - void attach(rbuf_type& rb) { m_rbuf = &rb; } - - //-------------------------------------------------------------------- - template - bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) - { - rect_i r(x1, y1, x2, y2); - if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) - { - int stride = pixf.stride(); - m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), - (r.x2 - r.x1) + 1, - (r.y2 - r.y1) + 1, - stride); - return true; - } - return false; - } - - //-------------------------------------------------------------------- - AGG_INLINE unsigned width() const { return m_rbuf->width(); } - AGG_INLINE unsigned height() const { return m_rbuf->height(); } - AGG_INLINE int stride() const { return m_rbuf->stride(); } - - //-------------------------------------------------------------------- - AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } - AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } - AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } - - //-------------------------------------------------------------------- - AGG_INLINE int8u* pix_ptr(int x, int y) - { - return m_rbuf->row_ptr(y) + x * pix_width; - } - - AGG_INLINE const int8u* pix_ptr(int x, int y) const - { - return m_rbuf->row_ptr(y) + x * pix_width; - } - - //-------------------------------------------------------------------- - void comp_op(unsigned op) { m_comp_op = op; } - unsigned comp_op() const { return m_comp_op; } - - //-------------------------------------------------------------------- - AGG_INLINE static void make_pix(int8u* p, const color_type& c) - { - ((value_type*)p)[order_type::R] = c.r; - ((value_type*)p)[order_type::G] = c.g; - ((value_type*)p)[order_type::B] = c.b; - ((value_type*)p)[order_type::A] = c.a; - } - - //-------------------------------------------------------------------- - color_type pixel(int x, int y) const - { - const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); - return color_type(p[order_type::R], - p[order_type::G], - p[order_type::B], - p[order_type::A]); - } - - //-------------------------------------------------------------------- - void copy_pixel(int x, int y, const color_type& c) - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, 255); - } - - //-------------------------------------------------------------------- - void blend_pixel(int x, int y, const color_type& c, int8u cover) - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); - } - - //-------------------------------------------------------------------- - void copy_hline(int x, int y, unsigned len, const color_type& c) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);; - do - { - blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); - p += 4; - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_vline(int x, int y, unsigned len, const color_type& c) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, 255); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_hline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); - p += 4; - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_vline(int x, int y, unsigned len, - const color_type& c, int8u cover) - { - - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, - cover); - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_solid_hspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, - p, c.r, c.g, c.b, c.a, - *covers++); - p += 4; - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_solid_vspan(int x, int y, unsigned len, - const color_type& c, const int8u* covers) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - c.r, c.g, c.b, c.a, - *covers++); - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_color_hspan(int x, int y, - unsigned len, - const color_type* colors) - { - - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - p += 4; - } - while(--len); - } - - //-------------------------------------------------------------------- - void copy_color_vspan(int x, int y, - unsigned len, - const color_type* colors) - { - do - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); - p[order_type::R] = colors->r; - p[order_type::G] = colors->g; - p[order_type::B] = colors->b; - p[order_type::A] = colors->a; - ++colors; - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_color_hspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, - p, - colors->r, - colors->g, - colors->b, - colors->a, - covers ? *covers++ : cover); - p += 4; - ++colors; - } - while(--len); - } - - //-------------------------------------------------------------------- - void blend_color_hspan_alpha(int x, int y, unsigned len, - const color_type* colors, - value_type alpha, - const int8u* covers, - int8u cover) - { - value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); - do - { - blender_type::blend_pix(m_comp_op, - p, - (colors->r * alpha + 255) >> 8, - (colors->g * alpha + 255) >> 8, - (colors->b * alpha + 255) >> 8, - (colors->a * alpha + 255) >> 8, - covers ? *covers++ : cover); - p += 4; - ++colors; - } - while(--len); - } - - - //-------------------------------------------------------------------- - void blend_color_vspan(int x, int y, unsigned len, - const color_type* colors, - const int8u* covers, - int8u cover) - { - do - { - blender_type::blend_pix( - m_comp_op, - (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), - colors->r, - colors->g, - colors->b, - colors->a, - covers ? *covers++ : cover); - ++colors; - } - while(--len); - - } - - //-------------------------------------------------------------------- - template void for_each_pixel(Function f) - { - unsigned y; - for(y = 0; y < height(); ++y) - { - row_data r = m_rbuf->row(y); - if(r.ptr) - { - unsigned len = r.x2 - r.x1 + 1; - value_type* p = - (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); - do - { - f(p); - p += 4; - } - while(--len); - } - } - } - - //-------------------------------------------------------------------- - void premultiply() - { - for_each_pixel(multiplier_rgba::premultiply); - } - - //-------------------------------------------------------------------- - void demultiply() - { - for_each_pixel(multiplier_rgba::demultiply); - } - - //-------------------------------------------------------------------- - template void apply_gamma_dir(const GammaLut& g) - { - for_each_pixel(apply_gamma_dir_rgba(g)); - } - - //-------------------------------------------------------------------- - template void apply_gamma_inv(const GammaLut& g) - { - for_each_pixel(apply_gamma_inv_rgba(g)); - } - - //-------------------------------------------------------------------- - template void copy_from(const RenBuf2& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len) - { - const int8u* p = from.row_ptr(ysrc); - if(p) - { - memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, - p + xsrc * pix_width, - len * pix_width); - } - } - - //-------------------------------------------------------------------- - template - void blend_from(const SrcPixelFormatRenderer& from, - int xdst, int ydst, - int xsrc, int ysrc, - unsigned len, - int8u cover) - { - typedef typename SrcPixelFormatRenderer::order_type src_order; - const value_type* psrc = (const value_type*)from.row_ptr(ysrc); - if(psrc) - { - psrc += xsrc << 2; - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - - int incp = 4; - if(xdst > xsrc) - { - psrc += (len-1) << 2; - pdst += (len-1) << 2; - incp = -4; - } - - do - { - blender_type::blend_pix(m_comp_op, - pdst, - psrc[src_order::R], - psrc[src_order::G], - psrc[src_order::B], - psrc[src_order::A], - cover); + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); psrc += incp; pdst += incp; } while(--len); } } + } - //-------------------------------------------------------------------- - template - void blend_from_color(const SrcPixelFormatRenderer& from, - const color_type& color, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); - do - { - blender_type::blend_pix(m_comp_op, - pdst, + cob_type::copy_or_blend_pix(pdst, color.r, color.g, color.b, color.a, (*psrc * cover + base_mask) >> base_shift); - ++psrc; - pdst += 4; - } - while(--len); + ++psrc; + pdst += 4; } + while(--len); } + } - //-------------------------------------------------------------------- - template - void blend_from_lut(const SrcPixelFormatRenderer& from, - const color_type* color_lut, - int xdst, int ydst, - int /*xsrc*/, int ysrc, - unsigned len, - int8u cover) + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) { - typedef typename SrcPixelFormatRenderer::value_type src_value_type; - const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); - if(psrc) + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + + if(cover == 255) { - value_type* pdst = - (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); do { const color_type& color = color_lut[*psrc]; - blender_type::blend_pix(m_comp_op, - pdst, - color.r, color.g, color.b, color.a, - cover); + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a); + ++psrc; + pdst += 4; + } + while(--len); + } + else + { + do + { + const color_type& color = color_lut[*psrc]; + cob_type::copy_or_blend_pix(pdst, + color.r, color.g, color.b, color.a, + cover); ++psrc; pdst += 4; } while(--len); } } + } - private: - rbuf_type* m_rbuf; - unsigned m_comp_op; +private: + rbuf_type* m_rbuf; +}; + + + + +//================================================pixfmt_custom_blend_rgba +template class pixfmt_custom_blend_rgba +{ +public: + typedef RenBuf rbuf_type; + typedef typename rbuf_type::row_data row_data; + typedef Blender blender_type; + typedef typename blender_type::color_type color_type; + typedef typename blender_type::order_type order_type; + typedef typename color_type::value_type value_type; + typedef typename color_type::calc_type calc_type; + enum base_scale_e + { + base_shift = color_type::base_shift, + base_scale = color_type::base_scale, + base_mask = color_type::base_mask, + pix_width = sizeof(value_type) * 4 }; + //-------------------------------------------------------------------- + pixfmt_custom_blend_rgba() : m_rbuf(0), m_comp_op(3) {} + explicit pixfmt_custom_blend_rgba(rbuf_type& rb, unsigned comp_op=3) : + m_rbuf(&rb), + m_comp_op(comp_op) + {} + void attach(rbuf_type& rb) { m_rbuf = &rb; } + + //-------------------------------------------------------------------- + template + bool attach(PixFmt& pixf, int x1, int y1, int x2, int y2) + { + rect_i r(x1, y1, x2, y2); + if(r.clip(rect_i(0, 0, pixf.width()-1, pixf.height()-1))) + { + int stride = pixf.stride(); + m_rbuf->attach(pixf.pix_ptr(r.x1, stride < 0 ? r.y2 : r.y1), + (r.x2 - r.x1) + 1, + (r.y2 - r.y1) + 1, + stride); + return true; + } + return false; + } + + //-------------------------------------------------------------------- + AGG_INLINE unsigned width() const { return m_rbuf->width(); } + AGG_INLINE unsigned height() const { return m_rbuf->height(); } + AGG_INLINE int stride() const { return m_rbuf->stride(); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* row_ptr(int y) { return m_rbuf->row_ptr(y); } + AGG_INLINE const int8u* row_ptr(int y) const { return m_rbuf->row_ptr(y); } + AGG_INLINE row_data row(int y) const { return m_rbuf->row(y); } + + //-------------------------------------------------------------------- + AGG_INLINE int8u* pix_ptr(int x, int y) + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + AGG_INLINE const int8u* pix_ptr(int x, int y) const + { + return m_rbuf->row_ptr(y) + x * pix_width; + } + + //-------------------------------------------------------------------- + void comp_op(unsigned op) { m_comp_op = op; } + unsigned comp_op() const { return m_comp_op; } + + //-------------------------------------------------------------------- + AGG_INLINE static void make_pix(int8u* p, const color_type& c) + { + ((value_type*)p)[order_type::R] = c.r; + ((value_type*)p)[order_type::G] = c.g; + ((value_type*)p)[order_type::B] = c.b; + ((value_type*)p)[order_type::A] = c.a; + } + + //-------------------------------------------------------------------- + color_type pixel(int x, int y) const + { + const value_type* p = (value_type*)m_rbuf->row_ptr(y) + (x << 2); + return color_type(p[order_type::R], + p[order_type::G], + p[order_type::B], + p[order_type::A]); + } + + //-------------------------------------------------------------------- + void copy_pixel(int x, int y, const color_type& c) + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); + } + + //-------------------------------------------------------------------- + void blend_pixel(int x, int y, const color_type& c, int8u cover) + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } + + //-------------------------------------------------------------------- + void copy_hline(int x, int y, unsigned len, const color_type& c) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2);; + do + { + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, 255); + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_vline(int x, int y, unsigned len, const color_type& c) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, 255); + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_hline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, p, c.r, c.g, c.b, c.a, cover); + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_vline(int x, int y, unsigned len, + const color_type& c, int8u cover) + { + + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + cover); + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_solid_hspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, c.r, c.g, c.b, c.a, + *covers++); + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_solid_vspan(int x, int y, unsigned len, + const color_type& c, const int8u* covers) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + c.r, c.g, c.b, c.a, + *covers++); + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_hspan(int x, int y, + unsigned len, + const color_type* colors) + { + + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + p += 4; + } + while(--len); + } + + //-------------------------------------------------------------------- + void copy_color_vspan(int x, int y, + unsigned len, + const color_type* colors) + { + do + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2); + p[order_type::R] = colors->r; + p[order_type::G] = colors->g; + p[order_type::B] = colors->b; + p[order_type::A] = colors->a; + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + p += 4; + ++colors; + } + while(--len); + } + + //-------------------------------------------------------------------- + void blend_color_hspan_alpha(int x, int y, unsigned len, + const color_type* colors, + value_type alpha, + const int8u* covers, + int8u cover) + { + value_type* p = (value_type*)m_rbuf->row_ptr(x, y, len) + (x << 2); + do + { + blender_type::blend_pix(m_comp_op, + p, + (colors->r * alpha + 255) >> 8, + (colors->g * alpha + 255) >> 8, + (colors->b * alpha + 255) >> 8, + (colors->a * alpha + 255) >> 8, + covers ? *covers++ : cover); + p += 4; + ++colors; + } + while(--len); + } - //----------------------------------------------------------------------- - typedef blender_rgba blender_rgba32; //----blender_rgba32 - typedef blender_rgba blender_argb32; //----blender_argb32 - typedef blender_rgba blender_abgr32; //----blender_abgr32 - typedef blender_rgba blender_bgra32; //----blender_bgra32 + //-------------------------------------------------------------------- + void blend_color_vspan(int x, int y, unsigned len, + const color_type* colors, + const int8u* covers, + int8u cover) + { + do + { + blender_type::blend_pix( + m_comp_op, + (value_type*)m_rbuf->row_ptr(x, y++, 1) + (x << 2), + colors->r, + colors->g, + colors->b, + colors->a, + covers ? *covers++ : cover); + ++colors; + } + while(--len); - typedef blender_rgba_pre blender_rgba32_pre; //----blender_rgba32_pre - typedef blender_rgba_pre blender_argb32_pre; //----blender_argb32_pre - typedef blender_rgba_pre blender_abgr32_pre; //----blender_abgr32_pre - typedef blender_rgba_pre blender_bgra32_pre; //----blender_bgra32_pre + } - typedef blender_rgba_plain blender_rgba32_plain; //----blender_rgba32_plain - typedef blender_rgba_plain blender_argb32_plain; //----blender_argb32_plain - typedef blender_rgba_plain blender_abgr32_plain; //----blender_abgr32_plain - typedef blender_rgba_plain blender_bgra32_plain; //----blender_bgra32_plain + //-------------------------------------------------------------------- + template void for_each_pixel(Function f) + { + unsigned y; + for(y = 0; y < height(); ++y) + { + row_data r = m_rbuf->row(y); + if(r.ptr) + { + unsigned len = r.x2 - r.x1 + 1; + value_type* p = + (value_type*)m_rbuf->row_ptr(r.x1, y, len) + (r.x1 << 2); + do + { + f(p); + p += 4; + } + while(--len); + } + } + } - typedef blender_rgba blender_rgba64; //----blender_rgba64 - typedef blender_rgba blender_argb64; //----blender_argb64 - typedef blender_rgba blender_abgr64; //----blender_abgr64 - typedef blender_rgba blender_bgra64; //----blender_bgra64 + //-------------------------------------------------------------------- + void premultiply() + { + for_each_pixel(multiplier_rgba::premultiply); + } - typedef blender_rgba_pre blender_rgba64_pre; //----blender_rgba64_pre - typedef blender_rgba_pre blender_argb64_pre; //----blender_argb64_pre - typedef blender_rgba_pre blender_abgr64_pre; //----blender_abgr64_pre - typedef blender_rgba_pre blender_bgra64_pre; //----blender_bgra64_pre + //-------------------------------------------------------------------- + void demultiply() + { + for_each_pixel(multiplier_rgba::demultiply); + } + + //-------------------------------------------------------------------- + template void apply_gamma_dir(const GammaLut& g) + { + for_each_pixel(apply_gamma_dir_rgba(g)); + } + + //-------------------------------------------------------------------- + template void apply_gamma_inv(const GammaLut& g) + { + for_each_pixel(apply_gamma_inv_rgba(g)); + } + + //-------------------------------------------------------------------- + template void copy_from(const RenBuf2& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len) + { + const int8u* p = from.row_ptr(ysrc); + if(p) + { + memmove(m_rbuf->row_ptr(xdst, ydst, len) + xdst * pix_width, + p + xsrc * pix_width, + len * pix_width); + } + } + + //-------------------------------------------------------------------- + template + void blend_from(const SrcPixelFormatRenderer& from, + int xdst, int ydst, + int xsrc, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::order_type src_order; + const value_type* psrc = (const value_type*)from.row_ptr(ysrc); + if(psrc) + { + psrc += xsrc << 2; + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + + int incp = 4; + if(xdst > xsrc) + { + psrc += (len-1) << 2; + pdst += (len-1) << 2; + incp = -4; + } + + do + { + blender_type::blend_pix(m_comp_op, + pdst, + psrc[src_order::R], + psrc[src_order::G], + psrc[src_order::B], + psrc[src_order::A], + cover); + psrc += incp; + pdst += incp; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template + void blend_from_color(const SrcPixelFormatRenderer& from, + const color_type& color, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + (*psrc * cover + base_mask) >> base_shift); + ++psrc; + pdst += 4; + } + while(--len); + } + } + + //-------------------------------------------------------------------- + template + void blend_from_lut(const SrcPixelFormatRenderer& from, + const color_type* color_lut, + int xdst, int ydst, + int /*xsrc*/, int ysrc, + unsigned len, + int8u cover) + { + typedef typename SrcPixelFormatRenderer::value_type src_value_type; + const src_value_type* psrc = (src_value_type*)from.row_ptr(ysrc); + if(psrc) + { + value_type* pdst = + (value_type*)m_rbuf->row_ptr(xdst, ydst, len) + (xdst << 2); + do + { + const color_type& color = color_lut[*psrc]; + blender_type::blend_pix(m_comp_op, + pdst, + color.r, color.g, color.b, color.a, + cover); + ++psrc; + pdst += 4; + } + while(--len); + } + } + +private: + rbuf_type* m_rbuf; + unsigned m_comp_op; +}; - //----------------------------------------------------------------------- - typedef int32u pixel32_type; - typedef pixfmt_alpha_blend_rgba pixfmt_rgba32; //----pixfmt_rgba32 - typedef pixfmt_alpha_blend_rgba pixfmt_argb32; //----pixfmt_argb32 - typedef pixfmt_alpha_blend_rgba pixfmt_abgr32; //----pixfmt_abgr32 - typedef pixfmt_alpha_blend_rgba pixfmt_bgra32; //----pixfmt_bgra32 - typedef pixfmt_alpha_blend_rgba pixfmt_rgba32_pre; //----pixfmt_rgba32_pre - typedef pixfmt_alpha_blend_rgba pixfmt_argb32_pre; //----pixfmt_argb32_pre - typedef pixfmt_alpha_blend_rgba pixfmt_abgr32_pre; //----pixfmt_abgr32_pre - typedef pixfmt_alpha_blend_rgba pixfmt_bgra32_pre; //----pixfmt_bgra32_pre - typedef pixfmt_alpha_blend_rgba pixfmt_rgba32_plain; //----pixfmt_rgba32_plain - typedef pixfmt_alpha_blend_rgba pixfmt_argb32_plain; //----pixfmt_argb32_plain - typedef pixfmt_alpha_blend_rgba pixfmt_abgr32_plain; //----pixfmt_abgr32_plain - typedef pixfmt_alpha_blend_rgba pixfmt_bgra32_plain; //----pixfmt_bgra32_plain +//----------------------------------------------------------------------- +typedef blender_rgba blender_rgba32; //----blender_rgba32 +typedef blender_rgba blender_argb32; //----blender_argb32 +typedef blender_rgba blender_abgr32; //----blender_abgr32 +typedef blender_rgba blender_bgra32; //----blender_bgra32 - struct pixel64_type { int16u c[4]; }; - typedef pixfmt_alpha_blend_rgba pixfmt_rgba64; //----pixfmt_rgba64 - typedef pixfmt_alpha_blend_rgba pixfmt_argb64; //----pixfmt_argb64 - typedef pixfmt_alpha_blend_rgba pixfmt_abgr64; //----pixfmt_abgr64 - typedef pixfmt_alpha_blend_rgba pixfmt_bgra64; //----pixfmt_bgra64 +typedef blender_rgba_pre blender_rgba32_pre; //----blender_rgba32_pre +typedef blender_rgba_pre blender_argb32_pre; //----blender_argb32_pre +typedef blender_rgba_pre blender_abgr32_pre; //----blender_abgr32_pre +typedef blender_rgba_pre blender_bgra32_pre; //----blender_bgra32_pre - typedef pixfmt_alpha_blend_rgba pixfmt_rgba64_pre; //----pixfmt_rgba64_pre - typedef pixfmt_alpha_blend_rgba pixfmt_argb64_pre; //----pixfmt_argb64_pre - typedef pixfmt_alpha_blend_rgba pixfmt_abgr64_pre; //----pixfmt_abgr64_pre - typedef pixfmt_alpha_blend_rgba pixfmt_bgra64_pre; //----pixfmt_bgra64_pre +typedef blender_rgba_plain blender_rgba32_plain; //----blender_rgba32_plain +typedef blender_rgba_plain blender_argb32_plain; //----blender_argb32_plain +typedef blender_rgba_plain blender_abgr32_plain; //----blender_abgr32_plain +typedef blender_rgba_plain blender_bgra32_plain; //----blender_bgra32_plain + +typedef blender_rgba blender_rgba64; //----blender_rgba64 +typedef blender_rgba blender_argb64; //----blender_argb64 +typedef blender_rgba blender_abgr64; //----blender_abgr64 +typedef blender_rgba blender_bgra64; //----blender_bgra64 + +typedef blender_rgba_pre blender_rgba64_pre; //----blender_rgba64_pre +typedef blender_rgba_pre blender_argb64_pre; //----blender_argb64_pre +typedef blender_rgba_pre blender_abgr64_pre; //----blender_abgr64_pre +typedef blender_rgba_pre blender_bgra64_pre; //----blender_bgra64_pre + + +//----------------------------------------------------------------------- +typedef int32u pixel32_type; +typedef pixfmt_alpha_blend_rgba pixfmt_rgba32; //----pixfmt_rgba32 +typedef pixfmt_alpha_blend_rgba pixfmt_argb32; //----pixfmt_argb32 +typedef pixfmt_alpha_blend_rgba pixfmt_abgr32; //----pixfmt_abgr32 +typedef pixfmt_alpha_blend_rgba pixfmt_bgra32; //----pixfmt_bgra32 + +typedef pixfmt_alpha_blend_rgba pixfmt_rgba32_pre; //----pixfmt_rgba32_pre +typedef pixfmt_alpha_blend_rgba pixfmt_argb32_pre; //----pixfmt_argb32_pre +typedef pixfmt_alpha_blend_rgba pixfmt_abgr32_pre; //----pixfmt_abgr32_pre +typedef pixfmt_alpha_blend_rgba pixfmt_bgra32_pre; //----pixfmt_bgra32_pre + +typedef pixfmt_alpha_blend_rgba pixfmt_rgba32_plain; //----pixfmt_rgba32_plain +typedef pixfmt_alpha_blend_rgba pixfmt_argb32_plain; //----pixfmt_argb32_plain +typedef pixfmt_alpha_blend_rgba pixfmt_abgr32_plain; //----pixfmt_abgr32_plain +typedef pixfmt_alpha_blend_rgba pixfmt_bgra32_plain; //----pixfmt_bgra32_plain + +struct pixel64_type { int16u c[4]; }; +typedef pixfmt_alpha_blend_rgba pixfmt_rgba64; //----pixfmt_rgba64 +typedef pixfmt_alpha_blend_rgba pixfmt_argb64; //----pixfmt_argb64 +typedef pixfmt_alpha_blend_rgba pixfmt_abgr64; //----pixfmt_abgr64 +typedef pixfmt_alpha_blend_rgba pixfmt_bgra64; //----pixfmt_bgra64 + +typedef pixfmt_alpha_blend_rgba pixfmt_rgba64_pre; //----pixfmt_rgba64_pre +typedef pixfmt_alpha_blend_rgba pixfmt_argb64_pre; //----pixfmt_argb64_pre +typedef pixfmt_alpha_blend_rgba pixfmt_abgr64_pre; //----pixfmt_abgr64_pre +typedef pixfmt_alpha_blend_rgba pixfmt_bgra64_pre; //----pixfmt_bgra64_pre } #endif diff --git a/include/mapnik/image_compositing.hpp b/include/mapnik/image_compositing.hpp index f0e39a901..5a7ac0025 100644 --- a/include/mapnik/image_compositing.hpp +++ b/include/mapnik/image_compositing.hpp @@ -74,7 +74,10 @@ enum composite_mode_e hue, saturation, _color, - _value + _value, + linear_dodge, + linear_burn, + divide }; MAPNIK_DECL boost::optional comp_op_from_string(std::string const& name); diff --git a/src/cairo/cairo_context.cpp b/src/cairo/cairo_context.cpp index 47f1305fc..c0f5978f0 100644 --- a/src/cairo/cairo_context.cpp +++ b/src/cairo/cairo_context.cpp @@ -179,6 +179,9 @@ void cairo_context::set_operator(composite_mode_e comp_op) case saturation: case _color: case _value: + case linear_dodge: + case linear_burn: + case divide: //case colorize_alpha: break; } diff --git a/src/image_compositing.cpp b/src/image_compositing.cpp index 2b0ff12b7..f971a5c23 100644 --- a/src/image_compositing.cpp +++ b/src/image_compositing.cpp @@ -75,6 +75,9 @@ static const comp_op_lookup_type comp_lookup = boost::assign::list_of comp_op_from_string(std::string const& name) From a8c6c5d71e60c7b25d38f1801d2887552ca7fed3 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 10:06:57 -0700 Subject: [PATCH 04/92] travis: upgrade harfbuzz to 0.9.34 --- .travis.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/.travis.yml b/.travis.yml index 2cd4df6af..b07d969c3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,9 +19,9 @@ before_install: - sudo add-apt-repository -y ppa:boost-latest/ppa - sudo apt-get update -y - sudo apt-get install -y gcc-4.8 g++-4.8 make boost1.55 libgdal-dev libgdal1-dev libgdal1h=1.10.0-1~precise1 python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev libcairo-dev python-cairo-dev libsqlite3-dev - - wget http://mapnik.s3.amazonaws.com/deps/harfbuzz-0.9.32.tar.bz2 - - tar xf harfbuzz-0.9.32.tar.bz2 - - cd harfbuzz-0.9.32 + - wget http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-0.9.34.tar.bz2 + - tar xf harfbuzz-0.9.34.tar.bz2 + - cd harfbuzz-0.9.34 - ./configure --with-icu --with-cairo=no --with-glib=no --with-gobject=no --with-graphite2=no --with-freetype --with-uniscribe=no --with-coretext=no && make && sudo make install - sudo ldconfig - cd ../ From 5af394e4967cdab38cb8745589ddce2297b5d03e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 10:24:11 -0700 Subject: [PATCH 05/92] scons: ensure cairo_renderer.cpp is built farther in the stack away from expression_grammar.cpp --- src/build.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/build.py b/src/build.py index 1d9617671..b49aa2d83 100644 --- a/src/build.py +++ b/src/build.py @@ -271,8 +271,8 @@ if env['HAS_CAIRO']: lib_env.Append(CPPDEFINES = '-DHAVE_CAIRO') libmapnik_defines.append('-DHAVE_CAIRO') lib_env.AppendUnique(CPPPATH=copy(env['CAIRO_CPPPATHS'])) - source.insert(0,'cairo/cairo_renderer.cpp') - source.insert(0,'cairo/cairo_context.cpp') + source.append('cairo/cairo_renderer.cpp') + source.append('cairo/cairo_context.cpp') for cpp in enabled_imaging_libraries: source.append(cpp) From a865a47cb5c94920b4d6b12f4ae8c30d812a97ce Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 10:24:27 -0700 Subject: [PATCH 06/92] travis: debug broken clang++ build with harfbuzz --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b07d969c3..5cbf15f9e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,6 +19,8 @@ before_install: - sudo add-apt-repository -y ppa:boost-latest/ppa - sudo apt-get update -y - sudo apt-get install -y gcc-4.8 g++-4.8 make boost1.55 libgdal-dev libgdal1-dev libgdal1h=1.10.0-1~precise1 python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev libcairo-dev python-cairo-dev libsqlite3-dev + - if [[ "${CXX}" == 'g++' ]]; then export CXX="g++-4.8" && export CC="gcc-4.8"; fi; + - if [[ "${CXX}" == 'clang++' ]]; then echo `which clang`; echo `which clang++`; fi; - wget http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-0.9.34.tar.bz2 - tar xf harfbuzz-0.9.34.tar.bz2 - cd harfbuzz-0.9.34 @@ -27,7 +29,6 @@ before_install: - cd ../ install: - - if [[ "${CXX}" == 'g++' ]]; then export CXX="g++-4.8" && export CC="gcc-4.8"; fi; - ./configure CXX="${CXX}" CC="${CC}" DEMO=True BENCHMARK=True CPP_TESTS=True CAIRO=True FAST=True - if [[ "${CXX}" == 'g++-4.8' ]]; then JOBS=3 make; else JOBS=10 make; fi; From 0da6098b35dd289d7d0501dadb3ebf5a5ded7c10 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 10:36:43 -0700 Subject: [PATCH 07/92] travis: try full path to clang++ to work around broken libtool/ linking of libharfbuzz-icu --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 5cbf15f9e..7731a48ec 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,8 +19,8 @@ before_install: - sudo add-apt-repository -y ppa:boost-latest/ppa - sudo apt-get update -y - sudo apt-get install -y gcc-4.8 g++-4.8 make boost1.55 libgdal-dev libgdal1-dev libgdal1h=1.10.0-1~precise1 python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev libcairo-dev python-cairo-dev libsqlite3-dev - - if [[ "${CXX}" == 'g++' ]]; then export CXX="g++-4.8" && export CC="gcc-4.8"; fi; - - if [[ "${CXX}" == 'clang++' ]]; then echo `which clang`; echo `which clang++`; fi; + - if [[ "${CXX}" == 'g++' ]]; then export CXX="g++-4.8"; export CC="gcc-4.8"; fi; + - if [[ "${CXX}" == 'clang++' ]]; then export CXX="$(which clang++)"; export CC="$(which clang)"; fi; - wget http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-0.9.34.tar.bz2 - tar xf harfbuzz-0.9.34.tar.bz2 - cd harfbuzz-0.9.34 From 2b1ab49463d3f7b489bb9dab5131200397689a4f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 12:10:26 -0700 Subject: [PATCH 08/92] finish python bindings + tests for #1448 and #1432 --- bindings/python/mapnik_image.cpp | 3 + .../python_tests/images/composited/divide.png | Bin 0 -> 10492 bytes .../images/composited/linear_burn.png | Bin 0 -> 10261 bytes .../images/composited/linear_dodge.png | Bin 0 -> 14279 bytes .../images/style-comp-op/divide.png | Bin 0 -> 3587 bytes .../images/style-comp-op/linear_burn.png | Bin 0 -> 2356 bytes .../images/style-comp-op/linear_dodge.png | Bin 0 -> 14410 bytes ...ar-comp-op-500-100-1.0-grid-reference.json | 34 +++++++++ ...near-comp-op-500-100-1.0-agg-reference.png | Bin 0 -> 6419 bytes ...ar-comp-op-500-100-1.0-cairo-reference.png | Bin 0 -> 7564 bytes ...near-comp-op-500-100-2.0-agg-reference.png | Bin 0 -> 4137 bytes ...ar-comp-op-500-100-2.0-cairo-reference.png | Bin 0 -> 5219 bytes ...r-with-background-image-linear-comp-op.xml | 67 ++++++++++++++++++ tests/visual_tests/test.py | 1 + 14 files changed, 105 insertions(+) create mode 100644 tests/python_tests/images/composited/divide.png create mode 100644 tests/python_tests/images/composited/linear_burn.png create mode 100644 tests/python_tests/images/composited/linear_dodge.png create mode 100644 tests/python_tests/images/style-comp-op/divide.png create mode 100644 tests/python_tests/images/style-comp-op/linear_burn.png create mode 100644 tests/python_tests/images/style-comp-op/linear_dodge.png create mode 100644 tests/visual_tests/grids/marker-with-background-image-linear-comp-op-500-100-1.0-grid-reference.json create mode 100644 tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-1.0-agg-reference.png create mode 100644 tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-1.0-cairo-reference.png create mode 100644 tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-agg-reference.png create mode 100644 tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-cairo-reference.png create mode 100644 tests/visual_tests/styles/marker-with-background-image-linear-comp-op.xml diff --git a/bindings/python/mapnik_image.cpp b/bindings/python/mapnik_image.cpp index c95a25617..e668ba7b5 100644 --- a/bindings/python/mapnik_image.cpp +++ b/bindings/python/mapnik_image.cpp @@ -253,6 +253,9 @@ void export_image() .value("saturation", mapnik::saturation) .value("color", mapnik::_color) .value("value", mapnik::_value) + .value("linear_dodge", mapnik::linear_dodge) + .value("linear_burn", mapnik::linear_burn) + .value("divide", mapnik::divide) ; class_ >("Image","This class represents a 32 bit RGBA image.",init()) diff --git a/tests/python_tests/images/composited/divide.png b/tests/python_tests/images/composited/divide.png new file mode 100644 index 0000000000000000000000000000000000000000..0a4b24f05adca170186fdd80fa1a668ede2cc306 GIT binary patch literal 10492 zcmcI~_dnI||Nrw0$H6hOw__9;5i%lv3JzMsZxJ=s0F$$eZ&iXH?^q`!D@K5B_bqQ5>}p)I^?| zt*j$!{`zAXW6QhJW<5jGjjC?l*8ya6&0bwExA{LBY_sp6)nDfPdE9}#&)(b=drCG} zOJGby6ROFiDde60pUFABD*Y;>*zBpSU42m$RsB=EY2Zu75UvoBp8`#Yl@tf;)AXlF zswRRgZCv;NE)ui_Ffxm*^H@&^! zw;;8Eb`S3$KflhDQZ)u+GqgZWAnjh8p9B#G)EXg&3L)Yl%pv?AOh6k6vHMC3HVgU- z4MdTeu0FL0{wCHYPVe}qSYf!8qOsB2`{EErq^Ech{x)7GFVhL0{nGeUk@f6QOTd#^ z*8Y{Z7H3K;G#p#SK+PVC2|7dtQ|Sfy1z^9u!YudNU7ia;cYT(BNy1*A%lnK!MYQM7 zaLAy=AgP5>p?oZfHy9VZuyMv0Wo_96ywaZL2wvCahwSinm6|ds!_+!#4kTOHACjuI z&I{1qL22z(2P)F@n6<3-`RTDwsC$f0K0L*#{-$1hBN*4B8LG9pxKZ^@=+kajPU@z( z`OK%yCjQL!P%-Md;@0^GLNF+g$Ry5g(5n0cQE0k2ZHlhR7?(s=?9`4ZLl1hoN$HI2 z9pry`c7{V;q6}-nWuyC5XwJHh@{B)UojE?oE|^32;kSbobHe8~_TqWf=yPO`tjYX(v;K*NkY6OKU+XDu!)n>OXbzsKxJF(-f-q0`(tt zwj`JGjV(um3V7>Qok&{s4?1O#ZiuK?QHdx~Xw}-K+7rFJuNeEeVX_pZ_7c2*;!>6{-8C%bSmRNS8CYXZg&#e zG&VS!pDmqqb;&sEYfv=%QkPOt;KCcL_nYYT>WZ{0uze#cW6QJf(Zx*gy}zyNQ;kyy z0{O1CHfTLlm|;RP`1}V&@~E9{WlN-vKQWT<;ab!4$XIQbXorKu&V^A%FJBdZ!=Fc3 z>qxtkbLW);ZD3uGH|s;=CtRUzb`yc5Y2vjN@I}EODadF2?Pl^DB3Xhh>(7R*t`OJO zCF`i*?ev5p+X#8`=wCIc7+aA}smCoaaMq5G#n;&<^J*cbk za@UlPyu%W$TgQ8&#S^{v88(7(L0gyO(tg9#s+Fx;$56j@Ss$JJA|wgGMkwAwl~3(i zd!H%Bzlv8!t^Atl=uBViq%3Z9nv5W{M2mg7`%HRcSuML<`Pr_x$jHY_qj?YsbxMF5 zVcrUMQo=kAjtQkxc1)$gVpvHiR}HBMZw<7epE=wYgu5_zCuw(CWv z4hZvDjW-*cs06+06xS0YoH@l_pZ0?bGH;4t#46$oi0%tFUy3!Vhl@L8|NZQroOF6a z>X%a$YfeBg*=y!`bp&O%QoVUm~C0Cr1)+@uzsvT`iRh1VpesdjC+ zQ}@`u6@PDly?s4IV1ANB`P;7~l)O_rt9ihjydW3!rfs}nMJ0IgoH&O&gEC_Qw!0}M zLhR>*NzuLAFbhM`5dUq&YcZ_35ihb(-+aUR_rzv_%!QhJuW|kl5q=xDStl_k0)AS{ zHxD|RW>tQ$8I+&0LG2@vYT_*Tav~5Ecyw13ykQ?|Ya!5g!k>TX+kqs0oS39-zEL|~ z_ana2cn}jnN-l@_I4h%n3dBz}G5c7?u=<2WX~TNhe=-@Mv!9BSYC#2=834J*a>+cb zeMl%Wm&)Q;cnN(JTP`uJ&X7M{Hc>Yl(`GQ=uWYr$?6jsLpvx7%>8W_cU%#fM3R@&M zvAumBJS|SzVT~~A*5Kh-kx_OOAG65IB= zzkA2D;geO=&_TXAdjL+MCa^;sRcY*jG$6zP9FOCtkK|87qHy7X+M_*U3DNkaDIG4J zGq4^SER$xO=Mu|(e|ERzaG4(pQs5G`vVkAe#j)e{NIKBv>68cLU~}xUaUSgBC-fW3 z-ta$Zs?jUaMWiGeq5dRUlP&I8G7)&s*7DnM)H*(30Bt}J+Si)=lAIL7 zeW>dm37tRIP@#sXQjfhT!EyBHXfAw+ta%rl+QrdWvAlx9|0WH?MH#}ygIHA?SFm=Q z&3(@gKOYL6I zoU`WBB}|WdwCAF8$`0i+TV}CEyWrUL+-Z}+xGF100;kJ49Z2{dj%6%{_lm$lqU27t z!Hx4zW{xiEI_~LqSG4(ddAf4{bW!sQ{b>-ykc3+IcpiN-F@r%}JP6kCYwk4UbNp|W z;|#lnW9*NEggv(Q(_Yk3hPTI4Q?($ULY?1eRg_4)Hi%?U!BC%`aCeckHC3OUj1W%U zeeV}LQL^Lz^Be7~)1GtI54%*`Dg>u7-JabzZTd=0E8#thA(wGxc`N7Ow2LOrmN{^L3O^%IcR>3)3A%BlWw2 zfnDDp_w`82ewBYxEO?*UdnQvZ-p8eR81}*>C(nwhMI05)6s9itqbQX#mh`4!%G3Xy z*wu?;o9u@%l?BBU5ub-4JI5IWa!6kVuK_7w419GgEpEjcT-ab-W}VE{qP<)+8rVy* z6ngerw2X&l>2~XPHuIWX%`Lu0=C?Rq0PZ7tU+`}tNvKNLKj zq1d_kUjyl?yVL6Gx08vUxu}4@0y@?lFO&6o%zLhNx)~*))JM)dzq|ZY|6(H182+Cp zxjY3S?Ei&=;Z@bSHgLavJUCZzH_}I{uQ)YPvlF=LJ+0T)Q~b+kcCRIU<5E8d{Q6Dx zJ2Fzxi4W>buT(_-CJ=s1h5gRO6(d^}@@cFtJ9Z19c+X5vihkAZjVel$jL9^DA0wg6 zNPE}U;oGr974N-^Bonc#jFtPBJ-}q!*1PH zqOrWLiPuaQ|MNiX;a0D8_WZ;_owr8JrPfWARDSUEF6k5gl%DifIUr(s1STe0)SwgZj~itKyqM!yb$gm2{jMyF)#lBsfs3)xCOxu42Nv;wLBl?GH6K;Xvsj}zOq=&%zc>V_>-mUQ;68(!=eO0fnAvq zt1if2^n`P>SOm|y^1EYks{Xs>^ap1r0FxQBQ2AfK6@v@3of#%=X}%VO2!%=V93R`idp5J&A{Z?x=T zk+}m-(KiP?PyOUu&?jjGL?!oX4YntvfxiFH(J%Ul2>QCOJG`abw#RV**X_FG4kobR zJZ^xo`Ai|80TJ(R|DC^_+T(n*yg;b}c%TyzIn&DVtve z-dJ00Pebx7xc38=?q%Z-S2Prb{+zhSewXYVeBU&^@s%>7kG+-KKexs{R)87#r9ET} zx58kD-n){qxsw@8^^`fWV{1L@qXFAueUDaBs9&uMqSrWF5IjTjyw&}^Bl>2s@=}j{ z&+i2;JQMKZLc_1{JiEhoBO;}rNl-cBxAaamM>N~*7;4qkz)R5kJAe6zJgdS5; zlXjm2q5->{hQ&!H^jStLc$vj9$GS%|1LgBwezqr$g}*Mt{koUD&Zsk&xV6auGVrfy zs$p&N@&jXuLC}V^a3V_jIgpQZCzc%A3HDRE&pclmm-Ppm^kiLyBRcx+Wq_~XQfw|# z41E1|vZ5zBrl_S$XDo`E*|6AdL&WRYZ0>whw53!$qHb#`->uZgTF72Bt5V0N;d-qr zT~(vbAKAGyt&T2@ePc` z4ugBxw_&AQ@lQYdQ;ms5;Khw%Yvv6 zX2k)q<>g5WQ!{muZX)2oFT>ywLRBfYE>3(ik1qC`2AC8L+8JDHe#|8Bb7S|4iR*vY z#P@z@;k@0%z<0CIas@oNUDuLqn=%p^8G0O?_hM~-7aw(N&&-`_BJ5X$z{aokb zCI)l^O_};DgFyRbQy*?63ncK-_yUG&;S>%y&?jVcUwk-Dx$aB5?(8?}an&4N+3}fY zLXzVz6a0gP3?P-o9tD*s67?fVfp*w0DBI1WD*`Y6fj+a`eknF;eAOJ_(3fUB6iQIe z1WSE{uAEPXClFGvfl10ZApb1dSi*YN^245;&q{yYWiCE&=w_fe2T=F{igniuN+%=QgEqXsqp>c_bq4)@T1do_YH6yQka;{yDlV00B$ zpsR{{y%%%cPIzpe4sIBoPtqOe%I&{ib)m>C^9V1o0+)+V!C#U)YcmDSRY)%7YelW_!-9Kkvsbo-%}Oe zQT4uj=-S=-#*ZQob!(QDSm1{pOTyXmgQT3NKMSdf&K|)R$xrx z0l!Ma?c_tSV{*lSSBGD0T(f}m=tO(>itb0sV=REQAUU%keBlpPnd~Jw0EKNP>|g<; zBw;+ou-*})*SJ9`-JvBUU{NB-Q8Vn&Ilc9Zs6Wx*5=pvw-F}7=5q%Bsc!1PB%xF(K zOJ%XIE;SZglc}e}`8g%qg$1hq%)hi54h10&&ov5D$ zktY0t6W3ID8-1;+9C6nt<7YhBu=OsW0h}f zs>5yUtB=5if9|CpLQ3TO0n)S}C43QRl$8gn+}N=F{8vpE1|i5(K&A6{etw0jnwXwH zn_Kyi5^Xx|I>SMRCOwcW*Z{gf9=gD2HIRa5?DvrGim!hFHJrdOJPKH75W_}U4}j@Y z#>)%*DuAF*l`>rbR&^_jYf)M?>41H=Fz~AjOggs+9AtgL>Kxt$g#4} zJpm<^DLd&=<8(Q{;`iqu9;fdLSP9{jOEXbSEcCtQtC^Q1z8>rg45b4DH%OHU_254q zC4I{tB?%1J0N7WvWe?;pwxp~ zNt`#J!3135l$U$g1xB$me9I7JenRIm(5vOVFXMG(5g2gmxBxtbVntb=<>tA7O4MOr zvS28EFg5`3(>@UKAQLYXA0b}S0PD@z2TMr-yCdkEUxIy=6oK8vl7b((SZIFnKw-Sc z>FUDx)wK?lQaKP46VQ4o;>PyJO9v}`AgfOLUh$Sv{}_DlG*TQiF#e61a1jT{(AVI| zAr!^32p~t43eOiOl}J@Wz2NZZ*V2tQL8JiSR+nGw3nLxSK!OTzU0kVnJOj#e)CorC z5<<spT$wv1Xw=DL1GN2i14^tz-pc=b%U{n8po75R}kHhWw(>K8NAs81o zG-|Xa_L|3@D1;4J13&VjDcn)h{ZWMnG;SgR z52eB!V%??uC`+ItMhy!CxWJzDQ~?uOPaczWAXtqiJW!HHGRcRaA7KT&Q^al{9?3w> zb|I?W9B3N-*5gd;w*?-_P){i;71B<*Z%`ogI#H+qLSj$Ccvnp=ObZcCqCX1r4+0vA zm_x-;N^vu}U3)JdgJ#1Dv8c53(G%%4D3k$FP$7*y4#J0&D+VFV3+#8Ql_YvGO^dWC zUs|_=#}1c&8WXmQ0gQft6-cd7=$yK0n$R6m0z*NK=VlB^t70QSckAA$=K~ZV>|_r7 zP1>ce`dIxWgb;)2F2wXIL{J}|5*+|Orlr>GVNxq}6U}rzb_Ur9znIwpMW}r?lVu{o z9Av=hQU|QNbuy(61FTqyd`asQ_DMkMJXx9^sbaV$Ogo&uKb*>A#y(GK*DIS!sD_)$ zGn%O~43jxH4qKpEG>H!iv}@P!QImm@tMrlp`mZFw?laV!V|=YoVxcP-4`VWuXUt=X zEq4^Ua2`|x6SE`jib+gv7k5|b&V|w|pKa%dbN|9v1qLC5Z`D}VU&D64F?cIoqLYLr zE=dI)Rnre;-ST^wxZ_>t7rv@HQJ|nU6fofOycdeN>^>=pd@n3BELaJ`GuD~P70fx; zM**h06s{QvZML{OQW!Llp+(PBLd<9hvVb{`lQEH#(?NR zUW)--(w-yqglmOf6+DT%%S}Q8-#hyq2o%HnJK5ak#mh5L9WmVo_?>m#PhaU}{WStq-1^9BOVOVD zkr(TkmugI>&q57nXdDGsb-T}uU89tGV+|Xe@mr@dpJn!r$Iwa>w$c|H%j*6 z2M0ez;?5b+8IJzlBNzIdnZ9*rZm4iA^v#Hj31LFM5Q5`Cs8&!qG_yd*p_==?-|Y%; z{Xd4YT}wWv8y20J)?8G^&eJ4bDiRq8!BhL+6#|X0CzV(f9HIW9F!5*dA6xxwg~$+m zI!DdEQ-a0O*<{;;M)LfBFPLnwEr;dJK^nw@cDWQgYV8+-0Z9_bx&H^*4l*J0nUe|D#*42dv{;AZK^*+7K^822d<-nCVCm}g@8myycDogE&%Jxd z-ndehn>&NSu9mpU!;M5@*-6Ni8Y2x3up<9qF78`_KGI5R0S>->%)rb9E~_r%vn;d%%5G%oW;-T5z?Hs& z(5HDY(V#@u4sf@>Amd?!e&-k=E*KL{I9SOrqQ9uAIq6v({d-YsO%aLBRl4wbSf{9d z&VaUp42+%g3TXaHL@{0wM=dd#Sunn3VFJ0HWS!L)mxScx0IX|Ei%KzSJ>sfngqfMP z8>BjyF$%uyP;NEp;Ng$mY##J|EnAG>{*|IXk1e9YiqpOjM2YY6^hrFDjTM2uI1v60 zLx-410t5KURkVO|E4*vTmENQgi_-ZZH3!E9Eal!Aa|SuFqj=;A75g>X$>j0ncvT)1 z-8G45hQIl=8}94@gvOg;;9C&>$e@XWZfOov*lkym;FI-ern%NbnR)($yRedD4YsaDl#m2+PA z!l5>6SfAz7FaB4ew)0@k_6S@Du|Z!PeHuu?%u@K5NRy6*dFh^;t-?F96!bSrc>3Dz z?FeJmXip~OKd@J7Pq09E~73qh;i#}I)biDYc*(Eqmudb%`&?|ir!|i?c z!vgsEn-&=q(FooF36LL)zgVBu0z{Y`Wo6(NZM|>ZETv^K<6bBaU2%!T>?H9c9Aq`C z3{BaPmlw#=`xpzE+!tH)YTPg|xi7}?h4KgA&=H%XSQLO>3v&w2wA#+I?eX-Cwi~NRWCzdx(N+#Ln^dYslkfHu|I?^gNIi z=?Jj&1>D^?MH;Iq*dubFJ)+JeGaI*cqKOIaiv4)Fgm8y9s_O)6s*br})FKl*SR5Hq z6GLdu?R%%h(J`q?em+XQsH@`spXlv2tysk5zK9@X@YsQI*od3bW_$*B{5%%#tQRkL zz#{?i{HTUWQsT$;sU?b-3Knu8y@t^`SygMz*_3y0mwkmz=Ys z6X-2J4@>C|tz*BhgjDp3JPsU>4Y;mf#-Tv0y@76ZQxY??mSY^cvblU?YPk%`?oEnP#8iYd_aG5%WD2)g3?;l# zX!~S!-(N_+{T(;&e-xFzq%Go(*E3FgP|Od%Dps+DzJX~f57EyZysgnlU$I_p{W(+n zUi{k@JgdJa{zfL?+P6~jxcHtp_Mfe+4Dvc^pC7uj43k;YU|(F@yGUX6{Dk>NG|Xpk zL+c>oKPhpjT~wiV;aBz@?^37rH}f|90te3KIazIl?TzQ*PVj#m3tI@N67XDYkFV+r z9)^z{D`t|q|5Zoy6IOG6*SuVEJy`9;5T@d%6WD77b@;e8!<`c%H42^J1};oloFgTA zaz@`Qd!tP{%{BunFXu-23_U-Le##tq7lU84(41t)LM>M%#9wdpMb>u4 zszf76^^OOR8wg};9~TAzG6eFcU8!b8*K1*e)z9fp$^G+LqRTTnJ+uu)dQYAy-reigWID;rZ#8+nM0IScKI-JKPXoP2KwR%Qnj)~Q8ZwFo zGV=ALp%)*|X~5<*^97tMy9nU8Ab znwi%*aH7*Ovtvhx%M#nhh(fFmh`fGbZW7bNy(N#|i|3;)KhH;n2GRi{1u=Z_PJ3?h z8}RL!9s=>&^RTDtMMCPbU0au)W^a6IjVukh5W+zowLN|MAE?9?y&z+i6C@Q49V`-R zvNE3aT~DaKbZFF8h`-S{W0A`fxrehR%oU|3lpGQGBUn5%)Wgm>^^A`3IQwod9p3eP zW{p}p+(S*TeeE|`&&Cy$ZfbPbS!tYdwhoN;Pwu(zW}!31?j-Hp8SwetS9;MCKYBgd z1kop)h$HrH@==O?=d-&;gBaWLichyClG!#h+W+Bac+?}Uk3}9-(jS_#{i#hso;Uu2)?azvF;c+NN#D?|ewCb$a zOUO@2SkJk z7ulj5HIhh`es16k&7ZIp#PoAs8=5eaBVV*s~GV zIrT(MqPJ1OnIcyB{TCFLy4k?!j zmyC#7sWv>PH$m6&-Pi)WA?4V5FYhg=*Z0O-b~~;6>=W*#|94$Yg{|W!<&_SAm908t?RPCjXg6(C>!#9EIG)P_!BNK714|QDJ zBI#Adu?56youeTmqz^tm+#1Yz5d)S9UY)@GGn%N z*I$~?r9b`UW7zUuhl6G9dmDvnzwIOTW}3g7v@R?sxI@Yphsp}(T}Xb&t5@kRrB1@8 zrgTlzs{O0$Qr>J+W$BDKlI|6Z%$23m(5a+P8H(nuopVE zq9U=wTaL=Sf}IF@dt7?R?%nOx&9)Wvn$|9Vm(G3Q`jHKY7wFP>v=Q1)t<#T^QM={$w3j-Xvd11+DPf?EPIV zC%QFB2s_l7vJvuk8twDif@~>Gi-bQUYhNiWh_~&$>(n-wjlzx2jjddsWAy6Wsati8&WftuIYMXi!)0;ssNC-sDXt1$ zWHPeOA|FXc)Gv*9&W}Ws@_-+?u*rRn?W60W)n058zn%qn69856XhkbqUCRwG<1!Ed ziCe$UN{^IJ8bi;|=`)792-DzLF@(fRGc@G$22!>uS{%{pJW>@W zf>ph;9kK;mATGcl9~*bHp2P++tSPefm87coSO$edN}MjsfVCSP`Do4w?P@wJ1S%d9 z2Jj~J9$&|eLKI#;1FbNBibjYf!8(<~qXG-EVqQ*w77CLIaNMaqFh4@~p?n|rzuVnD zX7oE;E{qAe|3u6SCBx|ihN5KPr$?4o;(iJU2}iesKxguH`A^Z}uUp-XW;I--5e<8_ zyvVTH_3z-+HeuqY0+vd@pU{aBgL|oJ$B)CC--}xCCt)uAMzu$4M*oc(xzLK+D7m5fGt<(J~A|} zgaDOm1$`|I&i-e*6}&~fm1=^TI&#J88FHTF-gF$%c|tAsNB+{72PpVCOK}pOzwuS~T&B1JUsH@q;#Hy&C~2>6-cDNzF0fnB7Q^tr<&+YyCL6f6T2aq!nX953dra3CDPc+vMhfk@YS)lxq9($O_swD{@Xohx;F~7h`EDrb~i>doI=Nc z43*seP{-&f*WEv^V8gHli%bxIP80objkfXwSJ-A`9@oN5O0$jCpY34`)AQke%uBl) zt6yJU&l!tyfBSw40FE^m^nlE>v~8B+p4$Pum+IyH*5A4w%DpJ&*$mlwQSJTQ4k9`_ zS$-&Xr$KV^Pc-}?-_FJcYB1K?cs`fz%v(qoD8w@uG zFrJ?xj%uPLftzgh*<}Jl9x1=zR$|GxQx1~qy zGg(glGjS=%w=z+b^#^b@2Z_f8Pi}psBbkZnGa#lrl1-5B`c1S78~JcuKao0yC7V!R z{oMT$dxvkeQBOD<`&tl(_+F{%1`1#jMhyoLtskmFWAKt?47*kdH4OJ|O_Yu{n28Sg zgsUm5y0(s+URmTOi-4_$!WL>-o$nq5--)SMyVY&UqHF_bp#E0Ozlf2^7-j>y0YrJY zmD4abC!FY%`IyH!?13X!h~Hn2kZ^o%=(mYi7&tCToI)YX=|B|rr2)K9yA z-`;c%;W|#v9h}d$t`*10m=c-u6sbgjb~qn1?cHPpe~oqT3tEXqNWNkms;5g?b9lw^6?f~lHUIGZDM{paf`N+rgV*`Qiq?*q=l z1f|e zFao98pkd1=+F#)+WkB!_P=1IVw`G3 z?lQQ$s>)@udsSoo)?elfw*HmcJs?Yaj;OEQW!Ar2NM+P}Iz;K_Tvsl@cs}8sjy*R2 zL$#$-$g%fymVB?LoM~g?bW;uI?1y2yd$gKIWA;tvZ`sJts~>GZyNMJUs0Y5F+O0+= z6VV7T+0g}!Qb9$TXte2ax*+n&0>ti0 ziw$SLs;8qq+2aOa`#m#GFe~jqdqr((Of;9WP1wB>8!UcjNs~;*&o^1!0djZ)r=Z(k zWc@?!$15Ul)lT<`B2CyWjNLM!s>iy%&Lae9>sd^{Yd;ayl} zrAsL&f2kJLuAB{bpg6PX*}C(HzDkmcqoHeMOB-Fv`bQ+%gd^lua{>)BAd$@ix4b=w zW?H;H)}NNZs(~Xw{cb;AdkYT|ihyT>UFpI%eq)+`j&jb~V~kRswSs2I!=8MybI_wvz029 zPn^b4D`cptox9y-H(c)HeX57n;su=j2xYLTP9@!4mRsF_;$Y+K|8ZJ-^&30W zRfNeUs$~>z7}b7oYJcbXlm4vqvQ#qB{d}I-AJ!W0yiq~1!`$UGu&OCA|0dZu1c;WH zZooUeWRQ&wR`19BT>Feno^#JD0@tXs{mi1`rRTof1^8}9noS-sB#u@E)_)zsm`*96 z%c~!F%UbWQQNN8?`;eusDj@g4bo-ye_kL-tr=R29x*l>spA-3Nl-lC&LR{+G9#(d; z-n?p>D1DfmWYAlGFoR#?vet6SjyLIvQ||=pCcc71Be~wUs9o(G9a~2nT5znR@2Gja zC)+}YuARXtxoma$uohV|U-!ZmJiP>Tuu5>#twtzVq39_(mg)vih_tH<0+G}kda)gG zt?Eu6;x)HIm{hg;l<;Uh@7^+nC;NlxF1pTg;f+SS z-`4|_KV4|N$MwGRz*p$~z#SjASAlK>xK_JU`M)R&pjSMtzaP(h%?6b%6K6EBDlpWE`nY?(CNJ%#o`)uOmorJB-{m} zQ}BN2R3?hQOuWgVdM8NzV>mxs0YePBdZ!Qh6w3IJx2ibpFMG;y6dImmIug@3UmtNe?P(8+iGPL~!7p3DDfZh-@Vo_lZvr^yu_Ygy$ZI&x{ zDh;gr5k*&)nq*Nw8z7cK7858^z=)wi#JA`8n^|UpmrwhWeZKe;B415UB+q6WVm;_< zWI&Td1n~7;B-^iYRBf<| z&JpnXF}^*em$jLP^uFyQ!#ObKYHnK{F`I2&T)SVDd6?Jr7eBl+ov|pT7AXxMDDtBw z*9#NP5FU#|V>Cl&z7++Oaf29vQ*(NDnEg2aPDUMeDN(@`cIy=P49%T4AX>gH&X1xNR&``@gwkLHbDj{Z@Mk-s`tAUb|Qg_hpiOj z4%7>k%PIBUw7Ge>%eK<4v%aH@w>%51J?)v zv~=)yMq*uiRcUuK33qncxW?CNyYI-8y%Yz;)ucP{#l(qvXT<(JKoAC579+V;-DMyY z^5=Bw5t@0}6cz{lbJBsgAs+y{s!BiB?}H(1&Cn~o8Ooes>}422x!O#K!H$l#17q%V zG*L^REd;gR^~a%2isl{wN^7{LMxLInqy5L)4K9b^^#+QY0bW&G*lq4o?D%LDxr&fd z1@7ce7K<09n$n)u5&U~fLG2tZL|DNfqvA;J^O0$wV)E%qpVBSQrFo)}paC0$1?)j3 zB?+b@n(PVcy^$!O$_Ib1?9-6QYBs%TDK!kEgFxSJQ!&*`btWi(2AM}C z$q}w%Y3g0BYd@CMzzGkh#u-OiBO(tS(`PH2=`ksBA6cLe@y_2S-Gg9N2LBgWL0~xQ z=(w+9Qzq(FpEtzhJDz_UhUGJy{G2s_z--oFjR_C?fIp)en8VUX7`cARw0ngOmJ+nJ z{i)rJ3z!B+SN}JHPmcl=V{tTxH0)ED(>vB?uQB@y>7xN8lPVg&wD0Uh`WILv=tQ1U zt!+MrTX4x1a_zG9Jb%dlz~B`ZM>yWk&3j*7?Eb_R)+l2RH})Hz8!x!q@Mk(YsAP~B zn?1OTGR2JyC9VLJ>0?^}tK|lFBES}Z00U_M>2bK44`HY+UH(S_K?cnE z&5;Le8gV!)8bh5_;Lw+>rjx~e3g-#;z7G?~?eP5l^7d!|Gk*4Mokvnv5XEb+$XvCe z$3?_x@^k=3{ftwg)l@LGnl3}nRNqkK3U?>LYAyXEejhG+3XU!+W)nhmTO%hABSl0f zI`!7HO|aS_?5=ePVN?mRze1nw1@#T4en$jtrm(-J$m58p%3rh`W0XfXhArc zDg(&F`3Yqv635s0`VZO@9Z7{p5{(a}2-f?VP8k#Vo`5%|40!fY)SlILCbIQGB}wZ8 zjiT4b43T_z++@^&pS)ncG+wYq`BtbTd4qP8w}=6amq?m?D-9QULtYfe{R%s-^)>GI zghPKr^1nGc=un}YWn`tA_0r_p%a^XK&^ z6{YX?@zH-BK{wqd)h=tb{>{*~c>HIJIqZz=32^UVi`;KYCKL?oG@2}TEs7H98 zYI;ZP&0}^Q%wyQsZ#@Lv649yhTsB+*Qf^E!$3;NE?bb_!4#rNB0J%0ufLxI30r|P3 z?tBbf?^1mm1|2>2pcJ;1qztO^Om7(20~p0;xm2X^O!;ODPa5%IMuCU7P1tApA|hz)q$>C zJqg9x$Qhs;9-zhlkfUij!1vLHXQ*E>sAJuF6AG!uzbn^Bun<(XYPLm6)=4Q zH{ioX7xwvRO<>n{b6+K(Q)99yK~;_uVcEVM_U&k3G2nZ&{%90UxL;|?ecIt5J(y^d zH&FsSmxuOR#Y>co_OF$dOy7(jz&beri#BO;bO4)dT$O8=H+qE3;RK35#MO?qm!eK- z0D!`JOACHU?MvW+85b9Crv`nYCLvC*>GVHfc3veMA2%}^t|*Nq}d{#t^aBFspxvK$7iwH1v_lI?zNo>jEuk?Pe5{oQZQh7(#$0VJZ z?_OpYc^LwzbMI-nwTDjDIz`m2!OM8l2j}5ACkdt7s}4b5_%)d*AdIG5ZHZlH_r)XD z(;2s?nLgVjDg3Paj&=&G#YCC>MZuzE^>gA-qhn&@4H@4 z@~ngiPU2fQ^5Z2Z?Dn(C$J^!7)z3>@F^vND@B38bJ{UwI_xO92K)XGDnbA?J82U&5 zZHfSxuIVJWqLGcJ(>zmjBHi-->q)Jkfk{5j--9%1y!M^TH*t<`Lvm-aTW z*13IvXf#}NXxzQ_im)LavsPrU@X$bMt+&T9Dq7nyJ<>i8tyC;Dt&TWriCkT7-XVwZIBuAx}-zLVKJK(z$|E`b`7qDU|NXYc+~5Es=I9h z`>S?e>^}|06=eq&P?z4~Pb9iiBM9+m>0%wlHUGS!lxHWhcSf3NJ+M(p&Y@JCg(uWs zi5bC>Hq4f6+e{xm9ue;8L@&I_sY0i%aCA|cB1JQs{H^jZqN}U}hJfrGT$KuEiQ5Kv zmQfyzLCRzAJjrrPmU*8ih_aCKM+Arr6k%CzUkbJqdqlLwJ&1GgNK39_yJxmVSaStq z<%gYKE!r9)mPKyB-mcnJHL6~M5b*_Looem)U2BhydO@BzJvsw#6zR#b-{Jb1tL)}B z7>TlC%b38)PTfgLd0ES6gsW54pRuzw!yqz}2%UCBa?f~N@zM*Bc1$llLRWcUQRfN* z3L&}%ChIByPB4;}7aY5_=R8~LTDH=O&@)(BJb^%31m~o6?{63$E-;0}y0lqZaEoAM zo0VmAKwikI=1wtRdd}*v^(Z(|K3e@p>{C@&9=S`_X};68ti!rzyD`d+E|itlO}K!c zV%Zg=JwiH3-B(JV9e*dF?sCbo*{WKMxoR{4cR#9MXpxcKsa+#hI*fcf(PK(NKiL|Q zy63D@FKsf@^#EG}mqH5snAz*=p?8U+ zyMxzgomPQUZ5fq~uRH4(M|h%t>KTD~|6cRx!eft}Ye>6Z*YgVB_LTn#T}AmlBCx2{ zo`*=Z>@wzgRZu)h>{dW;lA>BS>qnla#wMB2a;udUY@+-fc^N8HHwogVI;r>kZY7_i z#mI`)TxcEXcixORo&owBg6kMXW7|`?zv&ZiweIp!@DonQRuJW4eO=P*{@^BWb_>eB zLB;vUBn~V#?7j8oYD{5SqW)^ADbMX8CJm%jt{G}E+7|7F0Kl3Ztb^6u#Ze`_P^zT?GHkT7I*&Mr;3$G>H z;XlBu%rQG$(0Xc&kdE@P|J}GASNwHK@g7YwaPk6xLkHu8BHolr9R&`k+&%IqSg^xF z-l3K|ph5f+eFHJ~z!rE#O*$*l3)8}N0I-rTqzWsnz<1Te$H(=@0c52WW=)dQ(>-sq zdt)-$kbmUVYz+7L(ptTXAH;X!j+&-bZx)Zw&)pQe;mJz6lg=Hs&|*f!;3d0J{ZQ4?rAbR%ye)BY#~aaS+kC>d!WaucRJ!n zYz$H9Aq6j?p3&4Ez|8T^u8Ja|g5ZO7)xYf4)2eLx(SD<*iTmy(^fjZl&wnW!W3=dsx`lRq<{#)w$apH6r-3rJ?Jv7~5aCAlv!l zfpi82N;FO}n-B4?*u`5n>}_J_%*4UZ7iG;N z!o*L!1p};4CsthQmt|@HL-0hhVP2;KWFO9MxU##<9?0}?Ik<(K1WpgC9dgh#WtFt7 zZhOyfg*ESghaDTKc=#L}YplwYezxEe664Y}7O7im>67g;{Pm?uqBT+q)jZ5YdMmb| z9PjDby>PZ&6@~C07~W`T+!AR>(;Eog1<*64xEB{rmQ&KfNPY@#UpPn9WvnPXr91gi z_@c}Fxp72GVnvES@QO#2{>v%vu=$-9?Z#({pC7**$wa-~Si&f>ZC>#1GHjbdf(Vv( zDb}l4!_zU8wlXKo!-RyJe}I{mP0rvtu=jdM@eZ?o(cpac1!{Z2sAK3H+|VNuuJzjx zI*B$-um=w76C2f$rP(v55(Ky-VNrC)H~EL2Iatd1xUg2sppBVXb+Pw3su5s+$O)kb zS`Y9c%KM&Io7}1&oODxpd&r`YX1jMnI3Ez!Y8r&gxI5FgTP6<{+p>MvbvS12f^4IB zwD4|%x0gSrQ~fIGt<7GH_;HM)_w2vnZkAWf_jJ&|oC=Nldwkr;AdXCZ(@m?&G`#6G@7bl*uz)J#IOSJ3o>sZ;`#X_2(feFKZ4}hFmo6Ue7XGqJ zW~(GCy_p6Df-h~@476lUMBZ7-LQ8OePLem@b38(f$qMZ-i&(n_3`0F>Goe@fx3hlm ztx?;^jthfxp8uwgEixU7`?ba_2|nZD%*ZLJ?Fa0)DSTj3Eouiq?mp`|lpJ5FM+6 z?4*PqF)j~vYV6Y4BtRY3XYDP(bxT63bN0`mi(t7SfwDq3Y*IZ$h3qUziJ*1`A2UtV zQKW2c1Ow+N7`NkUp3D-T2H@o#RoZ*%kd3?n38Dh~F=>Xkj~l;Ln4O^dF~dJBcLI#H zR1Wt}s+PX3SmL<%sFFz{cBHEL%pN!n*y|Pmg$XUR(XUfc=fN~v^Gb{0070 zQa5it9nR4D@a>SGq}fJ$ig@4=4R6`T;4jM=;D_!C<_j!lADC2XZa8-vF)<~j2)+VQ?NB6|n--s!i)4SPX1-CFx1zVL;(wP z8Xn;rZGd&YXgc=1;4l6z!ow+O{jSQPSRJf_v@1S8LEQ`gCK!UtMu{Pe&_ zal{EJ2tjWKJL&NulkM5<`kxMYSJ$&ZO%JZ1-Nnwp@6PaVnD>2j*v|)+wBf`83wR3z z3kg-J;Qsch*~?yKk|v>vJIX7GyM{#{iDLsM!*INdNh+_(75yJ-Q-;ryyQ?3}n_)9b zCWTeGm=8 zXYwq7z#=sDUxV*++b_I0cT2eUS|#;l&+G3tPxm+fjz4=y5tkw(6fZ2o73S1HonIeg z9MFB}_LU+qF=y@XGtN(IUBe$*k#5G{p1IKaNg*Uu9wr3+=}G*PLkwlG5$gGvd=og- zf#sOEf$;}A%l*o{r84y#es)|s#^sUb1QVVW8vU|?J?aX(e&<=JCGzcd&~?d2&ws)V4?vlf{npf};a2+zk8?Jm(l;Wy@bbEXyPKNXBmZ<{^jnNnZb#+BXhkyE!cG Z$iDyp literal 0 HcmV?d00001 diff --git a/tests/python_tests/images/composited/linear_dodge.png b/tests/python_tests/images/composited/linear_dodge.png new file mode 100644 index 0000000000000000000000000000000000000000..848ddca176f4ee72e5ad1fa8b49318dab61ebdfc GIT binary patch literal 14279 zcmche_fu2P8}E|OV{#H^5&!@|uA{AK3;+OeKY;)u zFz)M>SGgkqAfKS4srJk-_pc>!;J6b8Q&j0c``$wL@2{ti^(us8iaXf1yB9Fh7EF(QW_k$PdL5};6H)DryA`3 z8o%HBuzGykX$1iO|GPr{$%vU@Am&qy-2$mjSQO1&I}y=Jb4>Ij&G8UCm3?){Ee!<^ zD_Iv3;@7vgJ!G9a1s&PLKRwV@NHr=f1UV*8Id8wCxn{+KNQ9wLq{uMJkv)}>J(lg+ z&*;_P!%lj=gywg$F-hz^ZaNEJD@k(Gb^XGT@Cf!4_-&Y{rjKkqXRfBgCr^gLq9|!% zOJaViU_F%V#@_aPhoM3inhkHn$+}l8Vv0)c^~Dtxl?|T%Yr-BA2^OVf_A7pL^`ki} zUwlzQdZh9-n(?}pU)gSD`%TD^Iau0!@I{wKD^-MJJi zX&zCF6xvP|bXLu{83 zjvG`+1FrrLmav`WG20JqB%2>isn!9TP3fsI)MSF<(M>Y`8+WqQ<%ULx)Cgr+&hM9y zNlV19`cP1y6^6R^F8A7gW;R_kW29M)7F$%n#zz^ZYgK$<`B! zspxZ5RSae7S(Yj5xpn1TA1>JF1hvs5?21|iX!qSx6WWY~1ui&#-GB1dPS))~X&A2$ zI$KpSo2f^5Gn)g+_$KC<6iRcVzlXbj!JSvLrL1qNN{Ev{4;2+(8F5geT5lrB&|C#)6PxQ*+ebtVpdS?z)P%as1QG>0t@Q<9$UoH!16?zc?vrsr5 z(GuHCpxT2U)!r%`G}$2c>>s~IT1gk4W9)zt`bt3I%uKcVm0tPnHWzJ3d06@fA)>bc z$>qM|SYicQxt%*%dIY$0?KX_``g|Q%JCr^TzQF^$s(6Q!52??oFRN@!3rRrtRmU%< ziz`W9Y33I|RF@46X#-6B;^x_Aj6%+#b#4v>N1LMOOH9_}?Fr>J=E^P1`V~4%AFI^z zB0v}eg^XsuzqZ`g$ZJnRk-C!jp&a6$Nt*BQeL5nv6*ICBYac@L2t>3v9-7Rj2Be9d zP|@ZPTKJJJT6t7NiDsHg3;`qD#GUJr_g1Z;KocWGam2Cn_7(utl%AKV?l&#FfUsy; zSSbu6mp7%_1*kVgulD0d(LhFT55)@bI*WgVvffcIDQWvp`6~a-B8G_kp^3cUP?2bG zq|(_YYzfQ1fk@=yYPcgj#>w?hj^~u2{ME`c@>uUx#D5Qtj(Y=Rq?-o*@w;OCJCEff z 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 L8EDq1+l2iez^n_m literal 0 HcmV?d00001 diff --git a/tests/python_tests/images/style-comp-op/divide.png b/tests/python_tests/images/style-comp-op/divide.png new file mode 100644 index 0000000000000000000000000000000000000000..551ee104302906e4778e136cb5bc828d7500cdf1 GIT binary patch literal 3587 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 a!y#U&Wv?)9UWOibz+?a6eN5+|OaBE=y$W0a literal 0 HcmV?d00001 diff --git a/tests/python_tests/images/style-comp-op/linear_burn.png b/tests/python_tests/images/style-comp-op/linear_burn.png new file mode 100644 index 0000000000000000000000000000000000000000..95a984bd8740134414673c3c886768ae67ce3d3b GIT binary patch literal 2356 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 Q-wg^wT{E3ZEtjbO0qg+LoB#j- literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-1.0-cairo-reference.png b/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-1.0-cairo-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..fe9f86448fe1bf5a36024a52ac8195f8e78ce33e GIT binary patch literal 7564 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 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-agg-reference.png b/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-agg-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..76bd8c286b32e6c5fed22e82fc664b4a3f03c73e GIT binary patch literal 4137 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 n%RHlZQy2v?(#UWAWq00000NkvXXu0mjf<~vN8 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-cairo-reference.png b/tests/visual_tests/images/marker-with-background-image-linear-comp-op-500-100-2.0-cairo-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..2a12a50737130a6487eea53ea5ddf95b9d71a94f GIT binary patch literal 5219 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 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/styles/marker-with-background-image-linear-comp-op.xml b/tests/visual_tests/styles/marker-with-background-image-linear-comp-op.xml new file mode 100644 index 000000000..58df8a1e8 --- /dev/null +++ b/tests/visual_tests/styles/marker-with-background-image-linear-comp-op.xml @@ -0,0 +1,67 @@ + + + + + + ellipse + + csv + +x,y +2.5,2.5 + + + + + + + + + + frame + + csv + +x,y +0,0 +5,0 +0,5 +5,5 + + + + + \ No newline at end of file diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index c86695a33..92f0b9198 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -120,6 +120,7 @@ files = { 'marker-on-line-spacing-eq-width': {'sizes':[(600,400)]}, 'marker-on-line-spacing-eq-width-overlap': {'sizes':[(600,400)]}, 'marker_line_placement_on_points':{}, + 'marker-with-background-image-linear-comp-op': {}, 'marker-with-background-image': {'sizes':[(600,400),(400,600),(257,256)]}, 'marker-with-background-image-and-hsla-transform': {'sizes':[(600,400),(400,600),(257,256)]}, 'marker-on-hex-grid': {'sizes':[(600,400),(400,600),(257,256)]}, From 75248e33760ab653259018b7873c24654b5cddd9 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 12:52:46 -0700 Subject: [PATCH 09/92] remove obsolete wrap-character option for text symbolizer - closes #2333 --- bindings/python/mapnik/__init__.py | 18 ------------------ bindings/python/mapnik_text_placement.cpp | 6 ------ include/mapnik/text/formatting/format.hpp | 1 - include/mapnik/text/text_properties.hpp | 2 -- src/text/formatting/format.cpp | 12 ------------ src/text/text_properties.cpp | 9 --------- tests/data/good_maps/point_symbolizer.xml | 2 +- tests/data/good_maps/text_breaks.xml | 4 ++-- tests/python_tests/object_test.py | 17 ----------------- 9 files changed, 3 insertions(+), 68 deletions(-) diff --git a/bindings/python/mapnik/__init__.py b/bindings/python/mapnik/__init__.py index 26a61e649..3f94a62bb 100644 --- a/bindings/python/mapnik/__init__.py +++ b/bindings/python/mapnik/__init__.py @@ -794,24 +794,6 @@ class _TextSymbolizer(TextSymbolizer,_injector): self.format.text_opacity = text_opacity - @property - def wrap_char(self): - return self.format.wrap_char - - @wrap_char.setter - def wrap_char(self, wrap_char): - self.format.wrap_char = wrap_char - - - @property - def wrap_character(self): - return self.format.wrap_character - - @wrap_char.setter - def wrap_character(self, wrap_character): - self.format.wrap_character = wrap_character - - @property def wrap_before(self): return self.format.wrap_before diff --git a/bindings/python/mapnik_text_placement.cpp b/bindings/python/mapnik_text_placement.cpp index d588dd245..a0c483689 100644 --- a/bindings/python/mapnik_text_placement.cpp +++ b/bindings/python/mapnik_text_placement.cpp @@ -463,8 +463,6 @@ void export_text_placement() .def_readwrite("character_spacing", &detail::evaluated_format_properties::character_spacing) .def_readwrite("line_spacing", &detail::evaluated_format_properties::line_spacing) .def_readwrite("text_opacity", &detail::evaluated_format_properties::text_opacity) - .def_readwrite("wrap_char", &detail::evaluated_format_properties::wrap_char) - .def_readwrite("wrap_character", &detail::evaluated_format_properties::wrap_char) .def_readwrite("fill", &detail::evaluated_format_properties::fill) .def_readwrite("halo_fill", &detail::evaluated_format_properties::halo_fill) .def_readwrite("halo_radius", &evaluated_format_properties::halo_radius) @@ -528,8 +526,6 @@ void export_text_placement() .def_readwrite_convert("character_spacing", &formatting::format_node::character_spacing) .def_readwrite_convert("line_spacing", &formatting::format_node::line_spacing) .def_readwrite_convert("text_opacity", &formatting::format_node::text_opacity) - .def_readwrite_convert("wrap_char", &formatting::format_node::wrap_char) - .def_readwrite_convert("wrap_character", &formatting::format_node::wrap_char) .def_readwrite_convert("text_transform", &formatting::format_node::text_transform) .def_readwrite_convert("fill", &formatting::format_node::fill) .def_readwrite_convert("halo_fill", &formatting::format_node::halo_fill) @@ -567,8 +563,6 @@ void export_text_placement() .def_readwrite("character_spacing", &formatting::expression_format::character_spacing) .def_readwrite("line_spacing", &formatting::expression_format::line_spacing) .def_readwrite("text_opacity", &formatting::expression_format::text_opacity) - .def_readwrite("wrap_char", &formatting::expression_format::wrap_char) - .def_readwrite("wrap_character", &formatting::expression_format::wrap_char) .def_readwrite("fill", &formatting::expression_format::fill) .def_readwrite("halo_fill", &formatting::expression_format::halo_fill) .def_readwrite("halo_radius", &formatting::expression_format::halo_radius) diff --git a/include/mapnik/text/formatting/format.hpp b/include/mapnik/text/formatting/format.hpp index 0b6d3fd15..bb63ff92a 100644 --- a/include/mapnik/text/formatting/format.hpp +++ b/include/mapnik/text/formatting/format.hpp @@ -50,7 +50,6 @@ public: boost::optional line_spacing; boost::optional text_opacity; boost::optional wrap_before; - boost::optional wrap_char; boost::optional text_transform; boost::optional fill; boost::optional halo_fill; diff --git a/include/mapnik/text/text_properties.hpp b/include/mapnik/text/text_properties.hpp index a647ad969..e0994a7a9 100644 --- a/include/mapnik/text/text_properties.hpp +++ b/include/mapnik/text/text_properties.hpp @@ -52,7 +52,6 @@ struct evaluated_format_properties double line_spacing; double text_opacity; double halo_opacity; - unsigned wrap_char; text_transform_e text_transform; //Per expression color fill; color halo_fill; @@ -80,7 +79,6 @@ struct MAPNIK_DECL format_properties symbolizer_base::value_type line_spacing; //Largest total height (fontsize+line_spacing) per line is chosen symbolizer_base::value_type text_opacity; symbolizer_base::value_type halo_opacity; - symbolizer_base::value_type wrap_char; symbolizer_base::value_type fill; symbolizer_base::value_type halo_fill; symbolizer_base::value_type halo_radius; diff --git a/src/text/formatting/format.cpp b/src/text/formatting/format.cpp index 9635f53fe..efdce2936 100644 --- a/src/text/formatting/format.cpp +++ b/src/text/formatting/format.cpp @@ -45,7 +45,6 @@ void format_node::to_xml(ptree & xml) const if (line_spacing) serialize_property("line-spacing", *line_spacing, new_node); if (text_opacity) serialize_property("opacity", *text_opacity, new_node); if (wrap_before) serialize_property("wrap-before", *wrap_before, new_node); - if (wrap_char) serialize_property("wrap_char", *wrap_char, new_node); if (fill) serialize_property("fill", *fill, new_node); if (halo_fill) serialize_property("halo-fill", *halo_fill, new_node); if (halo_radius) serialize_property("halo-radius", *halo_radius, new_node); @@ -70,7 +69,6 @@ node_ptr format_node::from_xml(xml_node const& xml, fontset_map const& fontsets) set_property_from_xml(n->text_opacity, "opacity", xml); //set_property_from_xml(n->halo_opacity, "halo-opacity", xml); FIXME set_property_from_xml(n->halo_radius, "halo-radius", xml); - set_property_from_xml(n->wrap_char, "wrap-character", xml); set_property_from_xml(n->fill, "fill", xml); set_property_from_xml(n->halo_fill, "halo-fill", xml); set_property_from_xml(n->text_transform, "text-transform", xml); @@ -109,15 +107,6 @@ void format_node::apply(evaluated_format_properties_ptr p, feature_impl const& f if (character_spacing) new_properties->character_spacing = boost::apply_visitor(extract_value(feature,attrs), *character_spacing); if (line_spacing) new_properties->line_spacing = boost::apply_visitor(extract_value(feature,attrs), *line_spacing); if (text_opacity) new_properties->text_opacity = boost::apply_visitor(extract_value(feature,attrs), *text_opacity); - - if (wrap_char) - { - std::string str = boost::apply_visitor(extract_value(feature,attrs), *wrap_char); - if (!str.empty()) - { - new_properties->wrap_char = str[0]; - } - } if (halo_radius) new_properties->halo_radius = boost::apply_visitor(extract_value(feature,attrs), *halo_radius); if (fill) new_properties->fill = boost::apply_visitor(extract_value(feature,attrs), *fill); if (halo_fill) new_properties->halo_fill = boost::apply_visitor(extract_value(feature,attrs), *halo_fill); @@ -160,7 +149,6 @@ void format_node::add_expressions(expression_set & output) const if (halo_radius && is_expression(*halo_radius)) output.insert(boost::get(*halo_radius)); if (text_opacity && is_expression(*text_opacity)) output.insert(boost::get(*text_opacity)); //if (halo_opacity && is_expression(*halo_opacity)) output.insert(boost::get(*halo_opacity)); - if (wrap_char && is_expression(*wrap_char)) output.insert(boost::get(*wrap_char)); if (wrap_before && is_expression(*wrap_before)) output.insert(boost::get(*wrap_before)); if (fill && is_expression(*fill)) output.insert(boost::get(*fill)); if (halo_fill && is_expression(*halo_fill)) output.insert(boost::get(*halo_fill)); diff --git a/src/text/text_properties.cpp b/src/text/text_properties.cpp index 2fa6321c1..20c0a2b17 100644 --- a/src/text/text_properties.cpp +++ b/src/text/text_properties.cpp @@ -87,10 +87,6 @@ void text_symbolizer_properties::process(text_layout & output, feature_impl cons format->text_opacity = boost::apply_visitor(extract_value(feature,attrs), format_defaults.text_opacity); format->halo_opacity = boost::apply_visitor(extract_value(feature,attrs), format_defaults.halo_opacity); format->halo_radius = boost::apply_visitor(extract_value(feature,attrs), format_defaults.halo_radius); - - std::string const& wrap_char = boost::apply_visitor(extract_value(feature,attrs), format_defaults.wrap_char); - if (!wrap_char.empty()) format->wrap_char = wrap_char[0]; - format->fill = boost::apply_visitor(extract_value(feature,attrs), format_defaults.fill); format->halo_fill = boost::apply_visitor(extract_value(feature,attrs), format_defaults.halo_fill); format->text_transform = boost::apply_visitor(extract_value(feature,attrs), format_defaults.text_transform); @@ -281,7 +277,6 @@ format_properties::format_properties() line_spacing(0.0), text_opacity(1.0), halo_opacity(1.0), - wrap_char(" "), fill(color(0,0,0)), halo_fill(color(255,255,255)), halo_radius(0.0), @@ -295,7 +290,6 @@ void format_properties::from_xml(xml_node const& node, fontset_map const& fontse set_property_from_xml(halo_radius, "halo-radius", node); set_property_from_xml(text_opacity, "opacity", node); set_property_from_xml(halo_opacity, "halo-opacity", node); - set_property_from_xml(wrap_char, "wrap-character", node); set_property_from_xml(fill, "fill", node); set_property_from_xml(halo_fill, "halo-fill", node); set_property_from_xml(text_transform,"text-transform", node); @@ -341,8 +335,6 @@ void format_properties::to_xml(boost::property_tree::ptree & node, bool explicit if (!(character_spacing == dfl.character_spacing) || explicit_defaults) serialize_property("character-spacing", character_spacing, node); if (!(line_spacing == dfl.line_spacing) || explicit_defaults) serialize_property("line-spacing", line_spacing, node); if (!(halo_radius == dfl.halo_radius) || explicit_defaults) serialize_property("halo-radius", halo_radius, node); - if (!(wrap_char == dfl.wrap_char) || explicit_defaults) serialize_property("wrap-character", wrap_char, node); - // for shield_symbolizer this is later overridden -- FIXME if (!(text_opacity == dfl.text_opacity) || explicit_defaults) serialize_property("opacity", text_opacity, node); if (!(halo_opacity == dfl.halo_opacity) || explicit_defaults) serialize_property("halo-opacity", halo_opacity, node); @@ -360,7 +352,6 @@ void format_properties::add_expressions(expression_set & output) const if (is_expression(halo_radius)) output.insert(boost::get(halo_radius)); if (is_expression(text_opacity)) output.insert(boost::get(text_opacity)); if (is_expression(halo_opacity)) output.insert(boost::get(halo_opacity)); - if (is_expression(wrap_char)) output.insert(boost::get(wrap_char)); if (is_expression(fill)) output.insert(boost::get(fill)); if (is_expression(halo_fill)) output.insert(boost::get(halo_fill)); if (is_expression(text_transform)) output.insert(boost::get(text_transform)); diff --git a/tests/data/good_maps/point_symbolizer.xml b/tests/data/good_maps/point_symbolizer.xml index 314a461ec..438c391b6 100644 --- a/tests/data/good_maps/point_symbolizer.xml +++ b/tests/data/good_maps/point_symbolizer.xml @@ -3,7 +3,7 @@ diff --git a/tests/python_tests/object_test.py b/tests/python_tests/object_test.py index 8d78519a3..0f23e7118 100644 --- a/tests/python_tests/object_test.py +++ b/tests/python_tests/object_test.py @@ -96,22 +96,6 @@ # # https://github.com/mapnik/mapnik/issues/1420 # eq_(s.text_transform, mapnik.text_transform.NONE) -# # https://github.com/mapnik/mapnik/issues/1427 -# eq_(s.wrap_char,ord(' ')) -# eq_(s.wrap_character,ord(' ')) -# s.wrap_char = ord('\n') -# eq_(s.wrap_char,ord('\n')) -# eq_(s.wrap_character,ord('\n')) -# eq_(s.format.wrap_character,ord('\n')) -# s.wrap_character = ord('\r') -# eq_(s.wrap_char,ord('\r')) -# eq_(s.wrap_character,ord('\r')) -# eq_(s.format.wrap_character,ord('\r')) -# s.format.wrap_character = ord(' ') -# eq_(s.wrap_char,ord(' ')) -# eq_(s.wrap_character,ord(' ')) -# eq_(s.format.wrap_character,ord(' ')) - # # old args required method # ts = mapnik.TextSymbolizer(mapnik.Expression('[Field_Name]'), 'Font Name', 8, mapnik.Color('black')) # # eq_(str(ts.name), str(mapnik2.Expression('[Field_Name]'))) name field is no longer supported @@ -146,7 +130,6 @@ # # 22.5 * M_PI/180.0 initialized by default # assert_almost_equal(s.max_char_angle_delta, 0.39269908169872414) -# eq_(s.wrap_character, ' ') # eq_(s.text_transform, mapnik.text_transform.NONE) # eq_(s.line_spacing, 0) # eq_(s.character_spacing, 0) From 03429f9bcb9c689c772bbdad3438b30b1495923c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 13:59:02 -0700 Subject: [PATCH 10/92] use std::unordered_map in non-perf critical code --- include/mapnik/mapped_memory_cache.hpp | 7 ++++--- src/mapped_memory_cache.cpp | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/include/mapnik/mapped_memory_cache.hpp b/include/mapnik/mapped_memory_cache.hpp index 0fb93c0eb..c1f9c5030 100644 --- a/include/mapnik/mapped_memory_cache.hpp +++ b/include/mapnik/mapped_memory_cache.hpp @@ -29,10 +29,11 @@ #include // boost -#include #include +#include #include -#include + +namespace boost { namespace interprocess { class mapped_region; } } namespace mapnik { @@ -44,7 +45,7 @@ class MAPNIK_DECL mapped_memory_cache : private mapnik::noncopyable { friend class CreateStatic; - boost::unordered_map cache_; + std::unordered_map cache_; public: bool insert(std::string const& key, mapped_region_ptr); boost::optional find(std::string const& key, bool update_cache = false); diff --git a/src/mapped_memory_cache.cpp b/src/mapped_memory_cache.cpp index efa144fc9..96bce78ad 100644 --- a/src/mapped_memory_cache.cpp +++ b/src/mapped_memory_cache.cpp @@ -56,7 +56,7 @@ boost::optional mapped_memory_cache::find(std::string const& #ifdef MAPNIK_THREADSAFE mapnik::scoped_lock lock(mutex_); #endif - using iterator_type = boost::unordered_map::const_iterator; + using iterator_type = std::unordered_map::const_iterator; boost::optional result; iterator_type itr = cache_.find(uri); if (itr != cache_.end()) From a73440496aef456b2590d06d6d680748ab62cb63 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 13:59:13 -0700 Subject: [PATCH 11/92] iwyu --- include/mapnik/marker.hpp | 7 ++----- include/mapnik/memory_featureset.hpp | 1 + 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/include/mapnik/marker.hpp b/include/mapnik/marker.hpp index 21fa4e5d3..99b1ee5a5 100644 --- a/include/mapnik/marker.hpp +++ b/include/mapnik/marker.hpp @@ -24,23 +24,20 @@ #define MAPNIK_MARKER_HPP // mapnik -#include #include -#include #include +#include #include #include // agg -#include "agg_path_storage.h" +#include "agg_array.h" // boost -#include #include // stl #include -#include namespace mapnik { diff --git a/include/mapnik/memory_featureset.hpp b/include/mapnik/memory_featureset.hpp index 51ff72155..9deb6fe5b 100644 --- a/include/mapnik/memory_featureset.hpp +++ b/include/mapnik/memory_featureset.hpp @@ -26,6 +26,7 @@ // mapnik #include #include +#include #include #include #include From 5134fdc0d36e35525979d7de711441592230d033 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 14:13:33 -0700 Subject: [PATCH 12/92] use std::sort over boost::sort --- include/mapnik/hextree.hpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/include/mapnik/hextree.hpp b/include/mapnik/hextree.hpp index 8f2327ec5..b54891ca9 100644 --- a/include/mapnik/hextree.hpp +++ b/include/mapnik/hextree.hpp @@ -28,9 +28,6 @@ #include #include -// boost -#include - // stl #include #include @@ -261,7 +258,7 @@ public: // find closest match based on mean of r,g,b,a std::vector::const_iterator pit = - boost::lower_bound(sorted_pal_, c, rgba::mean_sort_cmp()); + std::lower_bound(sorted_pal_, c, rgba::mean_sort_cmp()); ind = pit-sorted_pal_.begin(); if (ind == sorted_pal_.size()) ind--; @@ -334,7 +331,7 @@ public: create_palette_rek(sorted_pal_, root_.get()); // sort palette for binary searching in quantization - boost::sort(sorted_pal_, rgba::mean_sort_cmp()); + std::sort(sorted_pal_, rgba::mean_sort_cmp()); // returned palette is rearanged, so that colors with a<255 are at the begining pal_remap_.resize(sorted_pal_.size()); palette.clear(); From d7c3d8f77441f4d508729b76ab71a9b86ac6c2ee Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 14:42:24 -0700 Subject: [PATCH 13/92] fix std::sort and std::lower_bound usage --- include/mapnik/hextree.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mapnik/hextree.hpp b/include/mapnik/hextree.hpp index b54891ca9..b9a0d8c93 100644 --- a/include/mapnik/hextree.hpp +++ b/include/mapnik/hextree.hpp @@ -258,7 +258,7 @@ public: // find closest match based on mean of r,g,b,a std::vector::const_iterator pit = - std::lower_bound(sorted_pal_, c, rgba::mean_sort_cmp()); + std::lower_bound(sorted_pal_.begin(),sorted_pal_.end(), c, rgba::mean_sort_cmp()); ind = pit-sorted_pal_.begin(); if (ind == sorted_pal_.size()) ind--; @@ -331,7 +331,7 @@ public: create_palette_rek(sorted_pal_, root_.get()); // sort palette for binary searching in quantization - std::sort(sorted_pal_, rgba::mean_sort_cmp()); + std::sort(sorted_pal_.begin(), sorted_pal_.end(), rgba::mean_sort_cmp()); // returned palette is rearanged, so that colors with a<255 are at the begining pal_remap_.resize(sorted_pal_.size()); palette.clear(); From aa63d6c9a0b07da1fcd523061bcae8f0cb1bf367 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 14:42:51 -0700 Subject: [PATCH 14/92] include cleanups where we used to use boost --- include/mapnik/agg_renderer.hpp | 2 +- include/mapnik/cairo/cairo_context.hpp | 2 +- include/mapnik/cairo/cairo_renderer.hpp | 3 --- include/mapnik/datasource_cache.hpp | 3 --- include/mapnik/debug.hpp | 11 ++++------- include/mapnik/grid/grid_renderer.hpp | 3 +-- include/mapnik/grid/grid_util.hpp | 5 ----- include/mapnik/utils.hpp | 17 ++++++----------- include/mapnik/webp_io.hpp | 4 ---- 9 files changed, 13 insertions(+), 37 deletions(-) diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index d01c00685..40719e866 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -37,8 +37,8 @@ #include #include #include -// boost +// stl #include // fwd declaration to avoid dependence on agg headers diff --git a/include/mapnik/cairo/cairo_context.hpp b/include/mapnik/cairo/cairo_context.hpp index d33821b3c..ce2073e7c 100644 --- a/include/mapnik/cairo/cairo_context.hpp +++ b/include/mapnik/cairo/cairo_context.hpp @@ -36,7 +36,7 @@ #include #include -// boost +// stl #include // cairo diff --git a/include/mapnik/cairo/cairo_renderer.hpp b/include/mapnik/cairo/cairo_renderer.hpp index d27e3efa1..2b70b089d 100644 --- a/include/mapnik/cairo/cairo_renderer.hpp +++ b/include/mapnik/cairo/cairo_renderer.hpp @@ -42,9 +42,6 @@ // cairo #include -// boost - - namespace agg { struct trans_affine; } diff --git a/include/mapnik/datasource_cache.hpp b/include/mapnik/datasource_cache.hpp index f9460d625..556097a16 100644 --- a/include/mapnik/datasource_cache.hpp +++ b/include/mapnik/datasource_cache.hpp @@ -28,9 +28,6 @@ #include #include -// boost -#include - // stl #include #include diff --git a/include/mapnik/debug.hpp b/include/mapnik/debug.hpp index f26d78cc0..038e98b7f 100644 --- a/include/mapnik/debug.hpp +++ b/include/mapnik/debug.hpp @@ -29,19 +29,16 @@ #include #include -// boost -#include -#ifdef MAPNIK_THREADSAFE -#include -#endif - // std #include #include #include #include #include - +#include +#ifdef MAPNIK_THREADSAFE +#include +#endif namespace mapnik { diff --git a/include/mapnik/grid/grid_renderer.hpp b/include/mapnik/grid/grid_renderer.hpp index 3c9e2304b..8e3dc0c10 100644 --- a/include/mapnik/grid/grid_renderer.hpp +++ b/include/mapnik/grid/grid_renderer.hpp @@ -37,8 +37,7 @@ #include #include -// boost - +// stl #include // fwd declaration to avoid depedence on agg headers diff --git a/include/mapnik/grid/grid_util.hpp b/include/mapnik/grid/grid_util.hpp index b1b61c661..f681debb7 100644 --- a/include/mapnik/grid/grid_util.hpp +++ b/include/mapnik/grid/grid_util.hpp @@ -26,9 +26,6 @@ // mapnik #include -// boost -#include - namespace mapnik { /* @@ -60,8 +57,6 @@ static inline void scale_grid(mapnik::grid::data_type & target, unsigned yprt1 = 0; unsigned xprt = 0; unsigned xprt1 = 0; - boost::ignore_unused_variable_warning(yprt1); - boost::ignore_unused_variable_warning(xprt1); //no scaling or subpixel offset if (target_height == source_height && target_width == source_width && offs_x == 0 && offs_y == 0){ diff --git a/include/mapnik/utils.hpp b/include/mapnik/utils.hpp index 27f448c08..d6961d950 100644 --- a/include/mapnik/utils.hpp +++ b/include/mapnik/utils.hpp @@ -26,23 +26,18 @@ #include #include -// boost -#ifdef MAPNIK_THREADSAFE -#include -#endif - // stl #include // std::runtime_error #include // std::atexit #include // operator new +#ifdef MAPNIK_THREADSAFE +#include +#endif + namespace mapnik { -#ifdef MAPNIK_THREADSAFE -using std::mutex; -#endif - template class CreateUsingNew { @@ -119,7 +114,7 @@ template class CreatePolicy> mutex singleton::mutex_; + template class CreatePolicy> std::mutex singleton::mutex_; #endif template #include -// boost - - - namespace mapnik { template From db96f3c93344881ab8c038f31cd568cbd6324ca1 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 15:09:37 -0700 Subject: [PATCH 15/92] drop unnessary use of boost in transform_processor.hpp --- include/mapnik/transform_processor.hpp | 22 ++++------------------ 1 file changed, 4 insertions(+), 18 deletions(-) diff --git a/include/mapnik/transform_processor.hpp b/include/mapnik/transform_processor.hpp index a37abacc4..343531cd9 100644 --- a/include/mapnik/transform_processor.hpp +++ b/include/mapnik/transform_processor.hpp @@ -25,9 +25,6 @@ // mapnik #include -#ifdef MAPNIK_LOG -#include -#endif #include #include #include @@ -35,7 +32,7 @@ // boost #include #include -#include + // agg #include @@ -212,22 +209,11 @@ struct transform_processor { node_evaluator eval(tr, feat, vars, scale_factor); - #ifdef MAPNIK_LOG - MAPNIK_LOG_DEBUG(transform) << "transform: begin with " << to_string(matrix_node(tr)); - #endif - - for (transform_node const& node : boost::adaptors::reverse(list)) + transform_list::const_reverse_iterator rit; + for (rit = list.rbegin(); rit!= list.rend(); ++rit) { - boost::apply_visitor(eval, *node); - #ifdef MAPNIK_LOG - MAPNIK_LOG_DEBUG(transform) << "transform: apply " << to_string(*node); - MAPNIK_LOG_DEBUG(transform) << "transform: result " << to_string(matrix_node(tr)); - #endif + boost::apply_visitor(eval, *(*rit)); } - - #ifdef MAPNIK_LOG - MAPNIK_LOG_DEBUG(transform) << "transform: end"; - #endif } static std::string to_string(transform_node const& node) From a7e864b91807560826022f3b5b813bbb1c700e2e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 16:10:55 -0700 Subject: [PATCH 16/92] travis: drop jobs slightly given recent killed processes --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 7731a48ec..c9151c92b 100644 --- a/.travis.yml +++ b/.travis.yml @@ -19,7 +19,7 @@ before_install: - sudo add-apt-repository -y ppa:boost-latest/ppa - sudo apt-get update -y - sudo apt-get install -y gcc-4.8 g++-4.8 make boost1.55 libgdal-dev libgdal1-dev libgdal1h=1.10.0-1~precise1 python-nose libicu-dev libpng-dev libjpeg-dev libtiff-dev libwebp-dev libz-dev libfreetype6-dev libxml2-dev libproj-dev libcairo-dev python-cairo-dev libsqlite3-dev - - if [[ "${CXX}" == 'g++' ]]; then export CXX="g++-4.8"; export CC="gcc-4.8"; fi; + - if [[ "${CXX}" == 'g++' ]]; then export CXX="$(which g++-4.8)"; export CC="$(which gcc-4.8)"; fi; - if [[ "${CXX}" == 'clang++' ]]; then export CXX="$(which clang++)"; export CC="$(which clang)"; fi; - wget http://www.freedesktop.org/software/harfbuzz/release/harfbuzz-0.9.34.tar.bz2 - tar xf harfbuzz-0.9.34.tar.bz2 @@ -30,7 +30,7 @@ before_install: install: - ./configure CXX="${CXX}" CC="${CC}" DEMO=True BENCHMARK=True CPP_TESTS=True CAIRO=True FAST=True - - if [[ "${CXX}" == 'g++-4.8' ]]; then JOBS=3 make; else JOBS=10 make; fi; + - if [[ "${CXX}" == 'g++-4.8' ]]; then JOBS=2 make; else JOBS=6 make; fi; before_script: - make test From fb12fc8b68edc14dc955ca3ee706d7fc984e41bd Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 16:20:12 -0700 Subject: [PATCH 17/92] default to global alignment for polygon patterns - refs #2325 --- .../process_polygon_pattern_symbolizer.cpp | 2 +- src/cairo/cairo_renderer.cpp | 2 +- ...ate-patterns-200-200-1.0-agg-reference.png | Bin 8597 -> 8582 bytes ...ate-patterns-200-200-2.0-agg-reference.png | Bin 8816 -> 8779 bytes 4 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index cc92e74d4..bc0ceb89c 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -128,7 +128,7 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, agg::pixfmt_rgba32_pre pixf_pattern(pattern_rbuf); img_source_type img_src(pixf_pattern); - pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, LOCAL_ALIGNMENT); + pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); unsigned offset_x=0; unsigned offset_y=0; diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index a441f0b5d..5cbfcc88e 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -735,7 +735,7 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, } - //pattern_alignment_e align = sym.get_alignment(); + pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); //unsigned offset_x=0; //unsigned offset_y=0; diff --git a/tests/visual_tests/images/geometry-transform-translate-patterns-200-200-1.0-agg-reference.png b/tests/visual_tests/images/geometry-transform-translate-patterns-200-200-1.0-agg-reference.png index cdd2814edf156fe59e60357fbbc5dc66c7c41019..fa06b37f2d5480f30c272f7fc885a61397712a2c 100644 GIT binary patch literal 8582 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 U!qxWk|B4qXikb?w?<}GJ2V_RwH~;_u diff --git a/tests/visual_tests/images/geometry-transform-translate-patterns-200-200-2.0-agg-reference.png b/tests/visual_tests/images/geometry-transform-translate-patterns-200-200-2.0-agg-reference.png index d752e7c9d5b6a16c6c03b8298d1f86616fe5648b..c584eb6fadc544bd0effca33d17e916d71b35a59 100644 GIT binary patch delta 8755 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 Date: Mon, 4 Aug 2014 19:18:38 -0700 Subject: [PATCH 18/92] visual tests - keep default debug severity levels --- plugins/input/gdal/gdal_featureset.cpp | 2 +- tests/visual_tests/test.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/input/gdal/gdal_featureset.cpp b/plugins/input/gdal/gdal_featureset.cpp index 4eab0f048..d54efc716 100644 --- a/plugins/input/gdal/gdal_featureset.cpp +++ b/plugins/input/gdal/gdal_featureset.cpp @@ -404,7 +404,7 @@ feature_ptr gdal_featureset::get_feature(mapnik::query const& q) } else { - MAPNIK_LOG_ERROR(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band"; + MAPNIK_LOG_WARN(gdal) << "warning: nodata value (" << raster_nodata << ") used to set transparency instead of alpha band"; } } } diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 92f0b9198..d02efaa00 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -3,7 +3,7 @@ import sys import mapnik -mapnik.logger.set_severity(mapnik.severity_type.None) +#mapnik.logger.set_severity(mapnik.severity_type.None) #mapnik.logger.set_severity(mapnik.severity_type.Debug) import shutil import sys From 99a46f691034b2b16513e09b035dca7a99ebdd27 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 19:50:16 -0700 Subject: [PATCH 19/92] re-enable glyph_info caching - refs #2326, #2265, #2334 --- include/mapnik/text/face.hpp | 4 +- include/mapnik/text/harfbuzz_shaper.hpp | 23 +++---- src/text/face.cpp | 58 +++++++++--------- ...ine-offset-900-250-1.0-cairo-reference.png | Bin 14286 -> 14261 bytes ...ine-offset-900-250-2.0-cairo-reference.png | Bin 12410 -> 12345 bytes ...xt-bug1533-600-600-1.0-cairo-reference.png | Bin 11834 -> 11768 bytes ...xt-bug1533-600-600-2.0-cairo-reference.png | Bin 17866 -> 17730 bytes ...rplacement-512-512-1.0-cairo-reference.png | Bin 22109 -> 22286 bytes ...xt-spacing-512-512-1.0-cairo-reference.png | Bin 17161 -> 17399 bytes ...xt-spacing-512-512-2.0-cairo-reference.png | Bin 26550 -> 26454 bytes 10 files changed, 42 insertions(+), 43 deletions(-) diff --git a/include/mapnik/text/face.hpp b/include/mapnik/text/face.hpp index 7d3848855..7624aa290 100644 --- a/include/mapnik/text/face.hpp +++ b/include/mapnik/text/face.hpp @@ -69,13 +69,13 @@ public: bool set_character_sizes(double size); bool set_unscaled_character_sizes(); - void glyph_dimensions(glyph_info &glyph) const; + bool glyph_dimensions(glyph_info &glyph) const; ~font_face(); private: FT_Face face_; - mutable std::map dimension_cache_; + mutable std::map glyph_info_cache_; mutable double char_height_; }; using face_ptr = std::shared_ptr; diff --git a/include/mapnik/text/harfbuzz_shaper.hpp b/include/mapnik/text/harfbuzz_shaper.hpp index ae1426812..32f4f1f8d 100644 --- a/include/mapnik/text/harfbuzz_shaper.hpp +++ b/include/mapnik/text/harfbuzz_shaper.hpp @@ -101,18 +101,19 @@ static void shape_text(text_line & line, { glyph_info tmp; tmp.glyph_index = glyphs[i].codepoint; - face->glyph_dimensions(tmp); + if (face->glyph_dimensions(tmp)) + { + tmp.char_index = glyphs[i].cluster; + tmp.face = face; + tmp.format = text_item.format; + tmp.scale_multiplier = size / face->get_face()->units_per_EM; + //Overwrite default advance with better value provided by HarfBuzz + tmp.unscaled_advance = positions[i].x_advance; - tmp.char_index = glyphs[i].cluster; - tmp.face = face; - tmp.format = text_item.format; - tmp.scale_multiplier = size / face->get_face()->units_per_EM; - //Overwrite default advance with better value provided by HarfBuzz - tmp.unscaled_advance = positions[i].x_advance; - - tmp.offset.set(positions[i].x_offset * tmp.scale_multiplier, positions[i].y_offset * tmp.scale_multiplier); - width_map[glyphs[i].cluster] += tmp.advance(); - line.add_glyph(std::move(tmp), scale_factor); + tmp.offset.set(positions[i].x_offset * tmp.scale_multiplier, positions[i].y_offset * tmp.scale_multiplier); + width_map[glyphs[i].cluster] += tmp.advance(); + line.add_glyph(std::move(tmp), scale_factor); + } } line.update_max_char_height(face->get_char_height(size)); break; //When we reach this point the current font had all glyphs. diff --git a/src/text/face.cpp b/src/text/face.cpp index 52f119b3d..11afd18cb 100644 --- a/src/text/face.cpp +++ b/src/text/face.cpp @@ -32,18 +32,20 @@ namespace mapnik { font_face::font_face(FT_Face face) - : face_(face), dimension_cache_(), char_height_(0.0) -{ -} + : face_(face), + glyph_info_cache_(), + char_height_(0.0) {} double font_face::get_char_height(double size) const { if (char_height_ != 0.0) return char_height_; glyph_info tmp; tmp.glyph_index = FT_Get_Char_Index(face_, 'X'); - glyph_dimensions(tmp); - tmp.scale_multiplier = size / face_->units_per_EM; - char_height_ = tmp.height(); + if (glyph_dimensions(tmp)) + { + tmp.scale_multiplier = size / face_->units_per_EM; + char_height_ = tmp.height(); + } return char_height_; } @@ -59,45 +61,41 @@ bool font_face::set_unscaled_character_sizes() return !FT_Set_Char_Size(face_,0,face_->units_per_EM,0,0); } -void font_face::glyph_dimensions(glyph_info & glyph) const +bool font_face::glyph_dimensions(glyph_info & glyph) const { - //TODO - //Check if char is already in cache -// std::map::const_iterator itr; -// itr = dimension_cache_.find(glyph.glyph_index); -// if (itr != dimension_cache_.end()) { -// glyph = itr->second; -// return; -// } + // Check if glyph is already in cache + std::map::const_iterator itr; + itr = glyph_info_cache_.find(glyph.glyph_index); + if (itr != glyph_info_cache_.end()) { + glyph = itr->second; + return true; + } FT_Vector pen; pen.x = 0; pen.y = 0; - /* - FT_Matrix matrix; - matrix.xx = (FT_Fixed)( 1 * 0x10000L ); - matrix.xy = (FT_Fixed)( 0 * 0x10000L ); - matrix.yx = (FT_Fixed)( 0 * 0x10000L ); - matrix.yy = (FT_Fixed)( 1 * 0x10000L ); - FT_Set_Transform(face_, &matrix, &pen); - */ - // TODO - any benefit to using a matrix here? FT_Set_Transform(face_, 0, &pen); - if (FT_Load_Glyph (face_, glyph.glyph_index, FT_LOAD_NO_HINTING)) return; - + if (FT_Load_Glyph(face_, glyph.glyph_index, FT_LOAD_NO_HINTING)) + { + MAPNIK_LOG_ERROR(font_face) << "FT_Load_Glyph failed"; + return false; + } FT_Glyph image; - if (FT_Get_Glyph(face_->glyph, &image)) return; + if (FT_Get_Glyph(face_->glyph, &image)) + { + MAPNIK_LOG_ERROR(font_face) << "FT_Get_Glyph failed"; + return false; + } FT_BBox glyph_bbox; FT_Glyph_Get_CBox(image, FT_GLYPH_BBOX_TRUNCATE, &glyph_bbox); FT_Done_Glyph(image); - glyph.unscaled_ymin = glyph_bbox.yMin; glyph.unscaled_ymax = glyph_bbox.yMax; glyph.unscaled_advance = face_->glyph->advance.x; glyph.unscaled_line_height = face_->size->metrics.height; - -//TODO: dimension_cache_.insert(std::pair(c, dim)); + glyph_info_cache_.insert(std::make_pair(glyph.glyph_index, glyph)); + return true; } font_face::~font_face() diff --git a/tests/visual_tests/images/line-offset-900-250-1.0-cairo-reference.png b/tests/visual_tests/images/line-offset-900-250-1.0-cairo-reference.png index bf382a35864f3a77be58c9c999242f3f72d21c40..7ad8c3e0dd500f8aa04d4f3571cc1dc36df6a59f 100644 GIT binary patch literal 14261 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 RfAe<`(h>^dRicJL{{z@YVJ!dv literal 14286 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

ZXQ7X<7}|7PuH@dN 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 diff --git a/tests/visual_tests/images/line-offset-900-250-2.0-cairo-reference.png b/tests/visual_tests/images/line-offset-900-250-2.0-cairo-reference.png index c71d9ab9079a55746568ce5c4a3e5cfeb2491c63..3a5b783f539d8b43817661f5c72023d8e9aea136 100644 GIT binary patch delta 11794 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 LNkvXXu0mjfwD}s) diff --git a/tests/visual_tests/images/text-bug1533-600-600-1.0-cairo-reference.png b/tests/visual_tests/images/text-bug1533-600-600-1.0-cairo-reference.png index 9d64790f493f962d800173fcca5801ce3ec74942..cdde3e8b0e48f3cb7ac9fa14d468e913c8e57421 100644 GIT binary patch literal 11768 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 K%Sy#JA^!t+yuB6x literal 11834 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 diff --git a/tests/visual_tests/images/text-bug1533-600-600-2.0-cairo-reference.png b/tests/visual_tests/images/text-bug1533-600-600-2.0-cairo-reference.png index 16d3c77c568db4d65fdd30ec2016f295f683ef32..72051da70cb1753e35df68c92e84499c77896ad8 100644 GIT binary patch literal 17730 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 literal 17866 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 diff --git a/tests/visual_tests/images/text-charplacement-512-512-1.0-cairo-reference.png b/tests/visual_tests/images/text-charplacement-512-512-1.0-cairo-reference.png index 408e3d206353cb084a7d7f437244126d318fceff..2ecc0e7f47a63cb8f81e1a90438ded38afe3b978 100644 GIT binary patch literal 22286 zcmY(qbzD?k*FJt`7-Hxy>FzGcp`}4YkdUEE8WG8%LmH9BL0Vc+lpF*J36bs)L{hqA zeskZ?`#$gQ``0;powcrgt+hXA?|s(VC*DwBlL((49{>O%tp{ok0RW7-1p|0km`isV zM?a=vZ>al79n-|d2JrC#Vq$=t9H6EK=;;BbdmttzfSnx>5C9}30C{;pRTa?D0gR0S zOH07s9&mF5o;gDNe1Sk;?4TeZJQNfe2_!^gB_#oAX~63w?96m5w=_Z8st7tt$Xi>1 z?neBc8j{{}%C0V;yA8X&k?z}9aBnX#*hDh;k!+-$VE7yMWIor>5HQ?LG~P};Rn0Iq z44&vA82UyrJ`T(_Q_ocK&V3`AABN6-qnMk-nwtYQ-g7U`ftO|>OH07oF!5$9!`c|Z z+9KAkU%+NB_3kHjw7vaIKkx53{NKO88!HgB`_qjLU~>uQxLOeHYmRk&9blvV{m;$-bf7PKknQ3x?p@^rbha6Kg5mNEbhANxb%c$cr9&@LUtIy{HF9)N z5c-wd-H-sf_z`-S@OX#*c9IL-CyqYGy}JUVkD%x?9CWh=`Vw-tLy2CyhrR>Qx7g_2 zd+2LIbW{|&$rK$QbvGk@x5b4%qeZ`Zg+Ag&*LvQL8liJz&^t2d%uICdYxHk@bY331 zG95kTi7qKYuQ{QstIzO)Y{g zXU2?-rSBPAQAL47G6lcZ-bXjhT7g^RPG6kS%y~kr;)adOVDbUy?BkJ_Z(oiCdF+Ee z7!A2g2lIYWn7;TZh#GDsvTkXbRFR|azUtjLJDb{A%-hj%a(kNXQ)6%Yv`{BDrf%W$ z?1h!5hnGmSQvK@k)W@mWF0fNp?PA-jxcc@l-a)sn>erRi_Kc2wrMlVE5%;)&dmvIX zut#IjvdJnZT$q;W8LRrt=b&SNL`9VaE7gK)j4}mVN*9mX5Vta|P083c zJ7;5mof^3|3wEa?Y&iz(w35gX1ppo&s2Z};uZ2<^T3lFI;-NSp!q&a$&hapGSiGV7 z$pe~!B9P>$H$j>Y!Tw(UA-+MrjOww<+|I|Fk=WRuZ*CSlmBIB?0EiP&3NW}sd46s8 zo^1@5V7Jtt(X6YGB5D9U9?)*iizZHFT-A%Zx4<8BKG`60N`85b@FX%sJAlUps>X&9 zk|S2`VFNYp6`I6WjTHv8iBSPX%61UAFc6^y&@9C(gB_p2CHTppcy3F2y-cF?)drj| zkuX)r3L5~{0&qd3u@C`gILAkLRwb77U(Y*bTqN-I(`fJuBrDj93<&2y+}la+fCTix zzG$Q!dTeS9g}lQpcvUE(GHp99?GXhmKwzZM6%N2Q6=5cA_ON1$8Ov(q_Q~i_*h%R6 z^N-J3w(el;kQFW<;sIbf!uS%}@7xv74LZVq;;%u(e(7dmv7c=tliX8O>5l|~y)ZH1 zKokRUFtCuz?<}wWtf{UUX=TmW2R^rj&=`smrMzM8&p*hdU_dRH1p)DLS}@8&7+$6D z-uU(sa__UBs zzR>!Fw#juRD#K02>@Bc>joc$2C0tH!fxKS14xhauP-)#}t#ry&p$%n5+>@DQ{dNW5iTAv^4G-$v_kM0}z4Pl=Eabh)607a&p5rOrXg<(n0?s7|4j%v!($bES*$jTNQri6jT-Y{H zXNQ*_=kGNU8xUj-`KZ8j4?Bp1Zg|v>OT{r!XZd?v39jAvw30?5Df(TiN z^J8F+2c(COsNg^*noxzyMm=(UNZft?SKjearC_*(`jz6^cWGHM!&qP#A9jxu`LZlt z3!KouX(O>kLetWfo%{|3tHgN@pAyI0e)g`*VuA~H3?7w&I-3JMJfI?*cioB#HrT%^ zhqL{A(wU=P2R|sCH6-2(XYbo3;hL?Ebu58eNZl|09*c2C_1RkY^uBZbE2el3)Z^2ssK3%rR+2bPFl{ijWy)}Q z87)%5g&uNrtj7UekRztF5&MZ`(aOkcE@n6ToaVP8N%y~Tg7AcSGBa|#ep%yvsqzX7 z`D6E@Vu{9$6d??9u7nuAWY3Ppndl)|=yK#W^j9kQzGDw!YPS9eVk+02ovgz3s=nO# zG+1~{wXqY8H3>z%1)3g$e|5tJgDAbgZ!VQFhN425-7WPgfOPgGwD_SyLvpq?U4cB^hSfk?I z)$I}u@g>P%`GE)~0Y3(Gs6T;ez(qRQ3#coBoeB7W7pTbq5~keJnSZc@Sd4EEbSYkZ z-$}jRI=Qz^Jb`^ega}{T%|+l5(SN8M+t0ga|I9o#f<2`6EbBcv!T{u405NPby8D&H z!~smaS6&>_x#!J#e%+s=KN_}Q8vA>6{3iYS6MNIA&&MsE3%R3+Uc56|{^<8)2zO3@fFDB@(Zfkp z5$}zja7p?lL88zV#l&E)GM+(YfmhG`sFxSlcnair!?2XIEomGL1QWmpIS}93OW6|( z-VoC!NQcQyT@Z-1Kbe6bU0YjM}|Ug&Y#H2 z`S@_;{VD>9AG6qo(ll5norI&OOmc#e0V%9da9fR6Vp1YO;OMw|+vcji#RUz5#DZ=g@~Can)=f zb5`I+2R6jncS){m*LKNQyq~T6?djITqH9+#Dxbcwjm7y>v9LEQYZmSmS$YOVe1~69 zshy&8peu37rQ`&Nb2M-u40@^Xb4_hTg|h!xHN3xG{4Kru-{~ibVqdCOO(ZkDp5LDJ zJ{HB^{g|tUoU**MH&$ni2%=sVc8O-4W5pV;`bhgY9;hJ$Iyg}ZM4xidt&O8~y_73X zGhChI%o&m1yFZ%8?C?WkV&z8mN)YW9oY=b)@*}`?V8s5V({>W^w^GmqUH|8EVp0Y* zPH>Y3aPbCs0ceE885b!LRVe>3XkOeKphLQK8F*Ob?L~Os1^f6*WAE-&U87$MIUsJe z7IQ58@!mpoxVH&|FTzTM&mT;Re!zz~X95QTpe4zVYZNgL zpN?k=%jqJfpuk&l(t=TuqAS-VBYh#WEs{_XEOWY}JYPO@s16;R|W0`@v*_DI*(<9~+?rJxB?c zJiUumrH=v2GZn26RNxtxYk|}ZYNNr1Ul)dhPM}_nzg8Et3=ifZsgHX848KRZ&CM2l zNu`S(`9G96S@_ZJnWYz*F{;;T_*?J6(|cbxTfCDJe%~)!bY>V(po4q&ubv-kwO-KD zifPSpN;~9_ni%ntkRv~WQCX0S4|XDGX z!+@O5!}#*RXJ=U#a@5X_ntF1ejr#2)}m9jd$}og93(RQ!eWmg zmTgP-YDw<#<~s{H{`GRn1G7MEC&cXubJ*aMLvzY+>}^SSYR*`Pg6a9CL=U+6O~*mt zCUYPl9T5R-7i;Gqpx#?TKJ<_5c-uiGPEq{)&4grpj;P^C`rlyblbek>&BvRY%)YKg zZ-u9fE}@h0Ka?)B>5v4TG?k-m3@orJYy>y-phSbT{3Exi6-MnYdd#cnOYQoad`^D+6^B52)jJ+&$@*;w*v=M z*a1pB#z^djD;DS8DOsBpg-&cPi&?spG4l(trJw5j_LULDyPlrzLceQPR%)W);Y<$^ ztf?hZid&ESxk#dQuA!rWpcPFpPr^cn<)iS`GDmm*WyTcjR3p1Se$R81$d7`?kT}aR zG0)b#sjhP_SV4LJ=^jaq$R=wsK_#AW>*A*VJ10q94JMVMGKVYDf^#w?BN!D4={c6T zoi^YZd&P_Lq(R2T0^CbCia(Pg$`2p&A>`8DI{f;sq)+FstVET50Ir+*E8YsmhM&y`Dr zKl7GG2>6eP>*CA^F?gzJD4+fuHWLLstGzVRKeuH&Q5Qt~R3B%@AKtODv61y$E?%@AwHaAlmqxfzW6IH$;yhWdGSxn3Gfr1?s3_ zWVQ48rn1J?LUa)CbrI-qJH$B!kl+PP*uk?$X7Rwr@Gt6X62_6{;J%St{{5yhL?n`J z%V7?(7@sqaGrFM=uN3CDV|x)RMl`HS(Cj=xG=9muyRsj?1=F5YfH-FX65Jpg)jq#n z!RVKku~`x0f^$8$>Cp&^kgSJU`>|i!h)1SSyKSJ?=5)?n?AA8qsL*T?So?5$5=u!= zxbHw!V6id$6jj*wzhFw7&)hn0TxG(h(c~uz)FsvN+Fi!mc4mUg!mRVu_*=or~~n4N>(+0hMb}A0%mLNb+NU>~ogVQR!v0nVZhWH@66aRS0&@nYy$>oZkWx zoFMBo1Fle<$ouIxG@(yZz9Z#1a+pj&HuX7FJ$OHMPF*Qq)hJczDd72%H$NJ9@g3y;!E{%FpgcY;)-;a^M2 zEVi>|vKfXt19ryO)nZwbNZehfV;XoB63ckSCX!@}jF|~n7fFyxnt?x@{e*qnO7~yU zvkXz3SS#wKM7-Sh`NIfqG6p_t!Fu2O!tqn*(ag@4C&0{O3;IIAog(2q*5+EyR{KjY zk9XxCk5yWcOzg6|VK)s_aSfI}K-|dT*3+-_7Ne0anQMY;1#kw{8iFq`eT~@5&voBr zLPwv1R@gv_<^%{{ub^(Ht}P>z@Hc;#j`Sj!`m#-%ZT+zoJh)#0%%l5AGDsumV75S12^o%8Q`s>QC*_xy{f@);JM#q_8E`R9st+=4s zxqqP!#JL&pN&p8t;Fp9v;*cEw#WkxS>_m-cP(zHICi~J^)2e>^v)oUC-&kmr#!#;L zr4s}uIeP+@+H%7rA)8SJEfHZpF}P)pawffvuNPCuEc>}^{Wl!~ zWtnr8S6%&OA_6;fKnYI+mtCjXKy$)?Wgqy4`3+C1>q|Dx^PP%GNtbAErI@#gB+A0n zEi)qc*tv{}*?|wBKJyYGZq}QY9I$I_L=8lDc!(o?;1S<*yG%zO_-YsN{0~EyxE027kn3FU28&CyUA&3G<6j-BJxo+G=()Hs9 zRiVf?)mSodZA`6U+MkQnD!u}n`m%zMla0Gi?M=s`<$LRwBi@1De0nK_GgfYLs?LO< zC{nTA5VAggWOod$UmRcJE_ziKKatW^lYK@(<%FG9XT^rOW516h$& zL@Vp^Ec$1-&m-Km{HrKs?i08o;=%q4rq?(`D1$lE6J>~!Dk54x47u6g>*a(Bh<7*TDK@q`3gCii z?pAw)Sg{eM5RqqHl+I3E`x3-0%I>>9kPnYj<)Q}Jm>SsjiZdqI;p(jL5(?CSf3!+J zNP&*e9hf{AkwGBAC~fd}C#;7>{)K-e)+A14%BRH!lyFaw9)T(`ayN@CFUE{~v~le` z(}a;DDAH?A@B3J*y3w(?cQ@Xb6wcGDOD6TRp8*aea+9}^}V6$`F|2SoWc{MM)upzN6Wg~s}OpS51h!-!i7|ZYJ!Lj z((}5NRf9Szoav4fIV^0UsS6zo{TBt#BOWuvaQD z?!ScVx#n;Enk^4U3o(#LRuEpytIxir7mc^vvKn{Jkjc%OV-Bjs(y@p!AQpjDA)XrY z%5}wTbo+D5lPl~w-_I|oB-jAuE8wDkbqIezlxP#YWw87`g~oF`=zqeXrH1}F_ z16x6R-5^jVTo!A|`Q%QHAG0HGwDfFxdL&y&Osx&3-vJx`G!ytFUpp1HMj|e(;3%`| zdj4g}Er8gntdTJP`-X7?vOZQj=tnl!amRYe@I=s>ZKzt=A6a3aPmeCM0TnISniW7& zGtTWLjL^O(Iat$F2^PD3-1=&yT(O-8BMc7{T+^o(2hb^=!#LJ!fyKkWuGk#4vPH;I zwuCG)P=DreqC^?gGi`tbdI1%o zdQCdq5(be453=OhB-uf=zoGeM^GybAQt#~G4`PpmzVPnbKTPud`tb0UUx#JVsTiR@^pCf*nz_)x}Sr#yX3`}Y*4mu>m$FwG(hD6 zQ03D9n$9m7P}rLg&v`wUK!bO>>BsEX5%jauOkcnF2lnO-Gy9NqU~jAua=2s;6xZb2h2{!%s< zHT-h+dKnbZ%89sD;n-e^o_S3=?k(IOXu9}XPs@5Uroo>?Gs_5`n^`bcoLye=#CDYNbp)CL=htGuOZEISc2nkKu_hEpx);I59cm ziw{1-Z#R=idaA3sr~b+$CQy3+c`$^%%VIMs>(XZAvbNFO^>D>2w&oV%TnwqFMvT&) zM7fl@C*<#C-ZpSbP477tta1Y*jk2X94AI&Q(!C((a^kiYtTaIr&=Nk*(pfgI%^Z9B&%=PQh|m)?5T zOcHU)w)Al@zeW)j!}yh0o^ahf=z3`gsAp#W5^oCGWrqcEAO<~p;9MDVEe8~@Mx1G$ ziTLlh`@R}CZd9Kjj4^hDN`LuMnC|BC$ya6Q+320!+8iq=znR^0_~qJw**$3-WGD3TFQ2_a4r>OfY30Zp!{zWs zD3`BB(c|InN$!(FtFuTf&Av}h!7});^%NnF<6*pHMC zehb~-+;~D_EJhGXLW(>kN9h4789Z|)t|pL*(3!uN*^3@5_~4Z9_M<{K!smX7YVko< zsrN9%8y!Fs)PJu_qT`KqP7|VIk&i)IWb`@d2z8-RH`&A&MNZN;178)0t!vc~k97cP z(19LB%z{GCuwfTr=lXn^ES_MUZM8#?1N+zCxRnub8by4^`_vt$UC*NSoLNHWF<sX3$2$?_Az$Ax2tYwt?JM$oH#LYq^^O1ZPpUQXi6LC6M{Jt zUPY*b2|tDiArotkNxFN|wsCAB$Krn_+?__U8=l(s0rL0!;sC)+pw{ZZC+~X0;)W=_wq9FMpd9Ig&86N17_O^bWh#q zf9i4W`eQ+_f94YKu*pMnv%~@yPv;3-1*@RpZd6prX!21t{ja0%vGxf>hyXA#la*4}2Pgb6PTCT+mgBHwKOKY(q<+15;WkBG&MK^GF>4e1o z#(W1`JFD8B$gk3;87~%LA@)M562{H@vPgrQY z89V#$C1qAVf;)|r7>Cu#QC7e&Pr~^Eg7Xn>ulLS500f?V8oFP@&I@o{wmh^(M(Ee` ztPECTm0*&4Nf0k;L=TTRiA3&xMsdeq`}uhrKFMce6(8RipZuJm^(Sp$@+zymfu@pt zc*|S$0P*Glrc81$!e69Xhx1&TbP54*OAWozua3~a!aD<#DTmcP*6*QEC_ww>+-C7p zAgRbvPXNQ$ZUKVLQ&1!w#V-`GHFHHQmxC2C5n=t)=i}5D`Yt%O6R)o~tj?BebP?1K zfO9++he#vgtwFvO+z5%U;@ZFc@=Dp zxd*k;-w7aZIkwlGI$pZe&z8wGg3&RMzsF>2_sK_lXaP3h@1l^~R>PFMl7PhGDMxrPm_Sig5D7_w)c%ou)z$*oa~E)BHX$rbdy}1g+cu=}PV(BQ z00`EG`D$husV^v5-wb3K5wXjQuMsFJUTs@wvTDH@>qE!iQy?^?6==;Ofi^9`AT|Sk4=5V+#H-$Ep$1)~1BJxgRC6Ge ztYz8@4#0pMHNDlNA_v<%x`$PVDT076WDCsx#jt~4k4&i@m6G*<6p3Q*?Y3ksl%k;U&a zDSYpNp#oTfA9MpntPqp7-1OFujM-qSUL}wN9w6dhM%^ZFj>DfrNAv$rgf*|OjFG&C zV5$@UQNo(%t2012a$qVB|LLD4fEz|Zj;aFi{{G`Q=?w*<6>`A$KkAUd^N*N<;u|0o z8|L*-tRmqqj+ja$ALs`EKSXf4e2mO65+0B|!G9$V0hr<_*Z)bpv#dT!s{#7tsOJCe zN8lV+N&^u3|4W=A>Dd8X=!z8pd4U-HEsgi4QJIJw(GEEf`Y)YXBn}jX2@K7D0z+h* zy!gzp7y`#c=D*z^O}f1X1UQk{V3yBVm@!vwN&t2_{-0(w2a@W)PZKd;lK)SW;~u#F zLy__V)yzL5#A2=qK;Hp_>fz)dCW$6zmIo1Lqq#+J=sRUMu1JnJ906%uZAic<$|tB^ z4S`E^Z`#aCh-^g}Ymk!lUkmt?&k#|YYk{gkPO!Z5N|;+VM0B-U4Y5Y_hW{%EMr8I& zPBjkVy-L4)KY}BUU`O5wn!zHrVE@u59|K4za31q7{@H>^JU~J_!$i+PwgSSMUyH=x z!B@^vc+huPb(*~oNSQgn44(A`_^EgYi16u1cFs7GU?xU>pKt%QT9 z^h-Rfip;_c*iez6Wt!)ZqP@WGA7`&HZsL7b!t!ZjbTQ5QK>7Zg&S8W z={hRU=yE&ZCXU!S{~C}9ZyS=pUW)a$T~fB5!iHAG z{w2<-rVFos$AtJhXmmCR%IS9a*GugSDw{HwK(!Q}gO9y`0BtyNR@y&2`4K+h{9pWp zRY{89pz>`l-8a1G{_Pc9NYdYXQ$axb{U`ArEcthH4sQBC1|;3n#gCpWIeq{~A4?4T zu+)FfH2cRfrNl?vAb3#gXX4-l6B^RU*#}(z3=XqKVxb5HGL&Pa0~hvYeBc3uRPT~% zMenB_7ck61gHI{`UF#oFY)zWK^-&l|D}S@IN%rK(NvWlH2Wqz5CX=Op*xp zZ&x_q{>PZarkylwP`g_{1kabPJ^=`#3cN$do*Nu{VW4Y#V<+}e>!hv|ER3@`>9AQ%~v4E z{*U+KctoUUZ7KQY1086_`achjM6=7*7(5=0@ce5n9(NA-)#7MbpWLw!at@@bD>r_} zHPpCY)Aa8EtJyxlDbw-xIYwI|nH0`N%uHp5A+N`^Uxfo6B$3xyuaxd9c#a0@{87mnn+%=T>!%No0xYfnx50)~>Jx95{ z5$On}pNPO`X-DgOvL889S5H)SOERfJpkMVQ)aC#*F0mh0m-)LwGBWqJLe3!WPr7ly zTI~Kgj-iY%(+>f?x*?ycq=Kd~TNXqmXs319p{%JK_v>ek8*P=`dL=a?uO zX&AJWn+X%^>X*rq$wIegNfddNqMY$aja(03|1rR3g?WKnR0u)jiy~Z!;8an{yB#dQ zl@b$f{)8^tEMmkT9dn@cOTM0=0K_YdhH_R$>+YUkZBwToNzLQ-U@S6JSlL<>OFLzYE_TG_Q4CzvisL)VE(nEx=O;%badS8H^Glfk!vIL@=6yph-aWSytz9_z>XC zVD({uRq}*Dnsh}j@+*2ZB~5pL1^9pdEcxU3G+x=2V+*5B=Nq_I}m0VbH7BG*0-oW#o0t|htrPtSA zhY;t)2lqIzG~$RYUH{2HTh-xB-m%V&=JqZq+q%)6-#Ryr_Gw#KwwUX z6TTm)mJk_(YB`|Gevo1GF_}0%0{9t!GxRL<`RUcXyXmr3K>C;SO}06C%H5GX<#YPb z6Sw)HpDRVyuD^vwH1fw0CT>X8F8%sCqjxO8mQI0$i{bT7$rrugLjb)UHC!<+=KMl> z^tc6-_>$yHhm~cw>eW-mRi^kWE1uV5^SFs{q<5GGAw?Gb7`)vSr zkf6vL#n#hvb-8}4>T%d!-)qK1eL1%9yTch`Yz(jRF5R`;{qtoB(mIJ-YOn5zxN2#O zZJbY;k)Z^MZS5f$B|fq;hXnc-2>(>6_rjc>BGA&rWuXi$2n27dOIGU-!5Wu{&m6c5 ztF21^ovJ5%bjkzSNBm|d;PP=j=8V)mJ%!L-c!Aa2S*c4bPTb*GjT#I%(&8lL+k*n9 zB``rC$M^f(0+C^FF|wR1ryiMiPF=Tmq<)F-VuVX1C8hDSIGK0Y3qSYW zFqzM2@p9pSQ|$u|PXbojn?KiuyO9@()~n6U5(JoI;RJQkUnyPnS+~F(Lw2p7_iXxz z6O2_ZuL>cmm7XxD&e3U+V}lmb?AdtMM;OpDC%E%wcjMc{xCI6&6d&TVxjjwc(?n9` zXej@tdmL77Mtlf`t1S!cf~7iHF&sD74fs<=Zz&;uRa}H6Ec`l0gTlz)NLuhTiDV4{^M+y!!(vAM(&>|8gJQ-@`rf^(3)ZhMTKVP~cAU3-`NLCef3?YyJqbUm{PhNV*sNjS> zX(aUtIG8T5&C~$k!7*xNUOKls)*x$@`^cO_j!7FhN;{`a@%4T zv|Ci-k5;u2${RIIY7u~3gN{(<4!-c>{Jb$3wX!0~r3c1y9Z)Y^9a;TMTn zCBj@4kp@Sso$@^9@xVtd4x);G24!LMD@x!f z7&nbcsh0&hI9;^)7Gd=^>a#nSrv>>4(H-WP?LHSjIr?-oajTl+5qd_RVe)zGlavuD z3XSb(jj%JSASLCFJ7}-^pf=Dil6WvnJe;fi>Q5j{A-yP=Ulrn1mra(tbUD#=gH6(i-|l76?|JYmE*J`t@9K9Vs%I>(Ui56ZnEff$|%# z>&wkc_Mw*b-b=i#A5Kb4prCZW6x7Mws?;M07l!?0FqJXNTei_xQ8GfEJs5W+3a z`bqNqC8@26v)J1NY+lO_rA&RP`^*Y2p4Xj|RRGGm;(B+xC{*2r_>`B`6rS(8ABDI+U)11|WB1#1SGAJ}so*w&I@Q%KFQE#T+k%2ZDyP&w zT%S;~m&z9Lp$$rZ6*5M$x2@(lG4F`F zB+Sy`-g7O_+LjH)ZR0LD6gnp}-x&Z3be?`5VGuEjY-D4By;cO2kD>x>_lHwX*m!BF zpJ}`^Dq;ARqm$%-hb^oM$rd&tu~LTtW6btm`?iNphKMc}^blA*_+x$lpyw4OXiO zr*)iPzkN#iF4)7%>6z|D3Qa-Z_;QtKpdcG~L4eUuL;s`iS~BFQSLNri?GFB5igThOJOx%Jnajg4sw)54LqEp{WTlDsK=4_ zR>oek8%^G$1_*%qZ^i0AdBbEB>?g(frSOs}Uu4ho7VLr4^NPwR)D>HwXC)^4Au-2S z+HKi@FCm~-X4qliJ%ZAkpR@ZUvnPz-#0R6aO=bbdURhLE+dbd;3;WGV<_cxGCr%66 zx)AtM=-29K4@H^{DaiJk+<=q5KmBVfmACX}1eG=_p?pIeR8Dt{@->+XPr2dbBp|j< z+XbbcBv&8LntLo{3>rQ8cxS$zXut$#luvb*P4XY*hwo3W24YRyvci7ezJbnh8tY2r z2&Z7xx=(d#cwP7&+fk2p1fsV`G#@Q`yLpo$%z0Wm54Lv9L(g;?d!{C@rty*vv}qdS z7cXd}_&CYI)tmL##S^%XMQ9EZ+v*sN#kPXA+%UVtzb22Qm9lq@5lO>-l`?oRE~}Ya z`x&UKeBG+S{JaP?>ATnuFCAlJXdx`JI5Cu`=lATi>l@9Q`N+Yajr(s){xqf2>cP*e z=0&MfnPMnHvca~bKwEwAiuAoaC*xv>=)y%WTN)`cP94iH#E-0%*>7Y@6MW}11W^r_ zV)4V(D3=D1B3l>bU0>hEWcP0L3*aa z*Pb4qjr}?pxgWH+sP=`e3BeeI8zmT(p?C)GRw#C@WL*_Rp^#hdOvp697r ztYTwB$i*%&TbG$Ce$HxEF}=6pP)U_3HYfnWPwAdXGbi|!b9v>|dGRhbu^<%PYtLKd zML20BLv2IDjENd8-JHkhxpk+R2t~1b9K`r>{TP%)OE4KlQ6pT-w9xgy`v(o(o!C-! z2`!2#Se09o^4-IoS5?q3 zwiMs*V)1KV{SD9M1R#VGB^5Ze!TLTw_ z$l2L8ifd(H5>GtZM}L-z5~m=o3VcbZ06AiAZG=BykN^54+Eix2%n|}~N1Hx4f8Vec zcC0XZgdAcfe%cyV`|1gSBiSbc*xmqd>w}mWB){HL+j%XvK$=6ek8Hb0$EtNE_Hy`lPfeFSxFdXo3*Ly8FH1hsA?daYsvaA$Ih;9D9!}qIe7}T3eWd2tt z4xcRTbHt_bgk0&=$%+q6BR)EtUHzLnAU00&CVrO(AN%x2^QV%!NSoYGWIbd>h#&X` zG6Os3WFVnXdBF@caafCUgi+m}{NjDlk@#>PGbA!895xj(vX>{i)m= zZ1h7u?>oPFU0-w25+DED5^kRk9_y?EjKUFf>lMs=CmE^r42>S(-T8XoVfv=SBr6=y^Zc}h zPs#`))&8qVHTI+LrEDhbHx}j`VPfA@1lMyrmm>4nFL`t!pL7@cFN|p!tN<*6JYxAu+kNFumW-xg#GX!7~{T&o-{^ z@?~rk2&o!xuexs}wb?je&^w7mVRlPF8FdbKoR0%6xb=E3Ro#8UZeM@kn8X#7k+-OZ z!2Z5)20bdMrRwMdf7P$IcM0s!B%bomH~g?dfLTu#WxQv6;h2MiH-K}^4MQWPj2LvPIG-$rCN2Z`%gyxG=4(;j zTU|tQUw5$Rk(5YSLKrj&ru0@bfI(}58?_L)sN?bJcS1Xl9wNpEv&sMUo3h-B1I#BP zPxr2ku3dnohZbf5YTmK(Zv4A(ak>|1DlpmpYgg)87gc2G4};DvA5TjjMcq(p{qCE9 z(YCZmjPl<|7*>IvTQyouOXkg=p8Z%}tmS5xZr+~~UkB>1(~1Rzk3Sh@YbTM&TBoFS z>>Lki8@>xV?SD%&DgiG}K6|>@X4NO@JHK=9V;$xf1NW+A#(C2nF>fXE#B06fYy0lu ztSqqt2rO11WRF=(R?e0gpOWc95nw}2%GS=By{%fyZEYTqW%Kqee)@jDDsSEK*33?r zoNM>4LfAWG?78C`65^gK1$q_+g~#S3sU%)J;=@wo{6Zzo$w}_LeJGc zSr!;8k$v;Yi{Eeuf8$!98?{2I&SfQI7d45;sPxPn%duu9E~BvR@noGTznrXWqI`-l zgC2}=TI6ZvR<2%tR+A%>B-c;{otub_M!VUX$kz-;I7i@JE_2#eUea`Xh8Uw_kyO$& zJsEAcCY%$#1Nvy?oB8t6?MvCk(KI1e^PzI3q#aR=&8cltcmER`Dtv| z)P58k(4I)qU>jx`UO4%c8Y_(EoiY7R9F@mPfjoYpH+w8;X?zr%BvS8pP2ZrA=2(3! z+Ts#z6Z4%N8sJp&1f04BJjJ$UFnPZ$qw!am9NFUbea?DOa;LQO5lwt)I_go1q<_bt z7-7ldra4MFW%ATX$wf%&oq7y-v_J_g*ENT$i`cH6J$zs?{p^kLxG53V3zfw84ZZqt zT~dUWyHUnW0w8mdLlNg4;r9p^fsjNVlrD~m@34oT;jm<@aOk8+Din0SythK-;NL)m z)eVaFAkzV8!+s1Rlh8F{*ilQwOHv|`ijCZ)g0jwBw=;=b6SZF(LZa_`=!3MK?%_D% zpwi2Z7L!wi8n107pIHgKhh+gysiU2AjKL1a-E=_QlILE{h(*u(YJ0R z!Ks5Z{Kfr`)xz2989(dskRw01ote0PqhEr8MEPREufM)ZXz1-Yh&XjddcLQqaU! zaY(%|q(|lie^G(foFPGyIGTEwJ9^OhF*vyt*cBpB+RW`X>QbI&2wf$K4!>4GCA?5r zm;7r3&mi}b$A)JCxK@qc6$2PGe7!qRtf|*PxLL8v!N7gOXAi;2<-qPN?T2N_%%?qA zwUvg;xE!4-1x#_0#N*ZR(ha=OidK(H&^IB_S!>xtwjk`ilO>4i!TO2E7zbg>5QS;pC;F53Y>Ar z@wAp*>4$%CdynfXX9NF6>b1OBC0i9Ql9~ZwumjB)ATW63dUVz0mwvfsJ6?okVTDbtY5D(TcHePf%nE#byRi20AG?+HLmirmaKzm9%Y zTS*PJrR+wzva)ET!6lz}#EUANSu2cyy%2!<^hCAFMv93ljId0x3PV%3+DLrNjg8P= z5Y%T55IaJmFX#P9ut8?v&mh@sxdS_LKxgYG7tX0Ud}73si@iGNeI1$ z&_rrbkggyQq$IS^5lBR&MhRUJks_gmUR6M8p?3lzsC1Po7^MXaAWDgd(xiwWMaq}& zKHtZ??#o$wt-bf0IcN66nKQrt0DcjL@2K7gv@DF1ARh#|81VU0O)Wne3XyF=ar^`i zuA>D;=09LR#R)5+p0=tHt%Sv{5y$wlv@e%^eL|VESb6LK0fBz%utmFfvEa7QRx5RJ zI<_k*F)$un&%^WmSFrQLyL5lf1AEyBp0;=IgO`ueuxBA$ytH3`gV)1d$ZC$ei=n=C zE_0&~>+v>o>m6ql>S8%V={IkT)npw}vEwmg@S8mY__Lb-VzG$> z6;ToLcdFXOs!3BL*$|-jKN@Px)9FKKllA)^eHE|R#Mq8Dr3X0CJlWR{=J z7^RYPMLwR7tzk&57oE}ZQA@==H!1EWqh$gpx6XUkoxz(M6M@Qs@itu&8efYdOAQIZ z-xRh_ehx>tJ$)h8C~Z29VEJkBM)27y^VZf4c#nuo-&?jmY-BB`hbh<#`rPmCGjS1d z%du)GHc$ijTl$IO;3J34=K@UyRqU_8N)VkuR*yo_Qe~Z z(*x9nI|{z zpB_WqRE7fv6`!zBm=x|@FVZbNvXOq@KE*n4jd^)o?CuChRRP+d<{6@WHyh~UebAV0 zNSG`yJKF3k?ik)lVQq>vV6wISw)0X6^2u64G*3g9Wp)CqtEPAia&dpmb zV>jcZ|DGoN?y=5nIa8%#zJ#kCubbjBzX{k&adNFFuY>u-OTi+8F5xM=t~1Aem^FXY zz_rMvxcsUn1ncPAqgO?DA?0<@bzM;u#q>g=%V~t5UK_6}6NNdzoB3u)jPzg_yMKr& zUEp}Bwcq<2`Xi~wcq+P*_9`~`y7P>k4X(_9GdPa z$aAF$W0%{Tn#b6&H@>|#PdZkHlmxX6>z$bUCwgA>#s@4$MHdYW#v@u{RT;wLe9&`0G^KAa`_S2p7yXum0hh`v*GZz8@G$jftr}izs|I_ z3VhRRILYa;Lw2F=V9PeMUPGy^?j??X!Nc7s?~upzU|{PePgW9sXX^8tBzmq>Ah~)F zcN<%eW&m5qhk8TzQ*$tUe2bHJ^+Xcd%`>MFkblOOD=0dfLK&WY;8q<5gV0ReR`0#F zAc3TYEf}y6e}o=6p@(3=AUD)3`gvx($P5hsvQ@SHU8NuQa%c4G*Sp>&o_q=qEU=S@ z_x(N@gdHhEXv^Q7mby0vdf4qKV_eH-r7a~;4tb}`*!y?G<><3gEj$XRtDzi=-w$*f zWlUxS+S)|?J4R1=f$!pTCMd;SZVaAJwG+R@xc`lae#Pt|a~_n$YNIN&j2!~ImCDWt zG>SvCm!pyaw_^4N3E$}o?w^Q(J9=^jH|$Mh>=(1)i~pVL9W?7sK4-hibr@yiXzjlg z#>sTwRpOcsUtnTP*vW(7HOhivGGHNE1B+z>tHfo~Es!nG?l>@#@q(t~tw|LU>d;vY zQ=X$Yrk)~Z*|Lq8n?ad$6hg97r5K4QVu)pEX4Ft09jWp}v-b(Z&%itfEdD+#e|?$* zk<0$znM>+Br4XD92%$h#+LzgNGg3aCKw<5K2miQ`o7+PB`L~c;H#d)%C&6JFK$n~= z0?3^O;;Ozu_Iy=T!};@9N@7nmen&3m^G{Wofq6u=xg@$xm`&w0rst=%w6E4tWmR+l zSTXh;h*`Boc}}b*N*AmXC?|qYM2|%^bX;_X5teD2%+^eq=kkOzq~rjlQcbPur(YNk zZ;Zda1(>$R-`fUjf7j@J=NNUmc-BKR4RiI1Bm^0_<^Gz5d6lEho0H?GtN8jvv}OmU zk#H;?GIe^J@eiNr&wBsu7%>!n7hI$G=wMYUfgZL*>`hPz(-E}9_)_U>EaU6P6%V&& zEA#WG>MsVaE99-j^n{@*xDJah5nZgViObQ^Abo4r0$T+*(_vG70qX@?q6t^vmcpTb zKX`t6X0F4JA+bR)?bGGLa)Jh4ie6l-LBWZse>vm`C}R()mCy7S7x=lCj~=PSEEH7!2I?mZFnD2~lzd zaGjm|6-;heLn|&gB2}s=sm5Y{36%t!OrXPC}qodr9VamobS{yZkLS?L+ z8;7qwuY2JYo#p3q>Btw@4-q*Sk$Mm#_^D_7+DDyVq*w8Vbf%0&PUVT0e{+c;!Hp{! z@Lq%$_(+qEwB0uW!+)l;_zy`!Xt@Tk?n{aP_Y0`ffcP<5VeiTgbxt`u>YJC4W8)>Y zjJaW=A*-8DYz`j1QfSx^CZB~s`|?T{s@gwq?|GAUBzwK|=pXD*z{Kbq z?J?@nZHD*0hs)^a+h-Jtt`S{&SOaVHKP=iY2*x#LrmE5U^Uz8i1#>bn#oSRc7?nIh z>N%u>Z_ly_@#+ba%@8_l{7rE-XLM5;x< zrwZP?E`F~sRKDjGn$&)%rdn>j&O__ESGge4eF;N)Qz+$}5BOsp7tqwn^y_^0+Ok%; z?2fq=a9y&yI9Q=Rs$xMGL^BrQbOT)|(E)$1r($MP_jqZopU1E51kw%Mks=)ZSc*Dq z17eo8x(t%3w=0&fx+>(Eq0EBT^G$~nxOoYhyDf%*5O9R*K+P)+fj{w?q%%9lQLwBF zI)xhQ`9yEjd%6pe>Rz(%B=K$_uV*iM4sbP#XuW0?myYpx1 z|M0p(6CQki$>{uw_tZJdO(}vIb6=`EXh@);>R$blKLh;H3B>#p^tr~YN`*ed!vmmYZ2Qjr3~yi6M#Tk(UtJj9U={Va=~=p9jTFnQo-ulBhvd41d z>EOU`wBLK`TQIUppauqv`N8~pk=~Jnp-Lc~Z_zw^`~~qR6`2PJ)fw3$%H^jJW5cI0 zd})U+vW^`&fHqrCbFfKv14<)b(@Smv?O%yobr^1IQv!O#mKr&5o~FFPf!7UAZvl4C zd^8@km@QtLB!p({P?#tY8-MW4;o?9_waoqVAcgWe#N!5+a`N36JCDfE`s4zYPknYV zLXPK-n>aCr#jif%s;hkR(CoPYbPp*;xB&8!pb)WtpFF;DBLL;GdH_<&f0S->dv!^? zr)uLoJq&i|2vJKtwiTOHJ+u^#_r{mq8@E@4uQ&IC$;`2;HMWJAbP{#+7CIK!>GU@x ze@Mby{H9!xGO)3-snw8B$jn|o(kq4**RRt3A6tM||A?Fy0Kj?*ns64Gx>BvSn zzR|U)>j7IH{@w;iefQ%`mP=!2#0e|qO@O=KhO3QRcyxJXPKdmk+Mcw^E_cm#I_d6+ z^L}5Jt(tRNnnJ|)?HMD{f)eHI&izE&%FbP`T58BoB^Bpy;Kz`nI7wV~*G;r&1{mU_E7!0u?v#+dXz=;XEtrnO~b9_vu(BGeJm z2YwXh=(tx{f^RsYR|-QmbFs9;Al%w<{lC^ZMd#y{$q8%dg}rs+8gQ+X-06Z^j_IGu3jUZ>L^(lG=M*Xm&huT)#%fU^w?| zDqZHkbnLpc6Rm$}`UB^&Vx>ur%OOsr9Zn1>q$ODVS9!f78ME`Dntq{$q?1DYvMeG5 z^Y9G`nnACleVTbo!ZJ9FIj{k;to>tt{}TpR*Dh9?TEDc8q8pA!QsrUg*1&2TC>q&$tZWB3k-TglzL!Z$6e zwQ2O2pz6b1ebW`1zWoqdYiwcKTH)!5!E>k_;f1?4$>Y+H%?@OflHa|SFl27RASf;(SOQ6tW| z`P6@BTpIw8{ORQ4j%BkVjoXE&<=rI=_#tbf0s=`$XT+ZY83s2D zfG^gU$rl+l=q9t47=f*$pT)h`oRoty7*==2D>w&@*3x(l0E%geQ7_TKKz_rDJmb&e z3>9R|7?mS$PK_Vh{S?Q7HMs<)D4~KCMZIGH+u`tSXPghw$);y*zt8>ls^4_7P%TD; z`#kqMfaGd%N|tcYrmm0y0G$CyfB~DvcEr&6FaX<3xm(_$nTReo^!h>|Z{GRS|QujuL8MGkZ(#JQ9jkFO6nB zI#j5Y;4yMn#>;BRy+)QA?~6vp9WbyV@m8u;9^|ZrSa-Y}R3c8n`GUj8&JaOtZ*;D)5ODq~*P1Td z4i=zTkV^JF!mgKk(z(Skh8OyLuQ)x4q*nbs^h~1}nrW&ABmwl!2GZY7Pm^HK3(IRP zjY%6r9L#a(g7-0I;4Mk>l^WI{1!vZkT%twEOLm-Cp0NJoivj5Xc!zP7#|7%Q zh%?+R`EtLMVp3CdvG?; z9+YtCS!G*(Gf-_cWrSGEBN1aUe2KyGm0H*{PKbm^`iICoVbE-4zxEvy%G`wDX|BSF`?hpGqcThSa^Mf=x zwq)?9;FJQ^GSqr{=ayKGv&45Ym4AmN!2s-k3dtw-@ab`*z7NVn2uIg(vV{h%EEK2y zS_{CcCT^9ZmU>$$QEoywrSv6x>R{V1@Bt$R5#O)YC&?&LO|K}xQqrDRLLIX1Z(%l*s zWCWr~+fT3i|6NhDgaS+n@sF|;b=D;jUFhKGifyebF$q9kH~mPmWDq(=*pEw(t^(yEX&ppz~o;e!Fj zNsE1E+B#($3)(z8Dlot&IVslMB!p|zP9hmTipUupU^wYg%6BL_=m&Q{D|a!dQp&{P z-&0k9Ge)5F8ao^CN@xvkMP*8;+gTbAB%HUZb^Y?LDTe)9;Y*vki`QBL69LK+AnbHr zZbqN!nJJw+yA8U|1$8XP zJ8O@1Hg~O*vIr_1Z=f`~C2RKLjm0B+#Ct;i2%avc_Fv3@+u!x1GmpM* z`O~hnk`G|E!9>idB7aBcbU7!I&)v_MKA3V%0sm&8$>6u^=Glz@#`*u4&u|{PY_Z?J z5No-9BrD=p^+KO+r}S>b?i#|!V?oa8a=a|>zm@)msNHHK&EGU1Hq@=5H&6Cf8g%nm zHdw!D|Ck?R+#kzj&S(4fx;-_jtgIiw7nP0y=N*2sU+3o?&usjE&q@B*w5Lt+oBj7w aX2a=cDNb<#s`SRT08=9?!{_?gnEwDBFcRkg literal 22109 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 diff --git a/tests/visual_tests/images/text-spacing-512-512-1.0-cairo-reference.png b/tests/visual_tests/images/text-spacing-512-512-1.0-cairo-reference.png index e8f84c0a987bbfc29c4b8ad7158da051eb336883..074d58e7830645e24b9cc746cac33cb79b9fae13 100644 GIT binary patch literal 17399 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 UO)IzF0>bB}x{g}8s!jO+1Mb=`qyPW_ diff --git a/tests/visual_tests/images/text-spacing-512-512-2.0-cairo-reference.png b/tests/visual_tests/images/text-spacing-512-512-2.0-cairo-reference.png index ff2879c544144ec6b560c3ff557da66edfc96edf..3d2fe218fa77284a0bfe05ddda12ac88aa2cfb4e 100644 GIT binary patch literal 26454 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 literal 26550 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 G!Oc1%B-mF*+Xl=Q|0 z4-R@MjUo5ss0uV=zOpH!g1)k`;Ik%->1X(#k1%7KtsV(`eY#oQOTUb=N~1H;f|ROb zQIuiAYo&qyfhABZU;3-s4ZIl2xc5#8qNLMFpU7R(q)JTf8D}~;&_r$!ocHY?_q4wd zz=c!8-L!uV@@5*iwp2KYfI_P4&n##fX`;MSy~95bg=|_N#$zw5#Fn~Ki`Vt{Kw}!e zh2$d%D~p(D(*TUvuejgn>5Ampx}8qx9D_!(MU zPp77vQO4Oe)E4in|H};wF|kS4quclJO3hwD*4@QE$TJn2KXt}pk}g@Yf}(qRN|#J9 zd5J-uzARK&N9@czG~&N-R9|wSlt~Xaz#C)7Kvc)>XM;jK$YODdLLCLFZCHN$!kX%` zRo|W+^G|X8HhX*D0l)q)7&xlB9y9q*dO^j0rnb;@6$IWo6!CeeN7dOyGR%y8e-`3q z_VegsJhb5MbYrFB{NPvNcq2q=3c)*owO4YTmz7|09zZYp%+jGzk%BjZlEFb7l2^vr zGND6)(|SRsZRnL65bx6P@8^o{ETOw7#m6do5W592x+cL}_B-QDBiuj!{kH;qQI`#m zS57KU2TkgMg&zNdYx-G z^|}uqpIndj{RtG;fPK5xuEQ87kJf$b9$C?-thXQQ+wjoo5>a+YP-F#0-90Q?$I_Sm z*bZPXKCrEg9bMfss_=D7O{m!A(64#O=3eLpv2%Q^33zG}65(17LTP`kla?aU_Hl?{ zSnIW+VJfvqJ$nVFCdan!uaR=uOgcD8YEfB@_Gb@Pmzoc8JmTCXQbuC;JZn)&`~zD& zb!LIYy-E-4Pm%Q6hQw%3tqb?1j3%IvCGFS0Vog(Lprr{t<(vW2dCNp_hu4Ou#qN0M zOo}h0IlFQnt8nk%Tw6BH=VgswO@}1t#4+YZ_6|OE-6V-*3z&cmg1FdKOLL-UD(Vv; z=FGaOqf!nNE*P5AU+Z0IvA^|;_uXhm8o8zOUV9#Ti@*22kA@Cvk;rsH?Oz*~l-O9F z30AS+8Nj2=nfVrMUNZmIqj}4Yc|;{HJZ7D6MDEb32r#iBL9rODnSvS%QBD zoic|?=bEyNfUmC{<^;!5AOQHs1-N2yrd?NSZ%>cAmTT`+Y7)W+A901>C=z zC;l+?XNuOW>n+JrpkKtaKP6#HRBv6kv40(Ej7iPXGUbSN7na+*yl|r{glmw=^3uwR zskEo0B^B{VtN+!7m^6-}aBXX6r`W?_!lNsS9V!S73gBP>R78LXE8wOHtmXj-Sr9xF z4E*0tj7@TZDX54rsH`BcwBZeY#h7u5tr?4Rlk?gwsU=P|Dqj7inK7{n8g&y1_=DnA>^Eb9J?klBr;!5V}Hl2JLUlL+rY$9rT7p4mZJpa?QmK zj#@zL_{`?F<8x%RNi>vGy5&vwQJ|OTyyb&BRfHuDZyD8R{xfv(FHfs1aTqk`*Ht~@ zcQ2n!Bz#$b)SM`GC`&8nawuD9AT4q@2-7);PAg~je>>YHZi`N*{Y|IX;jQWao-_JW z$N7_s#*Em)rcRMV1G{c!YT28wB@W+Fq_@0~i(=Jv9M*A8NF~tzrZ*9!T;6n#yu4_` zw!F!2bt?;J6NXph5c6DD+@`8e=RoxLj*<4a0c%O!MV+z*2f1>g3#}d5|5;J((Qy{% z)AjFucRQ=&e92t)hJOrRr#e=Rlv=g5dwI&L~8k{%d43&q-|Tpa-oV6hbit<8q{7$1~MmH zRg#W2O~_2L>pC7N&E!l-7CYdE(t|~`;G)T{pf}}B;xh{k;YbBq-MzSLE%-D4yyv<` zO-N_Xspa3TwcsCB*L1i7@y>%2ZSJl5d(7Jkw7xZt&+}3iIT$%*L~DK9y`VJsvy(+d zCTIL4qB286I&JHL-iM#8O4{b+6kfKlw3;|BEQy5=k29G|wzIja-do}C^4y$8txxIP zp35p1_E>&R*V*dkAg|%{HREhF924{#vB3c8jqsdI?Q;Gz*q(Mjtgu9XWY^td>QkOw z# Date: Mon, 4 Aug 2014 20:29:25 -0700 Subject: [PATCH 20/92] text_line: remove unneeded acces to glyph storage --- include/mapnik/text/text_line.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/mapnik/text/text_line.hpp b/include/mapnik/text/text_line.hpp index 6e72a4562..678e3afe3 100644 --- a/include/mapnik/text/text_line.hpp +++ b/include/mapnik/text/text_line.hpp @@ -43,8 +43,6 @@ public: text_line(unsigned first_char, unsigned last_char); - // Get glyph vector. - glyph_vector const& glyphs() const { return glyphs_; } // Append glyph. void add_glyph(glyph_info && glyph, double scale_factor_); @@ -80,8 +78,8 @@ public: unsigned size() const; private: glyph_vector glyphs_; - double line_height_; //Includes line spacing (returned by freetype) - double max_char_height_; //Height of 'X' character of the largest font in this run. //TODO: Initialize this! + double line_height_; // Includes line spacing (returned by freetype) + double max_char_height_; // Height of 'X' character of the largest font in this run. //TODO: Initialize this! double width_; unsigned first_char_; unsigned last_char_; From 823218061411c3bab3a2934a365f670affe4d7e4 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 4 Aug 2014 23:42:42 -0700 Subject: [PATCH 21/92] c++11 style in harfbuzz_shaper.hpp --- include/mapnik/text/harfbuzz_shaper.hpp | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/include/mapnik/text/harfbuzz_shaper.hpp b/include/mapnik/text/harfbuzz_shaper.hpp index 32f4f1f8d..766019c27 100644 --- a/include/mapnik/text/harfbuzz_shaper.hpp +++ b/include/mapnik/text/harfbuzz_shaper.hpp @@ -48,7 +48,6 @@ static void shape_text(text_line & line, { unsigned start = line.first_char(); unsigned end = line.last_char(); - mapnik::value_unicode_string const& text = itemizer.text(); size_t length = end - start; if (!length) return; line.reserve(length); @@ -58,20 +57,22 @@ static void shape_text(text_line & line, const std::unique_ptr buffer(hb_buffer_create(),hb_buffer_deleter); hb_buffer_set_unicode_funcs(buffer.get(), hb_icu_get_unicode_funcs()); hb_buffer_pre_allocate(buffer.get(), length); + mapnik::value_unicode_string const& text = itemizer.text(); for (auto const& text_item : list) { face_set_ptr face_set = font_manager.get_face_set(text_item.format->face_name, text_item.format->fontset); double size = text_item.format->text_size * scale_factor; face_set->set_unscaled_character_sizes(); - font_face_set::iterator face_itr = face_set->begin(), face_end = face_set->end(); - for (; face_itr != face_end; ++face_itr) + std::size_t num_faces = face_set->size(); + std::size_t pos = 0; + for (auto const& face : *face_set) { + ++pos; hb_buffer_clear_contents(buffer.get()); hb_buffer_add_utf16(buffer.get(), text.getBuffer(), text.length(), text_item.start, text_item.end - text_item.start); hb_buffer_set_direction(buffer.get(), (text_item.rtl == UBIDI_RTL)?HB_DIRECTION_RTL:HB_DIRECTION_LTR); hb_buffer_set_script(buffer.get(), hb_icu_script_to_script(text_item.script)); - face_ptr const& face = *face_itr; hb_font_t *font(hb_ft_font_create(face->get_face(), nullptr)); hb_shape(font, buffer.get(), nullptr, 0); hb_font_destroy(font); @@ -91,7 +92,7 @@ static void shape_text(text_line & line, break; } } - if (!font_has_all_glyphs && face_itr+1 != face_end) + if (!font_has_all_glyphs && (pos < num_faces)) { //Try next font in fontset continue; From 59b666cb77ebbbd1bb24ae5f0d3521c6367f84ba Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 5 Aug 2014 11:43:56 +0100 Subject: [PATCH 22/92] Cairo : use vertex_converter in line_pattern_symbolizer (#1386) fix pattern alignment --- include/mapnik/cairo/cairo_context.hpp | 54 +++++++++ src/cairo/cairo_renderer.cpp | 145 ++++++++++++------------- 2 files changed, 125 insertions(+), 74 deletions(-) diff --git a/include/mapnik/cairo/cairo_context.hpp b/include/mapnik/cairo/cairo_context.hpp index ce2073e7c..eda80a533 100644 --- a/include/mapnik/cairo/cairo_context.hpp +++ b/include/mapnik/cairo/cairo_context.hpp @@ -412,6 +412,60 @@ private: cairo_ptr cairo_; }; +template +struct line_pattern_rasterizer +{ + line_pattern_rasterizer(Context & context, cairo_pattern & pattern, unsigned width, unsigned height) + : context_(context), + pattern_(pattern), + width_(width), + height_(height) {} + + template + void add_path(T & path, unsigned start_index = 0) + { + double length = 0.0; + double x0 = 0.0; + double y0 = 0.0; + double x, y; + path.rewind(start_index); + for (unsigned cm = path.vertex(&x, &y); cm != SEG_END; cm = path.vertex(&x, &y)) + { + if (cm == SEG_MOVETO) + { + length = 0.0; + } + else if (cm == SEG_LINETO) + { + double dx = x - x0; + double dy = y - y0; + double angle = std::atan2(dy, dx); + double offset = std::fmod(length, width_); + + cairo_matrix_t matrix; + cairo_matrix_init_identity(&matrix); + cairo_matrix_translate(&matrix, x0, y0); + cairo_matrix_rotate(&matrix, angle); + cairo_matrix_translate(&matrix, -offset, 0.5 * height_); + cairo_matrix_invert(&matrix); + pattern_.set_matrix(matrix); + context_.set_pattern(pattern_); + context_.move_to(x0, y0); + context_.line_to(x, y); + context_.stroke(); + length = length + hypot(x - x0, y - y0); + } + + x0 = x; + y0 = y; + } + } + + Context & context_; + cairo_pattern & pattern_; + unsigned width_; + unsigned height_; +}; } diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index 5cbfcc88e..a8f7d2439 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -343,7 +343,7 @@ void cairo_renderer_base::process(line_symbolizer const& sym, simplify_tag, smooth_tag, offset_transform_tag, dash_tag, stroke_tag>; - cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); bool clip = get(sym, keys::clip, feature, common_.vars_, false); double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); @@ -358,6 +358,7 @@ void cairo_renderer_base::process(line_symbolizer const& sym, double miterlimit = get(sym, keys::stroke_miterlimit, feature, common_.vars_, 4.0); double width = get(sym, keys::stroke_width, feature, common_.vars_, 1.0); + cairo_save_restore guard(context_); context_.set_operator(comp_op); context_.set_color(stroke, stroke_opacity); context_.set_line_join(stroke_join); @@ -601,11 +602,19 @@ void cairo_renderer_base::process(line_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - using clipped_geometry_type = agg::conv_clip_polyline; - using path_type = coord_transform; + + using conv_types = boost::mpl::vector; std::string filename = get(sym, keys::file, feature, common_.vars_); composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + bool clip = get(sym, keys::clip, feature, common_.vars_, false); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); boost::optional marker; if ( !filename.empty() ) @@ -619,13 +628,12 @@ void cairo_renderer_base::process(line_pattern_symbolizer const& sym, cairo_save_restore guard(context_); context_.set_operator(comp_op); - std::shared_ptr pattern; image_ptr image = nullptr; if ((*marker)->is_bitmap()) { pattern = std::make_unique(**((*marker)->get_bitmap_data())); - context_.set_line_width(height* common_.scale_factor_); // FIXME: do we need to scale height here? + context_.set_line_width(height); } else { @@ -643,55 +651,42 @@ void cairo_renderer_base::process(line_pattern_symbolizer const& sym, pattern->set_extend(CAIRO_EXTEND_REPEAT); pattern->set_filter(CAIRO_FILTER_BILINEAR); + agg::trans_affine tr; + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - for (std::size_t i = 0; i < feature.num_geometries(); ++i) + box2d clipping_extent = common_.query_extent_; + if (clip) { - geometry_type & geom = feature.get_geometry(i); + double padding = (double)(common_.query_extent_.width()/common_.width_); + double half_stroke = width/2.0; + if (half_stroke > 1) + padding *= half_stroke; + if (std::fabs(offset) > 0) + padding *= std::fabs(offset) * 1.2; + padding *= common_.scale_factor_; + clipping_extent.pad(padding); + } + using rasterizer_type = line_pattern_rasterizer; + rasterizer_type ras(context_, *pattern, width, height); + vertex_converter, rasterizer_type, line_pattern_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> + converter(clipping_extent, ras, sym, common_.t_, prj_trans, tr, feature, common_.vars_, common_.scale_factor_); + + if (clip) converter.set(); // optional clip (default: true) + converter.set(); // always transform + if (std::fabs(offset) > 0.0) converter.set(); // parallel offset + converter.set(); // optional affine transform + if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter + if (smooth > 0.0) converter.set(); // optional smooth converter + + + for (auto & geom : feature.paths()) + { if (geom.size() > 1) { - clipped_geometry_type clipped(geom); - clipped.clip_box(common_.query_extent_.minx(),common_.query_extent_.miny(),common_.query_extent_.maxx(),common_.query_extent_.maxy()); - path_type path(common_.t_,clipped,prj_trans); - - double length(0); - double x0(0), y0(0); - double x, y; - - for (unsigned cm = path.vertex(&x, &y); cm != SEG_END; cm = path.vertex(&x, &y)) - { - if (cm == SEG_MOVETO) - { - length = 0.0; - } - else if (cm == SEG_LINETO) - { - double dx = x - x0; - double dy = y - y0; - double angle = std::atan2(dy, dx); - double offset = std::fmod(length, width); - - cairo_matrix_t matrix; - cairo_matrix_init_identity(&matrix); - cairo_matrix_translate(&matrix,x0,y0); - cairo_matrix_rotate(&matrix,angle); - cairo_matrix_translate(&matrix,-offset,0.5*height); - cairo_matrix_invert(&matrix); - - pattern->set_matrix(matrix); - - context_.set_pattern(*pattern); - - context_.move_to(x0, y0); - context_.line_to(x, y); - context_.stroke(); - - length = length + hypot(x - x0, y - y0); - } - - x0 = x; - y0 = y; - } + converter.apply(geom); } } } @@ -700,10 +695,6 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - //using clipped_geometry_type = agg::conv_clip_polygon; - //using path_type = coord_transform; - - cairo_save_restore guard(context_); composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); std::string filename = get(sym, keys::file, feature, common_.vars_); bool clip = get(sym, keys::clip, feature, common_.vars_, false); @@ -714,15 +705,40 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, auto image_transform = get_optional(sym, keys::image_transform); if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); + cairo_save_restore guard(context_); context_.set_operator(comp_op); boost::optional marker = mapnik::marker_cache::instance().find(filename,true); if (!marker || !(*marker)) return; + unsigned offset_x=0; + unsigned offset_y=0; + box2d const& clip_box = common_.query_extent_;//clipping_extent(); + pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); + if (alignment == LOCAL_ALIGNMENT) + { + double x0 = 0.0; + double y0 = 0.0; + + if (feature.num_geometries() > 0) + { + using clipped_geometry_type = agg::conv_clip_polygon; + using path_type = coord_transform; + clipped_geometry_type clipped(feature.get_geometry(0)); + clipped.clip_box(clip_box.minx(), clip_box.miny(), + clip_box.maxx(), clip_box.maxy()); + path_type path(common_.t_, clipped, prj_trans); + path.vertex(&x0, &y0); + } + offset_x = std::abs(clip_box.width() - x0); + offset_y = std::abs(clip_box.height() - y0); + } + if ((*marker)->is_bitmap()) { cairo_pattern pattern(**((*marker)->get_bitmap_data())); pattern.set_extend(CAIRO_EXTEND_REPEAT); + pattern.set_origin(offset_x, offset_y); context_.set_pattern(pattern); } else @@ -731,29 +747,10 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, image_ptr image = render_pattern(ras, **marker, image_tr); cairo_pattern pattern(*image); pattern.set_extend(CAIRO_EXTEND_REPEAT); + pattern.set_origin(offset_x, offset_y); context_.set_pattern(pattern); } - - pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); - //unsigned offset_x=0; - //unsigned offset_y=0; - - //if (align == LOCAL_ALIGNMENT) - //{ - // double x0 = 0; - // double y0 = 0; - // if (feature.num_geometries() > 0) - // { - // clipped_geometry_type clipped(feature.get_geometry(0)); - // clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); - // path_type path(t_,clipped,prj_trans); - // path.vertex(&x0,&y0); - // } - // offset_x = unsigned(width_ - x0); - // offset_y = unsigned(height_ - y0); - //} - agg::trans_affine tr; auto geom_transform = get_optional(sym, keys::geometry_transform); if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } @@ -761,7 +758,7 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, using conv_types = boost::mpl::vector; vertex_converter, cairo_context, polygon_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(common_.query_extent_,context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); + converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); if (prj_trans.equal() && clip) converter.set(); //optional clip (default: true) converter.set(); //always transform From ebd183d58e2e8914c79e0bf304ba3bbfdb433cdc Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 5 Aug 2014 11:57:57 +0100 Subject: [PATCH 23/92] avoid overflowing --- src/agg/process_polygon_pattern_symbolizer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index bc0ceb89c..c35665535 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -143,8 +143,8 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, path_type path(common_.t_,clipped,prj_trans); path.vertex(&x0,&y0); } - offset_x = unsigned(current_buffer_->width() - x0); - offset_y = unsigned(current_buffer_->height() - y0); + offset_x = std::abs(current_buffer_->width() - x0); + offset_y = std::abs(current_buffer_->height() - y0); } span_gen_type sg(img_src, offset_x, offset_y); From d01a5407ae5a5cab02e12bf84a62808497535b33 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 5 Aug 2014 13:05:32 +0100 Subject: [PATCH 24/92] remove unused symbolizer hash --- include/mapnik/symbolizer_hash.hpp | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/include/mapnik/symbolizer_hash.hpp b/include/mapnik/symbolizer_hash.hpp index f729d0e7f..811ec7e58 100644 --- a/include/mapnik/symbolizer_hash.hpp +++ b/include/mapnik/symbolizer_hash.hpp @@ -87,18 +87,7 @@ struct hash_visitor : boost::static_visitor } }; -} +} // namespace mapnik -namespace std { - -template<> -struct hash -{ - std::size_t operator()(mapnik::symbolizer const& sym) const - { - return boost::apply_visitor(mapnik::hash_visitor(),sym); - } -}; -} #endif // MAPNIK_SYMBOLIZER_HASH_HPP From dd0552128909d9113c2c9829a3cd2e87e0bc1dc3 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 5 Aug 2014 13:13:52 +0100 Subject: [PATCH 25/92] Revert "avoid overflowing" This reverts commit ebd183d58e2e8914c79e0bf304ba3bbfdb433cdc. --- src/agg/process_polygon_pattern_symbolizer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index c35665535..bc0ceb89c 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -143,8 +143,8 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, path_type path(common_.t_,clipped,prj_trans); path.vertex(&x0,&y0); } - offset_x = std::abs(current_buffer_->width() - x0); - offset_y = std::abs(current_buffer_->height() - y0); + offset_x = unsigned(current_buffer_->width() - x0); + offset_y = unsigned(current_buffer_->height() - y0); } span_gen_type sg(img_src, offset_x, offset_y); From a8991cd6002e424c28e335205a9eedaa1184ee45 Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 5 Aug 2014 17:21:00 +0100 Subject: [PATCH 26/92] refactor clipping_extent into separate header for sharing --- include/mapnik/agg_renderer.hpp | 20 +------- .../renderer_common/clipping_extent.hpp | 49 +++++++++++++++++++ src/agg/agg_renderer.cpp | 33 ------------- src/agg/process_group_symbolizer.cpp | 2 +- src/agg/process_line_pattern_symbolizer.cpp | 2 +- src/agg/process_line_symbolizer.cpp | 2 +- src/agg/process_markers_symbolizer.cpp | 2 +- .../process_polygon_pattern_symbolizer.cpp | 2 +- src/agg/process_polygon_symbolizer.cpp | 2 +- src/agg/process_shield_symbolizer.cpp | 2 +- src/agg/process_text_symbolizer.cpp | 2 +- src/cairo/cairo_renderer.cpp | 2 +- 12 files changed, 59 insertions(+), 61 deletions(-) create mode 100644 include/mapnik/renderer_common/clipping_extent.hpp diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index 40719e866..7309622fc 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -37,7 +37,7 @@ #include #include #include - +#include // stl #include @@ -146,22 +146,6 @@ public: { return common_.vars_; } - - inline box2d clipping_extent() const - { - if (common_.t_.offset() > 0) - { - box2d box = common_.query_extent_; - double scale = static_cast(common_.query_extent_.width())/static_cast(common_.width_); - // 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 # - scale *= common_.t_.offset()*3; - box.pad(scale); - return box; - } - return common_.query_extent_; - } - protected: template void debug_draw_box(R& buf, box2d const& extent, @@ -182,8 +166,6 @@ private: void setup(Map const& m); }; -std::shared_ptr render_pattern(rasterizer & ras, marker const& marker, agg::trans_affine const& tr); - } // namespace mapnik #endif // MAPNIK_AGG_RENDERER_HPP diff --git a/include/mapnik/renderer_common/clipping_extent.hpp b/include/mapnik/renderer_common/clipping_extent.hpp new file mode 100644 index 000000000..b8dd70bfa --- /dev/null +++ b/include/mapnik/renderer_common/clipping_extent.hpp @@ -0,0 +1,49 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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_CLIPPING_EXTENT_HPP +#define MAPNIK_CLIPPING_EXTENT_HPP + + +#include + +namespace mapnik { + +template +box2d clipping_extent(T const& common) +{ + if (common.t_.offset() > 0) + { + box2d box = common.query_extent_; + double scale = static_cast(common.query_extent_.width())/static_cast(common.width_); + // 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 # + scale *= common.t_.offset() * 3; + box.pad(scale); + return box; + } + return common.query_extent_; +} + +} // namespace mapnik + +#endif // MAPNIK_CLIPPING_EXTENT_HPP diff --git a/src/agg/agg_renderer.cpp b/src/agg/agg_renderer.cpp index 92caa3964..21d31a7fe 100644 --- a/src/agg/agg_renderer.cpp +++ b/src/agg/agg_renderer.cpp @@ -502,39 +502,6 @@ void agg_renderer::draw_geo_extent(box2d const& extent, mapnik::c } } -std::shared_ptr render_pattern(rasterizer & ras, marker const& marker, agg::trans_affine const& tr) -{ - using pixfmt = agg::pixfmt_rgba32_pre; - using renderer_base = agg::renderer_base; - using renderer_solid = agg::renderer_scanline_aa_solid; - agg::scanline_u8 sl; - - //double width = marker.width(); - //double height = marker.height(); - - mapnik::box2d const& bbox = (*marker.get_vector_data())->bounding_box() * tr; - mapnik::coord c = bbox.center(); - agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y); - mtx.translate(0.5 * bbox.width(), 0.5 * bbox.height()); - mtx = tr * mtx; - - std::shared_ptr image = std::make_shared(bbox.width(), bbox.height()); - agg::rendering_buffer buf(image->getBytes(), image->width(), image->height(), image->width() * 4); - pixfmt pixf(buf); - renderer_base renb(pixf); - - mapnik::svg::vertex_stl_adapter stl_storage((*marker.get_vector_data())->source()); - mapnik::svg::svg_path_adapter svg_path(stl_storage); - mapnik::svg::svg_renderer_agg, - renderer_solid, - agg::pixfmt_rgba32_pre > svg_renderer(svg_path, - (*marker.get_vector_data())->attributes()); - - svg_renderer.render(ras, sl, renb, mtx, 1.0, bbox); - return image; -} - template class agg_renderer; template void agg_renderer::debug_draw_box( agg::rendering_buffer& buf, diff --git a/src/agg/process_group_symbolizer.cpp b/src/agg/process_group_symbolizer.cpp index 64b48bb7d..dc8d5e031 100644 --- a/src/agg/process_group_symbolizer.cpp +++ b/src/agg/process_group_symbolizer.cpp @@ -106,7 +106,7 @@ void agg_renderer::process(group_symbolizer const& sym, proj_transform const& prj_trans) { render_group_symbolizer( - sym, feature, common_.vars_, prj_trans, clipping_extent(), common_, + sym, feature, common_.vars_, prj_trans, clipping_extent(common_), common_, [&](render_thunk_list const& thunks, pixel_position const& render_offset) { thunk_renderer ren(*this, current_buffer_, common_, render_offset); diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index f0609fd97..31f97a7f2 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -140,7 +140,7 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, auto transform = get_optional(sym, keys::geometry_transform); if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); - box2d clip_box = clipping_extent(); + box2d clip_box = clipping_extent(common_); if (clip) { double padding = (double)(common_.query_extent_.width()/pixmap_.width()); diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index 581b12196..afc8daf72 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -130,7 +130,7 @@ void agg_renderer::process(line_symbolizer const& sym, auto transform = get_optional(sym, keys::geometry_transform); if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); - box2d clip_box = clipping_extent(); + box2d clip_box = clipping_extent(common_); bool clip = get(sym, keys::clip, feature, common_.vars_, false); double width = get(sym, keys::stroke_width, feature, common_.vars_, 1.0); diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index 1298e997d..6e21200d1 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -90,7 +90,7 @@ void agg_renderer::process(markers_symbolizer const& sym, } buf_type render_buffer(current_buffer_->raw_data(), current_buffer_->width(), current_buffer_->height(), current_buffer_->width() * 4); - box2d clip_box = clipping_extent(); + box2d clip_box = clipping_extent(common_); auto renderer_context = std::tie(render_buffer,*ras_ptr,pixmap_); using context_type = decltype(renderer_context); diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index bc0ceb89c..ed27a4f86 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -98,7 +98,7 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); double smooth = get(sym, keys::smooth, feature, common_.vars_, false); - box2d clip_box = clipping_extent(); + box2d clip_box = clipping_extent(common_); using color = agg::rgba8; using order = agg::order_rgba; diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index 532596520..b02a269aa 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -64,7 +64,7 @@ void agg_renderer::process(polygon_symbolizer const& sym, gamma_ = gamma; } - box2d clip_box = clipping_extent(); + box2d clip_box = clipping_extent(common_); agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(), current_buffer_->width() * 4); render_polygon_symbolizer( diff --git a/src/agg/process_shield_symbolizer.cpp b/src/agg/process_shield_symbolizer.cpp index 4d5f038e1..6e2680a94 100644 --- a/src/agg/process_shield_symbolizer.cpp +++ b/src/agg/process_shield_symbolizer.cpp @@ -36,7 +36,7 @@ void agg_renderer::process(shield_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - box2d clip_box = clipping_extent(); + box2d clip_box = clipping_extent(common_); text_symbolizer_helper helper( sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index 0994e9708..a808b9943 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -36,7 +36,7 @@ void agg_renderer::process(text_symbolizer const& sym, proj_transform const& prj_trans) { - box2d clip_box = clipping_extent(); + box2d clip_box = clipping_extent(common_); text_symbolizer_helper helper( sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index a8f7d2439..c6003ed21 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -713,7 +713,7 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, unsigned offset_x=0; unsigned offset_y=0; - box2d const& clip_box = common_.query_extent_;//clipping_extent(); + box2d const& clip_box = clipping_extent(common_); pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); if (alignment == LOCAL_ALIGNMENT) { From 2b90b382e7f7b4f486a1ab6d6525f4522389c1df Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 5 Aug 2014 17:40:15 +0100 Subject: [PATCH 27/92] move render_pattern into sepratre compilation module --- include/mapnik/agg_renderer.hpp | 1 + .../mapnik/renderer_common/render_pattern.hpp | 45 ++++++++++++ src/build.py | 1 + src/cairo/cairo_renderer.cpp | 3 +- src/renderer_common/render_pattern.cpp | 68 +++++++++++++++++++ 5 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 include/mapnik/renderer_common/render_pattern.hpp create mode 100644 src/renderer_common/render_pattern.cpp diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index 7309622fc..bab217653 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -38,6 +38,7 @@ #include #include #include +#include // stl #include diff --git a/include/mapnik/renderer_common/render_pattern.hpp b/include/mapnik/renderer_common/render_pattern.hpp new file mode 100644 index 000000000..f40bef907 --- /dev/null +++ b/include/mapnik/renderer_common/render_pattern.hpp @@ -0,0 +1,45 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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_RENDER_PATTERN_HPP +#define MAPNIK_RENDER_PATTERN_HPP + +#include +#include + +// fwd decl +namespace agg { +struct trans_affine; +} + +namespace mapnik { + +// fwd decl +struct rasterizer; +class marker; + +std::shared_ptr render_pattern(rasterizer & ras, marker const& marker, agg::trans_affine const& tr); + +} // namespace mapnik + + +#endif // MAPNIK_RENDER_PATTERN_HPP diff --git a/src/build.py b/src/build.py index b49aa2d83..aa273f8aa 100644 --- a/src/build.py +++ b/src/build.py @@ -230,6 +230,7 @@ source = Split( config_error.cpp color_factory.cpp renderer_common.cpp + renderer_common/render_pattern.cpp renderer_common/process_group_symbolizer.cpp """ ) diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index c6003ed21..a7ba32d30 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -59,7 +59,8 @@ #include #include #include -#include +#include +#include // mapnik symbolizer generics #include diff --git a/src/renderer_common/render_pattern.cpp b/src/renderer_common/render_pattern.cpp new file mode 100644 index 000000000..b291a2871 --- /dev/null +++ b/src/renderer_common/render_pattern.cpp @@ -0,0 +1,68 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 +#include +#include +#include +#include +#include +#include + +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgba.h" +#include "agg_color_rgba.h" +#include "agg_scanline_u.h" + +namespace mapnik { + +std::shared_ptr render_pattern(rasterizer & ras, marker const& marker, agg::trans_affine const& tr) +{ + using pixfmt = agg::pixfmt_rgba32_pre; + using renderer_base = agg::renderer_base; + using renderer_solid = agg::renderer_scanline_aa_solid; + agg::scanline_u8 sl; + + mapnik::box2d const& bbox = (*marker.get_vector_data())->bounding_box() * tr; + mapnik::coord c = bbox.center(); + agg::trans_affine mtx = agg::trans_affine_translation(-c.x,-c.y); + mtx.translate(0.5 * bbox.width(), 0.5 * bbox.height()); + mtx = tr * mtx; + + std::shared_ptr image = std::make_shared(bbox.width(), bbox.height()); + agg::rendering_buffer buf(image->getBytes(), image->width(), image->height(), image->width() * 4); + pixfmt pixf(buf); + renderer_base renb(pixf); + + mapnik::svg::vertex_stl_adapter stl_storage((*marker.get_vector_data())->source()); + mapnik::svg::svg_path_adapter svg_path(stl_storage); + mapnik::svg::svg_renderer_agg, + renderer_solid, + agg::pixfmt_rgba32_pre > svg_renderer(svg_path, + (*marker.get_vector_data())->attributes()); + + svg_renderer.render(ras, sl, renb, mtx, 1.0, bbox); + return image; +} + +} // namespace mapnik From 617524505b09f45c5849d47ef321cff7da81e05b Mon Sep 17 00:00:00 2001 From: Mike Morris Date: Tue, 5 Aug 2014 13:15:55 -0400 Subject: [PATCH 28/92] fix header include comment --- include/mapnik/font_engine_freetype.hpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/include/mapnik/font_engine_freetype.hpp b/include/mapnik/font_engine_freetype.hpp index a8fb6b453..1bae33087 100644 --- a/include/mapnik/font_engine_freetype.hpp +++ b/include/mapnik/font_engine_freetype.hpp @@ -28,18 +28,16 @@ #include #include -// boost +// stl #include #include #include // pair +#include #ifdef MAPNIK_THREADSAFE #include #endif -// stl -#include - struct FT_LibraryRec_; struct FT_MemoryRec_; namespace boost { template class optional; } From c3a83e6f74a969fefcc31363a3de0e8e2f0edf7b Mon Sep 17 00:00:00 2001 From: artemp Date: Tue, 5 Aug 2014 18:57:23 +0100 Subject: [PATCH 29/92] re-arrange headers --- include/mapnik/agg_renderer.hpp | 2 -- src/agg/process_group_symbolizer.cpp | 2 +- src/agg/process_line_pattern_symbolizer.cpp | 3 ++- src/agg/process_line_symbolizer.cpp | 2 +- src/agg/process_markers_symbolizer.cpp | 2 +- src/agg/process_polygon_pattern_symbolizer.cpp | 3 ++- src/agg/process_polygon_symbolizer.cpp | 2 +- src/agg/process_shield_symbolizer.cpp | 1 + src/agg/process_text_symbolizer.cpp | 1 + 9 files changed, 10 insertions(+), 8 deletions(-) diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index bab217653..4a8dd89e2 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -37,8 +37,6 @@ #include #include #include -#include -#include // stl #include diff --git a/src/agg/process_group_symbolizer.cpp b/src/agg/process_group_symbolizer.cpp index dc8d5e031..a4a4fc629 100644 --- a/src/agg/process_group_symbolizer.cpp +++ b/src/agg/process_group_symbolizer.cpp @@ -31,7 +31,7 @@ #include #include #include - +#include // agg #include "agg_trans_affine.h" diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index 31f97a7f2..bddc9e476 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -33,7 +33,8 @@ #include #include #include - +#include +#include // agg #include "agg_basics.h" #include "agg_pixfmt_rgba.h" diff --git a/src/agg/process_line_symbolizer.cpp b/src/agg/process_line_symbolizer.cpp index afc8daf72..01f6e1da6 100644 --- a/src/agg/process_line_symbolizer.cpp +++ b/src/agg/process_line_symbolizer.cpp @@ -28,7 +28,7 @@ #include #include #include - +#include // agg #include "agg_basics.h" #include "agg_rendering_buffer.h" diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index 6e21200d1..3ac666fd3 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -39,7 +39,7 @@ #include #include #include - +#include // agg #include "agg_basics.h" #include "agg_renderer_base.h" diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index ed27a4f86..fb1a50d15 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -35,7 +35,8 @@ #include #include #include - +#include +#include // agg #include "agg_basics.h" #include "agg_rendering_buffer.h" diff --git a/src/agg/process_polygon_symbolizer.cpp b/src/agg/process_polygon_symbolizer.cpp index b02a269aa..b2c86a0fa 100644 --- a/src/agg/process_polygon_symbolizer.cpp +++ b/src/agg/process_polygon_symbolizer.cpp @@ -32,7 +32,7 @@ #include #include #include - +#include // agg #include "agg_basics.h" #include "agg_rendering_buffer.h" diff --git a/src/agg/process_shield_symbolizer.cpp b/src/agg/process_shield_symbolizer.cpp index 6e2680a94..b9e77de0a 100644 --- a/src/agg/process_shield_symbolizer.cpp +++ b/src/agg/process_shield_symbolizer.cpp @@ -28,6 +28,7 @@ #include #include #include +#include namespace mapnik { diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index a808b9943..8a72e70b0 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace mapnik { From 2c9e089317586f19c574f410e97cd0c2387c10d7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 08:19:19 -0700 Subject: [PATCH 30/92] move harfbuzz_shaper inc + other iwyu fixups --- include/mapnik/text/text_layout.hpp | 15 ++++++++++++--- include/mapnik/text/text_line.hpp | 5 ++--- include/mapnik/text/text_properties.hpp | 15 +++++++++++++-- src/text/formatting/layout.cpp | 1 + src/text/text_layout.cpp | 3 ++- src/text/text_line.cpp | 2 ++ 6 files changed, 32 insertions(+), 9 deletions(-) diff --git a/include/mapnik/text/text_layout.hpp b/include/mapnik/text/text_layout.hpp index f9e5736cd..f115b5bee 100644 --- a/include/mapnik/text/text_layout.hpp +++ b/include/mapnik/text/text_layout.hpp @@ -23,20 +23,30 @@ #define MAPNIK_TEXT_LAYOUT_HPP //mapnik +#include +#include +#include +#include +#include +#include +#include #include #include -#include #include -#include #include //stl #include +#include #include +#include namespace mapnik { +class feature_impl; +class text_layout; + using text_layout_ptr = std::shared_ptr; using text_layout_vector = std::vector; @@ -46,7 +56,6 @@ public: using line_vector = std::vector; using const_iterator = line_vector::const_iterator; using child_iterator = text_layout_vector::const_iterator; - using shaper_type = harfbuzz_shaper; text_layout(face_manager_freetype & font_manager, double scale_factor, text_layout_properties const& properties); diff --git a/include/mapnik/text/text_line.hpp b/include/mapnik/text/text_line.hpp index 678e3afe3..96dd50b6b 100644 --- a/include/mapnik/text/text_line.hpp +++ b/include/mapnik/text/text_line.hpp @@ -22,15 +22,14 @@ #ifndef MAPNIK_TEXT_LINE_HPP #define MAPNIK_TEXT_LINE_HPP -//mapnik -#include -#include //stl #include namespace mapnik { +struct glyph_info; + // This class stores all glyphs of a line in left to right order. // It can be used for rendering but no text processing (like line breaking) // should be done! diff --git a/include/mapnik/text/text_properties.hpp b/include/mapnik/text/text_properties.hpp index e0994a7a9..13b679c1f 100644 --- a/include/mapnik/text/text_properties.hpp +++ b/include/mapnik/text/text_properties.hpp @@ -45,6 +45,17 @@ namespace mapnik { namespace detail { struct evaluated_format_properties { + evaluated_format_properties() : + face_name(), + text_size(0.0), + character_spacing(0.0), + line_spacing(0.0), + text_opacity(1.0), + halo_opacity(1.0), + text_transform(NONE), + fill(0,0,0), + halo_fill(0,0,0), + halo_radius(0.0) {} std::string face_name; boost::optional fontset; double text_size; @@ -52,7 +63,7 @@ struct evaluated_format_properties double line_spacing; double text_opacity; double halo_opacity; - text_transform_e text_transform; //Per expression + text_transform_e text_transform; color fill; color halo_fill; double halo_radius; @@ -147,7 +158,7 @@ struct MAPNIK_DECL text_symbolizer_properties void to_xml(boost::property_tree::ptree & node, bool explicit_defaults, text_symbolizer_properties const& dfl = text_symbolizer_properties()) const; - // Takes a feature and produces formated text as output. + // Takes a feature and produces formatted text as output. // The output object has to be created by the caller and passed in for thread safety. void process(text_layout &output, feature_impl const& feature, attributes const& vars); void evaluate_text_properties(feature_impl const& feature, attributes const& attrs); diff --git a/src/text/formatting/layout.cpp b/src/text/formatting/layout.cpp index 557ccb630..74e4d5e0a 100644 --- a/src/text/formatting/layout.cpp +++ b/src/text/formatting/layout.cpp @@ -23,6 +23,7 @@ // mapnik #include #include +#include #include #include #include diff --git a/src/text/text_layout.cpp b/src/text/text_layout.cpp index 75c33c92c..ba3d7c605 100644 --- a/src/text/text_layout.cpp +++ b/src/text/text_layout.cpp @@ -24,6 +24,7 @@ #include #include #include +#include // ICU #include @@ -228,7 +229,7 @@ void text_layout::clear() void text_layout::shape_text(text_line & line) { - shaper_type::shape_text(line, itemizer_, width_map_, font_manager_, scale_factor_); + harfbuzz_shaper::shape_text(line, itemizer_, width_map_, font_manager_, scale_factor_); } void text_layout::evaluate_properties(feature_impl const& feature, attributes const& attrs) diff --git a/src/text/text_line.cpp b/src/text/text_line.cpp index 46aed3a2b..f6c82f9a0 100644 --- a/src/text/text_line.cpp +++ b/src/text/text_line.cpp @@ -21,6 +21,8 @@ *****************************************************************************/ #include +#include +#include namespace mapnik { From e111f77310c08c4e6f268c40afa7059c433a3a52 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 12:33:39 -0700 Subject: [PATCH 31/92] pedantic fixes to line_pattern_rasterizer --- include/mapnik/cairo/cairo_context.hpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/mapnik/cairo/cairo_context.hpp b/include/mapnik/cairo/cairo_context.hpp index eda80a533..2c16216ed 100644 --- a/include/mapnik/cairo/cairo_context.hpp +++ b/include/mapnik/cairo/cairo_context.hpp @@ -440,7 +440,7 @@ struct line_pattern_rasterizer double dx = x - x0; double dy = y - y0; double angle = std::atan2(dy, dx); - double offset = std::fmod(length, width_); + double offset = std::fmod(length, static_cast(width_)); cairo_matrix_t matrix; cairo_matrix_init_identity(&matrix); @@ -453,7 +453,7 @@ struct line_pattern_rasterizer context_.move_to(x0, y0); context_.line_to(x, y); context_.stroke(); - length = length + hypot(x - x0, y - y0); + length = length + std::hypot(x - x0, y - y0); } x0 = x; From 2f9bb66ab0e4c4a1796f72115cdb215e1ddde420 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 12:34:57 -0700 Subject: [PATCH 32/92] update expected test images for patterns after cairo fixes - refs #1386 and #1010 --- ...e-patterns-200-200-1.0-cairo-reference.png | Bin 7238 -> 8689 bytes ...e-patterns-200-200-2.0-cairo-reference.png | Bin 7419 -> 8862 bytes ...symbolizer-900-250-1.0-cairo-reference.png | Bin 5683 -> 17508 bytes ...symbolizer-900-250-2.0-cairo-reference.png | Bin 6194 -> 19425 bytes ...er-opacity-512-512-1.0-cairo-reference.png | Bin 10328 -> 15983 bytes ...er-opacity-512-512-2.0-cairo-reference.png | Bin 10328 -> 15983 bytes 6 files changed, 0 insertions(+), 0 deletions(-) diff --git a/tests/visual_tests/images/geometry-transform-translate-patterns-200-200-1.0-cairo-reference.png b/tests/visual_tests/images/geometry-transform-translate-patterns-200-200-1.0-cairo-reference.png index a2987030665f474164de27aa374ae86d944412b1..a42e101d20302c36f80e3e9e1646e0c7f8f649ed 100644 GIT binary patch literal 8689 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 literal 5683 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 diff --git a/tests/visual_tests/images/line-pattern-symbolizer-900-250-2.0-cairo-reference.png b/tests/visual_tests/images/line-pattern-symbolizer-900-250-2.0-cairo-reference.png index 40e274035568c1ef3a8955372727fc5944a37d66..1e3888fd621d0f54bf02bfadedabec4ef56fbc45 100644 GIT binary patch literal 19425 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 z zLoT0ejBf65~6qTwHmcVn9!-R@5wojP9 zYcUGyJFZ3IQ4V>50=eBB77blvBo=$hDa%8hgr4GruUIXr`UhWduoJ7Wb>;b0C$luL zr?-sNOYbv)^*1Z$^hvPeaHm|B#1VxpR||6f%zc4NThup+*MH^(PwAI3oV3(9Zm3GW zXTM$>h!qwcbT$8g|9Z@4w&@^LLbg@n&hokn&OpJ{G~$v9yIU)hCz+?A8CWHSxE7mQ zc%Zs^_BxBs4!bHo!I%(>AVuM3g<8&tz7ywf*UY|#-Ouf{c*2`0L_o%=oaPOX)TUW^ zwj8zH9s5u~mLkKmfE7Mim2%cC6qpqlE>d80JIW?HhJ&G_GmVB$7AlvuPQKAhI6S3~ zf2S3f$ei%=O@Vr-uHSzoJ-$snU!k)BSHhLsIOP;-b6Ktwi+QjKhpW5_9%#TD*tD}8 zbEaQ0;yP*?0_ab%YVk<<>gaHbFRwAej429On1n#$j#y1DXY?eOg$#ZM%sj8n`WI&- zCFv922t2#a6tr~ZDdyBnTGGVJ+_6f8IUjp1#&(|RcqNB6htVuMpNpy5BbKq$oNI%n zgo|{M!4$rs9;5Eqnj7#19y}L!!?b2_Tn@8j;5ehA$*TQqdK#5~$=1VL1}pB^m&Q7$ zjj&-nodFWhsOxDK{4F4v8TRli9fxss(&rG7ZUqNpA@_YwCwLTi1FlNmF}q8oYE%|Mu+z#6O#KG{p;D^v_B1 z$=l~+A142T%eHdb4Slj3$Zd_#xv#>y-(wkvBG7iyrNjumw`3E)kpDg9l3dfETPeW* z`01W03M7t0H4(EJp8E;bLfULtFjj#f$|RPUX3^WISyoqFNdp3>+ww$JWt5V8yH9Av zk}@y}{xg}rD_DgGiSjvj*(gX$gN?FQWYM2mQTWUnIXj@w7UN)rT}t`d^zw_H8p-QqQq`Hnk9%~yp!+h2HM zreex&40XM}ssSHsR{WaQu=Jo?;XYu2bPJc?BE132dek+b1&$^j4%nN2)h{+vmJ&ke zXza!uci`uzdA_B(n_lOYMZxf6^9_&pCNa%SYd5E7Xx&<-D>;e6&x1UR%7g!MzH z34n6JM)mb3f{6QGceVS}rQ2r`ZS1L6jh_LX%?9%E9U?rF(^sf1jtfy5y%q~6(Fn5i zSFbkqi~`bX>OwS}t-3ct6$bs6R3T^RFvY0ETqvss``U|+pQC?@p`%cFuG2EPq+uO7 z2(rEk2!d%i=JiYc)`<+>q|8aFQhAm`Ez|1CGA0qb`^3(!|Ge0K>p${^PS?Dpa?DS1 z>9yHu7zM{-#ZgovatWryN{e3SNn1yoR6pv6AW4O&7YcgB0B%W4%G;K(D0RApoAK`H zq@tW2!#R(Ca*7C2H3d=0NruJ_aBZKnKL|g67W!$$-O6RVRg){w7F_e#`MD zV*Q8C*Gj2p*iWZaOTzQ1SF3?2T=Xp*qcFNst1(;MOJ>^C92TdSg%J}%VySx6mB+pJ z*SwULp?5;vOIDvb7rXhAuozX})$ELxW^3_=9~X9ubt*$N*6w(qjhTYfhLL^!k|qOR zrD_Bg6SVC6={JPu;qHyr)I^UYRWxMzJQOEQwJD>+#z5aa1aU;yJIPE)I+HAtz5`6U z1In0hus2dP2i+H(rvmQQ(=5yw79_1JdzV+O97Ou?83g_|^OP0m6u0m&9V>YM>xvS8 zcY?P2Bl4`@LFQ>fexw;z5ElZc%uD*t<@xAczfD*v@WbnrO9ak+9y%8KPFu+6d1Wzxp}l1?Toeghc2?v2GrU7 zzeU`?xJ!5oxGT8xxXZYUxXhEQXF{!~71&vg4syAQVQkZ_El#Zmcc(BoNziFa$`8>$ zpF$+Uk!CxS$n`v)w%;$&_hFA4L#I$B@)IDJMUzx~Ze0oDUJ)TAcwz!8^7dhpbqlSL zq!7aLv_+0|zg*EQ1488Y}6vJ{i zPy^GMS)C{S+giVRY}d+-{v@5@IPYj2F_~EovvX|U=305Xlv&x8$;%_%bm-`*Fwna2 z@nl#{+4)+%4Ddb;e?OMb?mN;5*;4+RqsMQUoVD3cT4;Zej72Lj5m9=ze;@!=3N57= z7|?(`+X~%Tja+sN^5-;e&Fk=#o1Tya`Z?K~##K$qpQ#M>TP^c^EZ*JEwQ2)lzJSM4 zwL(!(WVIKUQCxd3IPxR>EsqHWsOyq_5|lIxHCKLU>4|49tB>CkcX{%STM~sLvvfmi zNg+b_0vN7t9vH4WPCZfa^J9kvOZz+vo~OqVc3v#M`QG0IM+H{D*mn+Nw+`yRUjjil zpl_6&?fQZbgGK8;-ojiD8>54*Iyk|Uk=ON%>`wxPkykv2DB2;bSaN)G^|?_4 zfAfmy0`mC1k7u93Aulaf$SY{_RnEA9SdWO4Fw^_mNcz9N$>r>LJ90O8P5Y}9x^F@+90!Wr~9p?&qaNg11QJ+L1)>qE-8rCFc$a51SVkfJM)PMO2oc-ZUmL?sY9&3W2C)^J>JgEBjE z+artB*FyfQc`FpjjuBsG!T9sy-}aYmKKT(A(~)|u z)XyFh|KkIlyHai6Td@wjV!X5*IM zm`(3U${gPQvNOP`~`P>g_WsuI-oC8^`3V^cEvx?$Zs3<%y^bcCsdEgBe23PPSY&Vz$c2TK18TW-E=d_v?20_+>Dc?bWFn}m3-AY|WzZPa#%7YSb?52MBL}9M+bcEL6_VQ)57hWLB#O29 z59<5QBdSsi61*Dk)N*!vzW!9cIS0#G$xdFgR?;IHZk%2eu6#?VAyT9>(lpt4#oDV} zqjHe_E&3tj@2u7KS$YyI5QspWKW>W=UYV3Px6GVf(r~gtmGj{pM02Mb%Y|9yPo8 ztDdlg(tq_AQuq0`B*ri5G$ub0Ak)3m*Yno$EQ4m7kBHvqq_Vn@!LQha+_F&QnO_Q> z-==1N%69G|q+1I3HBXF@1N-j^tZp!xQ@naSNwf!TSYUpXt$q* zFBh$J^f77X8dG(y?y7bk11{z~Z~`b3L@7si*OsfZIpNy$ZjY17mJB>LW$l^M|2ajR zICSXx1$|~FuDH{(_L1ChjxrFC4wWqI_~~A(RX(%QehI;^bIxPY>iOHfME6`g3J`dp zXJ07g{l{TYkL?z#?0hEc9f@P<6!<9m>ooVPt+lU@h-8{6*^7g{<=Ds8;araVfo{!x z74$yiTq{LHP2OCm#|^C=flZx*SOGZ#K(kB>F6XwPu^keh3{6OOge=xittmiE z&$L@hgK^0=ap8yWuJ5;Sbk?ey$$)(R+I+OMT?!juO2Ez2KDYuw3p>2qu;4o%n`3F# z^&L^_l-%QC;`tH?mEfVxkBpZ(@K;sn;kGsti>iZ;tEQ07gKcD{hIcqSsb2+fkiGS( zm=a?ghGfsM>~o&-L!n9}Z94iy9>}vCb%pEZCb8ctuZVV`8ZN|#} ze3G>JHPfD4G*`~&T@di^%kwHi59RlaN{n%1j15VuH>++~u(Kqpxw)c|_uRPU608fWHL^ETXq$_I<4Ue@5-QiL4xy5I*(V`z7b_$q4_n^K*PRKnp=nNcYD%Ow zZZ}a3h5IP)hQEMdrbRzqI0;9ej6|_-$P^0V7ZM6XvBfLI{9R=3qx6HeTO$(L$a3mt z!`ThZO+R+b!Juoo%JCnR5oKn%G=$VqgsTrF#uJZ#{u$r?R4#clu~;+q-77l^;ilzM zPb2FoMw!%0ueZoWGz5Y|Zn>MvmWs-SzfP^#^|HQH?7JR?>^ z&Vx7{axO^Dw-sTgtgoU;-&UJM*GvLde?Nu$LJ)u78IyQOrN~!W+B$n4SS;86CGOWS z5MXv2Cg!N^pQWm_<7C_0$^M)LZ#Qw$Z-env#LjTi>LB6a1JN1MclGE$mta0)@R6dJ zKxE_9$aV^A5kBiX%Ip9tDg41r4n8sDS4c@AE7v?CpamD|04rrus zW?unEQm`AwDe0vxh%ckTr1y5;(YXnKD969EQn)?VGNdvOUY5X*@7QUj&0W&-D{Ks^ zX;jNfM2HrOP)P0vY?|ojveaQsqbT__Z74zDn)PBpP)ak~1!o^0g>>uHMs`?}W~{~6 zx?SNgGg5i-({f1G{1^WX+k<}Q$~%f)U!3i5hNmb>UIwfMZt_K41Hs34@l}};Hg&4d zr%XNe^j!?03m?4pdotay=J!}8Hau+zhAxgIi_cjcKpOS%?_8TA-SEfle|g6_80~f5H_FTlB|VZUzN9g*2TWn#(^@z z;Op_u*`FdT2Q14l{|*vr^~z>!1^Bew46|vx_g)AU^>JBMC2>aF3o?Hp zpCK)`rM}ID{LC>zyt(i#lZuh*LA86{bfD0p|QH~wJv`U&zu8U(?+5wfr8G3 zj^A#S4ZVVeRAAr1J^T!=O9M@Db3-}}jGgpt-_~*LM&(>jFj*xau7i{=uCI$T2RG37 zi#msl0M7lt@+I}he-$>S`XwSXX62Te5{S{O=8R$ose|IU3R{*0gT^lzrZ_rS))^=8 z>T<@r{(udamerpz@Mdi<4&7EVbCC<@P{(=N%`KF!@2RE>D~q3_IB>4&nUit;UgZJ! z7`VGNv}{nsTZr+nLaFnoI+QrYGME#1*vT&ElPfG3%NE3HT`LTX%><7&^byg@vebq> zXQxK$7xYV(?Ggp6zp0^m5FqK<#<5-SThi-aM+B-v&Uw8$p`a`8xIV|nEMJFaN5Oh* zM1APLsuX7Za?D&pxr$QwL3j%8| z`;GMW(H+Ro$AFv<`xveZ@`z4e$UMQFq$qK0sKDcc2`O3tVM95+LX zR-Z%xpOw+QvJ&9gPA908va~O?U8ih9=b+h?!}iLa_CAD}S0mAKEwCy2Sgs0V3Fl(x z0p(F!sR6mHo4kH613fT#lyqzt)GgAvit&Ly!wX1QRK$a|Ycoh9q3`9YDw9NczJnX; z*4$g3zdbL;puh7vi{Y(I9A3lLBHz%NoPk{BB(an1LT z=9|ZnKcb}zpy(MY#c#ACUT${6)>{hH5hmsw1+yPhy32A z+mThUYnG!L+icfskSji|h{G(b8j8;_)XS=7utAV5u2WtT$D&I{E!t`5BeXiewGs9h zN%_FmOg$C7CyD+?@FN($`}r~et{S)wn~)axIhev7kiNi~=^@Tef#o%2?nyeWfE`<1 z-(ezOkW9Z_Vnttwcs1N@=fglhq=sR!E5M0SA87L>sK#UjkKxcdId-p)mL4qgQ(V$3 z)W)l)SPI>o{I&X58eYCU0lgURFF*HFK`VTkY@JxAd|GfetWmYFHXODKs-7O1L1ddw zJLL&G+a8|@Byj|VAV^8{t3p$d zLKX=2v!pOJD39rfSuQ3yUDq}_TeKhvFX)B*4EhfOt)_bB=vUPgV)c7#!PlH1gV`^` z!IXmBqK9x`@%+Q%>(+ze(?j`cUq%6gXcH=)y zK|QBzGk9iZlopW?yn|hX9eK^&sL}H2GpU?*4H;4)eIzpw{pC2s9z<(?TS){X&&F@j z0y`*!FVwQpRA_11q^9YgKJ68%vT>2?nB$l428k)G9Nr&e-$1l5z{7LF@d%fD2E>m3U}`9=y1eBK+kaG`uK;Hyi`#&{;j1+(MTpff7x ziBR}_+=D>5)-tu^WmwYB*8X;vW5>v}@XZPxSt`}?eCtu8n!i&;A|!~+Q>nftPaT)R zD}4r@4(EBgh6mzc*=`?8Es4h^92xD>slO4_AIXl$#dhc{V$?l9Hz^c_|2$GNN}2V* zikhSIFNU-~X(~0+zvue=k&R^|aN}`-ftv|uXizDSyp{DEC@sZNE3;#-eX`o!K+ctE zq6N#S=zBWqRE4uB`I<gDrHKG zPu?K;4;&^auwb1jx4ZN zR){{904rHe?c$2^z%XRngH^M8KTu7j3Z@dQW0_Gi)Yh{oZqQ^MiMIT*fGOio3Ma2Z z5)e8vRv=((&q-MuqqXq^S=aOA z1x0X++nx|7g~4lgP@Iu~+oaP1zY3?E5ZMv!q*OJ{JqJG<1$l7596T$wgU*mt98G7X zwj0rW^g*AG(YpL}yooYKEc;a3a2#*hT3Pw^_msHgwpt3gwKz0#ZJ&AdjA0dTrD_x^ zQwhn%x=yQKZLMXM2;^4}kPO|}eD;dWhW?V$k8*^CfyELa3TTfvsc6U{%_U<4yE)~o;>!Oz{fQ)=HrnO~sbZJlPQ!qt|2f=%0BY;<3Rp3Fzkdbbtu>wCn8+o5Gi)6ocZc zD5PK{2yAHUdkDKNJ|A|K<2O%oadL=OQ=v`>% z>8<$oLr*vVl|kdO)4Jn;lTj`yI#GRsG9|CRC;HG{Z)%b+_ThI^WA?^upZJ`kw>PRT zkcjudqYC(mEr6paDQKvgkG^EtwjAgR>Dc!)(hr;{k}O^KBA*vrTWN4OJ9bYQ0UG|- zb+G0CJ;W0FFv1W*lKp&_H{c||+X zp1Y>huxztXn&Mf!9uWZp-MU)KN@BO=sl{+pLj3&S{0jmO>jgkg1awG6p4+O!E`G2= z>{;a^x1^Be0>Y^M_h%2(mcbZjYd%ktkwSR0e`1Xu)jsGaz))Kh0*nRNS3Ip>MoTR= z&ufVg{B_s=1nUCZD#6T~#V0X^nL2P2BI5tVHdsVbMK$1;C~kFy)gC^E%Gdcc+d`Ua zjo>;dBNsCpc<$z}k_=ALP%lv-UjrT?#U*!!Rty$5pCYe-+=KicgUj+Z5#T5cn6Sa+ z>DcR}qHu9AJ=hC-t^9i)kT#kEyR23R6LzPzBnSPv;TqcVJ)>=5?0#69a@7=}K`(s#M_0zl%pEBN|0zvr5o{~!M)`|xmrhA%AFEl@ z^cOd$z}x&^9w$?T`^a_3X{N}HyU29?x6a)iUK^Rc(>u~iCZE7Ug|W6@j%`~jF6PDx zS?kY}s@YbwZ20hAQLy`uuOWrjsU|!oWeq$zVO%ArZO5K{?$eg9>bFp-s$o^Vgd_qR ze!KTgW4gdAb|G&aMpI|yL=g`_0>%Q)8e^K>mZ4VYcAvZ}dBhW2vRAr7=oSNdE*k-O z{>R^P#+hoym;AFfd+WThp?`L4ntH1~wZ|VXhchpI>EM(3pWro%iq+@9jca)}`YCeQ zvp3nX?3U$cAw&1!FVMCSPrB?MjEC4-cIV72q!+?JcVA;n!(~VK14wLWQka4xbQ8It zP9ki(n@Ij^zjJwG$spuY(4*RI##k_t&AMIVMolAn-Qp@;Ev#$tOFq8`p&wkw*XWzx zo`NTl=J(nvsL%Y3;BPc$E3vDPu0@gu+EFSV+FsizGwoR&{|-82OuHH`X6GDG%9cudiJdT$i= zJUcx;i`=&d2=}LzkS)AfbB267_ioFjIkRqdw>e8%^^fFXY>?2duUQxQj)TAY-0(DY z?CocKRal+KpC{Rtqc64l(Rh*+76wL0Fb1IY*~HmY&EE}Wev9v+bQ=a(<9vT6m)`jK zw_$j7#K7nDQ(*s~RI5ZJO_QTax%0YIH*?3+^#9%bG6GDm+w43|!0NXqAq20SGw4; zf$V(cz<~XQ2@h$zv)xhAA*GfnaP1Fb8GX=uT6c)6CZnAoFV9A_N`!dcZrJ6-U$$N! zD-n3$X(*Qk&ag}@u&?a#!fl#tCl-}9EI+s~|JC6d>l1z0^(^q;;uwaNaO@KYkMB!- z^qIf#@Q-!E;k^7MY zChf^J;_b>vxfUV^|~Z-{z{g! z=VxPr>{-f)YjDWdHOE%z4A&{H=4;^`d<4SbG2boM#|&G*VN5tBqis zOLcKH{mDmq+{ieCuu@AW9r1Pmm9E%do{lmAqe*_Y*1kAnX#qRDj6Bx@RW8(wI!E3=~ zG|Gr6Q;2yQDso0FU$L-zc%e??3D zOJT%MSFnQ5JOB9zPimZq6lhxSHfCICTfu6-JmcKj>PO#6eQMCbXeYAguGQi|t^5a| zcXF42Pv2BujPzs+nouCAqPmN}Jq`>pk|Domy53qx#x9@+_GgXZ6>}psn`_^gxR{c% zk`Qn2mz9;Plf{JT881HV$t=s~-)i4Qw@vp)*T*Kt!gFHHh$(NOi2@;6eck&cP~-I6 zbak}cA?Lbgyv&{b`H>U0cLmK3n43Kc6JFH)XkMQ+qZWbyhsmy4?B5o17q?h(xQ8hm zmD);|vwZBrlJR+;ky7T@sl!599)^_?f`Z(+v8)4cWcWO{8qld;WM0)1YZq9ccMpW< zy$UXG3g1tN^PBQz{~nBv5OR#(V>50mcHsDH2kTjfdku@h`KJC2KfB+RJO8}-&*6uF zLEI&;`*@!Rx6CnK+2E^crg<(cQO?>`H)mQWW22`eJVCETlFFkQr?0!6B5vW_szd2w zaQB$mkf!}lK{R&V-vRgU7;m^kM$sZzTJ4OEDMBB=Kn6WMV>0%=EOsNX-Rq4jD7QDK zvXy7&#BAvDYERF-;<;vVIk`@aEM`xUghGbNV%hSNX!V7wc%`DtoG!kEmq#}~>G1{0 z)7+pK=$Q0Gx zC7&~>p15iDFvK=7W!%hP(N|ihtsGM3&)(n#0e2=pw>Wt}ZH8;(V>Ii2Jfc_7`r%_P z<#mo3l)XWis8p%{i3Un*O2FM;4Aa|y>biN{^(dGr^Z4>YLBGYb5qNx9 zqlO*U-t`f&fH0CPPYy+6^PS4I`;Y@34tp^ubIonfyOWn8AUN1M{5gOhno(rp8fWQ! zx^k2mP(Kc+57wxxm~srEa+|mr)VtzTXC!pYE|66!2e46{t3;$P(Q=cpNdW{_nw-{B z@-d)dK-}nYs1>41*=!b3S>bcx2o5nLy485whXiNDw}0eQg(A!Z>pJF}!M45jBY!UQ zm7T+(Je*Py8tXRJzlTH_u<;gJ?lQ=kN^0TEBDC3#Oo-7xO5quj4QK;~0qT4?FUlJ8 zeU+sYX7sHepsqQLx}js(u?fK>ZleRQzfIC7XS$GbZWW-Qzw0&|23lx5LR$Y6f&LZ_6@~YBzq$?ypt3goDZaLcogOvals9?(P8K@G*S0yBDF``}e2UH9cS}~ty z)O)vE-lw<9DPq0QarF6^_<6k)JHf+e0|%#NmVFd4??i1I?>&yDWp5fDSu)HoceUss zh0GDjJ7}Y1XacM!T}!Dqi6kQ2l}^mSTlJ>Nefl_TDxuL|2(K5u4vYRZ1`vigC2FKH zq|=z7i_~xxLd3Yhl_2a1Xi}BeBSV_+kk+*&;HxTz`Kj7Q7GEq)L=GHOQ<920Ngh^Q zv)M~hA569b4W>`NRPVHQko>f54Fgu6&0850e_nj-m7cP$4o#rp{F7!h^!tKfP5lkzwIs8?ZzrinZPV$wMVp0Fa^hgBa6wu~F4nkfwR>+4ff zttxDD=D_2-?Qw8)?3k9Iw2YD;S-h)QQdCYUK1X$&LD5r9@hQoX&VJK#CDY$#`HX^U zClqRJ=343KkLN6j-je!281dy2(aEqXhcrA1b51fP%)K4pM7><2k}cb*B~cV?lVa&{ zOsY6r9{yHE6qH=G*LyVp0`tZPxw6!IsT=P_(ulHe-;nTv1q2Zg0m-2orC|hy?(XjHMi3afo1sIbO9!a|q`NzHNMR`H{`NjU z;@s_<^{(f=T(>JmO+^+T_Z==88XCU597F>R?K$+n{SN#2e{(|3AM{_8sVQkmqXB3b z00u6Aix1!v0YoGK2{}Mc1yIoebRYo43b1kloV)-pKfo^x2#W*al7OT%AT1BbD+9{v zfVwuIZ2%aU045fIg$-ci05~`U&hCJ_58x931Ox-YVL(_U5E%o+Bm#*kKuRW%2?JmS zKtVB3Tn3a?1Jyr(AMHSU5709J42%I|)4=pRFuw+@Z2?>R!2U6C3;+NJ^|dD&8kw9t zL_*6i?ax5f@RveUtv!Ep;7f2s=+=gD*7$7!oZ1J|Terh%AJY%cQ`%QcIr z@ng5nC*7RSV8

=&k{V!`k@L+$j3W<6Mfq7G5Nl2(!a#H;&S0?*7wa z;Fm96ygw{S`xkTA7kg1GXH*w!1Hrmlf2G&s-EzIjfF4W6SvDjCplcYpX81Byl?+|) zz4z-r=I?@DgncQdu0szz!FHjgHQL~Io7Vl2@s6M{!_qHUf88Cw%>USJ9Mm((OwmCp zZa7zN)x}Dk1#>t54P&`d4EsO75mjf@7k?07mOZp7R2TAjk>~Q93M1mJt;u!j82}wS zb4gJpL)FP&y$?;|#QyowIl=0_w1PnYT2@r0y*(QJyu^ggs&O0mbIu@+0D6n8HxHHN zTr6_8L~+dPo6>EeK8jvBPu_;APGB$IAK_Jfv5Q4#M&h- zS5H55Eryj=!pSL7b!6Y~oZ4Pz5u^x26DlgbUT>xU6v}H_THD(rE|=Z9_wbR_Z0hHM zM<3c8hjHCj+vfs?fQ!=(n}>8;!a3&Fd!}=rVC?I9@f9iie{@~f%dsEUvhRlSx1bj@ zukf6TG&Nq46h%&AeJ0J&V=4;R32xa?b*cNp!7V;&`bY8VV5z z1pJjG-aVpXO>d8CpSw!z)}61$O`>5LP~2g}LG$IdQPz(J(=}!Y9!xFdskgxxeiYMA z;9(}MDJ?BoY>|@EFL%|DYdVO#386|4F=d_$QcJQ^_4Gp5WW%5n>QW?f;VX|PfT4#V z@epaK*46}k1o}nvTD7Gm+9tH_e3H)cuXpSW!F6Cwj3tE} zNi1~ffdGD_){iYA?W$^8gUi*Ab*F_E5Q-1eBQA~an*Izw7|iL}lcx)bEb3$j!koZ# z129?tcUk!w_YxlZ^3pQ*mpXOquaFT#8JiD*uecsDpeN0~r#q0t4xPC3NaV&r5~(5T zw5P&{?*V_PW>?S?z|g;^uijH8h~0VXKAnbfAm^rKmc)@8w)rE`W3y>OmM9R~Rm z>BBvsR`9R#va&U$%X#MIWp1MCb-MyS4=z3E*47uiN*-uNSXgxTA!@^?#Rdun8+O)VhPPj792vBsYvd%N@gn$KNhAWf?p8 zvbc!TYf*KK+3@ToYse>dyAR#i{_)3~fg1&(h^ss?OoTm-a=H-6Y5F)c@OnCE z?XZr2TmP7AmZP|xerA_ze|zhXU!YXfN16*OR;%(5l(Ml5s{TXlFX;-y>>&_Kad5z|r`a}UlB=aEjsSo0!w>K`5osc=o)%DL=wwy69 zcbEL9JsOQ14EV8{uRxlvfAur**J3WZ>Jca3u>c z?@kRuzt(*y*Es=By<7AsX8{fuT4Wvz1AzA+?!YoDXR10cWv-G2E!x_0;fsn2Y}+f0 z%YC2yn-8j_8+z{|tOt0j3DI?d3Z z{ZLm|6Yy0MUB|%5A6w2m6CA5qp>O0)A5GZ66l{Oi9XfU6YS3Ukops4=ie6YanHhL! z94_08djeH2b-C`ex3`|V(ulH`iVBvqBsr8zFZ9RXlj3SHfc4uS4Ehmu|CSSXL|G~x zlj)B9^4m=!kDl~`MGiD!Z6)3t>a3ZrRSTFG79JM9(U7+V%#q=Fw9N|L?Q*Gcz2g+V z@VyB=xuIM-q2K$a4oZ#Rf8>HJOR55yLtaT zqT4p;&eFBpLgt)-2TozQ5c@_BjmW3cG4vc4 zSwp*O>q5RQr`qu3x1!*-DH3$l-9yZEuPG}lFB61A<>qQ8kg(AySiX2N)H3x1jQRVQ zEi=#NjMOqQ^uqP@0GPJDE~I`7eVxy&AAMU~pCrJ>?H*J1tMMdCDxr5Pe2e&M9mhQ2 z+Y|_F`s$8C+UhOstt~C>2>PRw8%2oiLdzNay!&kWn|OZQ%xBY^mAj7V-G$G>A z_Gm}LwlWc5fo!9{gU^&`Ij%#9kqT^=Kw(99LAqv(<>2KbRP||OqQmOh_kiX(RrZJR zDwny|iS%3`e7gvL`c?OQELI$wx_voeEi)e@_!rtsPr-guKL6GEn1Q zzK)hH`5G*ncju|DwSTOHs&0CM^%gGu&;MLb25asIB`tZtL_L*wQP>E;1I2h+# zEUAM|XPl9o3h6U&jQJ6IS!>bOX!QE$3tTSufRQJt!O{VC;A?4D^|m?XrX}#|<|-!0 z7{}`%mY+eB5)i--@4hckc5~|+PTAMowVkYc`^@p6!IzXlXL>G47q<9V;1-Lm0v;2gzwBP>wB8FWTVGWjENW9Ud z3ET6jW`Zr=KFah1+9CmAVDM+qLqW)hhpKPc`Ys2|UmL&6@=;L({a*4yxs*WH;w*}j zBGE zo2Y>GSEHTUIa%n{fu|s@#H#GG`L5|Rs_ZA@0!dyZmm*C^S(-lG9to4lC~qZO$;AgO zH#fRVOT}uwanH${kNETO?9t7W`Ysg0p&7b_4H)lc<3R$_oOiMeJPn!IY(AA>Tn1bU zELR6ML(lT9%5LsYr+;Dn%O$yiZjsbL$7LCvdgLHkvE^a&u3Wv5csUXBb$c2TOc3?n zJ-K6DpEX#%&N_m=Y##K*DB9zkz(l@)a~n3-*f=E2;%Hf}o6i)Cif`{upzJH-Kn!KS z8Be9820AIr;EG)2l)g;Q<25v$WBzQ1fH#soH~Thpy`qGTX2iha(%`Jq8iB`jkYa9RG4`3;7syXfsRGnQ5z+}+40EY4R<4}mQ?}(>TQUYCHqA00q?o_%^x+$u=fg`r%sB>B*}WG(#Fm->1JZ)MO@U%va19r?zF7m9EA z5v6H;)?iKjo!S?5>wwg}=lrt|_yB$~wfnRbG-4~P^7op`emriIXNNvYWhj?)=rN5^ z51;UO{C-{0gSEAFN6arOVt(=ka~3{K77oo&AIlF!B-ZuL^%mxnZ^Hw?^DGr01)7;h z?ekvDvoEwgh2&-`L%F0wS7pUmm8v^*vSh2$=l2J{H=zoc?|3A7x1L+)&!0bj{P_9% zHqE%tTX(8Wpax4DC{Tl|pIhIF$Z11&`fm^(L1PcafwUdvghtnf1 zQ!q0G%6=P`;egwY3*U#nN%!t<+ksRJ&%Qa~0V$GHMDL2MsIn9}p(krt@a*eV881e} zLs2(u%y(EV`~98vL2^uf<$1=P&x@D^6E z7TKN_h_39@?4ew0B{eAtNpQpm-KS8Es)TpLCa$D-I>nv*CbwEhm2!?m+ zTHPfYi3BZfz6NWR$?FfF?nGFhKR8`&SMow@5N8OuHXaBLu*8HoE&-VL9+;Mhv&G0C=MNN)MAF9DgM?@k$}(|)pQu37pY&|r(EmZn zlvMT8e;`Yj{A5LHjqe2BA@WL7duw}x3wBcX@Tr)+9X&7+mE%~4O|T{{p}ax#dtAkfSlYub7ht}FV}5>m|9Hj1 z<|p{>2Q9~SCg3ZE{zl;#Ql9={{bDc^nDL5GPYv`lb;eyvf&u?06{m3HLq-0) z{qqG2%EWr!JD>ngEW#DawEOWQ)*UG?DZ^AGy1**}}?k zJm>1pYO^}`hL!l_Wu(KRN&3E>^;5EQ3kr&_9jluEW_~`SZVM5XofhYJ86>HI{ur!m z(0l0Ul&Ra?JoAstnoI)b3wNGp6U4puk8enj&Iy|>w)qJx2x@0FZLClqirOx%uAT$WrU9dr&acy>}Nsawm|dlAR*YzG~n`A~k~%@zw7Rn;slb5&B1vR94C%F4pjM`J<%#x~wD+FA6TBFhrl z6RFb{!VkC(pB72&MnjL;r0*WU+;r&H4cMj)r1yM_Gx4;Q-oY+R~mZP#^ z9{iUosqtgQ4y@-`4CX|fj@(?wUPV!42_N~~x+Tp3`>bh_H0>@0cK9sc#*Dk=p2Xv) z+gcNse?Gc<_hrk1?)z+xiY*HT%@*Nw97v~Cl9(aQMG`mCG4)ba@wnV z_667UWqSDamXSK^JY8lXG7E8v3n*hr;m7_->N&_Mf-8AGQ(SU zww#GK!*ISy37^9im_}TP(TF@fHs68r@?1x@6+2S>ETrhU1#_R`=^uscK@W##|Auat zn+c4&C5W31QuCvhd*4kw$~{TrKX%U+{z$f*i7%v33;gujQ}m~7LYKQW?b>(m6%`@i zxw$5E^bZI5Aq(Z}4h-Enixlh5>048u=4^as*Wl9w9fa;?`IjQnr3n~1Wsa!tB_>|x(!I_Hx089> zotKw1?hSjBVE>5q)?l_aiHqCCYHpZ#?))BDD11e;@gT77*z3m7YwHPgr>W^Ecq4Vz z9Q0#uuFhRo^(t~Z%cNew6m$dEz-LR31;=rO)FdN<%^C3fK zaw|%xqJxQySKqrZrUSD_Qjw8@V6Xe);>wxFhhr`{7x?EM@L`J}f z?rAZ%t1uy$viy?}bB<=DeuZH**BlwhJUo(y8AEvAbR}Q>5@1q}t<( zUb8~aN1yC4_g1N`A zsm9F}m2T&$*6Y-9=1vsdfz82NRma+KRTeQ%#Tk1E$q?wU{yK;CQU&|^jhOk4y-qW{ znSVE7l3oq1I})Uj*NVnr>IQT~o$%8qqL52>zEyS2c)1occW{*>XQv>Cko%h95^%_0 zl#knZ4Me)k?bgiwm#l0@ zu`bKjp_Zq({hj+y(v8ZDB296SJRI>JnQb7)UOc~`c-42;to?N=F$6t)c2+?)2Ys9l zJ%=Rr1x3z5K0AXe83P@!Nj6Gx%(z>&?;N_7qwurE2$=U(0-bc0q=SyPQ6<&tNgAGu zp=Z4|X2OICZ%!zl^nwx7CoJzGpDUra~|1;N%`ZmRnFfsAp!dC4->H zA8mlXYeDt$u7C7QSz z-aCOX$IuJ%^(r1N-C|vzHHc?r@Fk<5$K&VcnDb7STOnGQBkHgqPg66nRVN#L21z>Y zc0VmDK*5?LH+v+mt3@z$ne2rXkH`Cf9#<7Pu03G5cGrxwMa88aRhfGPVQY0BA?gLG+jlJ>YxN@m#0?OC& zaIHRvM0ME5{|)_53B1jjc`HPmda;p4-jo}b90UT?C4gm%`a%Q*y^6HWb8tV+;k*=6 z)fY;xReZ0=SRA82Ha8y|cpS$S=<_z;z3kUds$?v5sOZe0liT7k`_4nx$0@+I!nR=s zNxJ@OO?zI9O>z#h$_RV$i+@5brfS5@%c@qt>dpK-Y~7tCc+VAAbuvXV7P_`|xD_ZC z(i3O)orgZ01nS^6SuBeKixF6oPU>#RE+b`kRQ<`)sfGeSnG8Z-+xy;|&H}9Ii2S8L z_iibYjD?Qu=UN)dnYThTRF>Lz;J|TB4k$Wns)8_%Trn|4jjz&~=M!yDSbiJ8=Tz~X z2C>BIt5(e~eygC!Y1^?Pqa=f&qX6Ep@oeLCdhbJO-$9jqSVz1Ygzn5ffRS|4Ye7-l z9|d|vg~3Ww|Ux_Pd%s31ST>SdX~ zTJj1&XTrtc;ya-MVdWf9c3-CVOC)I(8;L{eUjNqtj^!1Ce%h+ASQ6bH*Hm;cJ%Oun z$hJ3y8^<_UFFbcv#!s~kuDn9f!S2m$)&J21%vtDe-HKmV^eQ(0fQzPhscL$@R9fWK zf!+zAn;UJ<6f!qcd-k$7^n8tM1sI-U>bb*l39eN5e=q+Bb;O=(jDu`N00000NkvXX Hu0mjf;7*d2 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-1.0-agg-reference.png b/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-1.0-agg-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..7f4eb3b8df7f170d257b8a7c2e0632361e88bc77 GIT binary patch literal 30478 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 z zaGqS?&=&C-WFBXSfiDrvB+BC6MjgmjSgKJ@tW zF*nWe+4sbTN3kljD^cc%UuYGr=dRGFWBk;*&e9gZZtV<7p6_O`WPqCTJQSeD&3xCZ z8e-$AoVfGZ+eIE~7BrJz0{R1|#($70VsGysR{$aSyLkN?N0Rnx5-ZhpkwhU+Sg@qg zWBK7Y7@F#u=7}t5O)uw|fQCel`xR$l@oUv6wDN~GZH$`*7AP7mAC`0ucF~Vl!n6y% z4eAL8Z;f5Q14!BTs5Z^l>V_MxTQ~kvEWXEseRi1hgtH{L255ghoLB>n-XOel zhNvNkq*phcx2dj`>@0)a=bL8qTDN@cSR@D&QYSU^G>GgDwS5%7^UspUUDs<<0(Rr4 zNQ%~#>Zi&Xe!hmV7a)HvjB#6=a2=2ZSL9ToB^`^_g(B64Nsb-n+m;4mfYM}%`KL_N z4=~{W)w1+ZBD+|z0?@)}jl7jo=10pe2R3E2l!{DO6PR0jjOjSR$kNHFAB2ZOond-u z;NYLZfY#-cQ|hZjC}j6r7vdW^HXW9<5dHPa=Fc?&yzbX8)OZX|x{ErDea*-{aK6RDHaJ}HI$hfU1hCiBydXf@ho_#Z zGc=F+aDZ1=?Y)&QaAtz9$MwGEI8}=A@iXW-&p;~<1~d=0C%2vv=w79DU60%ZF$Y1y zsxL?W4ZC~2I1sNhCApEov@;71j2EEoml!P2Mbhwsp(1>n1>#Dzi0hSf97dN1V>)#J zK{O2?Ok;eyL1qGJ~z$c`o)hNp7K3eIrEWt6p={T zVz)`&YnaUu5&6~6nC4Xi>Z)I`c;wdo22ZL-^O3IU+R#O6gCajNGWC8{p#%Xg72Wv| zYu|UHk8)$#+c#9MOQt?(IDn7YqxhKT`pE$|$Dm?v;-fTA(C6Cs0rBIzd!luOCf9+D zBRkIxk&&}Vw^*6P3RZ8>(%-bl@vcz>MuhU?iMnNIIu0!U^EJVZpuU$V$`m@9bKBlZ zzK@97m%2XdFwHjTRc%M}(EtN$B+Xb@UeZ7rJ6%O%nl#;4z%zSsCzKpPM2Z}N5nI!# zP4_KYsdraYM76-HQ|y59@K`)}!Ckf{ma_&o&fAO4)|^AeHr(7-WyU&;hMS9I0+l9(cm7|#*bOxyoSA&^b5ES)tLmAj*vbCIw zvrEctu-210y>ixsJQ75y1+w4>+o?Gob-q$AVr@<%REHoGG`W@$CX(4H*Z$#q9U}h9 zSe18nMjjr=CjU6=m);<1?kt~sVMb;j{}xJ%1X?z-i^hg582a2t+BgjKeybKCaUDJb zMfh^xW!yUpr&VO@3Ga^j9-1_YK!`N(_vn2Q5l{DiOO3sbx2>Pv4+iS4noZ?On%&%A z{QD{SaP^nF^X}96`5#~Z{557l>HBwNUf9Ye!k0W?_}E&^KVl`3st~b|NHiX6;1Mw0z!v+QglKSq`tB)vlf>R?PqaM%JTzpL2$6^7+nQd zDAyWln$f+&zZc6vy1tIoP%Q+#c3k}-F+Jn;)ndbo78Rhj875S$GWDTJ^5Jk?#0ae% zk6>i`ZIfL-^VEQA3?ThHoky;9>89rv6UC}2%4!msuv{38@~1K<)m7Tr(Tk+>q*lR!0xyCNb9qSnDH05x{2qayh z`A^Cn`c#hde-bhkr1gN1n9W8lj%0DSXWt}`gwp!TAZdZV_a903ztKJKQ2bgr6tUH2 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 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-2.0-agg-reference.png b/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-2.0-agg-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..3960b15ff5c1171fd59ae7e3ee7d19cd80893d28 GIT binary patch literal 34059 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 + + + + + + style + + shape + ../data/line.shp + + + diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index d02efaa00..d8f52f922 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -257,6 +257,7 @@ files = { 'text-halo-opacity':{'sizes':[(512,512)]}, # https://github.com/mapnik/mapnik/issues/2202 'line-smooth-and-offset':{'sizes':[(512,512)]}, + 'line-pattern-smooth-and-offset':{'sizes':[(512,512)]}, 'halo-comp-op-on-satellite':{'sizes':[(450,450)]}, 'marker-whole-multi-polygon':{'sizes':[(512,512)]} } From 76bd45fa30a308e90a0420dc87c59223a4ff27cc Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 13:54:10 -0700 Subject: [PATCH 35/92] fix order of smooth/offset - same bug as #2202 but for patterns --- src/agg/process_line_pattern_symbolizer.cpp | 5 ++++- ...h-and-offset-512-512-1.0-agg-reference.png | Bin 30478 -> 30367 bytes ...h-and-offset-512-512-2.0-agg-reference.png | Bin 34059 -> 35154 bytes 3 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index 2142d0dbe..bc5daecc1 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -155,7 +155,10 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, clip_box.pad(padding); } - using conv_types = boost::mpl::vector; + using conv_types = boost::mpl::vector; vertex_converter, rasterizer_type, line_pattern_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> converter(clip_box,ras,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); diff --git a/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-1.0-agg-reference.png b/tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-1.0-agg-reference.png index 7f4eb3b8df7f170d257b8a7c2e0632361e88bc77..bd0881a9bd9c0aad5ffc947fb3f5968a2fbf7e69 100644 GIT binary patch literal 30367 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 C(aZ+` literal 30478 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 literal 34059 zcmdQ~_dnI|`@hey*Rl7`-fu(^$Bc|*lt{K@XK%;eD)@M58wg7?mhq>IJYCns4+IbqtpV`&F94oIxA$0IBHus=3JY$@qi}GrQdv@192|cdUna)cFrqLb zA}p4OD1bVQj&3WMH6V&Eik23OrKMHPSLNm1jO2}!5dRU!_cl%zthDrc3V8B(K2!7EuXkWG3#_FQ+1A?bW`V3n z`Kqee%`BpQG&s%%ST(iXY@+on+S5Gn(Iopa5Bx0v*ZCmN;=@`td$C^0X(17|5Nzi& zcr|-n7ZE&rc7rX(#XfuXBS&I!3Sdi#mJ0scD&$>V0ypI}o263T9`oz#;G%+i?I&TS zb0xNl)z%h^wYBx|*o^FoTwfHkhnz`w83 zSTC>DCE<;A?voP&A0O}*EZJI*ReA*v$NQn-M-bWUpF@m+glr3I~%(@>lgcz>pOdU z>wCMqyZ`?6Z=Y^&@BF>Fm_7M*g5BQ!b#i`kdV2GB`}FTA_T=Q`&&}oO<>}w+o9h!S z7Arb}<^P|xs4FYzdwV1#b7>O+r5ZNMJz#&@9IDy>?T7jR?g^y-)>H-cBsFS*4MLSqDXmR5`fPAerv(^{@)x>6nnW6dEI0e5-?y!mDpo( z#CpX}#YM6ACQuqq3{X!5J9*D64K5I`boe(?!P|TFFKdSI6Te8u>9-~m z3LN=<$^nx_=1WTx??i{GD>^XrI;N*(&~Gzj^8plthh)IXb)5G&9UxmHMu4zUrUx&K zn`56iE`|@zR5sLR61AoeJQ#m+E(9nXoPE4zGUq+G?D-%-4q2e!viz6qDC3&G>!H2Z z{*TkkpW{lY(Z$B?K0j}oh-PG3@&q|JX}zMqUr__$lctZJlrHrXB&c%-VtxIC&-S~2 zvknp{lJlGIR$zet@78k!pxR$D^^)Gxr5Oxu===TNrL@MeF0poW4dhyqaW91&~Y(|)?wokK_m^@>DY(Ez?X z(9XJ`hV!Rs&rR#=4RKm{L(XUyxYG4xoK(Nyjmb;5~&A#j;@yZoHXle2neGzeJ@=O;(AB1(pi;#{bMzr~omI#|MO zsf2)Q`L^iUbH%R|{34YvjGt?V1H+Z{FIApFjC(8I&WpmEy<#4V!BXwBYiTS}wdI{R z2X&90JWtUxF;mNmqx{>jzs`H^8~o~DYyUGP&8+&Y{e#(RmDUz|SurO32pw`g;< zpwRj(qf+?DJjj}wQV*Utq5E&$DWCdW46Kgl3po5S(oJ~kwUz_(pcQ`67Px8jaN*CO zN3-Yti*tIff!dF@V)jACwKH>H>6F%9ZCG2UtrxAzeBz&Fw6^BBUPfRYuEc}&gSo=gR0f@MkcQ&`zh}ogB4(wcSi2ytC{45VvoNNCO}1o>!56 z_FjFR&2r?|D)r$IdasAn&=v~xCkjmprZ4*G{E4*tpLYYQR^@OpkPS=5BYv8oFI;z3 z#-s-Z|MMotc&rqV!}Zfc-}25;AEd1?%U@?|OO!Bwo-=(iV)_Xl7tDVmey;liE>EfH+hyFBW3k(c+tQyV5b{j0t3aGf`LeWmGKdjTzG%+>u zW^*@QGX|#9J^5l6k<%|cnRE~(f=a})Kg4Cw2SFNwpT@3#wzMad<-<$Z&i*`M1*lX) z)}^}7nwaM|Wg$kXn&hWU&~pM%VstPo;!!@n%w^3bQ~6iOiLgb26k^=oz--w56xV`$ z>I{kd;%BH_nI?J1*TsGsb>tt#JEV$i6dLz)MMstzeZ98`H^2R-{0y8wNO&|#Nqde5 zD8z=6>lgdOEEjSYMzcN#C!LpGYI9r0SN9f0<-b8YVtuVN)l?65?m~B_pCQhI(7LUR z=YCAyy*FxldTs^ZwwA<5C;Fc_<=84sxYC`SiVC}!0yc$5H^z4@Z{CS%J%3q$z$?h| zu4>y&h^MTf+^GI^&5ICwaTA&AG+Vv)Rp9ePk3@jfP=B*_{jIkx9WizG=MAUbT8;7mliya8WO`y+j@ZVIk_zA~ z%+E4y#V)+5@tq5~_aTOm=;Y*B(dXl@?B=VZaz43vMi?`tV$sA6NKx(>5B}Q zIXKu2zQO|`4mXu1%`azFj(A0L9V<6E%a-^A6+wnUzY6kY;L>SJOJ`@E#o2s~5ocb9 zXw?3H>ncKoqAx%;CLk~qUq#k%m6YH)hS!)yP52xQFXisu@XS8!baEWfMdW@&F}e|-@l zW$qJ84mPP^AcL@fO`tNp&B(DGZhY*$F8Xo+-ez)S?-v6a?P_8Sx)g-xV=DuQ=qG3pfzf>3(GIvAYR( z0XF&1tf%Xg?1>{f`Z(IP^R{N$Y`=WHfAqA{$J<<7xuvR;FSvXrhh{YG<<1olC82!v z)MY8dYF?F+#@wj(EYTw9-aEtSki6&0_XTCYWz{Ial^KYk>-?22pWKooG5BEj_wPEA z4;)QBR}<+z>w~ee*%+$d!vm2I@kovu=IwJt_DU8sFGUblZH(q0<;cKy(ecB^<#@hL zWf?Y~edqAyUFyFgHCa#V#CXJeBZ(v=_Bil)1?JY*gJMfBCw^sRo6cz5JoHvqFy5bF zkyCrZ{+0iQnmMI`ZeQ@@M{HY#S4PUZK0)uQS8izw0fuSyhb9m+DbH>Dxu$T%aFfa} zku*7BpEZ}-yU5WRVrYkT)LOKW%P^}HOzz@psJt-js7gTjG{b@be zmwn;&;rET`R*;0RzlM`j$A{ItJZ-DCteDuiteV=VSmZ&8YUe}wzF@*eQj@um0A^qW z+0%V<_p(b2YwXMKL@gE+{IO{JpZE}|&VQJ07(0FYLVER#)MqaJTbvT0Aa%QOqYIZ3 zJ=?-17x04zKi?E5`c#+@D+WY4>ptc*wA+d!jk>bSg5^ko!4+$%B#m$3FgAtgI^At0 zeJACea9yoO?Th)zh=aT)R(L0LTZJ`t&y9En$tFiB zOSP~J3=fmw6mR*glDD#bBmh7RApad@(?K@!piYlp6>oEBTdt_kkXDGQ`d|HRG0b{d_v7LrwHZjvTZKyZ$Qqm@> z%m*}p7&@aX`;Fu=E*v7TPUQX?|I`tbATab)MX-*Rxmm2{KN;JObhp6s7X4NP4E21e z<5y#&2y3)bBi#kl3N_bPPg((p2sRwGoR7)iH=-uSrH9giB0ToJJseDDVOhOC%yF*9 zE>kG^n(elhLgMgn!>gotb#{J}oxKJnM`SCb@}huOptAegbkne=kVob`LHm)IXe^9P znt7Jy6ZL`Lhq*(n#-oP#G>^qitZL0+-S71f2|hC^cwz!O$SgcbR~Y*l_%_|G?!Nsm z4IIYKWztA4Xa+)*z2gy78SjrZuqD&Md;ODgm_l{6@dA7F?Xz=$u0tC~4)4fl)<}V8 z@QvZ>e|$ajC9^gQL58Q?7O&)nNO0YVVu(T-zZY+PVcgo{t90+Enb*ixIG+C|MAX`@ zr1#`tcgicnK^K@QVm9TUsc7$XfiZTp2`d`}a}lI}=k?of>y9E=TJKO^;hmC=D^j4N zBmKbHw+d~W^QM(7iRn7<$YRhY7CVcGo@pcKg^RDmDt%Y#@Q>Od@C#f?cU$zyOE(h1 zx7tfG=fCLVl+`UPIis{H!ao+nxe^7bK>CHEUR`9z(`FL-(}gnG>z@<*tH17&=7h+a zQBy+VjEU-Oe$8qjFhs)(o?e~U1fjU+oxeqd!&*4uT$d*o^Bkm2`dSsx%}2+}s^tCY zWQhV`az-j_)c>VLL&t$<5$@mrKp2k8X$r;EC&fn1mLXd*?sTp_KEUKmfA|=^pWw$x~aK5#Gok7&hN!wqNaYbg0LXJ zFuxfgztqJssX5Le+VW1z_wTsB+;RVk0<@Yizk{oZ!!z9)O1oW7t?JFqX(7)guhLg! zALi@5dsCy=9zOnX)Vu0fyyqnnEXG?7k`?Fke%?o>pSgYt_4@bJV0%-(+-;P7Ww;TS z4|{LWH%wKDr|!jC!+;3>Q9nfrG)PVu!DcZMi8YTdsAFWt-yQ^N!3>7Q-z&zRn${;g z8sS0_Ck!%uv>xPhT$%UQ z9GtY%$af32Ii3)``=fkjJo&WDL4UIlp81YHgh&Aa<=$p$c4FibhM&FxcSuuh0cyDU zQZtMmj29JcZjyY|ks}9n>nSV;8pJIM>&QO->LH_aTctzj^XGGaO!>ZqS!ZcJx4|P( zCIA<{91Ysc^W58GA7dN*g)Q7&=a@E%HgP(dhj2g`p`4W>a-C^aTByRdwOHhHB5YaF zz$Y^dIA5UTz~@*VmJce8o0+B-PO>L%sVc3$`W`X1|i@rBh^?xkDQ9h$8F$SdGR zOn`Uh`k9;Tg2Thq#etP*CL`G%>>F-j&(P(G8VeSk_al=?#3X3YCwdw_F7b=V(_ugr z`4bnly=p_p8;SPX2&Su?h?SDc^?4vd#eckly<2?9BlA0{v8n5r%i}@9E3Z=032OfY zMrR49lTCKo`HA+fhm7R!SK%Fv?TTXd3Thb;oK-y9Ab--j0iQ2=RFD7$FhEuLX`Q4c zYn^vn-yWtPM4h3M8@Z0H&@PatfO?(c-RGrzS2|O9b%^~U&T-jSHM<(Wxv+p;J&s=V z$uULw)C|W4a|R7rI$=)DUh3=x9l2FEu1Vq$KyRH%c(-s%%S_<&0L8G?we#gAdjSx| zKK5{HEzan1`p7Qb8hZX_j~<3JhC{PF2RT1y3YJvMxdWeyi8Lz3nf@|%x`{aqd+OLLzc~{d2J|k;IZVx z9eXUmhlN1;9$W?SRcy&l3Yl9yn0D15u8nvW%%1Vk^5vilovtKB(;iBW803cr2JmPH-?%;cHiYgOn$+6#P# zbtD;>oQl=>!lC^9#Lyv&KPG_fA=4RJeIN(cPND)3*mvi)A9;3KrxnhQI}`LN%F8dz zvpvJrB(Q_RFQsr-E+XXdDi|j1t}hxk&)@z->WRYNR#a3Ad5+m@ALWkyK3FCh;gz!G zPz;~}j#<%Qw(_U#bIc2&S~|7ev)jboV>+G909vQc+ZFeaGj{>ZQY90j+g7^Xg;?p0 za83u!tF?N?V)1GvmqbAXNWpqSEPvAt~h-t(bZkX zc0&Kt;#md_?cl7`2NlNfdn(d01+HlU)IgfT*dUznq@1wIT6O>ag*+B9Jy6`D>(l64 zN%C%kY7gNtyAnbD3H%N{4}+BqxZZ6!)fK)Ap|Lpm?bOg-AXS?T#aHvSGmVYCtb7-# zwO;^q<_6>lK>}Z@%aKkY9?RD90V=w<0_w z-TgOu!8#-);eln%mtD`+uEVC%pU{fDZ1F!@y%cZqG}P*+;C@u=otMxvL_Zc8zh8@M z7VB@oiUSfl4Gi|jD{~73P%+-5bFot6Yr3$xEVmfne9M&&&n-NWZxlq`|4Un*zL{YF zthTVE@q~ADAf%COWc5BK{@vw(!dOvVp5@o@37QfXU@mYv`E@7&UahC z%TzG1J4yY~0)~W0=Smt4LWbtuq}Bv+e^)_Tp_^^$&qC?<*a7B0T;Q~a%}oca<+1o= zRUcP&-vwilOpq@(zEhh1M+D0Ey8J&JeAuCai$~GPyl(hF-5Mmj8VgFO_CtYM_vf2X zGEiPijmq{Bw>ji9-W5Kp==$Qh?cMV(0f)auA2B546#cNV!n6!>NM0_1hdKJGakCW> zqKQu>(qdzC^A+|)yngY>k4f8$ROoC9Papq9O-Le6hddKmq)Lc1#nPRo2uYLe6cF|B z?zgW*R-hVMbq9Srz?d6s81}IA5L3Ze1b7+H0-u?kujO4>HTLDIJ?64X?3Yz}%OEGG z?cp_b5>$^c&B%EwN8|RGzx+L97)o89hE_~Kf{OU&#(pZDj-WC>vZ$i{2M@$-Rb=d+ z6&3K9eu85f>A3Lxx*@{Oq`>9L;KCWH=372qUerXaylP?FPd-SMI5azG8Sap@%4#R! zN)+F4*(m#FN5?6iy}$QEhxekcyyF2s zsN!JSIP;Xg{-dGrGMAjn+Q{djkueu|ah*F}u~_*lHIdF6#)znaSA0dmP;>brK@|Wf zxku4gHIqS?Q7dvE-skarHYCJY0Y^N>oi(9!FEpdr9`Oe+)o^P z)Ooa!&uZOy$!qO+-zyQP@@!^*6N+q*!0$Xk>aTd4xWRgnacnjsBP#fgX2)t$Du6;P z?&45Ad1sD)`T*3H%w<^|Ow&u2eA5NoQ2zm=>YmM)&$zAG-WP;pvZFtf)wbpGF!Z3C ze{bOaI^Ktpv$Y8&NA*1op2JJ~`w?0)wE%Iub(NL_tbgQ6&{g-+RM|6;=QX~+33A^g z(q_L28>iEFhhgLo)3JgaVhi5|2E7;r5#R&$wjY>%76GZ!F!=eL5JQJbSM9r&7vtsZ ziU%ALy&9CQ0S{kBl>%Oj6$koh3~G%ST%8Kpt2Af_^G>|K;rot_!|wA%{*zjwjFPUl znozp%VR?Ug@RFAB2bbe^W&N!zDi~o+a(Yt^~Z? z?W|NLeMREu54*}9Y+PLF-v=C@H#Y6s-_^zn?(R&*V)$}#aT)oBBn%~VN@#-h1!$cql`&7&- zslp5Jy?-f%qF`wOGq@$+yJ#DsC{`SPBrodur@)_dV7gbFFOUZ-&SI) z2+go1Q{WjP&mpmma$nX|egdh=eF$O|O&j=O7|N*LH&hIN52mx=M^~Zbd&=!b0!6_dQlffR*RR>C-Me-w{lPK?)WwqC z)6SS7#EeP-sazZ9zIRXtq;wDfQYRJho*TqMezw5cR(_mYRo5hTIp)(kXks|vomqBY+>C8tj z0_2|&LZVS5B;<2dV>Q*zP_$zJ^#sV8-0q3^xuqB;Ohp042r+ko7Qnp2(vy{HL>(iT zG(t%6JIaC6YvdvAk}m>6hR zJY%CkK+kBCEtJ?8qB1aUe3Hvp zl$7WF?`yi@)fF2!TY+WVe1;=00@yb%X2bnWaYUCc7AxKB+sI0|IC8R5=hbs4Qa9R& zzI7#YAKue&7Pv7M?T+RRQklG`)fC)5n`IuzIYLG&y+9Sq9At7DM-z2zbzrI$;oy}E z!)!cq2cv$?lZT7UjR^Nl(v+EFrSLXFj6=)RneP%eg~GR4V{db=g|}O1PI;^I7;!uH zLb?-o0+b^_D|heU`Su0bkWf5Wt`N%{@8&}4S>EwH)fyK!glE1!lj5uoW1oEosu*F* zzgsRjnBwoYWDY)b##Iva+jt!KKPHsZP4XTx9ysl%sZ9vH7is@ot~_k}1Zz)7N~s*# zD{zc|xTTmPuvin;O*zRwY0s7dtap^MJ45jymF%LNxa?}&u+?$S8evD$Fy1-ru#)M4 zCHRWcK1>rfQ@X?Q6LWnG0lclD$X7QXs^YENKO#OS^HdqO{4v0o9dH5^|pJ*|~gBKmp) z7C;DGd1F(dxv}cJ)yhPp&0(&YW+S6ymwdnyEY~)ahHAhSF>`1n+4n931u{*N@*B-hN}mS!@A&G3*jQggi~j~ zzXNDO1so`;(nn+I_iB!O_=*7$Ol`mN!7bz+H?zDgi)wgJiet9;$^Bds0>=O3#{;8S zv^}|ySQvENPu#(^I`{kjlw4b<858pvn^~YhBnY^lQzlWU>&ST9Qy9|crt4@|hu5u@ zYV-{Chbz4Pfp=)^W9joe#H-54Juhi0)-Xo%iI-vjTD(Hwagwg|3_ezif1*Z-g!tT- z>bgK6`}%^iQo08NGbEY)6%k}Y8iAHJx20A=iNQrqnF0FI;Xur>xXb+AA%*9?a3rJv zf+4!j_jDD)LEp1*Y{5HaxgTu$bobG;{{E6s&zG1Ovp`-Yl##koe0f@V4<%Jp?WOv# zFW%zIRSCS83h!nKB7+u-9 zR0g~Wo`U)UWMJ&&y+5r<(5f@iIWKiVvv>Wp1Y~JMeGer%2|{}~R!5bgcEeKKcjHGg z@RM$voFO?J9&Wp}eOy`@%~M3shsTG(+6d93Jlq+Y5Y+8dN__Sqs2b%0RiVcEh9v?2 zF;E}rfl$HLSgCh!NxTl@sgjZgpM8yipde6nAQVwzY6B&&hg}H!Mq~-}J<#56R4J}V z`?`XF_NP{Bpohi(f0(8JJ3-A$&1UI$SXmuY zx20(QHAG3^iO$o3bci(dgU$|uM8DVb)1JEut%`shbB3$6NA5L3vw{1Q?3^9!c@YAN z0I_i?4&MN36ithi$!~#QRkPKpLblAWO!CDrI8AaH_w%?Z&2jR$>Hqzdo9PHdzlm*Q zFMHF&NT+Dmoq(TNsft77(us+Pa8Y7~AQ^MKnqF4CVf@zqiw>~}4ZN*3TGl20NVP~# zrFWLydtwq5f0H6Xv}Xy?9+&Tl0rJ*%El%1eEAsg~wB+_|zlL9N!Y^i651G6CRM`V> zD4gkbDFIv8R~b_)AXl19 zR`T3_{qEwSt{K-8_>$&-|8bRHaPo&4_Ck`3r6awFT8OEs10aCe>PH2CCy$=r&~!e9 zPX13_Fb`z^t*;qxm>z9T{z4rkWQ}VjsxN#z<*UUri~iUVg~S`1g2MR)y{z%3{P6=^fEX;!XY$=5O+Q5GcHTLK=g zBZ*iel0}ZCj2toZcO3LGr&%NC?dV2BGH()yCBeL7NiPB(E17CsV1(;+N&=F2tKPqv zQ|NSVl1t%73SD1Q1Gl>MpXztaD%S$}(-&5{g7PD_X(nwlxFUvfTIZN=j1@7)kL?bv zM%n+1SibG;>r5I60!%8B^>!U2xa>mt^!cO_$rBmUXM;sPJc3gs}wFgiRYps^_n}i9Apfeb9o^ zZH4>Tg{A0!zsaG}qE<36-g@hBm?jr=H1|YIN|B&I9a1|t=qVJl0ZX|t zqvNZwQ{_oTXe$!3ym5+$2_#0Dkk2jD3^kq>K;82G3v||tozn%0@;C3Ve=~kAtGfTJ zcan=18!(v^NT^|vrMdnnwr8zA#7QmZszAzRKK%;PP|lRcA1Y{@=OWJ>Wn#OZTQ@x9O)(OTARpeCyNw- zhz<{2e-&4zL_n{<40@^V<#_h=W6roc9;zQUkh84iN@d@L3r9USPL)xys`PAA z`yTnERlT;nGr2Mjz_Jh0gJs6thhgyO-7xRX^YEEFKuzG?o3{SH#1pC%cU$%4 zw$ES*9`0Q5N*{pU9al$;7@|^s$o`FBxT3V3e{8yOM9ISX3SrjJM0)p6j|7MGk@2|r zJY7XNeR{_a#Z97udq9~1Igb*U6g?o>6pVP@!X0X=aroIoBp&km(wm|3I_0xYQq!b0 zPLYFv4iVt@3=l+`#7^IQV0|WZObBtWD4tOnq}@rnz9t#Le$g6!CKonNj?>el()gMb zJRveF^+yt*ekuu|=q7Xwy|stUx#XV`ftm-k+gcN8&tjuF1xCWqiPX}g*|C#$QTOwD zp|!HewbdZ6A)_c~S-BNyw>lGRJ7R^HzMzHPhv^bhstILo+_4i(z^{tTMOABUE1y9L z2S-Ik<&yPN=Zxb>VX^V!Ee*k`h1ZG*dz!jJApxB$cDY71R-!Ro(A)7?HuvQE?05g8 zJG687-V^ctIju7}ckCdU@gpx-E$+T|9x!J=v1P&RsERa2y-3F0)Ni-+iV zVgZI*#PPG|6o-AjG2kCR#YL6F$+D(KIQUNK&nRfux}}(Q)okgE(|kv^J5wJUUaf*u*XHXV9XMg z=jp#U4b&x!-7l=o`w1nUvvD|j&?M!JN$0tX*lV*4R@>gCfaVO0&(y9U&h7osZObCs zb@j379VxHLz!PFY6O@Mw!|m>qp72fZ)t>1qwy&ABo~6Pa9CsICzPtBo9K0-XcAh5n zj6|ZX*~qvSAAh9Ac#Y12exI9`=ai54F)#k5TjRg?rQ9LXjxM{j9-LqX9@2z{j4OTa zl1xFFj~@(%yD^3Y*;3?7|C--zeHenekMDo@M&!>dp~NtRn@D+ju9!~27-bwVE4|Q# z{qUh$jih$rNk_$Bp+SViCGLCrr6PdYGAa}Y>!n+18`d1;Of(OV6{yrSk;7$iiFCepLO{zqFd77f;!i6q@cKjf3wKO=erbDHBd};*AVTTU?Hf{uU>vWfckLd-Hz-XBtnR68BSd zJgA2T)F9`{*vZT-P?ONf=8J1XDd1|ubJ{d(1nz}Oa69-b?Buk4RLxLmHe-N+hERPL z>NK{M%24)|-Y?O)!dhIwLQo|`o!HUnpG;ywAs^XM&Pf5RVt05& z`O?P3Kr_(LZKyyNE<83;Fv}H0lrBg#s(JBuK8DQVS2g3u;h1Maj0kj&tlp*?PtXB1 z*kQz&vMftt&k{La4cz>{Zbj>1XXKB?I{Dmf@7HQZy03BB6fNjO;nm=6RIBvAV= zai7?kp%>G;5H{bXuc1E;KRQ_APpqOkkx+{R#=(w$PW?UC{$v+SA;|c> zN;V!5nwF+A?Fdy3ExU(#jl+M{#_%fm1CN$bvKliiud)BNrg2CA7i9<6B6NAV12?Xn z?$!ft_8OR=ac>5s_R%Cfr`!zXd(RQFJON6LWaEDooZ6_tpW2&p`2ShrWSM;067}gG zdXVPHhINkeb9C$?0o0yP*~g1vb`&54h9y$7AIRjWamhaUIA;@F?t&77m57uCH9hXK zn}?c_9YOA_Pz^!r{wn|Dx9Y3D!&Hzea@59MYw0uQDBu#~Ux8yC+<)*N^J`_IU+n7= zw2i!JaXos``YktNaMY04pJZFX-tzTo~fFXmV3z+Swmr#gy9d7S2l@?D>0~32d9l|v<{sbwA=RuVrdad63rX@^R zKxcnm=5tMz^?f4c7sy<;s!dot#8Inf^EBwKj_ss(t*KOKy6*ycSX!u4R?H*}wRWgc{&P|XI zijF?W8Ow=*fYqN5h7GaHp=5+N*jm-NPF#WW3}ztUIw*hWqtcOav+8mQ zl&L^EGQnPU;0v5tvjfyR@hKBwak&lqXWZ*7AvmGAd*dwL_o+er=T8 zN?&#gN0Lc^mx0W|oDjOgfNvJxoJ3nfUl4RC4AgqkLqbZ3N-U8F2@*ze7*-C3cxC$< zNi02hiBLkkg@WNYzrGx^Ju-L=yDEOdM=|(opL{;S{CkjAycQ0&2M{*KkO2YyGJb)| z*nEgCj~GbB@$A33ZKcNBW3$TBYA>r*is0MSw7&lFfR%Qv7=geGekd3CzC&O{8Mr}` z;oh}5Ft&021#gQZ<<&t=e9{C8PYkaWzR|GtJmuFFO5#KJv0@(3?O@A`D@M z(F0kbQExnwq&TS@$JI1MwQl|8O3jewXM9b~jK3kihZWSsW1ej4A4D-lTwwi(ZKH-= zO~*0VlDAn8hBzu477-Nika0N{jt9BPm`Oq}uY&j&-DKxh*I0fT#%Poz^f3DDY2X{Rf9L3#JsJ zhCsfSubI(07_x>-G|45#0~1P@zE^Baf4UwpzvfhxCGGJ0xSC~=(lbJHoht}O3ikM2 zX1%9Vv|!`1NG^`g!XQM?TABogh2l;KaJM6?VrIUR1Lj@w+fnIZ1o~a5jbPNL?mZVf zutkr$LugC*x*7zGc)*Iu(b8HApHE>DZ-=*jsWBcMb|s4XX-V!@ejBjjU=zS71uL}? zYJfva?0bd|C}PS*QeN_-g$>1fTVMd?rdxJWtFn1r#0e%LPpEZaVFr)A-;7G4R!y&@ zX^VwA(03ER<74vl7_O#Qtej}a442&`v8;hs-C{!>Ef(+m1=)LFTmV;kxR0~ z%!XFA1-Pg?p-4+hOUOT!Mb}@fiPac_SEabSkDQ=DGVxao1aX^_jLC88aqI{`x_$CN0&&4ifa``JLcnXL zuP?jxxM5>eS`u|aWoE&XoI)Gr&p@U9Fq)QGcPX4vEMsOHpy8L7WTx!!y%IgPILih9nFui6J680=D63QrxlBf`dfW zUX8yHBv%N38ZLfpwWtOE?NYMT*Zd~{WecoBJSreG?rVh*lAE{Bd z0nG*S(C!BNl>cwHPj5ixhV?0qk7yV6D+M4~`CCi^YMw|(;lgT}>3BGhv|Mbz`Thaq z2aLEX%mu*RlyICQvQ!@Pjst$VpLMuZ5l8pp!JgtS8^hvBn7=lTqVTfX3iiQuN-i%1 zblyxo;TRpg#K!UcEu#7kWn)_Lf%RaYSbDs{C&9HPU)D>vTFwdtN!o0z#K(;_fq^0b zSel3A-j$Sm18(({;$aBW{L+?42jOR44jZ=+S$jZ;DW=(yxD%x6awGoN*?K2{>o4*S zw7%G%_mk>+NTLpZen&79NE{&;Q~r{G_m_&BVI?yV%-UX%^})gzt8nqdUERDS?jGli zeU?N~EGfer>e?z7{}kyZe>fI>`SxB${L?jZT9-SvU<8}XtT(dsWeg|J9di;W@HXmr zh4)rSDfh4s)#pCGdN^i=^28~9ysAZ1%nUwrvg+Iq{_}_Np zrMT+&f5P39|8|4KY?Dyz1?u+Q|1nH3k5-ofOh_m)3_=fXerkkV;SAwkyK&+nW%zoh zpU@TKVgv(6PT~bjb|V~pvY*sHwoWT}fYex%3pYX9+$!*Tu>HDk4mTKuYd)sVy4;g0 z(i6s}@46<`i(TpTwTi*OVQRtXyB?(mJKqQjnZX$wL6y2HGC`aq$ykSJ_2qKHCbuXw zrF9ZKx*O>AGJrEVdw~4TV39i}`-t=`AHf#ilAMg;WTpQWha^P>#Vj(>%)dC2@5>>L z!?#daiCPU>-xJ4RSD>)%PzgFT7c+t8PDzAaiG~!&u)_=-*BB)e+HfNgo1wHWoQJ!c z(>A6g$a?gr?!_IWcl$*(6p`cl!tqQTB`VQ_#1eR}m)Y6`#%}AJoNy3$oI8+5+iEtq z^jV&a%Ys~a+n&Fl|B z8`ynGpxTUk8v|SJPnXJiq(R=+jnaP z{HUIkib}#WGD--1|A7uUdeP(@Z z9>IRN+kslAZgTe>us`B6gc&cA9lB5V|EBh{z804B|`&k2_ns z>9{&fY*&hovHNQ7Z<|D|Ws{fQD%ed9um{~3r_f8-DA(s41;Vc{zgRwk$PPl1sFM_y zKhtoJOm|Wd`jg`mGroTyA(I62$aC(op1oM^PbL+-DhLm!PO<@C6BwZvVja=S(EA~T zN}{YE{uL^b;&wL9^6jiW7z49=?}=XiU9;GCcNBfYTes=om58104|L;Ca{rIT=OUS$ z^I^gTYxXpGA@lRkY*nm1KGnPz7_F2qktEFN*_k9HoX-=dA6hcyeS6JmB7YX+r#rqX z0Y@^gVtoxR8VI|CoFMWXR+*1dRz=arU7x=O7VE+8L@j!_tVca$fzZdFlQd?kQf8~$ zU*y&%IF28rAB(Aq!ex*9D@Q)fZhn`o&YDs|%;rfKAQa#dGcISZURf(7AC}D3cyvC7 zfBoJ``yBzU5MWZ_i1~WV?~UTn2O|Qo3g?%Jvt9Wt0p2zbb7*uC|4Hum%~`kNb%hsg z12neQlk($6DW-xv^M^>!_3t~lR^+1;N~MM;#&Q1+<=+qq4cY##CRDyC2;aIz3;lb% zJd!l4Os@i}4+#EfMle_eeqVW^$#*2d}+wOX^o}blFujS)Dn!!2%e{ukW7p9 zfMP5`lXfv&e7Qkv+tnOf8RQT(wB=3?J4RsI8>_4NIyDGjIvjF#`pZ4uiumMye^GZV zn0{fVOKV{mYX@jaHDc;>j*de@nKFW&! z;ESDdnY{qgC|5l0YHOvPek$QhttR|K!Xe>LLkrKlr@o(LU3kRU$fCRCEt6+GUuqDR z!fgdE`1unJc&5zn3u(G3&XZ>(I|0mha}T{kT{tix)3$R@qg1PRC}u!M>@(m7Kaos^ z8$MmJOe&bFPoel=wJ`R6fWAO!c2)j<(-Q_XIx`bo<=XNZ`~V=;{FgZwHHtYI+mGHGDZ4g(_Oy2C_PwI zbX>mba9qFUV9>vH9?tF?)_bl6HQ7#I?fJ?6t&+4{wO&iP%{TDhB!*dxnM#G;!g6fZ zrSl$plP82ZHA=;P_DqU|%N|*Uk-5WD@V!$)tC0LYS1UkrE14vTye%@5%%twKDlSP} z`&shi(DNOxS`>L)J~VMUk}}D``GTkNyEk1ND!G@qKxoOg7iQgl4xCK}@;9Z_08`wH zV3tbTa@@!M^mW`*j21@AIFq^q#)OSDhu;XuQ|)4HjC~=PUvMV{FjoANCtKWDCFOJ9b8PlAE9k{BR>Ec_?_-+y&l%fE!}vJCVEY; z!*?0#%PXe`L$QO+0T-_26iQc;$CWwaTos^dd|8)p&>8*jkj0{E})c^ zInkickSPL(qLvwVb4sys+N-*?-S?}=S?BqPQRHMNbfRAbjf~fZUl}u6p6Zw6d_~dp z=r^Dd5YcCB=52<_|M{;itx+0fcx7t?gti&=)vF4>|5BX@dm+y^;M^wKXz>|SPGXdU zP4uf)w5vGwUrNv=tq|1Tj^7c!SJxn)PT`6^=j6ahxC+bH)0RJ{&B6WPkwD=VdiSCReZVG= zB+f5WrV3roB?M-;7yrl6Sq4Pav|;#c(&f^*lpvsV*U})3fGCopfYeHtuyl!ZDJ9Yv zfYJ&}Nl1f)bcaZH?YHmu=lncp;>^Gy;+y&I5VrUt zklcBd#yuo^rR85Xl@Aft_1V#ch;|Kg&_iYo-WnGz9stdgNQX}=xh#3ubOfSxUr706 z=;iNhbm--mpQb3_OE4aR-1w>XoXWtZG}bJwNy5J3A7}m{0!sYD6&G91p8qD6u(rEw^V=1nxm1t*iY9PR~mf@>4(>W=Gg6!n`+9IyE>m|=ZJB~$L z6Z+lZ0_EQL4(4g}n(0fzBB))ohz+HNNe@(2FZV?=f>3YZ2!e>*q*V%YN?Z*hIxZv? zp?N#(j>W%^=Nal}ymP56-8V+X>s!IaltN&)clB&_KMJ*h6}oqNl~#GHVQgv~iq@*w z!ylfY2b4rh0I&GAy)kD$>Mde~mQ2e{%Sk*QK*omn>O1rh8T}~}#^*%gxC2DbXDa%8rb77$k&_l7K$mB7@aB%c!h?V7U0We} zKK39HMB-`RZ^igCik41x@He$(8C6dFN8&=z8k%QLVzeEb&@FcZdlkX)h!^_7B`RnT zVUdU^C18MflYPwq$856KalUe8w7UhAjV_mhDYdM5|MYRMP(5S+vhroq~0U&syRyWN3TK)K1_k95)A|R zZE%77>sFQCx!%8Cx^;7%;Rhy08^!LaGX_`SW^`Xe?!MNLb*5 zuk!Wq7tG~eL`xeWq=7aADbeZv-nXj4;paVAf)5yzd+`Fb!v`m%&XBw|I#f(V(3@~p zKvKAvOR>Ar1SJ%Jszx*=@NVS^Jw53MkO9B>T23d*Oz&?ffiv+Y<0IDS^(kvKw3;n& zuQh8s&Ud2Iv=F>U#Z3MXGi1$m6LCdH3#{XUH}p^&Tcghwd=OyD!uy?hCRYT<2L*5W zmD)lsx&oG49U*`;3%)!nL>Uqo4~N7&STZsdPP{ndx{N9cEJm>+w(=f$uNh?(#TUQ`om5nptLjlzL8qLrsgnFxB?TMHC{T&R0_q~FxQ*eR+d0eG8szLS#W7=Sru zt!2=#%Aa!CQkY?@M}aG)C4F$JM-K?+|~ zcb?D@N(qY7l|_tN-o5MIkgN_&z7E9X7(tjbEEa|63Kyc8NmsI`;XA7Gi0-*q? zYU=Iv>u+wG((FB7jVK%M(*fU*B>5|q)PU@mb$;l~!V#PZu-AyLppO=VCh8#BKC_?v zLX%@YGHS{zwO*TQ&T_UY6%)D9dfE3^Y~Ylzl1oGGD({#P7$j#0 z>H}a%UeNx*A!y$`-@>{6v(RC7($AQmVQz)}!&P3G65Xw+fyG2A z?E3`&_D)m>QQs1$cWSpCA-zoC8C^2&lOzu%-Ur*sKee$qB73w$HAE=!@42zA&tuN0 ztLO7^l!>}ME5e`qs~Ijuzd{DNp2&k0_7^B52n4f)y($QB4)}ciqRqMlY^$!nUiUS4tdKPR%rmh^ z{#B-B$_`-}-?D}(wpp6o5X(^p^%f%`8@hf&DS%5wWYRMkc+iT9YX4;uCqJrO)E^U* zl$4NETP{19klSXi8=(M~(8V7mk+qE!4~p99gxMhfB%i}WZmTS7$pD@I!0Q;*tu8xdEvx}NWc$6!*ZIhTSI-qYIqZW!EroQj`?{>Qx^WTXrEiT6 zj4?Ir!0YKh<&D?^vcZE=$h!O>YF3R()BXq+#qb49Xg6s099akXQL+mD@y;8-ri7eC zw+dCAwMl!#lAQZiO2e26;Tu63(O>B|@c!}lq6cLvQNjbz%)Kk4?MIOzZb5g~)O?|! z!;;(p*HGZ=k;CkyE_bbWtDPXIPtc>W;?+Cw4_#FuV z83tZh7^Ts~T4m0l4vL<_#8*{4Wal&I$}~nUmyC8(J12j6fWbLm!zpu#HX=>ZD&UFO z@yTm-p~=1E z9GF^I@>vo=M9V7s8)Z7zSr{-UpZ_`>&UE;y_ifP21^4+3x7V&X z-5VC$->=)R8-JYgRg(@YF9}e+;%8>wzYKajD4O^(&v$Q54Dw$jtbV*y%^^T)4QKB^4<8|u ziF|_$-mCJ*m)}1ZWBvHqBH0u`>%*1FK%EnIY3;M#;m~RkHU58z>{dN8WNSp-XQYC+ z1_Em>f9_5N*spuDfjIFw1ACl@sg64}#{x<8fGupV?|j#bVOcO!p_PD5VAV@g2b$Bvrp3i5q6riI_VUOUC zI@F*T5oNfh5?Z2a4KnkbgL!&Le33-m#-8@$x-;rcJV^;qW3dEI`sf!jAk6D16Ty3G zfPwCN3pz*{0$jOYv0`~88N%!W8%TAO5rTZnq?I|^WXz3SBB9rJ`3HxpzhU0z?+mhh zM6J(y8UJ?u8nVyk56fF~SyDObqbCRc@RrK8A~vBw0wQzi)8EMKln{KIbG*X?N#Ku= z+V>K=C1X^~+*7HLL&C+8EuB6dd})Q0=sOWfUs%S9=0j@}SU%sr(56DWiDE483jrVf z3?N8Rk7_WWpRJm(n0tYfy<7()E7b1yY=?P^+%IUlRL7%q^Ya7AGn1GI3 z-}TVOwc`{CpBxj5z86d#EI9osM2EwRU4HbKS~0%K-msyzB;Kc|mu+2~!kU z4u4rVe_$%4sju}YM*%3U5a9okN-vZWLW%Rz(As+@goPG zs#5rwr@8-HbdsbP$XNhmJ>qKTUW;mL-xexzI)^GQ$YX%LSHFTS*%;RjHN3tokPu_J z=nHGZ?or~J**-e`A&5Y(($LVD{3O!3i~9dO$b?u>Lt33zG12LzWq?hU>N@_^YDla> z{f?)_5w5>A%_EPA2PCx9FhT1g-wom4FO{B*XU|s`d$G5Ypg^$|aEy~uiua{&?9{D% z7u9HF`Yha%{Jl(o2?ap#Zmua>z3XT7Ewwa%5z28OV79T0*(eN!!mUIg`?3a{$X)DC~p#K70`9b;*;;s0K>c}oP z$bm{w!B-YBJe?H1L3=wFDFMlQ{HjS3Us={V^y48#P(v?}zfuaN^#;?G@;5P4Ogjn> z(KWJ2@gG)2@(%v~HF5{vEMfr3EpyKQ5-SM8gq_tt0%0!d*xH#B*^3{x44&l`L+cb+ z)vR!;VNhT=`ZoLCeK*-KTV?5=A-8<4m&rG5t$E?Gu`CUJi_nv5dd*jZaU2U2W#=F1 zP={T=={fYeg0jlOR3FE&YICK)f&I+C=LqZD9j)+EzrQ6am4xXunA2LIJJ0rZ6Zc>J z+OEzQ$r8f;p6=_wp3UcN&Di_=MCrmw8{)UTA2JeEK2T2Afp4Arn%N5{lAnnZeq3A= zzIeaAIj9&fq83^W`I_JeaM?On@SJT95KAq^)2BqnIJ9TTP?jhT^y31|fk~o$y(-2} z!PVzeBjBbE(n214Z!l1+G~=F|ZNvSzyrB2Vj&KbF*8J281QihH0h6a$^?z+Z-UXx+Z$3|;3h?e zZfRE2=ctsT0+viCOvy48$scBreO@Oq^VuK?Jou46sa+sx&J1)!u>4cl+mW8Bsg9^b zHk`sJPA@j@=y`3qSN5kBx-xgJ9P%I_x;-IYoq3Q=@)xQ!~zH~|G;f>Xic`fPpDF5ofc7tSP501UgzY_5=-lW1YU)niQ}! zdwxr}k!T|dfxF;QW&CLe^Bin%nNJ0f0in!!{~*AWAG6N}rXD}i0p;(;_9?gk@0a>~ z>G+aI>}-70Z@qkHg2=7G_f`#T=~Kf_-)M4*&IT3QD*omAz4YFE%gDg-Mr>?iEKvB; z2RAU^YnrC6Vpsjh0rRjWcz1puF{f^!-`Es2sxs}1#vTQ+Zsk-q zy@p~5qS#TtGQ*a!hfkJmyo3{-cto=02na6#0ME zCkY1Xch1k|+r?9QwMU7%Na_r}&;O@~_(oa@EC}scfAxIwWxB;&+?Dc%i8?h+McMxJ zhBY5aCHvoq*DwRalT?PJgja$B-*12UQDK`u`LLetjNW+rT>W%u|DrCq9KfE*QY#Z| zIMXh##_&gyEti~zM0cmVu8dlpjBqp)r0UcvA{HnHQZ2mKKKMTdTx@;ai=F^rOr~~= z)sH}HiqBK!3p4(B0-YQ%V!#VG`L@Z70-^b8Lhzqq3NS>Z=(O2Uv&Pvlkmlq}Yq-9q* zgWei23jr$ixQ&C^dL!NpUCF^Q0Y;?M2|Bdb*e72GU3I<5fgq02ie88Cm(`Ct21nnU z+8B|tNM!E@8=6S?1@x`TUR!qrP1a%VyJiV3D75mYEfKxKP$h#$OO(kjH|uRI?B)E(Q-$GCwl|Z4@8pTO zlBLWSQ@1E|UxBlZRPYaUTh zIWthocjuAM`xKs8PL1|9iyM8DvF~iX{i|T4pdda?g8y)6QaNv1#xWCB*KRVvCE4Oj z^}P3`{vba{r;xH9*Lluby%|ur?qR3l{v5y2+H+3leK<_u#lvpeG<<@%>Lli;)0`$A z_oY1sm_qsp&`3Zovbx{PWuRomVv&Q6^mMXQ9^-H%wT;847&b`(zgchatGJMQSEewI z??r|WecQE-bOY;NotRlpEmL3?2m9uNnoHy^EFERX6zmQOy-XKk4*B-4`#t7j)mLEM zezZ{&hJOeC{4sg9r~FKffedbJZ0bj8&;tv6^lbG4;!60$tm1iCbpZ3TtAwvnlZIGh zln{OI;NY)c5A*&Wd~}$%MPj|kmK49FZJVy~l{He`>T34&5)kB})m4)*C9DV5e4a)R zQE125_i?56_0i?;X)*I{etKC4pd+VVjjw&Koa$vajHo{2#>4;G)H^avOiKADStMA| z=g_NcY_EI$P8f~Nf+Av)4WGLFhcmDV;@x%Iy1xze{z6Y^H|uy_abHyT&1n^!W@dxo zmHF3V&$X2<&(`kD9>G3=PtxNN8s|@`=s+{BpjMM!r}>5BccU^el7=&_ z4fm>vf8oPNYHH6S_7LSl&~iTA9185ye?Mg?pmy43CNPw>eX7&i6PWZv9Z6NXm@^)B_>u@`iwg~@T4E|Q`dahiQ;@uPuRQqH#pW<^2_nITK+w%j1Lu_ z3YjFyVldQ;%Tni+`Zr}1e|_{)Iu<+_0TwSDFTawKg6nh!)ylE#nEuiUvmsbR!NmJDLX>;5X_-%Kw6q#hxqmW#e+@RF__=|q_hu9%lQHPYcv&Aiy1-4t*TBe_3&9~Tw!bd^U&d&1(v@eU*~ zRG{}yf^g`>{C95S-yOGTjaLA+ba}5hK>;Z#GGh0Yn34?zOh%ixJy)VF6$&0#_L6-< zBBJ&qS~Mi66E*Z-vOECvR=H^tCKGLwY78q86b@?+BJGwJ%jvjhaJIJ4tL9PnyikUG z;|ZJS&t5g#FHfTPXqrAt?+$9)a6aVN`6F|4lJ#fsE_8z&dmTFcE(wnvQK&b7Sf@9! zV;_-k`Iw3sA9PLR`}Y$(Q*>~ntr4Umy>oNW%B(yn>qISbZ&#fuslg}h^(4OJTtOC{ zI>_W@ATl*G`Db#BKCWIMpG(79rF}wno|AAW9iRhG44-~B8E4NUX#*Loj8f*eVG5bY zc0X=Nh0|K98P3?N>015SU1;LkFm=`Z)KgVDw%;V0n3e#RPJ8y3T%{&>rpB~y&&Aah z4t$f4#`AG!BR}-F+AEO14>8QoFQ#_f`16ngdwDT!2n9lPwm-nMQ_&lj+KwvgBq?@vOacQkz`B? z7RPx1>hm8X3yXjqM)Cu$&mHGeYk>pzRqlqMxF;E&>CkLDPQ^EyO2UE#v_Wx(+Von` z%?AbO{}vgcAUsxmxvK-?3&Jp>mq+Kqn;ss`ib{ap@4ILt+n0h({2oo&d)YkSXd4@I z;2Niw%ysQ*__OtlL`iu)?A=cs@T}iqvHEV!I+QdyU(%N9m04sd-;f^6j1C_FrloB- z<>=O(rn_DwmUm={Ws$`C<84{@-R_; zH#JsFQbHK|t(M1)c`7u(D>IoESWq*k2cFP6OM_oFgW!q7;n>2 zyS;D@Pbyjb(?UbrUsYOPT3U%r&D&j73=lj$Cd17WZxq7F_saVML1G}lo~D? zB+R<|;%RKvvk2Il=ZN6UUeFS+vKxf1tO-Pj6Fl({tPERU=N-Bj?CsahOW1auFoft9J$Bpo9Q<u4(B2R$&qHRXuMF)<06fur#&;gs2Pp83P=4U zVEdSVKIdc}cs|V?0>v9>5EMna(&ne=5gS`x6%@1Arefk{u=xQrW)?li9lBzjX;*FR z1r=rdO_76Ajrn(v@OA&0^|}c&lVion;@tw6_Cu406S>sJ=H@@1Wf3Ek7}gt@WPMZ@j@dv=|s~(B*vE`?TSo>>8SHaVD196Ia$F9 z$mPAvOx4VLB2^;#w(eu&Npi){mgSM2t!IZQC`wVESL~Jly|2(DSV%ake(`L*c&+~a zW?ro#d;Eu6N_GO_e6ad>eL{mGAXn8uC$GXaUVC%UbFLO<*+=+c@~r5YW$ruOhVm05 zp1QTXFBZq-qriE@`^`Rp7fHL)b-%O(sqjq;jIYs9UI!5yes3)UWyj!^_ZU@5Ro3y9 z%yt{dJUM{ul+8gqqrD?HpY3j_UI>0tnD|je!BP|a>(?L!EQ_(ywxjbtp(;}1JIU4? zzu}}xij*D`-i1Md~W46d^?!#-n-r3oQrW`ItD-6F=V#$e~+s z7Nz6wY*O#oW*O**fbeE{)34WYBU96&b}>#-U;eeMKFN^$km~Fre_+Eq$fR`d22ps1 zND>mHk-qR@rIJEK^`?xk{ZTFiH-5qQIe*lBrj=2i7AaKT5(#Q5APwr!-5TjKh+6i# zqBFhpI`LLUJB(+UoJVX;Dwe}<9XLnqWqEOPKl{5-c=;2L7i@d zdrX8lB>}lPVoBOJ7INa#&jfX&56~{Q$4wQ*SGLZ)4whFiSG!&%vO`dMzo=g zRK&i2E&OLA$oMvc_c2B}sAKyq_#POhzp|M2%lt9^KgOE>5 zSn@U54W}_W1ldrSY9cjYHS&4SQUWrwo=O$Ra?M$|bD(St7VxOX4ZL?bELqt27&|gJ zuWpEZds{zfTMZlPK_py>9IzWKG7}pg8=INAs*`&vwj~F=0mpl%gX;%~*(UB4Petyp z%nM(?r>&PvrTX*=QE<{~tx5e<`$SftMK&s3f4`dbgZ2I$&jzXO3Gcgc#KdFUUG!{f zOis?RHMiSIgD)6!2+%Ju1NT8^Kx)Gb%q|kH@MHPY9JweS2K7|Mm6z^kRk*S`MBwA` z6CbB(rsY@C2||@u>Bp_wXV7lx&Q4fE0}N}EDNV}#wrcI?nw`6bWo|=v87P%vs0@x_ zkm9TZ1N68S<>e;}m1iKLg@V`MN!%z1eBMhuZEJqR5;cd8ekB>78{B(=K9(cJ*mhHW zT;ja*bO9tGUMEpk+sr0n2&sb`5W}4Sc_zv<@M~s2gdGV4Ywl1$(FbDyFmWRPVXACc zDWrA+uQUGi;>HhRnzy~<i>8){Bg!THG=-V2}QTipe+EBg1?^HPVx2faNlx zTMaO1Uy-+o2hPC`L^~|cRt{sb{g601qkq90u9JffNA9F0wM7zOT1%&hT2VN##Lvf| zTCSAi2jI(#?qGYl=;>n2Xfg>x#d5uSP$lUiPzJH+AM zxXkWfG!?H-(u*US@>Dtvpd(R~voz`?f5@sKB@N&-dY#?cT-1r3z9CJ%W z6~e2fEQW~%Q?UX5%1@Kbu9^&A7;Po8XBBO!{sA4}q1(d(+SfjO*ZRqbX z?9`w7EX;s^28ctWN2w~06M-g=^haqOr`5uN zKd%059_|-j8U_zjL->RqG>_-yENq7F2>9SNJrr3a-$5YNUTSuakW})`$9Nfal@$%o zZ6$r*fl1Ki7ep`eN^!;g=BHrG#^p=8*~i;I2qa+BS4|Y2^qDhlWguhm4M%ebioLfk z;cf0-cF+vs4_Pnv%BKuBoJ$%!u@cM9@u0Gu4%AD>U4(ovwq6Mz`kk)|3FPEUdfbvI zzZminL^cF_e+bUr!jY}-w7jz2ZTg~J)I@Zwo zCdzMOZAySVUGx!DRvh>S1p{yG^rbF&gccy4dW-F@VN+5ul8QkYp6 z^X(yXKbO!Crze0i$48UUprXNs${WNt_pHdUgL}S)AmEKB(+0ucR4(BA72A*gM)zGV z#Q`UO>ld6i9d`zG?UB$ie;_{$IP*Zz@O3{yDw0tqs4w-n8S4Ayd**XiKDY(!9Rzb6 zU%3hFBd$~7cU$usH-w?jkr{1afITJ3oV=bMU1`fV3`m|kst=!ek0Ds4Bmj(F3#Mrd#H`ClodVl+8ehm#R?6iz~xU-~?s{yRzU zMmSFLss@)|Qhe{xkBs51hq>+=QLK%&uAaRqcB-c8F7`^mF^5tCF*wmEvB8!XC3PUS zgj)%*-TT}P2G(#fQQ6u3zSbiz7|(q)2njyKeP?G62dEIn{{SwE!Uxf2h)pC$2YQf; zeh+F}jKr@C(ERD&=JEWRAPJ1C*}BE4y$kX6Rr4N0KnVkLnh5=p=#|jM6^~ zFWew<^JO{?w;!j_#C(nhfW!H+8-gFU_Sa(4eVqhCU^ykFaLio=GMkIQ=+B`5r^dZx z6%gL)74P*xu2B|7k?(MI7F)RY+&M&JXZ&;eNS~p1E)s+rW^4E0CjLusZ#6GPLUQn4 zBoYsEE9RjW!=e;5AEpkw+)z9oG0}AS@{l5b410Ha9_5XC=c?UWu1pbuR03dpB8={g z6cAA|A;fVw{wc&z&MyL>sATAHC371q_qIGN*)d@7TnDCZCOi|fgTy2&a}gqoRic=- zf@A&L@>uAJhr}I$*An~E1UR-o(>?N(pH2b~Xby`BKnVHO$dy=D7-&g|rP?Omktirp zKZ1S_+=wItI1_$c1!MWI-B@QD9d?|)^w0WN=6v5dW+^W4`Iq}uazodV8XfCj!=waE zAz1xrkHc}E_?;w-8hEX?wu-Y3xWsGsV)wi5Ucg({<5_joHmd%12ymn3OcS~8w))FR zmBAGt5e?U z#oEmPMWz8mRP-YWeo&=zUrsZMHZT?q!zRyif9Y5lj5y5n+O5#;6ofI5f z!4*!Y{Oo8-iw!lvh|`#)Ptq;%F^UDobvr+FS(l$M5e!vT)0bLSOoimISqJ;@hD9$T zOpm*e%;)m*{TY{!Dfthe$uD0-tB1cPL@I=Wx$nS6{sFm2V5lzPd2jCCc6N4hX9{Lq=We_zfISbCP;twC}VDMxO1kPd;Y3K+i`a|{-;Mt_5p zhP6FtF_d3~u!PK(kWz!HKl=3HxqP4VQf?z3pubq?L{p+Z%5!gP{WN<&;sU;9P93R? z+CQz@eqX>N7l7aRE>mq@3u(W2dc(HeadD`DVWAe=w0YP)p94qckNF|5qy~FN?>wH5 zv_!2D9OUkWyjXBGiZlfRuIqoZ9Di|~aXhR-NPyvvZbQP5*O`&M1Y9xJ7R0JLC~@k7 z^NcCHK|kMhY}ip8nQfI6fKZ;}TyONvza1}_etC+bw5E%3;C$okvqMln3aIjJ_Hmq> zCQ1Vs#u>y-=jqqSr|gb^&aq9}I~>CFe!%Vm^zsvrAqpD?6q#zCQq(DDI|4=|r3q2U z+Y3%t+;Gf8HSN8jZ5tKHhvsY6^sO5%81Ty>&+e8K`HjA;!<=iLQ%f8by3<|2Q=eks zQh6w&5Ojq0ElBr#oD{gMdF-300Y)UUshkC3kHQmNSOAod7J$X`UqDh0U%lIux^%xA zf~jeX&!4UK;)Q4}YVpb}Z@KQkT+(h;EHnA(`RW1}A*(u=ko1Ke1OX-uER>dAlJ|{X zJ2@!Q)t|Dm`@5DM7Q**7q3-I=7Q{Ojj?9E25`CckeaY8Ycis*FXw(8QTxlaRbLowa z@6J4?U%7gWE>jGM3m}u9IMVeUJm8`zy=N#3I+M20Duw9 zT)2MqZTd;)d9(3S-1^`<+`*H}GbgyfWY&W%SQ98pleO|t3@C#I>g6Cl%P9Lv;7vPu z;bjMaj_}7LW$k2rJ1)NXDe%|}Ft)Ds)9Q{AW{$xC2lwtr#A|vG=QL4v0}Th$=cdu6=FxPA+dG*)BcaA#z2P1{?kOzQl)c?M zOHZV`Sh6a;D6T?@%VXVuZxTH-AQ|#}X$EF#@LJC!SXAVD2SO(1u=wuFUh5@uEQp_r zoPgnFPS@mbjr_3FX3iV$g;p~69Pb3`e9IydG9aCS^de~&tS!KT1aCJU+{)1u-PC;W$R|$Jq>r za>qrh#a#>B&&p~^R0~K`qh!*aJqS&UD2RE|))tm%9%^K;Vid{udp;{*r()+W6Y0;@ zZ|;K`Z&Ev~XS|vNEKlXe*018fL+-0#v~H|&gOMnr16Ne2Q5)vnt%cZGyJ||5wqER5 z_&9|`09Cd8qKTI_x*>*f!L)utMQT6B6-WjaqI=jn$h+omzr}{O$Q%~Hcggam#OOhG z?3i@<=J`WLYf17eN@J7=!q(aOBN*C!5c0}p<2d^`nSag~a`w%53Atl65V@tzNNm{-zO}X%E`&xs3`VVO$Jg&GUxZ5vuK5U~7&u z3C-NEeYGV*j$Anhpk$CqLW%A`d#?lWHaPYaR>kS{i z7h4GbpO|lK0?s(9G3Fxf>>y%KkXzV}hj#%@h+GN-rac*ndT(u>{?+oskIAczPln4( zFV<9~DDq7FPCk=P&|uPG=~~G6Oo1-SZ{~`<>FCfGOr62no(zACiBam9MWdK|OX&PP zZw@OnrwbbG?qKJS+v1z5w7>Nf5%U#kP%Yh*X7Xg#|6W6kY9a`1V@b(Z*P${icrtKL zhM)Z{ZdzIH`KIGv)_mvhuYK;Lx8saK)Z15&f1UQUXY8C7bQxodE@nA`$1YWIJZb;~ z*kJ-OB0lVn7!hh1qcuz@jAm(tVCG@nlzT=M_zNgdp9qV`pC1ga|LU?2YI4SM*uByO3GDZpJhaGtaJNbjF@XE+3SGU6DF*Du@*QtCa0kxY zkS$_EId%wH0E1g6hd*{ZymHqZ6(6nQnBh!)qt)5Bx^b871CGmLd%wBlbX%#I@?UH{ zGNdY?%jpgedrO{rjrC86wJR>p>UcBh(3xv30mvvPR0o+^ahg4p!c^A$!ljCiW~}5aMNG; z#M}p+>^n1jl~Z4Gt(!LYZ4ZF7C~#`ui=i_>%d#kAmPH3yw2iSG-E3f`d)Yn zs`RORJH08k$KXU)cM+6;cZag#9<&Nne>(`d0UdI8`6@6*d_C@MgjVASVH1>L zxexjxQ=Dr1JBw%|cTQQ>@n zV26Z9XL}*dQNP~GG(ykw#LH{83J;Vc)IhU2vef=aFtuTF zD+=NdO2ksPtdS1Tp|{r$r=&TFt))v+XIA-wm_eYe8uf~gCQrZGp$oa43yFtzPMedS zLfDy(2JJpwbqiynAczi=)G#^n{LJtlYvQ_WHy#&l~SI>3`60Op#m7D_b~+G9XAqArR2i zNm4ByhQHS3Wj^=W&go-R@>@YZt%5timMKalTDu^4oIzM3Xshg_-#Sgf_F>Ebw|koe z&si3EaiF0%KsDUlcrfTB%y-tvTWIA)C}92Xl|%2>$?6lM;g@s7><)Yj4VnbS{)s_) z*L_DqS#CuiN`J6q-u^>rs#X8c6D_irzo84f$){nZWr+Z$b=4p!t8~epaQ*&0BP>yV z0I0fHOgzS5mg`pV_8+5r@~AQchlWj1MvK|4fyZt5+bf1J8!8y6e z{uMq$7wmYLmqVM?`0PcHfk&!=^J+2zRK3PjOCZYnDf28)p{s}Pz|UUmJKmH&i_;u=gg#dGXX(in z`Jv6A3`7Ip#l@vJ3t;s069~+i`SC-6MMZ_?MJ;gm#D@*rT+423_S*Lce<&dI(+o@;D{R~Tk1Ayn;0cN_%}V6y5UHj z_IAy>vwichYt5^rWQ~g0s}zGur#rg(T$j%uSoE?*n-I5okD4RshWC1E%}YV>pES^D zGuyj+(<_QCwMk*BR*3vZ=4S=VyN8~dva`Rfe;i!%0yfM#70KFb+Ma?Lx+;&1X*YFW zG%ch?u=nH?d{j_4oMN;H#}yP7$X^zh;QcMgcEBiT$pQ>>USw zFK<|5Em2Ya=ZujOa;2CTgpJKLa-XeL$aE;{I>ezH**PO^f|;E&2MPINLWCpnbSr-q z`lk)vQatlZH<=09NbHCz3$GNhEeQBg8C%lJtyHd^b31LZbi$nv^rD|jG^GCS=L1kF zc*Aob|Eh`Q$vpaSe9b! z#57n;eJ)@h|Mh{b<@H~t&u!eiziJ(pF**DJx@&yJ#iYDXixqB0%!y_u##320!eae0 zL=4s4Sh|uA*ed*`5KH9sBE-=Si*#trBt{{@XTHiWm^M6aSG6+nEn~?5!>&@ur6R7_ z<&IvD)g0f&F~dz*I2fA*_+WqAAZdcBb8>T8PG5Z&Waf9IvHa)(&)yX6u&>cNWDCAr zEkm}}>Elj*U5=UW6s@#ye`aha(-PkT4Hc^%0q{<7Kj1Tn5OlFM@i<8YQ}OJf-D@vJ zp-v!lLtZW6Pa?0p*U>pFL1&rKO9BR~eK$!J#Pj4Gp)K`Bw)aJI|MOw3pJF;h;KF!p z%8zEZ4s>#^ocyJdYVlm?>X55JCP~h_a!FwlU!Esk-BD0kpXyOBcX_uO57iZ!Y$VFjj)|s1uOU*KGivQ2~sfS(I>_X{6qL2+kC0P()7xU!<~`K(K@mg`yLhF$(0`}1UFe(D7`e9# z6_VQb`h6FZCF?d{Z5|b-8`t^^{@`{vaLL4l9C^q>BC)yzbFFE@@mn^2ULGy#~a z9zmu4N|WcPiuQMvXFy$t{LUjZ%`3TvI>J~LefLhE+UQ;}{)L54+tVAoE?Q{E?hy`^ z%j?8?5?aD$UPU)fkj#@JalzlXUf}a}G%pf{08#=KPR#s^20oBL6KxM=^(pw`ZxIE2 z;Y*9;yTmQn*!oIzf%05ylC?@3Ubr;Nn7jQOIH!w?%F$a-mQLL43ksGCx?0)))n3fA zHMHe%q|34emm(iyK}KTUQvtDFPARchIc>_2om*zmefAuxtrCD$KB$)9FG{ZdF^8Lc z*IYV9g_o(q@ugfelZ`JFfY+B_kwmP*DKS6%tN2YW`w1%pK)>@WbJ96P&%Y`~cs|}= zJkEo?d_bB6RL#3q!Gh8s*#7k2Otj#J8*q77%Dj4duIP6zd#<342ga56rj~$6sL7vy0I3Qy5TL_#{F4B&m_e1Gv96QnP5y-i! zbDjObAX^SM^AmFZDU$bJfaG?%fTqSfiITw;Uno>b41ve(r{=krLJhXI>o^!3Q0dqs zqI8Y@1ispuv;2IS$Xno|_C4_L%EIyZ)<-Vv_SX1c`P+dn_d8D7CVID6I8$)v;)={K z%}MismuJc!(=bc&_22W#vQrW*SB`GMf?ghg&;^zhalh;hKzDtNTniVVmHSr|bPSY8 z1*@fDnSJwr>+ZscDvm5(*RR`kd-`Z7t zVpb{hk0u6&XTKR=rASf8LG09kM*CD(#<5tn_h!z^vxeP7l*&IP9h81%Se~2C9-kNR zUSw9jhhS|4s{e5dfCj)*RLHp~lVvqoUBLFYw)VT7=|5E4Hz%8L-!GP*>Y09BH78hb z4sj(f@45U|qx;{^)~lVE!0_=R_YI@Fs`WSQIGq2@y>!WI=bnB0_E=0k^0Q#Fj`shI zm+Gu?|JO`VWjr9bfGfdg>VAzkr^FBJRaUzfBy4-~^qw!1li2s}Uo%0Iu|qOq0gFWN zsn*UjHwEV};I^Neq_A1afif_Y$(CF8i@dck4q8R$WGcYh2dAc};crMdl%9LTWGsNk+esqd2gU6?k)3J}1 zPIndCui+u+AokDl+@9|6dP(JCCWl$uBV$i%URwJ6_BmtTgwpm-vGfC{?ELCZ$V3V^ z7&M%lz9!edQ=>n+p))3mS;f_UTddAInMXo11Qm*zIxh8v-Hi>a`C}8za56))mtp6p z+r=?VCPF<83@20l_ii#v?KY@yiexzLwYp(vub1ref4y9b6&Pf#&RISP)t>#ig;`jK zqhYFl*(9xs9e-9aS$7n^xqQMvib;U0WuO20zqboZDnqJY=dIhkYhlvKZO4u;7dtJT zxAaw~CqqYIVhBqD$HF`ILeA-j7B6=0vRW^mz3F7oj31JUZr%)Bo(z14y3#JO_C2rP z@`H(`WAT(`d50w@p7vj>Kk`F}rDOM_-3~uGR{V4C)pu&hYuQpSvDCimk0*z~;y3#R q{^_td)F>)2@~{gXC>YMv@&Am^jEs&6B%Kds00K`}KbLh*2~7Z5 Date: Tue, 5 Aug 2014 14:02:57 -0700 Subject: [PATCH 36/92] visual tests for patterns + svg - refs #1010 --- ...tterns-svg-200-200-1.0-grid-reference.json | 58 ++++++++++ ...patterns-svg-200-200-1.0-agg-reference.png | Bin 0 -> 7986 bytes ...tterns-svg-200-200-1.0-cairo-reference.png | Bin 0 -> 8015 bytes ...patterns-svg-200-200-2.0-agg-reference.png | Bin 0 -> 10689 bytes ...tterns-svg-200-200-2.0-cairo-reference.png | Bin 0 -> 10955 bytes ...metry-transform-translate-patterns-svg.xml | 106 ++++++++++++++++++ tests/visual_tests/test.py | 1 + 7 files changed, 165 insertions(+) create mode 100644 tests/visual_tests/grids/geometry-transform-translate-patterns-svg-200-200-1.0-grid-reference.json create mode 100644 tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-1.0-agg-reference.png create mode 100644 tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-1.0-cairo-reference.png create mode 100644 tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-2.0-agg-reference.png create mode 100644 tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-2.0-cairo-reference.png create mode 100644 tests/visual_tests/styles/geometry-transform-translate-patterns-svg.xml diff --git a/tests/visual_tests/grids/geometry-transform-translate-patterns-svg-200-200-1.0-grid-reference.json b/tests/visual_tests/grids/geometry-transform-translate-patterns-svg-200-200-1.0-grid-reference.json new file mode 100644 index 000000000..6af61731c --- /dev/null +++ b/tests/visual_tests/grids/geometry-transform-translate-patterns-svg-200-200-1.0-grid-reference.json @@ -0,0 +1,58 @@ +{ + "keys": [ + "" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-1.0-agg-reference.png b/tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-1.0-agg-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..7400aa8da3558471c4143e1a4424f75b356a3258 GIT binary patch literal 7986 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 RcNhQw002ovPDHLkV1g2_x!eE% literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-2.0-agg-reference.png b/tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-2.0-agg-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..21b651bf1179d8892bc1ec7e5800dfebff2e8a4c GIT binary patch literal 10689 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 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-2.0-cairo-reference.png b/tests/visual_tests/images/geometry-transform-translate-patterns-svg-200-200-2.0-cairo-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..93d0ec519c881181533956e9db8f98274fd790c3 GIT binary patch literal 10955 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 literal 0 HcmV?d00001 diff --git a/tests/visual_tests/styles/geometry-transform-translate-patterns-svg.xml b/tests/visual_tests/styles/geometry-transform-translate-patterns-svg.xml new file mode 100644 index 000000000..633eb085a --- /dev/null +++ b/tests/visual_tests/styles/geometry-transform-translate-patterns-svg.xml @@ -0,0 +1,106 @@ + + + + + + + + polygon + + csv + +wkt +"POLYGON ((1 1, 4 1, 4 4, 1 4, 1 1), (2 2, 2 3, 3 3, 3 2, 2 2))" + + + + + + line + + csv + +wkt +"LINESTRING (0.5 0.5, 4.5 4.5)" + + + + + + point + + csv + +wkt +"POINT (1 4)" + + + + + + + + + + frame + + csv + +x,y +0,0 +5,0 +0,5 +5,5 + + + + + diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index d8f52f922..4e1324e53 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -109,6 +109,7 @@ files = { 'shield-on-line-spacing-eq-width': {'sizes':[(600,400)]}, 'geometry-transform-translate': {'sizes':[(200,200)]}, 'geometry-transform-translate-patterns': {'sizes':[(200,200)]}, + 'geometry-transform-translate-patterns-svg': {'sizes':[(200,200)]}, 'marker-svg-opacity':{}, 'marker-svg-opacity2':{}, 'marker-svg-empty-g-element':{}, From 7a013e8151dfc18f38b1aa1d48e2fd1c65b1d5ae Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 14:31:29 -0700 Subject: [PATCH 37/92] switch glyph_info cache to an unordered_map (but no perf diff on osx) --- include/mapnik/text/face.hpp | 5 +++-- src/text/face.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/include/mapnik/text/face.hpp b/include/mapnik/text/face.hpp index 7624aa290..0a4908ff0 100644 --- a/include/mapnik/text/face.hpp +++ b/include/mapnik/text/face.hpp @@ -36,7 +36,7 @@ extern "C" } //stl -#include +#include #include #include #include @@ -47,6 +47,7 @@ namespace mapnik class font_face : mapnik::noncopyable { public: + using glyph_info_cache_type = std::unordered_map; font_face(FT_Face face); std::string family_name() const @@ -75,7 +76,7 @@ public: private: FT_Face face_; - mutable std::map glyph_info_cache_; + mutable glyph_info_cache_type glyph_info_cache_; mutable double char_height_; }; using face_ptr = std::shared_ptr; diff --git a/src/text/face.cpp b/src/text/face.cpp index 11afd18cb..3f57bc89a 100644 --- a/src/text/face.cpp +++ b/src/text/face.cpp @@ -64,7 +64,7 @@ bool font_face::set_unscaled_character_sizes() bool font_face::glyph_dimensions(glyph_info & glyph) const { // Check if glyph is already in cache - std::map::const_iterator itr; + glyph_info_cache_type::const_iterator itr; itr = glyph_info_cache_.find(glyph.glyph_index); if (itr != glyph_info_cache_.end()) { glyph = itr->second; From d27b45553a2aa1f0dd6e2d7472e708f79a5a85a7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 15:19:37 -0700 Subject: [PATCH 38/92] use emplace/emplace_back over insert/push_back - refs #2336 --- include/mapnik/attribute_collector.hpp | 6 +++--- include/mapnik/feature.hpp | 4 ++-- .../renderer_common/process_group_symbolizer.hpp | 2 +- include/mapnik/symbolizer.hpp | 7 ++----- include/mapnik/util/geometry_to_wkb.hpp | 4 ++-- include/mapnik/xml_attribute_cast.hpp | 2 +- plugins/input/postgis/postgis_datasource.cpp | 2 +- plugins/input/python/python_datasource.cpp | 2 +- src/cairo/cairo_context.cpp | 3 +-- src/datasource_cache.cpp | 2 +- src/font_engine_freetype.cpp | 6 +++--- src/grid/grid.cpp | 4 ++-- src/load_map.cpp | 2 +- src/map.cpp | 4 ++-- src/mapped_memory_cache.cpp | 6 ++---- src/marker_cache.cpp | 12 ++++++------ src/text/face.cpp | 2 +- src/text/formatting/registry.cpp | 2 +- src/text/placements/registry.cpp | 2 +- src/xml_tree.cpp | 2 +- 20 files changed, 35 insertions(+), 41 deletions(-) diff --git a/include/mapnik/attribute_collector.hpp b/include/mapnik/attribute_collector.hpp index 16d397ca4..2e0eec6cf 100644 --- a/include/mapnik/attribute_collector.hpp +++ b/include/mapnik/attribute_collector.hpp @@ -56,7 +56,7 @@ struct expression_attributes : boost::static_visitor void operator() (attribute const& attr) const { - names_.insert(attr.name()); + names_.emplace(attr.name()); } template @@ -289,7 +289,7 @@ inline void group_attribute_collector::operator() (group_symbolizer const& sym) { std::string col_idx_name = col_name; boost::replace_all(col_idx_name, "%", col_idx_str); - names_.insert(col_idx_name); + names_.emplace(col_idx_name); } } } @@ -298,7 +298,7 @@ inline void group_attribute_collector::operator() (group_symbolizer const& sym) { // This is not an indexed column, or we are ignoring indexes. // Insert the name as is. - names_.insert(col_name); + names_.emplace(col_name); } } } diff --git a/include/mapnik/feature.hpp b/include/mapnik/feature.hpp index 10be7d64f..9547ba86b 100644 --- a/include/mapnik/feature.hpp +++ b/include/mapnik/feature.hpp @@ -67,13 +67,13 @@ public: inline size_type push(key_type const& name) { size_type index = mapping_.size(); - mapping_.insert(std::make_pair(name, index)); + mapping_.emplace(name, index); return index; } inline void add(key_type const& name, size_type index) { - mapping_.insert(std::make_pair(name, index)); + mapping_.emplace(name, index); } inline size_type size() const { return mapping_.size(); } diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index c4cc390d3..abf13dbfc 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -268,7 +268,7 @@ void render_group_symbolizer(group_symbolizer const& sym, *(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)); + matches.emplace_back(rule, sub_feature); // construct a bounding box around all symbolizers for the matched rule bound_box bounds; diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index 56a55e852..a84d7c7be 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -311,10 +311,7 @@ struct put_impl } 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))); + sym.properties.emplace(key, enumeration_wrapper(val)); } } }; @@ -331,7 +328,7 @@ struct put_impl } else { - sym.properties.insert(std::make_pair(key, val)); + sym.properties.emplace(key, val); } } }; diff --git a/include/mapnik/util/geometry_to_wkb.hpp b/include/mapnik/util/geometry_to_wkb.hpp index ff89bd721..53245aecb 100644 --- a/include/mapnik/util/geometry_to_wkb.hpp +++ b/include/mapnik/util/geometry_to_wkb.hpp @@ -196,13 +196,13 @@ wkb_buffer_ptr to_polygon_wkb( GeometryType const& g, wkbByteOrder byte_order) if (command == SEG_MOVETO) { rings.push_back(new linear_ring); // start new loop - rings.back().push_back(std::make_pair(x,y)); + rings.back().emplace_back(x,y); size += 4; // num_points size += 2 * 8; // point } else if (command == SEG_LINETO) { - rings.back().push_back(std::make_pair(x,y)); + rings.back().emplace_back(x,y); size += 2 * 8; // point } } diff --git a/include/mapnik/xml_attribute_cast.hpp b/include/mapnik/xml_attribute_cast.hpp index 9398b4ff8..2e4c666b1 100644 --- a/include/mapnik/xml_attribute_cast.hpp +++ b/include/mapnik/xml_attribute_cast.hpp @@ -194,7 +194,7 @@ struct do_xml_attribute_cast else { mapnik::expression_ptr expr = parse_expression(source); - tree.expr_cache_.insert(std::make_pair(source,expr)); + tree.expr_cache_.emplace(source,expr); return expr; } } diff --git a/plugins/input/postgis/postgis_datasource.cpp b/plugins/input/postgis/postgis_datasource.cpp index 9ca1756f0..5ce128af3 100644 --- a/plugins/input/postgis/postgis_datasource.cpp +++ b/plugins/input/postgis/postgis_datasource.cpp @@ -684,7 +684,7 @@ processor_context_ptr postgis_datasource::get_context(feature_style_context_map } else { - return ctx.insert(std::make_pair(ds_name,std::make_shared())).first->second; + return ctx.emplace(ds_name,std::make_shared()).first->second; } } diff --git a/plugins/input/python/python_datasource.cpp b/plugins/input/python/python_datasource.cpp index 4cd7813bd..dbc964e80 100644 --- a/plugins/input/python/python_datasource.cpp +++ b/plugins/input/python/python_datasource.cpp @@ -29,7 +29,7 @@ python_datasource::python_datasource(parameters const& params) { if((kv.first != "type") && (kv.first != "factory")) { - kwargs_.insert(std::make_pair(kv.first, *params.get(kv.first))); + kwargs_.emplace(kv.first, *params.get(kv.first)); } } diff --git a/src/cairo/cairo_context.cpp b/src/cairo/cairo_context.cpp index c0f5978f0..3a908ef8f 100644 --- a/src/cairo/cairo_context.cpp +++ b/src/cairo/cairo_context.cpp @@ -525,9 +525,8 @@ cairo_face_ptr cairo_face_manager::get_face(face_ptr face) else { entry = std::make_shared(font_engine_, face); - cache_.insert(std::make_pair(face, entry)); + cache_.emplace(face, entry); } - return entry; } diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp index 3c6b0c4e4..08af17caa 100644 --- a/src/datasource_cache.cpp +++ b/src/datasource_cache.cpp @@ -224,7 +224,7 @@ bool datasource_cache::register_datasource(std::string const& filename) } else { - if (plugins_.insert(std::make_pair(plugin->name(),plugin)).second) + if (plugins_.emplace(plugin->name(),plugin).second) { MAPNIK_LOG_DEBUG(datasource_cache) << "datasource_cache: Registered=" diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index da78888f0..87209f569 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -177,7 +177,7 @@ bool freetype_engine::register_font_impl(std::string const& file_name, FT_Librar // skip fonts with leading . in the name if (!boost::algorithm::starts_with(name,".")) { - name2file_.insert(std::make_pair(name, std::make_pair(i,file_name))); + name2file_.emplace(name,std::make_pair(i,file_name)); success = true; } } @@ -332,7 +332,7 @@ face_ptr freetype_engine::create_face(std::string const& family_name) std::fseek(file.get(), 0, SEEK_SET); std::unique_ptr buffer(new char[file_size]); std::fread(buffer.get(), file_size, 1, file.get()); - auto result = memory_fonts_.insert(std::make_pair(itr->second.second, std::make_pair(std::move(buffer),file_size))); + auto result = memory_fonts_.emplace(itr->second.second, std::make_pair(std::move(buffer),file_size)); FT_Error error = FT_New_Memory_Face (library_, reinterpret_cast(result.first->second.first.get()), static_cast(result.first->second.second), @@ -377,7 +377,7 @@ face_ptr face_manager::get_face(std::string const& name) face_ptr face = engine_.create_face(name); if (face) { - face_ptr_cache_.insert(make_pair(name,face)); + face_ptr_cache_.emplace(name,face); } return face; } diff --git a/src/grid/grid.cpp b/src/grid/grid.cpp index 96ead5719..208fe663e 100644 --- a/src/grid/grid.cpp +++ b/src/grid/grid.cpp @@ -127,7 +127,7 @@ void hit_grid::add_feature(mapnik::feature_impl const& feature) { // TODO - consider shortcutting f_keys if feature_id == lookup_value // create a mapping between the pixel id and the feature key - f_keys_.insert(std::make_pair(feature_id,lookup_value)); + f_keys_.emplace(feature_id,lookup_value); // if extra fields have been supplied, push them into grid memory if (!names_.empty()) { @@ -136,7 +136,7 @@ void hit_grid::add_feature(mapnik::feature_impl const& feature) // https://github.com/mapnik/mapnik/issues/1198 mapnik::feature_ptr feature2(mapnik::feature_factory::create(ctx_,feature_id)); feature2->set_data(feature.get_data()); - features_.insert(std::make_pair(lookup_value,feature2)); + features_.emplace(lookup_value,feature2); } } else diff --git a/src/load_map.cpp b/src/load_map.cpp index aa03500b8..5ae2c2349 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -501,7 +501,7 @@ void map_parser::parse_fontset(Map & map, xml_node const& node) // XXX Hack because map object isn't accessible by text_symbolizer // when it's parsed - fontsets_.insert(std::make_pair(name, fontset)); + fontsets_.emplace(name, fontset); map.insert_fontset(name, std::move(fontset)); } catch (config_error const& ex) diff --git a/src/map.cpp b/src/map.cpp index d3163f49f..227544c76 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -201,7 +201,7 @@ Map::const_style_iterator Map::end_styles() const bool Map::insert_style(std::string const& name,feature_type_style style) { - return styles_.insert(make_pair(name, std::move(style))).second; + return styles_.emplace(name, std::move(style)).second; } void Map::remove_style(std::string const& name) @@ -224,7 +224,7 @@ bool Map::insert_fontset(std::string const& name, font_set fontset) { throw mapnik::config_error("Fontset name must match the name used to reference it on the map"); } - return fontsets_.insert(make_pair(name, std::move(fontset))).second; + return fontsets_.emplace(name, std::move(fontset)).second; } boost::optional Map::find_fontset(std::string const& name) const diff --git a/src/mapped_memory_cache.cpp b/src/mapped_memory_cache.cpp index 96bce78ad..36b2aa8d0 100644 --- a/src/mapped_memory_cache.cpp +++ b/src/mapped_memory_cache.cpp @@ -48,7 +48,7 @@ bool mapped_memory_cache::insert(std::string const& uri, mapped_region_ptr mem) #ifdef MAPNIK_THREADSAFE mapnik::scoped_lock lock(mutex_); #endif - return cache_.insert(std::make_pair(uri,mem)).second; + return cache_.emplace(uri,mem).second; } boost::optional mapped_memory_cache::find(std::string const& uri, bool update_cache) @@ -71,12 +71,10 @@ boost::optional mapped_memory_cache::find(std::string const& { boost::interprocess::file_mapping mapping(uri.c_str(),boost::interprocess::read_only); mapped_region_ptr region(std::make_shared(mapping,boost::interprocess::read_only)); - result.reset(region); - if (update_cache) { - cache_.insert(std::make_pair(uri,*result)); + cache_.emplace(uri,*result); } return result; } diff --git a/src/marker_cache.cpp b/src/marker_cache.cpp index 6620efcc8..f64ae152e 100644 --- a/src/marker_cache.cpp +++ b/src/marker_cache.cpp @@ -61,7 +61,7 @@ marker_cache::marker_cache() boost::optional bitmap_data = boost::optional(std::make_shared(4,4)); (*bitmap_data)->set(0xff000000); marker_ptr mark = std::make_shared(bitmap_data); - marker_cache_.insert(std::make_pair("image://square",mark)); + marker_cache_.emplace("image://square",mark); } marker_cache::~marker_cache() {} @@ -103,7 +103,7 @@ bool marker_cache::insert_svg(std::string const& name, std::string const& svg_st iterator_type itr = svg_cache_.find(key); if (itr == svg_cache_.end()) { - return svg_cache_.insert(std::make_pair(key,svg_string)).second; + return svg_cache_.emplace(key,svg_string).second; } return false; } @@ -113,7 +113,7 @@ bool marker_cache::insert_marker(std::string const& uri, marker_ptr path) #ifdef MAPNIK_THREADSAFE mapnik::scoped_lock lock(mutex_); #endif - return marker_cache_.insert(std::make_pair(uri,path)).second; + return marker_cache_.emplace(uri,path).second; } boost::optional marker_cache::find(std::string const& uri, @@ -165,7 +165,7 @@ boost::optional marker_cache::find(std::string const& uri, result.reset(mark); if (update_cache) { - marker_cache_.insert(std::make_pair(uri,*result)); + marker_cache_.emplace(uri,*result); } } // otherwise assume file-based @@ -194,7 +194,7 @@ boost::optional marker_cache::find(std::string const& uri, result.reset(mark); if (update_cache) { - marker_cache_.insert(std::make_pair(uri,*result)); + marker_cache_.emplace(uri,*result); } } else @@ -218,7 +218,7 @@ boost::optional marker_cache::find(std::string const& uri, result.reset(mark); if (update_cache) { - marker_cache_.insert(std::make_pair(uri,*result)); + marker_cache_.emplace(uri,*result); } } else diff --git a/src/text/face.cpp b/src/text/face.cpp index 3f57bc89a..20d487317 100644 --- a/src/text/face.cpp +++ b/src/text/face.cpp @@ -94,7 +94,7 @@ bool font_face::glyph_dimensions(glyph_info & glyph) const glyph.unscaled_ymax = glyph_bbox.yMax; glyph.unscaled_advance = face_->glyph->advance.x; glyph.unscaled_line_height = face_->size->metrics.height; - glyph_info_cache_.insert(std::make_pair(glyph.glyph_index, glyph)); + glyph_info_cache_.emplace(glyph.glyph_index, glyph); return true; } diff --git a/src/text/formatting/registry.cpp b/src/text/formatting/registry.cpp index fe653e265..86ffb25fd 100644 --- a/src/text/formatting/registry.cpp +++ b/src/text/formatting/registry.cpp @@ -44,7 +44,7 @@ void registry::register_name(std::string const& name, from_xml_function_ptr ptr, if (overwrite) { map_[name] = ptr; } else { - map_.insert(make_pair(name, ptr)); + map_.emplace(name, ptr); } } diff --git a/src/text/placements/registry.cpp b/src/text/placements/registry.cpp index adbd662d7..95ebd1e88 100644 --- a/src/text/placements/registry.cpp +++ b/src/text/placements/registry.cpp @@ -42,7 +42,7 @@ void registry::register_name(std::string name, from_xml_function_ptr ptr, bool o if (overwrite) { map_[name] = ptr; } else { - map_.insert(make_pair(name, ptr)); + map_.emplace(name, ptr); } } diff --git a/src/xml_tree.cpp b/src/xml_tree.cpp index 1c7ee10b9..f2f79bb85 100644 --- a/src/xml_tree.cpp +++ b/src/xml_tree.cpp @@ -226,7 +226,7 @@ xml_node &xml_node::add_child(std::string && name, unsigned line, bool is_text) void xml_node::add_attribute(const char * name, const char * value) { - attributes_.insert(std::make_pair(name,xml_attribute(value))); + attributes_.emplace(name,xml_attribute(value)); } xml_node::attribute_map const& xml_node::get_attributes() const From ce8aee1994b192a854da6286a33942dd0c45d12f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 17:03:30 -0700 Subject: [PATCH 39/92] be explicit about copy needed to safely pass glyph_info into text_line - closes #2337 --- include/mapnik/text/harfbuzz_shaper.hpp | 2 +- include/mapnik/text/icu_shaper.hpp | 2 +- include/mapnik/text/text_line.hpp | 2 +- src/text/text_line.cpp | 4 ++-- 4 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/mapnik/text/harfbuzz_shaper.hpp b/include/mapnik/text/harfbuzz_shaper.hpp index 766019c27..4d0ab729f 100644 --- a/include/mapnik/text/harfbuzz_shaper.hpp +++ b/include/mapnik/text/harfbuzz_shaper.hpp @@ -113,7 +113,7 @@ static void shape_text(text_line & line, tmp.offset.set(positions[i].x_offset * tmp.scale_multiplier, positions[i].y_offset * tmp.scale_multiplier); width_map[glyphs[i].cluster] += tmp.advance(); - line.add_glyph(std::move(tmp), scale_factor); + line.add_glyph(tmp, scale_factor); } } line.update_max_char_height(face->get_char_height(size)); diff --git a/include/mapnik/text/icu_shaper.hpp b/include/mapnik/text/icu_shaper.hpp index b93c993f3..92df713e1 100644 --- a/include/mapnik/text/icu_shaper.hpp +++ b/include/mapnik/text/icu_shaper.hpp @@ -107,7 +107,7 @@ static void shape_text(text_line & line, face->glyph_dimensions(tmp); tmp.scale_multiplier = size / face->get_face()->units_per_EM; width_map[i] += tmp.advance(); - line.add_glyph(std::move(tmp), scale_factor); + line.add_glyph(tmp, scale_factor); ++i; } } diff --git a/include/mapnik/text/text_line.hpp b/include/mapnik/text/text_line.hpp index 96dd50b6b..36694bbee 100644 --- a/include/mapnik/text/text_line.hpp +++ b/include/mapnik/text/text_line.hpp @@ -43,7 +43,7 @@ public: text_line(unsigned first_char, unsigned last_char); // Append glyph. - void add_glyph(glyph_info && glyph, double scale_factor_); + void add_glyph(glyph_info const& glyph, double scale_factor_); // Preallocate memory. void reserve(glyph_vector::size_type length); diff --git a/src/text/text_line.cpp b/src/text/text_line.cpp index f6c82f9a0..28d48fe77 100644 --- a/src/text/text_line.cpp +++ b/src/text/text_line.cpp @@ -36,7 +36,7 @@ text_line::text_line(unsigned first_char, unsigned last_char) first_line_(false) {} -void text_line::add_glyph(glyph_info && glyph, double scale_factor_) +void text_line::add_glyph(glyph_info const& glyph, double scale_factor_) { line_height_ = std::max(line_height_, glyph.line_height() + glyph.format->line_spacing); double advance = glyph.advance(); @@ -49,7 +49,7 @@ void text_line::add_glyph(glyph_info && glyph, double scale_factor_) // Only add character spacing if the character is not a zero-width part of a cluster. width_ += advance + glyphs_.back().format->character_spacing * scale_factor_; } - glyphs_.push_back(std::move(glyph)); + glyphs_.push_back(glyph); } From ec97b8b744f0a70c5dded077cd6968218925f5d0 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 6 Aug 2014 12:32:50 +0100 Subject: [PATCH 40/92] c++ style --- include/mapnik/text/vertex_cache.hpp | 69 ++++++++++++++-------------- 1 file changed, 34 insertions(+), 35 deletions(-) diff --git a/include/mapnik/text/vertex_cache.hpp b/include/mapnik/text/vertex_cache.hpp index a966ac325..259826ec4 100644 --- a/include/mapnik/text/vertex_cache.hpp +++ b/include/mapnik/text/vertex_cache.hpp @@ -40,7 +40,7 @@ namespace mapnik class vertex_cache; using vertex_cache_ptr = std::shared_ptr; -/** Caches all path points and their lengths. Allows easy moving in both directions. */ +// Caches all path points and their lengths. Allows easy moving in both directions. class vertex_cache { struct segment @@ -50,7 +50,7 @@ class vertex_cache double length; }; - /* The first segment always has the length 0 and just defines the starting point. */ + // The first segment always has the length 0 and just defines the starting point. struct segment_vector { segment_vector() : vector(), length(0.) {} @@ -65,8 +65,8 @@ class vertex_cache }; public: - /** This class has no public members to avoid acciedential modification. - * It should only be used with save_state/restore_state. */ + // This class has no public members to avoid acciedential modification. + // It should only be used with save_state/restore_state. class state { segment_vector::iterator current_segment; @@ -92,7 +92,7 @@ public: bool restored_; }; - /********************************************************************************************/ + /////////////////////////////////////////////////////////////////////// template vertex_cache(T &path); @@ -104,73 +104,72 @@ public: double linear_position() const { return position_; } - /** Returns a parallel line in the specified distance. */ - vertex_cache &get_offseted(double offset, double region_width); + // Returns a parallel line in the specified distance. + vertex_cache & get_offseted(double offset, double region_width); - /** Skip a certain amount of space. - * - * This function automatically calculates new points if the position is not exactly - * on a point on the path. - */ + // Skip a certain amount of space. + // This function automatically calculates new points if the position is not exactly + // on a point on the path. + bool forward(double length); - /** Go backwards. */ + // Go backwards. bool backward(double length); - /** Move in any direction (based on sign of length). Returns false if it reaches either end of the path. */ + // Move in any direction (based on sign of length). Returns false if it reaches either end of the path. bool move(double length); - /** Work on next subpath. Returns false if the is no next subpath. */ + // Work on next subpath. Returns false if the is no next subpath. bool next_subpath(); // Compatibility with standard path interface - void rewind(unsigned); - unsigned vertex(double *x, double *y); + void rewind(unsigned) const; + unsigned vertex(double *x, double *y) const; - //State + // State state save_state() const; void restore_state(state const& s); - /** Go back to initial state. */ + // Go back to initial state. void reset(); - /** position on this line closest to the target position */ + // position on this line closest to the target position double position_closest_to(pixel_position const &target_pos); private: void rewind_subpath(); bool next_segment(); bool previous_segment(); - /** Position as calculated by last move/forward/next call. */ + // Position as calculated by last move/forward/next call. pixel_position current_position_; - /** First pixel of current segment. */ + // First pixel of current segment. pixel_position segment_starting_point_; - /** List of all subpaths. */ + // List of all subpaths. std::vector subpaths_; - /** Currently active subpath. */ + // Currently active subpath. std::vector::iterator current_subpath_; - /** Current segment for normal operation (move()). */ + // Current segment for normal operation (move()). segment_vector::iterator current_segment_; - /** Current segment in compatibility mode (vertex(), rewind()). */ + // Current segment in compatibility mode (vertex(), rewind()). segment_vector::iterator vertex_segment_; - /** Currently active subpath in compatibility mode. */ + // Currently active subpath in compatibility mode. std::vector::iterator vertex_subpath_; - /** State is initialized (after first call to next_subpath()). */ + // State is initialized (after first call to next_subpath()). bool initialized_; - /** Position from start of segment. */ + // Position from start of segment. double position_in_segment_; - /** Angle for current segment. */ + // Angle for current segment. mutable double angle_; - /** Is the value in angle_ valid? - * Used to avoid unnecessary calculations. */ + // Is the value in angle_ valid? + // Used to avoid unnecessary calculations. mutable bool angle_valid_; using offseted_lines_map = std::map; - /** Cache of all offseted lines already computed. */ + // Cache of all offseted lines already computed. offseted_lines_map offseted_lines_; - /** Linear position, i.e distance from start of line. */ + // Linear position, i.e distance from start of line. double position_; }; template -vertex_cache::vertex_cache(T &path) +vertex_cache::vertex_cache(T & path) : current_position_(), segment_starting_point_(), subpaths_(), From 9835057b0f2c6e37318182474c5a7dafff27c5db Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 6 Aug 2014 13:10:24 +0100 Subject: [PATCH 41/92] Use vertex_converters in text placement --- .../process_polygon_symbolizer.hpp | 10 +- include/mapnik/text/placement_finder_impl.hpp | 108 ++++++++++++++++++ include/mapnik/text/symbolizer_helpers.hpp | 34 +++++- include/mapnik/text/vertex_cache.hpp | 4 +- src/text/placement_finder.cpp | 75 +----------- src/text/symbolizer_helpers.cpp | 58 +++++----- 6 files changed, 177 insertions(+), 112 deletions(-) create mode 100644 include/mapnik/text/placement_finder_impl.hpp diff --git a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp index e4a33ee0c..42bbf12d6 100644 --- a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp @@ -27,11 +27,11 @@ namespace mapnik { template void render_polygon_symbolizer(polygon_symbolizer const &sym, - mapnik::feature_impl &feature, - proj_transform const &prj_trans, - renderer_common &common, - box2d const &clip_box, - rasterizer_type &ras, + mapnik::feature_impl & feature, + proj_transform const& prj_trans, + renderer_common & common, + box2d const& clip_box, + rasterizer_type & ras, F fill_func) { agg::trans_affine tr; diff --git a/include/mapnik/text/placement_finder_impl.hpp b/include/mapnik/text/placement_finder_impl.hpp new file mode 100644 index 000000000..530d8ecb3 --- /dev/null +++ b/include/mapnik/text/placement_finder_impl.hpp @@ -0,0 +1,108 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// agg +#include "agg_conv_clip_polyline.h" + +// stl +#include + +namespace mapnik +{ + +template +bool placement_finder::find_line_placements(T & path, bool points) +{ + if (!layouts_.line_count()) return true; //TODO + vertex_cache pp(path); + + bool success = false; + while (pp.next_subpath()) + { + if (points) + { + if (pp.length() <= 0.001) + { + success = find_point_placement(pp.current_position()) || success; + continue; + } + } + else + { + if ((pp.length() < info_.properties.minimum_path_length * scale_factor_) + || + (pp.length() <= 0.001) // Clipping removed whole geometry + || + (pp.length() < layouts_.width())) + { + continue; + } + } + + double spacing = get_spacing(pp.length(), points ? 0. : layouts_.width()); + + //horizontal_alignment_e halign = layouts_.back()->horizontal_alignment(); + + // halign == H_LEFT -> don't move + if (horizontal_alignment_ == H_MIDDLE || horizontal_alignment_ == H_AUTO) + { + pp.forward(spacing/2.0); + } + else if (horizontal_alignment_ == H_RIGHT) + { + pp.forward(pp.length()); + } + + if (move_dx_ != 0.0) path_move_dx(pp, move_dx_); + + do + { + tolerance_iterator tolerance_offset(info_.properties.label_position_tolerance * scale_factor_, spacing); //TODO: Handle halign + while (tolerance_offset.next()) + { + vertex_cache::scoped_state state(pp); + if (pp.move(tolerance_offset.get()) + && ( + (points && find_point_placement(pp.current_position())) + || (!points && single_line_placement(pp, info_.properties.upright)))) + { + success = true; + break; + } + } + } while (pp.forward(spacing)); + } + return success; +} + +}// ns mapnik diff --git a/include/mapnik/text/symbolizer_helpers.hpp b/include/mapnik/text/symbolizer_helpers.hpp index 3abf849a5..6554b15db 100644 --- a/include/mapnik/text/symbolizer_helpers.hpp +++ b/include/mapnik/text/symbolizer_helpers.hpp @@ -30,9 +30,37 @@ #include #include #include +#include namespace mapnik { +template +struct placement_finder_adapter +{ + using placement_finder_type = T; + placement_finder_adapter(T & finder, bool points_on_line) + : finder_(finder), + points_on_line_(points_on_line) {} + + template + void add_path(PathT & path) + { + status_ = finder_.find_line_placements(path, points_on_line_); + } + + bool status() const { return status_;} + // Place text at points on a line instead of following the line (used for ShieldSymbolizer) + placement_finder_type & finder_; + bool points_on_line_; + mutable bool status_ = false; + +}; + +using conv_types = boost::mpl::vector; +using vertex_converter_type = vertex_converter, placement_finder_adapter , symbolizer_base, + CoordTransform, proj_transform, agg::trans_affine, + conv_types, feature_impl>; + class base_symbolizer_helper { public: @@ -116,10 +144,8 @@ protected: bool next_line_placement(bool clipped); placement_finder finder_; - - // Place text at points on a line instead of following the line (used for ShieldSymbolizer) - bool points_on_line_; - + placement_finder_adapter adapter_; + vertex_converter_type converter_; //ShieldSymbolizer only void init_marker(); }; diff --git a/include/mapnik/text/vertex_cache.hpp b/include/mapnik/text/vertex_cache.hpp index 259826ec4..552b6845d 100644 --- a/include/mapnik/text/vertex_cache.hpp +++ b/include/mapnik/text/vertex_cache.hpp @@ -121,8 +121,8 @@ public: bool next_subpath(); // Compatibility with standard path interface - void rewind(unsigned) const; - unsigned vertex(double *x, double *y) const; + void rewind(unsigned); + unsigned vertex(double *x, double *y); // State state save_state() const; diff --git a/src/text/placement_finder.cpp b/src/text/placement_finder.cpp index cad774ada..09fc7150a 100644 --- a/src/text/placement_finder.cpp +++ b/src/text/placement_finder.cpp @@ -24,7 +24,7 @@ #include #include #include -#include +#include #include #include #include @@ -169,71 +169,6 @@ bool placement_finder::find_point_placement(pixel_position const& pos) return true; } -template -bool placement_finder::find_line_placements(T & path, bool points) -{ - if (!layouts_.line_count()) return true; //TODO - vertex_cache pp(path); - - bool success = false; - while (pp.next_subpath()) - { - if (points) - { - if (pp.length() <= 0.001) - { - success = find_point_placement(pp.current_position()) || success; - continue; - } - } - else - { - if ((pp.length() < info_.properties.minimum_path_length * scale_factor_) - || - (pp.length() <= 0.001) // Clipping removed whole geometry - || - (pp.length() < layouts_.width())) - { - continue; - } - } - - double spacing = get_spacing(pp.length(), points ? 0. : layouts_.width()); - - //horizontal_alignment_e halign = layouts_.back()->horizontal_alignment(); - - // halign == H_LEFT -> don't move - if (horizontal_alignment_ == H_MIDDLE || horizontal_alignment_ == H_AUTO) - { - pp.forward(spacing/2.0); - } - else if (horizontal_alignment_ == H_RIGHT) - { - pp.forward(pp.length()); - } - - if (move_dx_ != 0.0) path_move_dx(pp, move_dx_); - - do - { - tolerance_iterator tolerance_offset(info_.properties.label_position_tolerance * scale_factor_, spacing); //TODO: Handle halign - while (tolerance_offset.next()) - { - vertex_cache::scoped_state state(pp); - if (pp.move(tolerance_offset.get()) - && ( - (points && find_point_placement(pp.current_position())) - || (!points && single_line_placement(pp, info_.properties.upright)))) - { - success = true; - break; - } - } - } while (pp.forward(spacing)); - } - return success; -} - bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e orientation) { // @@ -502,12 +437,4 @@ pixel_position const& glyph_positions::marker_pos() const return marker_pos_; } - -using clipped_geometry_type = agg::conv_clip_polyline; -using ClippedPathType = coord_transform; -using PathType = coord_transform; -template bool placement_finder::find_line_placements(ClippedPathType &, bool); -template bool placement_finder::find_line_placements(PathType &, bool); - - }// ns mapnik diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index e77a3e9f9..6632f2623 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -72,7 +72,6 @@ struct largest_bbox_first box2d b1 = g1->envelope(); return b0.width()*b0.height() > b1.width()*b1.height(); } - }; void base_symbolizer_helper::initialize_geometries() @@ -182,8 +181,21 @@ text_symbolizer_helper::text_symbolizer_helper( DetectorT &detector, box2d const& query_extent) : base_symbolizer_helper(sym, feature, vars, prj_trans, width, height, scale_factor, t, query_extent), finder_(feature, vars, detector, dims_, *placement_, font_manager, scale_factor), - points_on_line_(false) + adapter_(finder_,false), + converter_(query_extent_, adapter_, sym_, t, prj_trans, agg::trans_affine(), feature, vars, scale_factor) { + + // setup vertex converter + bool clip = mapnik::get(sym_, keys::clip, feature_, vars_, false); + double simplify_tolerance = mapnik::get(sym_, keys::simplify_tolerance, feature_, vars_, 0.0); + double smooth = mapnik::get(sym_, keys::smooth, feature_, vars_, 0.0); + + if (clip) converter_.template set(); //optional clip (default: true) + converter_.template set(); //always transform + converter_.template set(); + if (simplify_tolerance > 0.0) converter_.template set(); // optional simplify converter + if (smooth > 0.0) converter_.template set(); // optional smooth converter + if (geometries_to_process_.size()) finder_.next_position(); } @@ -212,31 +224,15 @@ bool text_symbolizer_helper::next_line_placement(bool clipped) geo_itr_ = geometries_to_process_.begin(); continue; //Reexecute size check } - bool success = false; - if (clipped) - { - using clipped_geometry_type = agg::conv_clip_polyline; - using path_type = coord_transform; - clipped_geometry_type clipped(**geo_itr_); - clipped.clip_box(query_extent_.minx(), query_extent_.miny(), - query_extent_.maxx(), query_extent_.maxy()); - path_type path(t_, clipped, prj_trans_); - success = finder_.find_line_placements(path, points_on_line_); - } - else - { - using path_type = coord_transform; - path_type path(t_, **geo_itr_, prj_trans_); - success = finder_.find_line_placements(path, points_on_line_); - } - if (success) + converter_.apply(**geo_itr_); + if (adapter_.status()) { //Found a placement geo_itr_ = geometries_to_process_.erase(geo_itr_); return true; } - //No placement for this geometry. Keep it in geometries_to_process_ for next try. + // No placement for this geometry. Keep it in geometries_to_process_ for next try. ++geo_itr_; } return false; @@ -266,8 +262,6 @@ bool text_symbolizer_helper::next_point_placement() return false; } -/*****************************************************************************/ - template text_symbolizer_helper::text_symbolizer_helper( shield_symbolizer const& sym, @@ -276,11 +270,22 @@ text_symbolizer_helper::text_symbolizer_helper( proj_transform const& prj_trans, unsigned width, unsigned height, double scale_factor, CoordTransform const& t, FaceManagerT & font_manager, - DetectorT &detector, const box2d &query_extent) + DetectorT & detector, box2d const& query_extent) : base_symbolizer_helper(sym, feature, vars, prj_trans, width, height, scale_factor, t, query_extent), finder_(feature, vars, detector, dims_, *placement_, font_manager, scale_factor), - points_on_line_(true) + adapter_(finder_,true), + converter_(query_extent_, adapter_, sym_, t, prj_trans, agg::trans_affine(), feature, vars, scale_factor) { + // setup vertex converter + bool clip = mapnik::get(sym_, keys::clip, feature_, vars_, false); + double simplify_tolerance = mapnik::get(sym_, keys::simplify_tolerance, feature_, vars_, 0.0); + double smooth = mapnik::get(sym_, keys::smooth, feature_, vars_, 0.0); + + if (clip) converter_.template set(); //optional clip (default: true) + converter_.template set(); //always transform + converter_.template set(); + if (simplify_tolerance > 0.0) converter_.template set(); // optional simplify converter + if (smooth > 0.0) converter_.template set(); // optional smooth converter if (geometries_to_process_.size()) { init_marker(); @@ -325,7 +330,6 @@ void text_symbolizer_helper::init_marker() finder_.set_marker(std::make_shared(*marker, trans), bbox, unlock_image, marker_displacement); } -/*****************************************************************************/ template text_symbolizer_helper::text_symbolizer_helper( text_symbolizer const& sym, From 0490b7887c3a5bd532c4018d1c05d24a32cedfa8 Mon Sep 17 00:00:00 2001 From: artemp Date: Wed, 6 Aug 2014 14:54:38 +0100 Subject: [PATCH 42/92] text_symbolizer - ```geometry-transform``` support --- include/mapnik/text/symbolizer_helpers.hpp | 10 ++++-- src/agg/process_shield_symbolizer.cpp | 17 ++++++---- src/agg/process_text_symbolizer.cpp | 32 +++++++++++-------- src/cairo/cairo_renderer.cpp | 10 ++++-- src/grid/process_shield_symbolizer.cpp | 11 ++++--- src/grid/process_text_symbolizer.cpp | 7 ++-- .../process_group_symbolizer.cpp | 4 +-- src/text/symbolizer_helpers.cpp | 17 ++++++---- .../styles/text-charplacement.xml | 2 +- 9 files changed, 69 insertions(+), 41 deletions(-) diff --git a/include/mapnik/text/symbolizer_helpers.hpp b/include/mapnik/text/symbolizer_helpers.hpp index 6554b15db..2e9dbbdac 100644 --- a/include/mapnik/text/symbolizer_helpers.hpp +++ b/include/mapnik/text/symbolizer_helpers.hpp @@ -56,7 +56,7 @@ struct placement_finder_adapter }; -using conv_types = boost::mpl::vector; +using conv_types = boost::mpl::vector; using vertex_converter_type = vertex_converter, placement_finder_adapter , symbolizer_base, CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl>; @@ -122,7 +122,8 @@ public: CoordTransform const& t, FaceManagerT & font_manager, DetectorT & detector, - box2d const& query_extent); + box2d const& query_extent, + agg::trans_affine const&); template text_symbolizer_helper(shield_symbolizer const& sym, @@ -135,7 +136,8 @@ public: CoordTransform const& t, FaceManagerT & font_manager, DetectorT & detector, - box2d const& query_extent); + box2d const& query_extent, + agg::trans_affine const&); // Return all placements. placements_list const& get(); @@ -144,6 +146,7 @@ protected: bool next_line_placement(bool clipped); placement_finder finder_; + placement_finder_adapter adapter_; vertex_converter_type converter_; //ShieldSymbolizer only @@ -151,4 +154,5 @@ protected: }; } //namespace + #endif // SYMBOLIZER_HELPERS_HPP diff --git a/src/agg/process_shield_symbolizer.cpp b/src/agg/process_shield_symbolizer.cpp index b9e77de0a..ad86e41ad 100644 --- a/src/agg/process_shield_symbolizer.cpp +++ b/src/agg/process_shield_symbolizer.cpp @@ -34,16 +34,19 @@ namespace mapnik { template void agg_renderer::process(shield_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) + mapnik::feature_impl & feature, + proj_transform const& prj_trans) { box2d clip_box = clipping_extent(common_); + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); text_symbolizer_helper helper( - sym, feature, common_.vars_, prj_trans, - common_.width_, common_.height_, - common_.scale_factor_, - common_.t_, common_.font_manager_, *common_.detector_, - clip_box); + sym, feature, common_.vars_, prj_trans, + common_.width_, common_.height_, + common_.scale_factor_, + common_.t_, common_.font_manager_, *common_.detector_, + clip_box, tr); halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer, feature, common_.vars_, HALO_RASTERIZER_FULL); composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); diff --git a/src/agg/process_text_symbolizer.cpp b/src/agg/process_text_symbolizer.cpp index 8a72e70b0..bb45bed85 100644 --- a/src/agg/process_text_symbolizer.cpp +++ b/src/agg/process_text_symbolizer.cpp @@ -33,17 +33,20 @@ namespace mapnik { template void agg_renderer::process(text_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) + mapnik::feature_impl & feature, + proj_transform const& prj_trans) { box2d clip_box = clipping_extent(common_); + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); text_symbolizer_helper helper( - sym, feature, common_.vars_, prj_trans, - common_.width_, common_.height_, - common_.scale_factor_, - common_.t_, common_.font_manager_, *common_.detector_, - clip_box); + sym, feature, common_.vars_, prj_trans, + common_.width_, common_.height_, + common_.scale_factor_, + common_.t_, common_.font_manager_, *common_.detector_, + clip_box, tr); halo_rasterizer_enum halo_rasterizer = get(sym, keys::halo_rasterizer,feature, common_.vars_, HALO_RASTERIZER_FULL); composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); @@ -55,13 +58,16 @@ void agg_renderer::process(text_symbolizer const& sym, common_.scale_factor_, common_.font_manager_.get_stroker()); - agg::trans_affine halo_transform; - auto transform = get_optional(sym, keys::halo_transform); - if (transform) - { - evaluate_transform(halo_transform, feature, common_.vars_, *transform); - ren.set_halo_transform(halo_transform); + { // halo transform + agg::trans_affine halo_transform; + auto transform = get_optional(sym, keys::halo_transform); + if (transform) + { + evaluate_transform(halo_transform, feature, common_.vars_, *transform); + ren.set_halo_transform(halo_transform); + } } + placements_list const& placements = helper.get(); for (glyph_positions_ptr glyphs : placements) { diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index fc60d6b81..a357f11fc 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -573,12 +573,15 @@ void cairo_renderer_base::process(shield_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); text_symbolizer_helper helper( sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, - common_.query_extent_); + common_.query_extent_, tr); cairo_save_restore guard(context_); composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); @@ -969,12 +972,15 @@ void cairo_renderer_base::process(text_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); text_symbolizer_helper helper( sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, - common_.query_extent_); + common_.query_extent_, tr); cairo_save_restore guard(context_); composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); diff --git a/src/grid/process_shield_symbolizer.cpp b/src/grid/process_shield_symbolizer.cpp index 28ce40acc..920fff033 100644 --- a/src/grid/process_shield_symbolizer.cpp +++ b/src/grid/process_shield_symbolizer.cpp @@ -1,4 +1,3 @@ - /***************************************************************************** * * This file is part of Mapnik (c++ mapping toolkit) @@ -43,12 +42,16 @@ void grid_renderer::process(shield_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); + text_symbolizer_helper helper( sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, - common_.query_extent_); + common_.query_extent_, tr); bool placement_found = false; composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); @@ -60,12 +63,12 @@ void grid_renderer::process(shield_symbolizer const& sym, placements_list const& placements = helper.get(); value_integer feature_id = feature.id(); - + for (glyph_positions_ptr glyphs : placements) { if (glyphs->marker()) { - render_marker(feature, + render_marker(feature, pixmap_.get_resolution(), glyphs->marker_pos(), *(glyphs->marker()->marker), diff --git a/src/grid/process_text_symbolizer.cpp b/src/grid/process_text_symbolizer.cpp index 27b3d9344..1e719c054 100644 --- a/src/grid/process_text_symbolizer.cpp +++ b/src/grid/process_text_symbolizer.cpp @@ -36,12 +36,15 @@ void grid_renderer::process(text_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); text_symbolizer_helper helper( sym, feature, common_.vars_, prj_trans, common_.width_, common_.height_, common_.scale_factor_ * (1.0/pixmap_.get_resolution()), common_.t_, common_.font_manager_, *common_.detector_, - common_.query_extent_); + common_.query_extent_, tr); bool placement_found = false; composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); @@ -55,7 +58,7 @@ void grid_renderer::process(text_symbolizer const& sym, for (glyph_positions_ptr glyphs : placements) { - ren.render(*glyphs, feature_id); + ren.render(*glyphs, feature_id); placement_found = true; } if (placement_found) diff --git a/src/renderer_common/process_group_symbolizer.cpp b/src/renderer_common/process_group_symbolizer.cpp index 62f4df481..14ac14899 100644 --- a/src/renderer_common/process_group_symbolizer.cpp +++ b/src/renderer_common/process_group_symbolizer.cpp @@ -104,7 +104,7 @@ void render_thunk_extractor::operator()(text_symbolizer const& sym) const common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, - clip_box); + clip_box, agg::trans_affine()); extract_text_thunk(helper, sym); } @@ -117,7 +117,7 @@ void render_thunk_extractor::operator()(shield_symbolizer const& sym) const common_.width_, common_.height_, common_.scale_factor_, common_.t_, common_.font_manager_, *common_.detector_, - clip_box); + clip_box, agg::trans_affine()); extract_text_thunk(helper, sym); } diff --git a/src/text/symbolizer_helpers.cpp b/src/text/symbolizer_helpers.cpp index 6632f2623..34330c9d9 100644 --- a/src/text/symbolizer_helpers.cpp +++ b/src/text/symbolizer_helpers.cpp @@ -178,11 +178,12 @@ text_symbolizer_helper::text_symbolizer_helper( proj_transform const& prj_trans, unsigned width, unsigned height, double scale_factor, CoordTransform const& t, FaceManagerT & font_manager, - DetectorT &detector, box2d const& query_extent) + DetectorT &detector, box2d const& query_extent, + agg::trans_affine const& affine_trans) : base_symbolizer_helper(sym, feature, vars, prj_trans, width, height, scale_factor, t, query_extent), finder_(feature, vars, detector, dims_, *placement_, font_manager, scale_factor), adapter_(finder_,false), - converter_(query_extent_, adapter_, sym_, t, prj_trans, agg::trans_affine(), feature, vars, scale_factor) + converter_(query_extent_, adapter_, sym_, t, prj_trans, affine_trans, feature, vars, scale_factor) { // setup vertex converter @@ -270,13 +271,13 @@ text_symbolizer_helper::text_symbolizer_helper( proj_transform const& prj_trans, unsigned width, unsigned height, double scale_factor, CoordTransform const& t, FaceManagerT & font_manager, - DetectorT & detector, box2d const& query_extent) + DetectorT & detector, box2d const& query_extent, agg::trans_affine const& affine_trans) : base_symbolizer_helper(sym, feature, vars, prj_trans, width, height, scale_factor, t, query_extent), finder_(feature, vars, detector, dims_, *placement_, font_manager, scale_factor), adapter_(finder_,true), - converter_(query_extent_, adapter_, sym_, t, prj_trans, agg::trans_affine(), feature, vars, scale_factor) + converter_(query_extent_, adapter_, sym_, t, prj_trans, affine_trans, feature, vars, scale_factor) { - // setup vertex converter + // setup vertex converter bool clip = mapnik::get(sym_, keys::clip, feature_, vars_, false); double simplify_tolerance = mapnik::get(sym_, keys::simplify_tolerance, feature_, vars_, 0.0); double smooth = mapnik::get(sym_, keys::smooth, feature_, vars_, 0.0); @@ -342,7 +343,8 @@ template text_symbolizer_helper::text_symbolizer_helper( CoordTransform const& t, face_manager &font_manager, label_collision_detector4 &detector, - box2d const& query_extent); + box2d const& query_extent, + agg::trans_affine const&); template text_symbolizer_helper::text_symbolizer_helper( shield_symbolizer const& sym, @@ -355,5 +357,6 @@ template text_symbolizer_helper::text_symbolizer_helper( CoordTransform const& t, face_manager &font_manager, label_collision_detector4 &detector, - box2d const& query_extent); + box2d const& query_extent, + agg::trans_affine const&); } //namespace diff --git a/tests/visual_tests/styles/text-charplacement.xml b/tests/visual_tests/styles/text-charplacement.xml index 5a8a705c4..92467e5ef 100644 --- a/tests/visual_tests/styles/text-charplacement.xml +++ b/tests/visual_tests/styles/text-charplacement.xml @@ -2,7 +2,7 @@ + + + lines + markers + + csv + + wkt, placement + "LINESTRING(0 0)", "vertex-first" + "LINESTRING(0 1, 10 1)", "vertex-first" + "LINESTRING(0 2, 2 3, 4 2, 6 3, 8 2, 10 3)", "vertex-first" + + + + diff --git a/tests/visual_tests/styles/marker-on-line-and-vertex-last-placement.xml b/tests/visual_tests/styles/marker-on-line-and-vertex-last-placement.xml new file mode 100644 index 000000000..b35a65d1a --- /dev/null +++ b/tests/visual_tests/styles/marker-on-line-and-vertex-last-placement.xml @@ -0,0 +1,28 @@ + + + + + + + lines + markers + + csv + + wkt, placement + "LINESTRING(0 0)", "vertex-last" + "LINESTRING(0 1, 10 1)", "vertex-last" + "LINESTRING(0 2, 2 3, 4 2, 6 3, 8 2, 10 3)", "vertex-last" + + + + diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 4e1324e53..887901a51 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -121,6 +121,10 @@ files = { 'marker-on-line-spacing-eq-width': {'sizes':[(600,400)]}, 'marker-on-line-spacing-eq-width-overlap': {'sizes':[(600,400)]}, 'marker_line_placement_on_points':{}, + 'marker-on-line-and-vertex-first-placement':{'sizes':[(600,400)], + 'bbox': mapnik.Box2d(-1, -1, 11, 4)}, + 'marker-on-line-and-vertex-last-placement':{'sizes':[(600,400)], + 'bbox': mapnik.Box2d(-1, -1, 11, 4)}, 'marker-with-background-image-linear-comp-op': {}, 'marker-with-background-image': {'sizes':[(600,400),(400,600),(257,256)]}, 'marker-with-background-image-and-hsla-transform': {'sizes':[(600,400),(400,600),(257,256)]}, From 04effe9a36df84f34fef27988ced9427c250f569 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Thu, 7 Aug 2014 05:47:37 +0000 Subject: [PATCH 65/92] remove duplicate import --- tests/visual_tests/test.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/visual_tests/test.py b/tests/visual_tests/test.py index 887901a51..da095b1b8 100755 --- a/tests/visual_tests/test.py +++ b/tests/visual_tests/test.py @@ -6,7 +6,6 @@ import mapnik #mapnik.logger.set_severity(mapnik.severity_type.None) #mapnik.logger.set_severity(mapnik.severity_type.Debug) import shutil -import sys import os.path from compare import compare, compare_grids From 9b0953a9550a662a8f7dc50e6a11f2fc526423c5 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Fri, 8 Aug 2014 05:09:01 +0000 Subject: [PATCH 66/92] remove needless virtual inheritance --- include/mapnik/markers_placements/point.hpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/mapnik/markers_placements/point.hpp b/include/mapnik/markers_placements/point.hpp index 4329761c2..bbe97a103 100644 --- a/include/mapnik/markers_placements/point.hpp +++ b/include/mapnik/markers_placements/point.hpp @@ -55,13 +55,12 @@ public: { rewind(); } - virtual ~markers_point_placement() {} /** Start again at first marker. * \note Returns the same list of markers only works when they were NOT added * to the detector. */ - virtual void rewind() + void rewind() { locator_.rewind(0); done_ = false; @@ -75,7 +74,7 @@ public: * \param ignore_placement Whether to add selected position to detector * \return True if a place is found, false if none is found. */ - virtual bool get_point(double &x, double &y, double &angle, bool ignore_placement) + bool get_point(double &x, double &y, double &angle, bool ignore_placement) { if (done_) { From 705260aa06ea91ec36320b903b04ea3b07bdc363 Mon Sep 17 00:00:00 2001 From: Jiri Drbalek Date: Fri, 8 Aug 2014 06:11:05 +0000 Subject: [PATCH 67/92] prefer c++ style comments --- include/mapnik/markers_placement.hpp | 12 ++---------- include/mapnik/markers_placements/line.hpp | 6 +++--- include/mapnik/markers_placements/point.hpp | 17 +++-------------- 3 files changed, 8 insertions(+), 27 deletions(-) diff --git a/include/mapnik/markers_placement.hpp b/include/mapnik/markers_placement.hpp index bbc15b85e..ca7cf967a 100644 --- a/include/mapnik/markers_placement.hpp +++ b/include/mapnik/markers_placement.hpp @@ -78,22 +78,14 @@ public: { } - /** Get a point where the marker should be placed. - * Each time this function is called a new point is returned. - * \param x Return value for x position - * \param y Return value for x position - * \param angle Return value for rotation angle - * \param ignore_placement Whether to add selected position to detector - * \return True if a place is found, false if none is found. - */ + // Get next point where the marker should be placed. Returns true if a place is found, false if none is found. bool get_point(double &x, double &y, double &angle, bool ignore_placement) { return boost::apply_visitor(get_point_visitor(x, y, angle, ignore_placement), placement_); } private: - /** Factory function for particular placement implementations. - */ + // Factory function for particular placement implementations. static markers_placement create(marker_placement_e placement_type, Locator &locator, box2d const& size, diff --git a/include/mapnik/markers_placements/line.hpp b/include/mapnik/markers_placements/line.hpp index 3244ede79..782a4a04e 100644 --- a/include/mapnik/markers_placements/line.hpp +++ b/include/mapnik/markers_placements/line.hpp @@ -206,13 +206,13 @@ private: double last_y; double next_x; double next_y; - /** If a marker could not be placed at the exact point where it should - * go the next marker's distance will be a bit lower. */ + // If a marker could not be placed at the exact point where it should + // go the next marker's distance will be a bit lower. double error_; double spacing_left_; unsigned marker_nr_; - /** Set spacing_left_, adjusts error_ and performs sanity checks. */ + // Set spacing_left_, adjusts error_ and performs sanity checks. void set_spacing_left(double sl, bool allow_negative=false) { double delta_error = sl - spacing_left_; diff --git a/include/mapnik/markers_placements/point.hpp b/include/mapnik/markers_placements/point.hpp index bbe97a103..60ec39320 100644 --- a/include/mapnik/markers_placements/point.hpp +++ b/include/mapnik/markers_placements/point.hpp @@ -56,24 +56,14 @@ public: rewind(); } - /** Start again at first marker. - * \note Returns the same list of markers only works when they were NOT added - * to the detector. - */ + // Start again at first marker. Returns the same list of markers only works when they were NOT added to the detector. void rewind() { locator_.rewind(0); done_ = false; } - /** Get a point where the marker should be placed. - * Each time this function is called a new point is returned. - * \param x Return value for x position - * \param y Return value for x position - * \param angle Return value for rotation angle - * \param ignore_placement Whether to add selected position to detector - * \return True if a place is found, false if none is found. - */ + // Get next point where the marker should be placed. Returns true if a place is found, false if none is found. bool get_point(double &x, double &y, double &angle, bool ignore_placement) { if (done_) @@ -128,7 +118,7 @@ protected: double marker_width_; bool done_; - /** Rotates the size_ box and translates the position. */ + // Rotates the size_ box and translates the position. box2d perform_transform(double angle, double dx, double dy) { double x1 = size_.minx(); @@ -155,4 +145,3 @@ protected: } #endif // MAPNIK_MARKERS_PLACEMENTS_POINT_HPP - From 09e78e3ee9a311c691c6a37b93bdf3d0dfcc13e6 Mon Sep 17 00:00:00 2001 From: artemp Date: Thu, 7 Aug 2014 16:53:32 +0100 Subject: [PATCH 68/92] remove unused includes --- include/mapnik/value.hpp | 6 ++---- tests/data/pngsuite/linepattern.png | Bin 212 -> 3354 bytes 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index dba068f6a..31cfca2a6 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -29,9 +29,6 @@ #include // boost -#include -#include -#include #include #include @@ -980,7 +977,8 @@ operator << (std::basic_ostream& out, return out; } -inline std::size_t hash_value(const value& val) { +inline std::size_t hash_value(value const& val) +{ return hash_value(val.base()); } diff --git a/tests/data/pngsuite/linepattern.png b/tests/data/pngsuite/linepattern.png index d4987f1dc77e7428c91ec2f21093584a82d1e18a..9a89f215f3781c7b45f87e41877c5679775fb0da 100644 GIT binary patch literal 3354 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 From 471eaed9df7c10875dab71bbc9a8b746dfc04697 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Thu, 7 Aug 2014 17:42:24 -0700 Subject: [PATCH 69/92] initialize is_geographic --- src/projection.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/projection.cpp b/src/projection.cpp index 9c6e338cf..06dc5e4c8 100644 --- a/src/projection.cpp +++ b/src/projection.cpp @@ -49,6 +49,7 @@ namespace mapnik { projection::projection(std::string const& params, bool defer_proj_init) : params_(params), defer_proj_init_(defer_proj_init), + is_geographic_(false), proj_(nullptr), proj_ctx_(nullptr) { From 5a35422ee56aa8c01e2920cd0a5ea62057645cd3 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 08:17:41 -0700 Subject: [PATCH 70/92] build: remove -finline-functions which is no longer supported by clang-3.5 --- SConstruct | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SConstruct b/SConstruct index 42015153c..6e594967b 100644 --- a/SConstruct +++ b/SConstruct @@ -1785,7 +1785,7 @@ if not preconfigured: else: # TODO - add back -fvisibility-inlines-hidden # https://github.com/mapnik/mapnik/issues/1863 - env.Append(CXXFLAGS = common_cxx_flags + '-O%s -fno-strict-aliasing -finline-functions -Wno-inline -Wno-parentheses -Wno-char-subscripts' % (env['OPTIMIZATION'])) + env.Append(CXXFLAGS = common_cxx_flags + '-O%s -fno-strict-aliasing -Wno-inline -Wno-parentheses -Wno-char-subscripts' % (env['OPTIMIZATION'])) if env['DEBUG_UNDEFINED']: env.Append(CXXFLAGS = '-fsanitize=undefined-trap -fsanitize-undefined-trap-on-error -ftrapv -fwrapv') From e33e0150ad863d3e104a51b5d00846efb11ab209 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 12:34:41 -0700 Subject: [PATCH 71/92] 2x faster compile of value_types.hpp - start working on #2346 --- include/mapnik/value_types.hpp | 44 ++++++++++++---------------------- 1 file changed, 15 insertions(+), 29 deletions(-) diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index 0d08d1567..8e810199e 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -26,11 +26,8 @@ // icu #include // for UnicodeString -// boost -#include - // stl -#include // for ostream +#include namespace mapnik { @@ -47,82 +44,71 @@ using value_bool = bool; struct value_null { - bool operator==(value_null const& other) const + bool operator==(value_null const&) const { - boost::ignore_unused_variable_warning(other); return true; } template - bool operator==(T const& other) const + bool operator==(T const&) const { - boost::ignore_unused_variable_warning(other); return false; } - bool operator!=(value_null const& other) const + bool operator!=(value_null const&) const { - boost::ignore_unused_variable_warning(other); return false; } template - bool operator!=(T const& other) const + bool operator!=(T const&) const { - boost::ignore_unused_variable_warning(other); return true; } template - value_null operator+ (T const& other) const + value_null operator+ (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } template - value_null operator- (T const& other) const + value_null operator- (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } template - value_null operator* (T const& other) const + value_null operator* (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } template - value_null operator/ (T const& other) const + value_null operator/ (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } template - value_null operator% (T const& other) const + value_null operator% (T const&) const { - boost::ignore_unused_variable_warning(other); return *this; } }; -inline std::size_t hash_value(const value_null& val) +inline std::size_t hash_value(value_null const&) { - boost::ignore_unused_variable_warning(val); return 0; } -inline std::ostream& operator<< (std::ostream & out,value_null const& v) -{ - boost::ignore_unused_variable_warning(v); +template +inline std::basic_ostream& operator<<(std::basic_ostream& out, value_null const& v) { return out; } -inline std::istream& operator>> ( std::istream & s, value_null & null ) + +inline std::istream& operator>> ( std::istream & s, value_null & ) { - boost::ignore_unused_variable_warning(null); return s; } From 1727fae6e7d3bba491d4b71e7fa37adddaeb15b8 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 13:15:57 -0700 Subject: [PATCH 72/92] remove boost concept_check usage - refs #2346 --- include/mapnik/image_filter.hpp | 7 +-- include/mapnik/symbolizer.hpp | 11 +--- include/mapnik/symbolizer_utils.hpp | 3 +- include/mapnik/text/placements/dummy.hpp | 2 - include/mapnik/transform_processor.hpp | 6 +- include/mapnik/value.hpp | 75 ++++++++---------------- src/parse_path.cpp | 3 +- src/save_map.cpp | 14 ++--- src/transform_expression.cpp | 3 +- 9 files changed, 38 insertions(+), 86 deletions(-) diff --git a/include/mapnik/image_filter.hpp b/include/mapnik/image_filter.hpp index 35fa4d257..50ccb0772 100644 --- a/include/mapnik/image_filter.hpp +++ b/include/mapnik/image_filter.hpp @@ -31,8 +31,6 @@ // boost #include #include -#include - // agg #include "agg_basics.h" @@ -176,11 +174,8 @@ void process_channel_impl (Src const& src, Dst & dst, Conv const& k) } template -void process_channel (Src const& src, Dst & dst, Conv const& k) +void process_channel (Src const&, Dst &, Conv const&) { - boost::ignore_unused_variable_warning(src); - boost::ignore_unused_variable_warning(dst); - boost::ignore_unused_variable_warning(k); } template diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index a84d7c7be..ad3a0c9bb 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -51,7 +51,6 @@ #include // boost #include -#include namespace agg { struct trans_affine; } @@ -163,10 +162,8 @@ struct evaluate_path_wrapper { using result_type = T; template - result_type operator() (T1 const& expr, T2 const& feature) const + result_type operator() (T1 const&, T2 const&) const { - boost::ignore_unused_variable_warning(expr); - boost::ignore_unused_variable_warning(feature); return result_type(); } @@ -291,9 +288,8 @@ template struct enumeration_result { using result_type = T; - static result_type convert(enumeration_wrapper const& e) + static result_type convert(enumeration_wrapper const&) { - boost::ignore_unused_variable_warning(e); return result_type();// FAIL } }; @@ -425,9 +421,8 @@ struct extract_value : public boost::static_visitor } template - auto operator() (T1 const& val) const -> result_type + auto operator() (T1 const&) const -> result_type { - boost::ignore_unused_variable_warning(val); return result_type(); } diff --git a/include/mapnik/symbolizer_utils.hpp b/include/mapnik/symbolizer_utils.hpp index d92375da2..ee788a85e 100644 --- a/include/mapnik/symbolizer_utils.hpp +++ b/include/mapnik/symbolizer_utils.hpp @@ -127,9 +127,8 @@ struct symbolizer_name_impl : public boost::static_visitor { public: template - std::string operator () (Symbolizer const& sym) const + std::string operator () (Symbolizer const&) const { - boost::ignore_unused_variable_warning(sym); return symbolizer_traits::name(); } }; diff --git a/include/mapnik/text/placements/dummy.hpp b/include/mapnik/text/placements/dummy.hpp index 6d54f3f29..d3ed4aac3 100644 --- a/include/mapnik/text/placements/dummy.hpp +++ b/include/mapnik/text/placements/dummy.hpp @@ -25,8 +25,6 @@ // mapnik #include #include -// boost -#include namespace mapnik { diff --git a/include/mapnik/transform_processor.hpp b/include/mapnik/transform_processor.hpp index 343531cd9..063ac1f6e 100644 --- a/include/mapnik/transform_processor.hpp +++ b/include/mapnik/transform_processor.hpp @@ -57,9 +57,8 @@ struct transform_processor attribute_collector(Container& names) : collect_(names) {} - void operator() (identity_node const& node) const + void operator() (identity_node const&) const { - boost::ignore_unused_variable_warning(node); } void operator() (matrix_node const& node) const @@ -113,9 +112,8 @@ struct transform_processor vars_(v), scale_factor_(scale_factor) {} - void operator() (identity_node const& node) + void operator() (identity_node const&) { - boost::ignore_unused_variable_warning(node); } void operator() (matrix_node const& node) diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 31cfca2a6..5c96e257f 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -31,7 +31,6 @@ // boost #include -#include #include #include "hash_variant.hpp" @@ -179,9 +178,8 @@ struct not_equals // back compatibility shim to equate empty string with null for != test // https://github.com/mapnik/mapnik/issues/1859 // TODO - consider removing entire specialization at Mapnik 3.x - bool operator() (value_null lhs, value_unicode_string const& rhs) const + bool operator() (value_null, value_unicode_string const& rhs) const { - boost::ignore_unused_variable_warning(lhs); if (rhs.isEmpty()) return false; return true; } @@ -354,15 +352,13 @@ struct add : public boost::static_visitor return lhs + rhs; } - value_type operator() (value_unicode_string const& lhs, value_null rhs) const + value_type operator() (value_unicode_string const& lhs, value_null) const { - boost::ignore_unused_variable_warning(rhs); return lhs; } - value_type operator() (value_null lhs, value_unicode_string const& rhs) const + value_type operator() (value_null, value_unicode_string const& rhs) const { - boost::ignore_unused_variable_warning(lhs); return rhs; } @@ -418,11 +414,9 @@ struct sub : public boost::static_visitor return lhs - rhs ; } - value_type operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const + value_type operator() (value_unicode_string const&, + value_unicode_string const&) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_type(); } @@ -457,11 +451,9 @@ struct mult : public boost::static_visitor return lhs * rhs; } - value_type operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const + value_type operator() (value_unicode_string const&, + value_unicode_string const&) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_type(); } @@ -475,10 +467,8 @@ struct mult : public boost::static_visitor return lhs * rhs; } - value_type operator() (value_bool lhs, value_bool rhs) const + value_type operator() (value_bool, value_bool) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_integer(0); } }; @@ -500,18 +490,14 @@ struct div: public boost::static_visitor return lhs / rhs; } - value_type operator() (value_bool lhs, value_bool rhs) const + value_type operator() (value_bool, value_bool) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return false; } - value_type operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const + value_type operator() (value_unicode_string const&, + value_unicode_string const&) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_type(); } @@ -544,19 +530,15 @@ struct mod: public boost::static_visitor return lhs % rhs; } - value_type operator() (value_unicode_string const& lhs, - value_unicode_string const& rhs) const + value_type operator() (value_unicode_string const&, + value_unicode_string const&) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return value_type(); } - value_type operator() (value_bool lhs, - value_bool rhs) const + value_type operator() (value_bool, + value_bool) const { - boost::ignore_unused_variable_warning(lhs); - boost::ignore_unused_variable_warning(rhs); return false; } @@ -597,9 +579,8 @@ struct negate : public boost::static_visitor return val ? value_integer(-1) : value_integer(0); } - value_type operator() (value_unicode_string const& ustr) const + value_type operator() (value_unicode_string const&) const { - boost::ignore_unused_variable_warning(ustr); return value_type(); } }; @@ -621,9 +602,8 @@ struct convert : public boost::static_visitor return !ustr.isEmpty(); } - value_bool operator() (value_null const& val) const + value_bool operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return false; } @@ -667,9 +647,8 @@ struct convert : public boost::static_visitor return operator()(utf8); } - value_double operator() (value_null const& val) const + value_double operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return 0.0; } }; @@ -707,9 +686,8 @@ struct convert : public boost::static_visitor return operator()(utf8); } - value_integer operator() (value_null const& val) const + value_integer operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return value_integer(0); } }; @@ -740,9 +718,8 @@ struct convert : public boost::static_visitor return str; } - std::string operator() (value_null const& val) const + std::string operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return ""; } }; @@ -771,9 +748,8 @@ struct to_unicode : public boost::static_visitor return value_unicode_string(str.c_str()); } - value_unicode_string operator() (value_null const& val) const + value_unicode_string operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return value_unicode_string(""); } }; @@ -806,9 +782,8 @@ struct to_expression_string : public boost::static_visitor return val ? "true":"false"; } - std::string operator() (value_null const& val) const + std::string operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return "null"; } }; @@ -996,16 +971,14 @@ struct is_null : public boost::static_visitor return val.is_null(); } - bool operator() (value_null const& val) const + bool operator() (value_null const&) const { - boost::ignore_unused_variable_warning(val); return true; } template - bool operator() (T const& val) const + bool operator() (T const&) const { - boost::ignore_unused_variable_warning(val); return false; } diff --git a/src/parse_path.cpp b/src/parse_path.cpp index f12889bb5..d5f25da4e 100644 --- a/src/parse_path.cpp +++ b/src/parse_path.cpp @@ -102,9 +102,8 @@ namespace path_processor_detail { collect_ (std::set & cont) : cont_(cont) {} - void operator() (std::string const& token) const + void operator() (std::string const&) const { - boost::ignore_unused_variable_warning(token); } void operator() (attribute const& attr) const diff --git a/src/save_map.cpp b/src/save_map.cpp index 356b09275..fa2df5a2e 100644 --- a/src/save_map.cpp +++ b/src/save_map.cpp @@ -51,7 +51,7 @@ #include #include #include -#include + // stl #include @@ -488,27 +488,23 @@ public: serialize_type( boost::property_tree::ptree & node): node_(node) {} - void operator () ( mapnik::value_integer val ) const + void operator () ( mapnik::value_integer ) const { - boost::ignore_unused_variable_warning(val); node_.put(".type", "int" ); } - void operator () ( mapnik::value_double val ) const + void operator () ( mapnik::value_double ) const { - boost::ignore_unused_variable_warning(val); node_.put(".type", "float" ); } - void operator () ( std::string const& val ) const + void operator () ( std::string const& ) const { - boost::ignore_unused_variable_warning(val); node_.put(".type", "string" ); } - void operator () ( mapnik::value_null val ) const + void operator () ( mapnik::value_null ) const { - boost::ignore_unused_variable_warning(val); node_.put(".type", "string" ); } diff --git a/src/transform_expression.cpp b/src/transform_expression.cpp index f235255d4..69f831296 100644 --- a/src/transform_expression.cpp +++ b/src/transform_expression.cpp @@ -38,9 +38,8 @@ struct transform_node_to_expression_string transform_node_to_expression_string(std::ostringstream& os) : os_(os) {} - void operator() (identity_node const& node) const + void operator() (identity_node const&) const { - boost::ignore_unused_variable_warning(node); } void operator() (matrix_node const& node) From 578da317020e267021776568f19e850cdd111ce3 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 14:16:49 -0700 Subject: [PATCH 73/92] use extern template to fix osx -flto bug - closes #2339 --- include/mapnik/datasource_cache.hpp | 3 +++ src/datasource_cache.cpp | 2 ++ 2 files changed, 5 insertions(+) diff --git a/include/mapnik/datasource_cache.hpp b/include/mapnik/datasource_cache.hpp index 556097a16..6646888bd 100644 --- a/include/mapnik/datasource_cache.hpp +++ b/include/mapnik/datasource_cache.hpp @@ -58,6 +58,9 @@ private: bool registered_; std::set plugin_directories_; }; + +extern template class singleton; + } #endif // MAPNIK_DATASOURCE_CACHE_HPP diff --git a/src/datasource_cache.cpp b/src/datasource_cache.cpp index 08af17caa..152107ba1 100644 --- a/src/datasource_cache.cpp +++ b/src/datasource_cache.cpp @@ -42,6 +42,8 @@ namespace mapnik { +template class singleton; + extern datasource_ptr create_static_datasource(parameters const& params); extern std::vector get_static_datasource_names(); From fc70ab6c0a5d367cce21f811c35e908f31635e7d Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 15:01:35 -0700 Subject: [PATCH 74/92] test a crazy matrix --- .travis.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 6bb81ad0e..440b25f43 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,11 @@ compiler: - clang # - gcc +env: + matrix: + - DEBUG=True ENABLE_LOG=True DEFAULT_LOG_SEVERITY=debug XMLPARSER="libxml2" DEMO=False BENCHMARK=False CUSTOM_CXXFLAGS="" CUSTOM_LDFLAGS="" + - DEBUG=False ENABLE_LOG=False DEFAULT_LOG_SEVERITY=none XMLPARSER="ptree" DEMO=False BENCHMARK=False CUSTOM_CXXFLAGS="-flto" CUSTOM_LDFLAGS="-flto" + addons: postgresql: "9.3" @@ -37,7 +42,7 @@ before_install: install: - export RANLIB=/bin/true - - ./configure CXX="${CXX}" CC="${CC}" CUSTOM_CXXFLAGS="-flto" CUSTOM_LDFLAGS="-flto" DEMO=True BENCHMARK=True CPP_TESTS=True CAIRO=True FAST=True || cat config.log + - ./configure CXX="${CXX}" CC="${CC}" CUSTOM_CXXFLAGS="${CUSTOM_CXXFLAGS}" CUSTOM_LDFLAGS="${CUSTOM_LDFLAGS}" XML_PARSER=${XML_PARSER} ENABLE_LOG=${ENABLE_LOG} DEBUG=${DEBUG} DEMO=${DEMO} BENCHMARK=${BENCHMARK} CPP_TESTS=True CAIRO=True FAST=True || cat config.log # workaround ar bug: https://sourceware.org/bugzilla/show_bug.cgi?id=13256 - echo 'ar "$@" --plugin /usr/lib/LLVMgold.so' > ar-lto && chmod +x ./ar-lto && export AR=$(pwd)/ar-lto - if [[ "${CXX}" == 'g++-4.8' ]]; then JOBS=2 make; else JOBS=6 make; fi; From 4cb7b56f6676669a2951ffa6f03bd4a345a1b647 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 15:01:48 -0700 Subject: [PATCH 75/92] remove uneeded logging --- src/symbolizer.cpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/symbolizer.cpp b/src/symbolizer.cpp index fdceb66f7..7107fe706 100644 --- a/src/symbolizer.cpp +++ b/src/symbolizer.cpp @@ -36,10 +36,6 @@ void evaluate_transform(agg::trans_affine& tr, { if (trans_expr) { -#ifdef MAPNIK_LOG - MAPNIK_LOG_DEBUG(transform) << "transform: evaluate " - << transform_processor_type::to_string(*trans_expr); -#endif transform_processor_type::evaluate(tr, feature, vars, *trans_expr, scale_factor); } } From 95430a3bebf6d61d8697b9025878cde9c4af4684 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 15:41:18 -0700 Subject: [PATCH 76/92] remove uneeded debug statement --- include/mapnik/offset_converter.hpp | 4 ---- 1 file changed, 4 deletions(-) diff --git a/include/mapnik/offset_converter.hpp b/include/mapnik/offset_converter.hpp index 685c25d80..e7316d0f9 100644 --- a/include/mapnik/offset_converter.hpp +++ b/include/mapnik/offset_converter.hpp @@ -387,10 +387,6 @@ private: void push_vertex(vertex2d const& v) { - #ifdef MAPNIK_LOG - MAPNIK_LOG_DEBUG(ctrans) << "offset_converter: " << v; - #endif - vertices_.push_back(v); } From 1c9afc9a866b8dc1939a95f927ba3b70ba1859e0 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:37:25 -0700 Subject: [PATCH 77/92] boolean_type cleanup/code re-use --- include/mapnik/boolean.hpp | 34 +++++++++++++--------------------- 1 file changed, 13 insertions(+), 21 deletions(-) diff --git a/include/mapnik/boolean.hpp b/include/mapnik/boolean.hpp index ea267d3cb..bbee2b513 100644 --- a/include/mapnik/boolean.hpp +++ b/include/mapnik/boolean.hpp @@ -22,17 +22,22 @@ #ifndef MAPNIK_BOOLEAN_HPP #define MAPNIK_BOOLEAN_HPP +// mapnik +#include +#include + // std -#include +#include #include #include -#include +//#include +//#include namespace mapnik { -// Helper for class bool -class boolean_type { +class MAPNIK_DECL boolean_type +{ public: boolean_type() : b_(false) {} @@ -63,25 +68,12 @@ template std::basic_istream & operator >> ( std::basic_istream & s, boolean_type & b ) { - std::string word; - s >> word; - std::transform(word.begin(), word.end(), word.begin(), ::tolower); if ( s ) { - if ( word == "true" || word == "yes" || word == "on" || - word == "1") - { - b = true; - } - else if ( word == "false" || word == "no" || word == "off" || - word == "0") - { - b = false; - } - else - { - s.setstate( std::ios::failbit ); - } + std::string word; + s >> word; + bool result; + if (util::string2bool(word,result)) b = result; } return s; } From d61efc0b5a5f9824d58cb580f1adb967b17f514e Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:40:05 -0700 Subject: [PATCH 78/92] -fvisibility=hidden fixes on osx with -flto --- include/mapnik/enumeration.hpp | 6 +++--- include/mapnik/group/group_rule.hpp | 2 +- include/mapnik/image_data.hpp | 3 ++- include/mapnik/symbolizer.hpp | 18 +++++++++--------- include/mapnik/value_types.hpp | 5 ++++- plugins/input/gdal/gdal_datasource.cpp | 1 + 6 files changed, 20 insertions(+), 15 deletions(-) diff --git a/include/mapnik/enumeration.hpp b/include/mapnik/enumeration.hpp index f60a16f45..c0ca1c79e 100644 --- a/include/mapnik/enumeration.hpp +++ b/include/mapnik/enumeration.hpp @@ -333,8 +333,8 @@ operator>>(std::istream & is, mapnik::enumeration & e) */ #define IMPLEMENT_ENUM( name, strings ) \ - template <> const char ** name ::our_strings_ = strings; \ - template <> std::string name ::our_name_ = #name; \ - template <> bool name ::our_verified_flag_( name ::verify_mapnik_enum(__FILE__, __LINE__)); + template <> MAPNIK_DECL const char ** name ::our_strings_ = strings; \ + template <> MAPNIK_DECL std::string name ::our_name_ = #name; \ + template <> MAPNIK_DECL bool name ::our_verified_flag_( name ::verify_mapnik_enum(__FILE__, __LINE__)); #endif // MAPNIK_ENUMERATION_HPP diff --git a/include/mapnik/group/group_rule.hpp b/include/mapnik/group/group_rule.hpp index da83a6707..267093b78 100644 --- a/include/mapnik/group/group_rule.hpp +++ b/include/mapnik/group/group_rule.hpp @@ -36,7 +36,7 @@ namespace mapnik * be rendered atomically when the filter attached to * this rule is matched. */ -struct group_rule +struct MAPNIK_DECL group_rule { using symbolizers = std::vector; diff --git a/include/mapnik/image_data.hpp b/include/mapnik/image_data.hpp index f576e09d0..599387e04 100644 --- a/include/mapnik/image_data.hpp +++ b/include/mapnik/image_data.hpp @@ -25,6 +25,7 @@ // mapnik #include +#include // stl #include @@ -34,7 +35,7 @@ namespace mapnik { template -class ImageData +class MAPNIK_DECL ImageData { public: using pixel_type = T; diff --git a/include/mapnik/symbolizer.hpp b/include/mapnik/symbolizer.hpp index ad3a0c9bb..92df57b47 100644 --- a/include/mapnik/symbolizer.hpp +++ b/include/mapnik/symbolizer.hpp @@ -90,7 +90,7 @@ using dash_array = std::vector >; class text_placements; using text_placements_ptr = std::shared_ptr; -struct MAPNIK_DECL symbolizer_base +struct MAPNIK_DECL symbolizer_base { using value_type = boost::variant }; template -void put(symbolizer_base & sym, keys key, T const& val) +MAPNIK_DECL void put(symbolizer_base & sym, keys key, T const& val) { constexpr bool enum_ = std::is_enum::value; detail::put_impl::apply(sym, key, val); } template -bool has_key(symbolizer_base const& sym, keys key) +MAPNIK_DECL bool has_key(symbolizer_base const& sym, keys key) { return (sym.properties.count(key) == 1); } template -T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars, T const& _default_value = T()) +MAPNIK_DECL T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars, T const& _default_value = T()) { using const_iterator = symbolizer_base::cont_type::const_iterator; const_iterator itr = sym.properties.find(key); @@ -478,7 +478,7 @@ T get(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, } template -boost::optional get_optional(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars) +MAPNIK_DECL boost::optional get_optional(symbolizer_base const& sym, keys key, mapnik::feature_impl const& feature, attributes const& vars) { using const_iterator = symbolizer_base::cont_type::const_iterator; const_iterator itr = sym.properties.find(key); @@ -490,7 +490,7 @@ boost::optional get_optional(symbolizer_base const& sym, keys key, mapnik::fe } template -T get(symbolizer_base const& sym, keys key, T const& _default_value = T()) +MAPNIK_DECL T get(symbolizer_base const& sym, keys key, T const& _default_value = T()) { using const_iterator = symbolizer_base::cont_type::const_iterator; const_iterator itr = sym.properties.find(key); @@ -502,7 +502,7 @@ T get(symbolizer_base const& sym, keys key, T const& _default_value = T()) } template -boost::optional get_optional(symbolizer_base const& sym, keys key) +MAPNIK_DECL boost::optional get_optional(symbolizer_base const& sym, keys key) { using const_iterator = symbolizer_base::cont_type::const_iterator; const_iterator itr = sym.properties.find(key); @@ -520,8 +520,8 @@ constexpr auto to_integral(Enum e) -> typename std::underlying_type::type } using property_meta_type = std::tuple, property_types>; -property_meta_type const& get_meta(mapnik::keys key); -mapnik::keys get_key(std::string const& name); +MAPNIK_DECL property_meta_type const& get_meta(mapnik::keys key); +MAPNIK_DECL mapnik::keys get_key(std::string const& name); // concrete symbolizer types struct MAPNIK_DECL point_symbolizer : public symbolizer_base {}; diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index 8e810199e..fb6e2d8c7 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -23,6 +23,9 @@ #ifndef MAPNIK_VALUE_TYPES_HPP #define MAPNIK_VALUE_TYPES_HPP +// mapnik +#include + // icu #include // for UnicodeString @@ -42,7 +45,7 @@ using value_double = double; using value_unicode_string = U_NAMESPACE_QUALIFIER UnicodeString; using value_bool = bool; -struct value_null +struct MAPNIK_DECL value_null { bool operator==(value_null const&) const { diff --git a/plugins/input/gdal/gdal_datasource.cpp b/plugins/input/gdal/gdal_datasource.cpp index 6da44d0cd..ed714019c 100644 --- a/plugins/input/gdal/gdal_datasource.cpp +++ b/plugins/input/gdal/gdal_datasource.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include From 52b1da225b0a0edc816bcdad6d844129321f2ef5 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:41:34 -0700 Subject: [PATCH 79/92] less verbose ifdefs --- src/image_util.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/image_util.cpp b/src/image_util.cpp index 6f3536e81..79f74b2bf 100644 --- a/src/image_util.cpp +++ b/src/image_util.cpp @@ -58,17 +58,16 @@ extern "C" #include #ifdef CAIRO_HAS_PDF_SURFACE #include -#endif // CAIRO_HAS_PDF_SURFACE +#endif #ifdef CAIRO_HAS_PS_SURFACE #include -#endif // CAIRO_HAS_PS_SURFACE +#endif #ifdef CAIRO_HAS_SVG_SURFACE #include -#endif // CAIRO_HAS_SVG_SURFACE +#endif #endif // boost - #include // stl From 1c0b1884c3fcf72efbb3d565a2a4a66f30fdb26b Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:44:08 -0700 Subject: [PATCH 80/92] use extern template to solve -fvisibility=hidden issues on osx --- include/mapnik/image_util.hpp | 57 ++++++++++++++--------------------- 1 file changed, 23 insertions(+), 34 deletions(-) diff --git a/include/mapnik/image_util.hpp b/include/mapnik/image_util.hpp index c9bfe1fa7..fcd7dbdf3 100644 --- a/include/mapnik/image_util.hpp +++ b/include/mapnik/image_util.hpp @@ -25,10 +25,8 @@ // mapnik #include - -#ifdef _MSC_VER -#include -#endif +#include +#include // boost #include @@ -37,6 +35,7 @@ // stl #include #include +#include namespace mapnik { @@ -132,44 +131,43 @@ void save_as_jpeg(std::string const& filename, T const& image); #endif -inline bool is_png (std::string const& filename) +inline bool is_png(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".png")); } -inline bool is_jpeg (std::string const& filename) +inline bool is_jpeg(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".jpg")) || boost::algorithm::iends_with(filename,std::string(".jpeg")); } -inline bool is_tiff (std::string const& filename) +inline bool is_tiff(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".tif")) || boost::algorithm::iends_with(filename,std::string(".tiff")); } -inline bool is_pdf (std::string const& filename) +inline bool is_pdf(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".pdf")); } -inline bool is_svg (std::string const& filename) +inline bool is_svg(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".svg")); } -inline bool is_ps (std::string const& filename) +inline bool is_ps(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".ps")); } -inline bool is_webp (std::string const& filename) +inline bool is_webp(std::string const& filename) { return boost::algorithm::iends_with(filename,std::string(".webp")); } - inline boost::optional type_from_filename(std::string const& filename) { @@ -193,15 +191,6 @@ inline std::string guess_type( std::string const& filename ) return ""; } -template -double distance(T x0,T y0,T x1,T y1) -{ - double dx = x1-x0; - double dy = y1-y0; - return std::sqrt(dx * dx + dy * dy); -} - - // add 1-px border around image - useful for debugging alignment issues template void add_border(T & image) @@ -257,53 +246,53 @@ MAPNIK_DECL void save_to_stream(image_32 const& image, /////////////////////////////////////////////////////////////////////////// -#ifdef _MSC_VER -template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_32 const&, std::string const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_32 const&, std::string const&, std::string const&); -template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_32 const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL void save_to_file(image_data_32 const&, +extern template MAPNIK_DECL void save_to_file(image_data_32 const&, std::string const&); -template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, std::string const&); -template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL void save_to_file > (image_view const&, +extern template MAPNIK_DECL void save_to_file > (image_view const&, std::string const&); -template MAPNIK_DECL std::string save_to_string(image_data_32 const&, +extern template MAPNIK_DECL std::string save_to_string(image_data_32 const&, std::string const&); -template MAPNIK_DECL std::string save_to_string(image_data_32 const&, +extern template MAPNIK_DECL std::string save_to_string(image_data_32 const&, std::string const&, rgba_palette const&); -template MAPNIK_DECL std::string save_to_string > (image_view const&, +extern template MAPNIK_DECL std::string save_to_string > (image_view const&, std::string const&); -template MAPNIK_DECL std::string save_to_string > (image_view const&, +extern template MAPNIK_DECL std::string save_to_string > (image_view const&, std::string const&, rgba_palette const&); +#ifdef _MSC_VER template MAPNIK_DECL void save_to_stream( image_data_32 const& image, From bcc92c96935d2d82a060bbe52bbf2ec225b3a3c4 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 16:06:04 -0700 Subject: [PATCH 81/92] Travis: disable notifications + only run bench when built --- .travis.yml | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/.travis.yml b/.travis.yml index 440b25f43..e60523602 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,10 +51,4 @@ before_script: - make test script: - - make bench - -notifications: - irc: - channels: - - "irc.freenode.org#mapnik" - use_notice: true + - if [[ ${BENCHMARK} ]]; then make bench; fi; From 8ff987af6de5e7f6d8023f8af3df83d3b8287252 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Fri, 8 Aug 2014 21:58:08 -0700 Subject: [PATCH 82/92] iwyu --- bindings/python/python_to_value.hpp | 1 + include/mapnik/evaluate_global_attributes.hpp | 1 + include/mapnik/label_collision_detector.hpp | 3 +++ include/mapnik/util/conversions.hpp | 1 - include/mapnik/value.hpp | 5 ++++- include/mapnik/value_types.hpp | 7 ++++++- 6 files changed, 15 insertions(+), 3 deletions(-) diff --git a/bindings/python/python_to_value.hpp b/bindings/python/python_to_value.hpp index fd2eb4da2..6d220b61f 100644 --- a/bindings/python/python_to_value.hpp +++ b/bindings/python/python_to_value.hpp @@ -27,6 +27,7 @@ // mapnik #include +#include #include diff --git a/include/mapnik/evaluate_global_attributes.hpp b/include/mapnik/evaluate_global_attributes.hpp index c2f6a75f2..9dedee2c4 100644 --- a/include/mapnik/evaluate_global_attributes.hpp +++ b/include/mapnik/evaluate_global_attributes.hpp @@ -30,6 +30,7 @@ #include #include #include +#include // boost #include diff --git a/include/mapnik/label_collision_detector.hpp b/include/mapnik/label_collision_detector.hpp index af5eef979..254704205 100644 --- a/include/mapnik/label_collision_detector.hpp +++ b/include/mapnik/label_collision_detector.hpp @@ -28,6 +28,9 @@ #include #include +// icu +#include + // stl #include diff --git a/include/mapnik/util/conversions.hpp b/include/mapnik/util/conversions.hpp index e9bd716a8..22cafea52 100644 --- a/include/mapnik/util/conversions.hpp +++ b/include/mapnik/util/conversions.hpp @@ -30,7 +30,6 @@ // stl #include #include -#include namespace mapnik { namespace util { diff --git a/include/mapnik/value.hpp b/include/mapnik/value.hpp index 5c96e257f..5869e35eb 100644 --- a/include/mapnik/value.hpp +++ b/include/mapnik/value.hpp @@ -38,6 +38,9 @@ #include #include #include +#include +#include +#include // icu #include @@ -118,7 +121,7 @@ struct equals } template - bool operator() (T const& /*lhs*/, U const& /*rhs*/) const + bool operator() (T const&, U const&) const { return false; } diff --git a/include/mapnik/value_types.hpp b/include/mapnik/value_types.hpp index fb6e2d8c7..01709781a 100644 --- a/include/mapnik/value_types.hpp +++ b/include/mapnik/value_types.hpp @@ -27,10 +27,15 @@ #include // icu -#include // for UnicodeString +#include // for U_NAMESPACE_QUALIFIER // stl #include +#include + +namespace U_ICU_NAMESPACE { + class UnicodeString; +} namespace mapnik { From 678907e027e34b2a35127d130c130f383e8ff0b4 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 13:57:01 -0700 Subject: [PATCH 83/92] silence webp -Wunused-function warning --- include/mapnik/webp_io.hpp | 3 +++ src/webp_reader.cpp | 3 +++ 2 files changed, 6 insertions(+) diff --git a/include/mapnik/webp_io.hpp b/include/mapnik/webp_io.hpp index f6e80767f..851bd53d6 100644 --- a/include/mapnik/webp_io.hpp +++ b/include/mapnik/webp_io.hpp @@ -30,7 +30,10 @@ // webp #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-function" +extern "C" +{ #include +} #pragma clang diagnostic pop // stl diff --git a/src/webp_reader.cpp b/src/webp_reader.cpp index c4327c66c..bd618f222 100644 --- a/src/webp_reader.cpp +++ b/src/webp_reader.cpp @@ -25,11 +25,14 @@ #include #include +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wunused-function" extern "C" { #include #include } +#pragma clang diagnostic pop // boost #include From b0392ff002ad9e43ad6b7939545ad36ad5292319 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 14:01:28 -0700 Subject: [PATCH 84/92] travis: fix benchmark run logic [skip ci] --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index e60523602..96d7b2173 100644 --- a/.travis.yml +++ b/.travis.yml @@ -51,4 +51,4 @@ before_script: - make test script: - - if [[ ${BENCHMARK} ]]; then make bench; fi; + - if [[ ${BENCHMARK} != False ]]; then make bench; fi; From 378ab71a51293b8f754eea48d64d2407498fb140 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sat, 9 Aug 2014 14:23:23 -0700 Subject: [PATCH 85/92] more -fvisibility=hidden fixes for osx --- include/mapnik/agg_renderer.hpp | 3 +++ include/mapnik/datasource_cache.hpp | 2 +- include/mapnik/text/vertex_cache.hpp | 3 ++- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/include/mapnik/agg_renderer.hpp b/include/mapnik/agg_renderer.hpp index 4a8dd89e2..bade3b4c1 100644 --- a/include/mapnik/agg_renderer.hpp +++ b/include/mapnik/agg_renderer.hpp @@ -53,6 +53,7 @@ namespace mapnik { class marker; class proj_transform; struct rasterizer; + class image_32; } namespace mapnik { @@ -165,6 +166,8 @@ private: void setup(Map const& m); }; +extern template class MAPNIK_DECL agg_renderer; + } // namespace mapnik #endif // MAPNIK_AGG_RENDERER_HPP diff --git a/include/mapnik/datasource_cache.hpp b/include/mapnik/datasource_cache.hpp index 6646888bd..bd646abb8 100644 --- a/include/mapnik/datasource_cache.hpp +++ b/include/mapnik/datasource_cache.hpp @@ -59,7 +59,7 @@ private: std::set plugin_directories_; }; -extern template class singleton; +extern template class MAPNIK_DECL singleton; } diff --git a/include/mapnik/text/vertex_cache.hpp b/include/mapnik/text/vertex_cache.hpp index 552b6845d..6069d03e7 100644 --- a/include/mapnik/text/vertex_cache.hpp +++ b/include/mapnik/text/vertex_cache.hpp @@ -25,6 +25,7 @@ // mapnik #include #include +#include // agg #include "agg_basics.h" @@ -41,7 +42,7 @@ class vertex_cache; using vertex_cache_ptr = std::shared_ptr; // Caches all path points and their lengths. Allows easy moving in both directions. -class vertex_cache +class MAPNIK_DECL vertex_cache { struct segment { From 4c10d901457e66f65eeee88f73f484a6b58a8f1c Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:02:34 -0700 Subject: [PATCH 86/92] declare segment y_order inline --- include/mapnik/segment.hpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/mapnik/segment.hpp b/include/mapnik/segment.hpp index f5ea1605f..ef0582118 100644 --- a/include/mapnik/segment.hpp +++ b/include/mapnik/segment.hpp @@ -31,7 +31,7 @@ namespace mapnik using segment_t = std::tuple; -static bool y_order(segment_t const& first,segment_t const& second) +static inline bool y_order(segment_t const& first,segment_t const& second) { double miny0 = std::min(std::get<1>(first), std::get<3>(first)); double miny1 = std::min(std::get<1>(second), std::get<3>(second)); From 9a1423e66937588fed49b3170da609c297f03668 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:03:07 -0700 Subject: [PATCH 87/92] create cairo context raster than passing surface --- bindings/python/mapnik_python.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/bindings/python/mapnik_python.cpp b/bindings/python/mapnik_python.cpp index 11abd698f..dffecb821 100644 --- a/bindings/python/mapnik_python.cpp +++ b/bindings/python/mapnik_python.cpp @@ -241,7 +241,7 @@ void render3(mapnik::Map const& map, { python_unblock_auto_block b; mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - mapnik::cairo_renderer ren(map,surface,scale_factor,offset_x,offset_y); + mapnik::cairo_renderer ren(map,mapnik::create_context(surface),scale_factor,offset_x,offset_y); ren.apply(); } @@ -249,7 +249,7 @@ void render4(mapnik::Map const& map, PycairoSurface* py_surface) { python_unblock_auto_block b; mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - mapnik::cairo_renderer ren(map,surface); + mapnik::cairo_renderer ren(map,mapnik::create_context(surface)); ren.apply(); } @@ -304,7 +304,7 @@ void render_with_detector4( { python_unblock_auto_block b; mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - mapnik::cairo_renderer ren(map, surface, detector); + mapnik::cairo_renderer ren(map, mapnik::create_context(surface), detector); ren.apply(); } @@ -318,7 +318,7 @@ void render_with_detector5( { python_unblock_auto_block b; mapnik::cairo_surface_ptr surface(cairo_surface_reference(py_surface->surface), mapnik::cairo_surface_closer()); - mapnik::cairo_renderer ren(map, surface, detector, scale_factor, offset_x, offset_y); + mapnik::cairo_renderer ren(map, mapnik::create_context(surface), detector, scale_factor, offset_x, offset_y); ren.apply(); } From 7cae3c34cad073d90e558ab72aee88e2fd86faa3 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:04:20 -0700 Subject: [PATCH 88/92] iwyu in renderer_common --- .../renderer_common/process_building_symbolizer.hpp | 8 +++++++- .../renderer_common/process_group_symbolizer.hpp | 11 ++++++----- .../renderer_common/process_markers_symbolizer.hpp | 3 +++ .../renderer_common/process_point_symbolizer.hpp | 1 + .../renderer_common/process_raster_symbolizer.hpp | 6 +++++- 5 files changed, 22 insertions(+), 7 deletions(-) diff --git a/include/mapnik/renderer_common/process_building_symbolizer.hpp b/include/mapnik/renderer_common/process_building_symbolizer.hpp index aeea04cb2..5785e7bda 100644 --- a/include/mapnik/renderer_common/process_building_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_building_symbolizer.hpp @@ -23,6 +23,12 @@ #ifndef MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP #define MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP +#include +#include +#include + +#include + namespace mapnik { template @@ -106,4 +112,4 @@ void render_building_symbolizer(mapnik::feature_impl &feature, } // namespace mapnik -#endif /* MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP */ +#endif // MAPNIK_RENDERER_COMMON_PROCESS_BUILDING_SYMBOLIZER_HPP diff --git a/include/mapnik/renderer_common/process_group_symbolizer.hpp b/include/mapnik/renderer_common/process_group_symbolizer.hpp index abf13dbfc..db8c3de4a 100644 --- a/include/mapnik/renderer_common/process_group_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_group_symbolizer.hpp @@ -23,28 +23,29 @@ #ifndef MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP #define MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP +// mapnik #include #include #include #include #include -#include #include #include -#include #include -#include #include #include -#include #include #include +#include +// agg #include namespace mapnik { class proj_transform; +struct glyph_info; +class text_symbolizer_helper; // General: @@ -345,4 +346,4 @@ void render_group_symbolizer(group_symbolizer const& sym, } // namespace mapnik -#endif /* MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP */ +#endif // MAPNIK_RENDERER_COMMON_PROCESS_GROUP_SYMBOLIZER_HPP diff --git a/include/mapnik/renderer_common/process_markers_symbolizer.hpp b/include/mapnik/renderer_common/process_markers_symbolizer.hpp index 7500db447..68ffb07b5 100644 --- a/include/mapnik/renderer_common/process_markers_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_markers_symbolizer.hpp @@ -27,6 +27,9 @@ #include #include #include +#include + +// boost #include namespace mapnik { diff --git a/include/mapnik/renderer_common/process_point_symbolizer.hpp b/include/mapnik/renderer_common/process_point_symbolizer.hpp index e7cc3b5a7..6694bada8 100644 --- a/include/mapnik/renderer_common/process_point_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_point_symbolizer.hpp @@ -26,6 +26,7 @@ #include #include #include +#include namespace mapnik { diff --git a/include/mapnik/renderer_common/process_raster_symbolizer.hpp b/include/mapnik/renderer_common/process_raster_symbolizer.hpp index f575d2931..deddb74bc 100644 --- a/include/mapnik/renderer_common/process_raster_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_raster_symbolizer.hpp @@ -25,6 +25,10 @@ // mapnik #include +#include +#include +#include +#include // agg #include "agg_rendering_buffer.h" @@ -136,4 +140,4 @@ void render_raster_symbolizer(raster_symbolizer const &sym, } // namespace mapnik -#endif /* MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP */ +#endif // MAPNIK_RENDERER_COMMON_PROCESS_RASTER_SYMBOLIZER_HPP From 9c7f8284bd78bdbb6194276bd56ce008255a5b4a Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:52:45 -0700 Subject: [PATCH 89/92] iwyu --- src/renderer_common/process_group_symbolizer.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/renderer_common/process_group_symbolizer.cpp b/src/renderer_common/process_group_symbolizer.cpp index 14ac14899..8041507b7 100644 --- a/src/renderer_common/process_group_symbolizer.cpp +++ b/src/renderer_common/process_group_symbolizer.cpp @@ -21,6 +21,7 @@ *****************************************************************************/ #include +#include namespace mapnik { From c285cfa188a9f2231de48e5ff8637eafef1a9437 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 13:53:45 -0700 Subject: [PATCH 90/92] refactor cairo_renderer - splits process functions into new cpp files to reduce peak compile memory usage - drops cairo_renderer_base to match agg_renderer design - only cairo_ptr is accepted so cairo_surface_ptr must be converted into a context first - fixes -fvisibility=hidden --- include/mapnik/cairo/cairo_render_vector.hpp | 49 + include/mapnik/cairo/cairo_renderer.hpp | 112 +- .../process_point_symbolizer.hpp | 4 +- .../process_polygon_symbolizer.hpp | 2 + src/build.py | 14 +- src/cairo/cairo_context.cpp | 2 +- src/cairo/cairo_render_vector.cpp | 131 +++ src/cairo/cairo_renderer.cpp | 1045 +---------------- src/cairo/process_building_symbolizer.cpp | 84 ++ src/cairo/process_debug_symbolizer.cpp | 110 ++ src/cairo/process_group_symbolizer.cpp | 126 ++ src/cairo/process_line_pattern_symbolizer.cpp | 141 +++ src/cairo/process_line_symbolizer.cpp | 116 ++ src/cairo/process_markers_symbolizer.cpp | 224 ++++ src/cairo/process_point_symbolizer.cpp | 66 ++ .../process_polygon_pattern_symbolizer.cpp | 135 +++ src/cairo/process_polygon_symbolizer.cpp | 66 ++ src/cairo/process_raster_symbolizer.cpp | 59 + src/cairo/process_text_symbolizer.cpp | 107 ++ src/feature_style_processor.cpp | 1 - 20 files changed, 1549 insertions(+), 1045 deletions(-) create mode 100644 include/mapnik/cairo/cairo_render_vector.hpp create mode 100644 src/cairo/cairo_render_vector.cpp create mode 100644 src/cairo/process_building_symbolizer.cpp create mode 100644 src/cairo/process_debug_symbolizer.cpp create mode 100644 src/cairo/process_group_symbolizer.cpp create mode 100644 src/cairo/process_line_pattern_symbolizer.cpp create mode 100644 src/cairo/process_line_symbolizer.cpp create mode 100644 src/cairo/process_markers_symbolizer.cpp create mode 100644 src/cairo/process_point_symbolizer.cpp create mode 100644 src/cairo/process_polygon_pattern_symbolizer.cpp create mode 100644 src/cairo/process_polygon_symbolizer.cpp create mode 100644 src/cairo/process_raster_symbolizer.cpp create mode 100644 src/cairo/process_text_symbolizer.cpp diff --git a/include/mapnik/cairo/cairo_render_vector.hpp b/include/mapnik/cairo/cairo_render_vector.hpp new file mode 100644 index 000000000..3016fad35 --- /dev/null +++ b/include/mapnik/cairo/cairo_render_vector.hpp @@ -0,0 +1,49 @@ +/***************************************************************************** + * + * 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +#ifndef MAPNIK_CAIRO_RENDER_VECTOR_HPP +#define MAPNIK_CAIRO_RENDER_VECTOR_HPP + +// mapnik +#include + +namespace agg { struct trans_affine; } + +namespace mapnik { + +class cairo_context; +struct pixel_position; +template class box2d; +namespace svg { struct path_attributes; } + +void render_vector_marker(cairo_context & context, pixel_position const& pos, + svg::svg_path_adapter & svg_path, box2d const& bbox, + agg::pod_bvector const & attributes, + agg::trans_affine const& tr, double opacity, bool recenter); + +} + +#endif // MAPNIK_CAIRO_RENDER_VECTOR_HPP + +#endif \ No newline at end of file diff --git a/include/mapnik/cairo/cairo_renderer.hpp b/include/mapnik/cairo/cairo_renderer.hpp index 2b70b089d..0abfc7294 100644 --- a/include/mapnik/cairo/cairo_renderer.hpp +++ b/include/mapnik/cairo/cairo_renderer.hpp @@ -28,19 +28,13 @@ // mapnik #include #include -#include -#include -#include -#include -#include // for all symbolizers #include +#include // for all symbolizers #include -#include -#include // for CoordTransform #include -// cairo -#include +// stl +#include namespace agg { struct trans_affine; @@ -48,34 +42,57 @@ struct trans_affine; namespace mapnik { +class Map; +class feature_impl; +class feature_type_style; +class label_collision_detector4; +class layer; class marker; - -class MAPNIK_DECL cairo_renderer_base : private mapnik::noncopyable +class proj_transform; +class request; +struct pixel_position; +struct cairo_save_restore +{ + cairo_save_restore(cairo_context & context) + : context_(context) + { + context_.save(); + } + ~cairo_save_restore() + { + context_.restore(); + } + cairo_context & context_; +}; + +template +class MAPNIK_DECL cairo_renderer : public feature_style_processor >, + private mapnik::noncopyable { -protected: - cairo_renderer_base(Map const& m, - cairo_ptr const& cairo, - attributes const& vars, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - cairo_renderer_base(Map const& m, - request const& req, - cairo_ptr const& cairo, - attributes const& vars, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - cairo_renderer_base(Map const& m, - cairo_ptr const& cairo, - attributes const& vars, - std::shared_ptr detector, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); public: - ~cairo_renderer_base(); + using processor_impl_type = cairo_renderer; + cairo_renderer(Map const& m, + T const& obj, + double scale_factor=1.0, + unsigned offset_x=0, + unsigned offset_y=0); + cairo_renderer(Map const& m, + request const& req, + attributes const& vars, + T const& obj, + double scale_factor=1.0, + unsigned offset_x=0, + unsigned offset_y=0); + cairo_renderer(Map const& m, + T const& obj, + std::shared_ptr detector, + double scale_factor=1.0, + unsigned offset_x=0, + unsigned offset_y=0); + + ~cairo_renderer(); void start_map_processing(Map const& map); + void end_map_processing(Map const& map); void start_layer_processing(layer const& lay, box2d const& query_extent); void end_layer_processing(layer const& lay); void start_style_processing(feature_type_style const& st); @@ -155,34 +172,11 @@ protected: renderer_common common_; cairo_face_manager face_manager_; void setup(Map const& m); + }; -template -class MAPNIK_DECL cairo_renderer : public feature_style_processor >, - public cairo_renderer_base -{ -public: - using processor_impl_type = cairo_renderer_base; - cairo_renderer(Map const& m, - T const& obj, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - cairo_renderer(Map const& m, - request const& req, - attributes const& vars, - T const& obj, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - cairo_renderer(Map const& m, - T const& obj, - std::shared_ptr detector, - double scale_factor=1.0, - unsigned offset_x=0, - unsigned offset_y=0); - void end_map_processing(Map const& map); -}; +extern template class MAPNIK_DECL cairo_renderer; + } #endif // MAPNIK_CAIRO_RENDERER_HPP diff --git a/include/mapnik/renderer_common/process_point_symbolizer.hpp b/include/mapnik/renderer_common/process_point_symbolizer.hpp index 6694bada8..a58a6a714 100644 --- a/include/mapnik/renderer_common/process_point_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_point_symbolizer.hpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -24,6 +24,8 @@ #define MAPNIK_RENDERER_COMMON_PROCESS_POINT_SYMBOLIZER_HPP #include +#include +#include #include #include #include diff --git a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp index 42bbf12d6..901158d5b 100644 --- a/include/mapnik/renderer_common/process_polygon_symbolizer.hpp +++ b/include/mapnik/renderer_common/process_polygon_symbolizer.hpp @@ -23,6 +23,8 @@ #ifndef MAPNIK_RENDERER_COMMON_PROCESS_POLYGON_SYMBOLIZER_HPP #define MAPNIK_RENDERER_COMMON_PROCESS_POLYGON_SYMBOLIZER_HPP +#include + namespace mapnik { template diff --git a/src/build.py b/src/build.py index aa273f8aa..cd360f997 100644 --- a/src/build.py +++ b/src/build.py @@ -272,8 +272,20 @@ if env['HAS_CAIRO']: lib_env.Append(CPPDEFINES = '-DHAVE_CAIRO') libmapnik_defines.append('-DHAVE_CAIRO') lib_env.AppendUnique(CPPPATH=copy(env['CAIRO_CPPPATHS'])) - source.append('cairo/cairo_renderer.cpp') source.append('cairo/cairo_context.cpp') + source.append('cairo/cairo_renderer.cpp') + source.append('cairo/cairo_render_vector.cpp') + source.append('cairo/process_markers_symbolizer.cpp') + source.append('cairo/process_text_symbolizer.cpp') + source.append('cairo/process_group_symbolizer.cpp') + source.append('cairo/process_line_symbolizer.cpp') + source.append('cairo/process_line_pattern_symbolizer.cpp') + source.append('cairo/process_polygon_symbolizer.cpp') + source.append('cairo/process_polygon_pattern_symbolizer.cpp') + source.append('cairo/process_debug_symbolizer.cpp') + source.append('cairo/process_point_symbolizer.cpp') + source.append('cairo/process_raster_symbolizer.cpp') + source.append('cairo/process_building_symbolizer.cpp') for cpp in enabled_imaging_libraries: source.append(cpp) diff --git a/src/cairo/cairo_context.cpp b/src/cairo/cairo_context.cpp index 3a908ef8f..1c59a8303 100644 --- a/src/cairo/cairo_context.cpp +++ b/src/cairo/cairo_context.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2013 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public diff --git a/src/cairo/cairo_render_vector.cpp b/src/cairo/cairo_render_vector.cpp new file mode 100644 index 000000000..31a24f33d --- /dev/null +++ b/src/cairo/cairo_render_vector.cpp @@ -0,0 +1,131 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include + +namespace mapnik +{ + +void render_vector_marker(cairo_context & context, pixel_position const& pos, + svg::svg_path_adapter & svg_path, box2d const& bbox, + agg::pod_bvector const & attributes, + agg::trans_affine const& tr, double opacity, bool recenter) +{ + using namespace mapnik::svg; + agg::trans_affine mtx = tr; + if (recenter) + { + coord c = bbox.center(); + mtx = agg::trans_affine_translation(-c.x,-c.y); + mtx *= tr; + mtx.translate(pos.x, pos.y); + } + + agg::trans_affine transform; + + for(unsigned i = 0; i < attributes.size(); ++i) + { + mapnik::svg::path_attributes const& attr = attributes[i]; + if (!attr.visibility_flag) + continue; + cairo_save_restore guard(context); + transform = attr.transform; + transform *= mtx; + + // TODO - this 'is_valid' check is not used in the AGG renderer and also + // appears to lead to bogus results with + // tests/data/good_maps/markers_symbolizer_lines_file.xml + //if (transform.is_valid() && !transform.is_identity()) + if (!transform.is_identity()) + { + double m[6]; + transform.store_to(m); + cairo_matrix_t matrix; + cairo_matrix_init(&matrix,m[0],m[1],m[2],m[3],m[4],m[5]); + context.transform(matrix); + } + + if (attr.fill_flag || attr.fill_gradient.get_gradient_type() != NO_GRADIENT) + { + context.add_agg_path(svg_path,attr.index); + if (attr.even_odd_flag) + { + context.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); + } + else + { + context.set_fill_rule(CAIRO_FILL_RULE_WINDING); + } + if(attr.fill_gradient.get_gradient_type() != NO_GRADIENT) + { + cairo_gradient g(attr.fill_gradient,attr.fill_opacity * attr.opacity * opacity); + + context.set_gradient(g,bbox); + context.fill(); + } + else if(attr.fill_flag) + { + double fill_opacity = attr.fill_opacity * attr.opacity * opacity * attr.fill_color.opacity(); + context.set_color(attr.fill_color.r/255.0,attr.fill_color.g/255.0, + attr.fill_color.b/255.0, fill_opacity); + context.fill(); + } + } + + if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT || attr.stroke_flag) + { + context.add_agg_path(svg_path,attr.index); + if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) + { + context.set_line_width(attr.stroke_width); + context.set_line_cap(line_cap_enum(attr.line_cap)); + context.set_line_join(line_join_enum(attr.line_join)); + context.set_miter_limit(attr.miter_limit); + cairo_gradient g(attr.stroke_gradient,attr.fill_opacity * attr.opacity * opacity); + context.set_gradient(g,bbox); + context.stroke(); + } + else if (attr.stroke_flag) + { + double stroke_opacity = attr.stroke_opacity * attr.opacity * opacity * attr.stroke_color.opacity(); + context.set_color(attr.stroke_color.r/255.0,attr.stroke_color.g/255.0, + attr.stroke_color.b/255.0, stroke_opacity); + context.set_line_width(attr.stroke_width); + context.set_line_cap(line_cap_enum(attr.line_cap)); + context.set_line_join(line_join_enum(attr.line_join)); + context.set_miter_limit(attr.miter_limit); + context.stroke(); + } + } + } +} + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index a357f11fc..62d6c959a 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -2,7 +2,7 @@ * * This file is part of Mapnik (c++ mapping toolkit) * - * Copyright (C) 2011 Artem Pavlenko + * Copyright (C) 2014 Artem Pavlenko * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,113 +23,56 @@ #if defined(HAVE_CAIRO) // mapnik -#include -#include #include #include -#include -#include #include -#include #include -#include -#include -#include -#include -#include -#include -#include -#include +#include #include #include -#include -#include -#include -#include -#include -#include -#include -#include -#include // todo - only need some of this expensive header -#include #include -#include -#include -#include -#include #include -#include -#include -#include - -// mapnik symbolizer generics -#include -#include -#include -#include -#include -#include -// cairo -#include -#include -#include - -// boost -#include +#include +#include +#include +#include // agg -#include "agg_conv_clip_polyline.h" -#include "agg_conv_clip_polygon.h" -#include "agg_conv_smooth_poly1.h" -#include "agg_rendering_buffer.h" -#include "agg_pixfmt_rgba.h" -// markers -#include "agg_path_storage.h" -#include "agg_ellipse.h" +#include "agg/include/agg_trans_affine.h" // for trans_affine, etc // stl -#include #include namespace mapnik { -struct cairo_save_restore -{ - cairo_save_restore(cairo_context & context) - : context_(context) - { - context_.save(); - } - ~cairo_save_restore() - { - context_.restore(); - } - cairo_context & context_; -}; +class feature_type_style; -cairo_renderer_base::cairo_renderer_base(Map const& m, - cairo_ptr const& cairo, - attributes const& vars, - double scale_factor, - unsigned offset_x, - unsigned offset_y) - : m_(m), +template +cairo_renderer::cairo_renderer(Map const& m, + T const& cairo, + double scale_factor, + unsigned offset_x, + unsigned offset_y) + : feature_style_processor(m, scale_factor), + m_(m), context_(cairo), - common_(m, vars, offset_x, offset_y, m.width(), m.height(), scale_factor), + common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor), face_manager_(common_.shared_font_engine_) { setup(m); } -cairo_renderer_base::cairo_renderer_base(Map const& m, - request const& req, - cairo_ptr const& cairo, - attributes const& vars, - double scale_factor, - unsigned offset_x, - unsigned offset_y) - : m_(m), +template +cairo_renderer::cairo_renderer(Map const& m, + request const& req, + attributes const& vars, + T const& cairo, + double scale_factor, + unsigned offset_x, + unsigned offset_y) + : feature_style_processor(m, scale_factor), + m_(m), context_(cairo), common_(req, vars, offset_x, offset_y, req.width(), req.height(), scale_factor), face_manager_(common_.shared_font_engine_) @@ -137,54 +80,27 @@ cairo_renderer_base::cairo_renderer_base(Map const& m, setup(m); } -cairo_renderer_base::cairo_renderer_base(Map const& m, - cairo_ptr const& cairo, - attributes const& vars, - std::shared_ptr detector, - double scale_factor, - unsigned offset_x, - unsigned offset_y) - : m_(m), +template +cairo_renderer::cairo_renderer(Map const& m, + T const& cairo, + std::shared_ptr detector, + double scale_factor, + unsigned offset_x, + unsigned offset_y) + : feature_style_processor(m, scale_factor), + m_(m), context_(cairo), - common_(m, vars, offset_x, offset_y, m.width(), m.height(), scale_factor, detector), + common_(m, attributes(), offset_x, offset_y, m.width(), m.height(), scale_factor, detector), face_manager_(common_.shared_font_engine_) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Scale=" << m.scale(); + setup(m); } -template <> -cairo_renderer::cairo_renderer(Map const& m, cairo_ptr const& cairo, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,cairo,attributes(),scale_factor,offset_x,offset_y) {} +template +cairo_renderer::~cairo_renderer() {} -template <> -cairo_renderer::cairo_renderer(Map const& m, cairo_surface_ptr const& surface, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,create_context(surface),attributes(),scale_factor,offset_x,offset_y) {} - -template <> -cairo_renderer::cairo_renderer(Map const& m, request const& req, attributes const& vars, cairo_ptr const& cairo, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,req,cairo,vars,scale_factor,offset_x,offset_y) {} - -template <> -cairo_renderer::cairo_renderer(Map const& m, request const& req, attributes const& vars, cairo_surface_ptr const& surface, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,req,create_context(surface),attributes(),scale_factor,offset_x,offset_y) {} - -template <> -cairo_renderer::cairo_renderer(Map const& m, cairo_ptr const& cairo, std::shared_ptr detector, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,cairo,attributes(),detector,scale_factor,offset_x,offset_y) {} - -template <> -cairo_renderer::cairo_renderer(Map const& m, cairo_surface_ptr const& surface, std::shared_ptr detector, double scale_factor, unsigned offset_x, unsigned offset_y) - : feature_style_processor(m,scale_factor), - cairo_renderer_base(m,create_context(surface),attributes(),detector,scale_factor,offset_x,offset_y) {} - -cairo_renderer_base::~cairo_renderer_base() {} - -void cairo_renderer_base::setup(Map const& map) +template +void cairo_renderer::setup(Map const& map) { boost::optional bg = m_.background(); if (bg) @@ -221,36 +137,30 @@ void cairo_renderer_base::setup(Map const& map) } } } - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Scale=" << map.scale(); + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Scale=" << map.scale(); } -void cairo_renderer_base::start_map_processing(Map const& map) +template +void cairo_renderer::start_map_processing(Map const& map) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Start map processing bbox=" << map.get_current_extent(); + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Start map processing bbox=" << map.get_current_extent(); box2d bounds = common_.t_.forward(common_.t_.extent()); context_.rectangle(bounds.minx(), bounds.miny(), bounds.maxx(), bounds.maxy()); context_.clip(); } -template <> -void cairo_renderer::end_map_processing(Map const& ) +template +void cairo_renderer::end_map_processing(Map const&) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: End map processing"; + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: End map processing"; } -template <> -void cairo_renderer::end_map_processing(Map const& ) +template +void cairo_renderer::start_layer_processing(layer const& lay, box2d const& query_extent) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: End map processing"; - - context_.show_page(); -} - -void cairo_renderer_base::start_layer_processing(layer const& lay, box2d const& query_extent) -{ - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: Start processing layer=" << lay.name() ; - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: -- datasource=" << lay.datasource().get(); - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: -- query_extent=" << query_extent; + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: Start processing layer=" << lay.name() ; + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: -- datasource=" << lay.datasource().get(); + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: -- query_extent=" << query_extent; if (lay.clear_label_cache()) { @@ -259,263 +169,26 @@ void cairo_renderer_base::start_layer_processing(layer const& lay, box2d common_.query_extent_ = query_extent; } -void cairo_renderer_base::end_layer_processing(layer const&) +template +void cairo_renderer::end_layer_processing(layer const&) { - MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer_base: End layer processing"; + MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer: End layer processing"; } -void cairo_renderer_base::start_style_processing(feature_type_style const& st) +template +void cairo_renderer::start_style_processing(feature_type_style const& st) { MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:start style processing"; } -void cairo_renderer_base::end_style_processing(feature_type_style const& st) +template +void cairo_renderer::end_style_processing(feature_type_style const& st) { MAPNIK_LOG_DEBUG(cairo_renderer) << "cairo_renderer:end style processing"; } -void cairo_renderer_base::process(polygon_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using conv_types = boost::mpl::vector; - using vertex_converter_type = vertex_converter, cairo_context, polygon_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, - conv_types, feature_impl>; - - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - context_.set_operator(comp_op); - - render_polygon_symbolizer( - sym, feature, prj_trans, common_, common_.query_extent_, context_, - [&](color const &fill, double opacity) { - context_.set_color(fill, opacity); - // fill polygon - context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); - context_.fill(); - }); -} - -void cairo_renderer_base::process(building_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using path_type = coord_transform; - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - mapnik::color fill = get(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128)); - double opacity = get(sym, keys::fill_opacity, feature, common_.vars_, 1.0); - double height = get(sym, keys::height, feature, common_.vars_, 0.0); - - context_.set_operator(comp_op); - - render_building_symbolizer( - feature, height, - [&](geometry_type &faces) { - path_type faces_path(common_.t_, faces, prj_trans); - context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8 / 255.0, - fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0); - context_.add_path(faces_path); - context_.fill(); - }, - [&](geometry_type &frame) { - path_type path(common_.t_, frame, prj_trans); - context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8/255.0, - fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0); - context_.set_line_width(common_.scale_factor_); - context_.add_path(path); - context_.stroke(); - }, - [&](geometry_type &roof) { - path_type roof_path(common_.t_, roof, prj_trans); - context_.set_color(fill, opacity); - context_.add_path(roof_path); - context_.fill(); - }); -} - -void cairo_renderer_base::process(line_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using conv_types = boost::mpl::vector; - - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - bool clip = get(sym, keys::clip, feature, common_.vars_, false); - double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); - double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); - - mapnik::color stroke = get(sym, keys::stroke, feature, common_.vars_, mapnik::color(0,0,0)); - double stroke_opacity = get(sym, keys::stroke_opacity, feature, common_.vars_, 1.0); - line_join_enum stroke_join = get(sym, keys::stroke_linejoin, feature, common_.vars_, MITER_JOIN); - line_cap_enum stroke_cap = get(sym, keys::stroke_linecap, feature, common_.vars_, BUTT_CAP); - auto dash = get_optional(sym, keys::stroke_dasharray, feature, common_.vars_); - double miterlimit = get(sym, keys::stroke_miterlimit, feature, common_.vars_, 4.0); - double width = get(sym, keys::stroke_width, feature, common_.vars_, 1.0); - - cairo_save_restore guard(context_); - context_.set_operator(comp_op); - context_.set_color(stroke, stroke_opacity); - context_.set_line_join(stroke_join); - context_.set_line_cap(stroke_cap); - context_.set_miter_limit(miterlimit); - context_.set_line_width(width * common_.scale_factor_); - if (dash) - { - context_.set_dash(*dash, common_.scale_factor_); - } - - agg::trans_affine tr; - auto geom_transform = get_optional(sym, keys::geometry_transform); - if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - - box2d clipping_extent = common_.query_extent_; - if (clip) - { - double padding = (double)(common_.query_extent_.width()/common_.width_); - double half_stroke = width/2.0; - if (half_stroke > 1) - padding *= half_stroke; - if (std::fabs(offset) > 0) - padding *= std::fabs(offset) * 1.2; - padding *= common_.scale_factor_; - clipping_extent.pad(padding); - } - vertex_converter, cairo_context, line_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clipping_extent,context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); - - if (clip) converter.set(); // optional clip (default: true) - converter.set(); // always transform - if (std::fabs(offset) > 0.0) converter.set(); // parallel offset - converter.set(); // optional affine transform - if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter - if (smooth > 0.0) converter.set(); // optional smooth converter - - for (geometry_type & geom : feature.paths()) - { - if (geom.size() > 1) - { - converter.apply(geom); - } - } - // stroke - context_.set_fill_rule(CAIRO_FILL_RULE_WINDING); - context_.stroke(); -} - -void cairo_renderer_base::render_box(box2d const& b) -{ - cairo_save_restore guard(context_); - context_.move_to(b.minx(), b.miny()); - context_.line_to(b.minx(), b.maxy()); - context_.line_to(b.maxx(), b.maxy()); - context_.line_to(b.maxx(), b.miny()); - context_.close_path(); - context_.stroke(); -} - -void render_vector_marker(cairo_context & context, pixel_position const& pos, - svg::svg_path_adapter & svg_path, box2d const& bbox, - agg::pod_bvector const & attributes, - agg::trans_affine const& tr, double opacity, bool recenter) -{ - using namespace mapnik::svg; - agg::trans_affine mtx = tr; - if (recenter) - { - coord c = bbox.center(); - mtx = agg::trans_affine_translation(-c.x,-c.y); - mtx *= tr; - mtx.translate(pos.x, pos.y); - } - - agg::trans_affine transform; - - for(unsigned i = 0; i < attributes.size(); ++i) - { - mapnik::svg::path_attributes const& attr = attributes[i]; - if (!attr.visibility_flag) - continue; - cairo_save_restore guard(context); - transform = attr.transform; - transform *= mtx; - - // TODO - this 'is_valid' check is not used in the AGG renderer and also - // appears to lead to bogus results with - // tests/data/good_maps/markers_symbolizer_lines_file.xml - if (/*transform.is_valid() && */ !transform.is_identity()) - { - double m[6]; - transform.store_to(m); - cairo_matrix_t matrix; - cairo_matrix_init(&matrix,m[0],m[1],m[2],m[3],m[4],m[5]); - context.transform(matrix); - } - - if (attr.fill_flag || attr.fill_gradient.get_gradient_type() != NO_GRADIENT) - { - context.add_agg_path(svg_path,attr.index); - if (attr.even_odd_flag) - { - context.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); - } - else - { - context.set_fill_rule(CAIRO_FILL_RULE_WINDING); - } - if(attr.fill_gradient.get_gradient_type() != NO_GRADIENT) - { - cairo_gradient g(attr.fill_gradient,attr.fill_opacity * attr.opacity * opacity); - - context.set_gradient(g,bbox); - context.fill(); - } - else if(attr.fill_flag) - { - double fill_opacity = attr.fill_opacity * attr.opacity * opacity * attr.fill_color.opacity(); - context.set_color(attr.fill_color.r/255.0,attr.fill_color.g/255.0, - attr.fill_color.b/255.0, fill_opacity); - context.fill(); - } - } - - if (attr.stroke_gradient.get_gradient_type() != NO_GRADIENT || attr.stroke_flag) - { - context.add_agg_path(svg_path,attr.index); - if(attr.stroke_gradient.get_gradient_type() != NO_GRADIENT) - { - context.set_line_width(attr.stroke_width); - context.set_line_cap(line_cap_enum(attr.line_cap)); - context.set_line_join(line_join_enum(attr.line_join)); - context.set_miter_limit(attr.miter_limit); - cairo_gradient g(attr.stroke_gradient,attr.fill_opacity * attr.opacity * opacity); - context.set_gradient(g,bbox); - context.stroke(); - } - else if (attr.stroke_flag) - { - double stroke_opacity = attr.stroke_opacity * attr.opacity * opacity * attr.stroke_color.opacity(); - context.set_color(attr.stroke_color.r/255.0,attr.stroke_color.g/255.0, - attr.stroke_color.b/255.0, stroke_opacity); - context.set_line_width(attr.stroke_width); - context.set_line_cap(line_cap_enum(attr.line_cap)); - context.set_line_join(line_join_enum(attr.line_join)); - context.set_miter_limit(attr.miter_limit); - context.stroke(); - } - } - } -} - - -void cairo_renderer_base::render_marker(pixel_position const& pos, +template +void cairo_renderer::render_marker(pixel_position const& pos, marker const& marker, agg::trans_affine const& tr, double opacity, @@ -552,598 +225,6 @@ void cairo_renderer_base::render_marker(pixel_position const& pos, } } -void cairo_renderer_base::process(point_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - - cairo_save_restore guard(context_); - context_.set_operator(comp_op); - - render_point_symbolizer( - sym, feature, prj_trans, common_, - [this](pixel_position const& pos, marker const& marker, - agg::trans_affine const& tr, double opacity) { - render_marker(pos, marker, tr, opacity); - }); -} - -void cairo_renderer_base::process(shield_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - agg::trans_affine tr; - auto transform = get_optional(sym, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); - text_symbolizer_helper helper( - sym, feature, common_.vars_, prj_trans, - common_.width_, common_.height_, - common_.scale_factor_, - common_.t_, common_.font_manager_, *common_.detector_, - common_.query_extent_, tr); - - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - composite_mode_e halo_comp_op = get(sym, keys::halo_comp_op, feature, common_.vars_, src_over); - double opacity = get(sym,keys::opacity,feature, common_.vars_, 1.0); - - placements_list const &placements = helper.get(); - for (glyph_positions_ptr glyphs : placements) - { - if (glyphs->marker()) { - pixel_position pos = glyphs->marker_pos(); - render_marker(pos, - *(glyphs->marker()->marker), - glyphs->marker()->transform, - opacity); - } - context_.add_text(glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); - } -} - -void cairo_renderer_base::process(line_pattern_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - - using conv_types = boost::mpl::vector; - - std::string filename = get(sym, keys::file, feature, common_.vars_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - bool clip = get(sym, keys::clip, feature, common_.vars_, false); - double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); - double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); - - boost::optional marker; - if ( !filename.empty() ) - { - marker = marker_cache::instance().find(filename, true); - } - if (!marker || !(*marker)) return; - - unsigned width = (*marker)->width(); - unsigned height = (*marker)->height(); - - cairo_save_restore guard(context_); - context_.set_operator(comp_op); - std::shared_ptr pattern; - image_ptr image = nullptr; - // TODO - re-implement at renderer level like polygon_pattern symbolizer - double opacity = get(sym, keys::opacity, feature, common_.vars_,1.0); - if ((*marker)->is_bitmap()) - { - pattern = std::make_unique(**((*marker)->get_bitmap_data())); - context_.set_line_width(height); - } - else - { - mapnik::rasterizer ras; - agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); - auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); - image = render_pattern(ras, **marker, image_tr, opacity); - pattern = std::make_unique(*image); - width = image->width(); - height = image->height(); - context_.set_line_width(height); - } - - pattern->set_extend(CAIRO_EXTEND_REPEAT); - pattern->set_filter(CAIRO_FILTER_BILINEAR); - - agg::trans_affine tr; - auto geom_transform = get_optional(sym, keys::geometry_transform); - if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - - box2d clipping_extent = common_.query_extent_; - if (clip) - { - double padding = (double)(common_.query_extent_.width()/common_.width_); - double half_stroke = width/2.0; - if (half_stroke > 1) - padding *= half_stroke; - if (std::fabs(offset) > 0) - padding *= std::fabs(offset) * 1.2; - padding *= common_.scale_factor_; - clipping_extent.pad(padding); - } - - using rasterizer_type = line_pattern_rasterizer; - rasterizer_type ras(context_, *pattern, width, height); - vertex_converter, rasterizer_type, line_pattern_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clipping_extent, ras, sym, common_.t_, prj_trans, tr, feature, common_.vars_, common_.scale_factor_); - - if (clip) converter.set(); // optional clip (default: true) - converter.set(); // always transform - if (std::fabs(offset) > 0.0) converter.set(); // parallel offset - converter.set(); // optional affine transform - if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter - if (smooth > 0.0) converter.set(); // optional smooth converter - - - for (auto & geom : feature.paths()) - { - if (geom.size() > 1) - { - converter.apply(geom); - } - } -} - -void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - std::string filename = get(sym, keys::file, feature, common_.vars_); - bool clip = get(sym, keys::clip, feature, common_.vars_, false); - double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); - double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); - - agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); - auto image_transform = get_optional(sym, keys::image_transform); - if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); - - cairo_save_restore guard(context_); - context_.set_operator(comp_op); - - boost::optional marker = mapnik::marker_cache::instance().find(filename,true); - if (!marker || !(*marker)) return; - - unsigned offset_x=0; - unsigned offset_y=0; - box2d const& clip_box = clipping_extent(common_); - pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); - if (alignment == LOCAL_ALIGNMENT) - { - double x0 = 0.0; - double y0 = 0.0; - - if (feature.num_geometries() > 0) - { - using clipped_geometry_type = agg::conv_clip_polygon; - using path_type = coord_transform; - clipped_geometry_type clipped(feature.get_geometry(0)); - clipped.clip_box(clip_box.minx(), clip_box.miny(), - clip_box.maxx(), clip_box.maxy()); - path_type path(common_.t_, clipped, prj_trans); - path.vertex(&x0, &y0); - } - offset_x = std::abs(clip_box.width() - x0); - offset_y = std::abs(clip_box.height() - y0); - } - - if ((*marker)->is_bitmap()) - { - cairo_pattern pattern(**((*marker)->get_bitmap_data())); - pattern.set_extend(CAIRO_EXTEND_REPEAT); - pattern.set_origin(offset_x, offset_y); - context_.set_pattern(pattern); - } - else - { - mapnik::rasterizer ras; - double opacity = get(sym,keys::opacity, feature, common_.vars_, 1.0); - image_ptr image = render_pattern(ras, **marker, image_tr, opacity); - cairo_pattern pattern(*image); - pattern.set_extend(CAIRO_EXTEND_REPEAT); - pattern.set_origin(offset_x, offset_y); - context_.set_pattern(pattern); - } - - agg::trans_affine tr; - auto geom_transform = get_optional(sym, keys::geometry_transform); - if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } - - using conv_types = boost::mpl::vector; - vertex_converter, cairo_context, polygon_pattern_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> - converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); - - if (prj_trans.equal() && clip) converter.set(); //optional clip (default: true) - converter.set(); //always transform - converter.set(); - if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter - if (smooth > 0.0) converter.set(); // optional smooth converter - - for ( geometry_type & geom : feature.paths()) - { - if (geom.size() > 2) - { - converter.apply(geom); - } - } - // fill polygon - context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); - context_.fill(); -} - -void cairo_renderer_base::process(raster_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - cairo_save_restore guard(context_); - render_raster_symbolizer( - sym, feature, prj_trans, common_, - [&](image_data_32 &target, composite_mode_e comp_op, double opacity, - int start_x, int start_y) { - context_.set_operator(comp_op); - context_.add_image(start_x, start_y, target, opacity); - } - ); -} - -namespace detail { - -template -struct markers_dispatch : mapnik::noncopyable -{ - markers_dispatch(SvgPath & marker, - Attributes const& attributes, - box2d const& bbox, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - feature_impl const& feature, - mapnik::attributes const& vars, - bool snap_to_pixels, - RendererContext const& renderer_context) - :marker_(marker), - attributes_(attributes), - bbox_(bbox), - marker_trans_(marker_trans), - sym_(sym), - detector_(detector), - scale_factor_(scale_factor), - feature_(feature), - vars_(vars), - ctx_(std::get<0>(renderer_context)) - {} - - - template - void add_path(T & path) - { - marker_placement_enum placement_method = get( - sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); - bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); - bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); - double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); - double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); - double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - coord2d center = bbox_.center(); - agg::trans_affine_translation recenter(-center.x, -center.y); - agg::trans_affine tr = recenter * marker_trans_; - markers_placement_finder placement_finder( - placement_method, - path, - bbox_, - tr, - detector_, - spacing * scale_factor_, - max_error, - allow_overlap); - double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) - { - agg::trans_affine matrix = tr; - matrix.rotate(angle); - matrix.translate(x, y); - render_vector_marker( - ctx_, - pixel_position(x, y), - marker_, - bbox_, - attributes_, - matrix, - opacity, - false); - } - } - - SvgPath & marker_; - Attributes const& attributes_; - box2d const& bbox_; - agg::trans_affine const& marker_trans_; - markers_symbolizer const& sym_; - Detector & detector_; - double scale_factor_; - feature_impl const& feature_; - attributes const& vars_; - cairo_context & ctx_; -}; - -template -struct raster_markers_dispatch : mapnik::noncopyable -{ - raster_markers_dispatch(mapnik::image_data_32 & src, - agg::trans_affine const& marker_trans, - markers_symbolizer const& sym, - Detector & detector, - double scale_factor, - feature_impl const& feature, - mapnik::attributes const& vars, - RendererContext const& renderer_context) - : src_(src), - detector_(detector), - sym_(sym), - marker_trans_(marker_trans), - scale_factor_(scale_factor), - feature_(feature), - vars_(vars), - ctx_(std::get<0>(renderer_context)) {} - - template - void add_path(T & path) - { - marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); - double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); - double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); - double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); - bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); - bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); - box2d bbox_(0,0, src_.width(),src_.height()); - markers_placement_finder placement_finder( - placement_method, - path, - bbox_, - marker_trans_, - detector_, - spacing * scale_factor_, - max_error, - allow_overlap); - double x, y, angle = .0; - while (placement_finder.get_point(x, y, angle, ignore_placement)) - { - agg::trans_affine matrix = marker_trans_; - matrix.rotate(angle); - matrix.translate(x, y); - ctx_.add_image(matrix, src_, opacity); - } - } - - image_data_32 & src_; - Detector & detector_; - markers_symbolizer const& sym_; - agg::trans_affine const& marker_trans_; - double scale_factor_; - feature_impl const& feature_; - attributes const& vars_; - cairo_context & ctx_; -}; - -} -void cairo_renderer_base::process(markers_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using svg_attribute_type = agg::pod_bvector; - - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - context_.set_operator(comp_op); - box2d clip_box = common_.query_extent_; - - auto renderer_context = std::tie(context_); - - using RendererContextType = decltype(renderer_context); - using vector_dispatch_type = detail::markers_dispatch >, - svg_attribute_type,label_collision_detector4>; - - using raster_dispatch_type = detail::raster_markers_dispatch; - - - render_markers_symbolizer( - sym, feature, prj_trans, common_, clip_box, - renderer_context); -} - -void cairo_renderer_base::process(text_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - agg::trans_affine tr; - auto transform = get_optional(sym, keys::geometry_transform); - if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); - text_symbolizer_helper helper( - sym, feature, common_.vars_, prj_trans, - common_.width_, common_.height_, - common_.scale_factor_, - common_.t_, common_.font_manager_, *common_.detector_, - common_.query_extent_, tr); - - cairo_save_restore guard(context_); - composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); - composite_mode_e halo_comp_op = get(sym, keys::halo_comp_op, feature, common_.vars_, src_over); - - placements_list const& placements = helper.get(); - for (glyph_positions_ptr glyphs : placements) - { - context_.add_text(glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); - } -} - -namespace { - -/** - * Render a thunk which was frozen from a previous call to - * extract_bboxes. We should now have a new offset at which - * to render it, and the boxes themselves should already be - * in the detector from the placement_finder. - */ -struct thunk_renderer : public boost::static_visitor<> -{ - using renderer_type = cairo_renderer_base; - - thunk_renderer(renderer_type &ren, - cairo_context &context, - cairo_face_manager &face_manager, - renderer_common &common, - pixel_position const &offset) - : ren_(ren), context_(context), face_manager_(face_manager), - common_(common), offset_(offset) - {} - - void operator()(point_render_thunk const &thunk) const - { - pixel_position new_pos(thunk.pos_.x + offset_.x, thunk.pos_.y + offset_.y); - ren_.render_marker(new_pos, *thunk.marker_, thunk.tr_, thunk.opacity_, - thunk.comp_op_); - } - - void operator()(text_render_thunk const &thunk) const - { - cairo_save_restore guard(context_); - context_.set_operator(thunk.comp_op_); - - render_offset_placements( - thunk.placements_, - offset_, - [&] (glyph_positions_ptr glyphs) - { - if (glyphs->marker()) - { - ren_.render_marker(glyphs->marker_pos(), - *(glyphs->marker()->marker), - glyphs->marker()->transform, - thunk.opacity_, thunk.comp_op_); - } - context_.add_text(glyphs, face_manager_, common_.font_manager_, src_over, src_over, common_.scale_factor_); - }); - } - - template - void operator()(T const &) const - { - // TODO: warning if unimplemented? - } - -private: - renderer_type &ren_; - cairo_context &context_; - cairo_face_manager &face_manager_; - renderer_common &common_; - pixel_position offset_; -}; - -} // anonymous namespace - -void cairo_renderer_base::process(group_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - render_group_symbolizer( - sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, - [&](render_thunk_list const& thunks, pixel_position const& render_offset) - { - thunk_renderer ren(*this, context_, face_manager_, common_, render_offset); - for (render_thunk_ptr const& thunk : thunks) - { - boost::apply_visitor(ren, *thunk); - } - }); -} - -namespace { - -// special implementation of the box drawing so that it's pixel-aligned -void render_debug_box(cairo_context &context, box2d const& b) -{ - cairo_save_restore guard(context); - double minx = std::floor(b.minx()) + 0.5; - double miny = std::floor(b.miny()) + 0.5; - double maxx = std::floor(b.maxx()) + 0.5; - double maxy = std::floor(b.maxy()) + 0.5; - context.move_to(minx, miny); - context.line_to(minx, maxy); - context.line_to(maxx, maxy); - context.line_to(maxx, miny); - context.close_path(); - context.stroke(); -} - -} // anonymous namespace - -void cairo_renderer_base::process(debug_symbolizer const& sym, - mapnik::feature_impl & feature, - proj_transform const& prj_trans) -{ - using detector_type = label_collision_detector4; - cairo_save_restore guard(context_); - - debug_symbolizer_mode_enum mode = get(sym, keys::mode, feature, common_.vars_, DEBUG_SYM_MODE_COLLISION); - - context_.set_operator(src_over); - context_.set_color(mapnik::color(255, 0, 0), 1.0); - context_.set_line_join(MITER_JOIN); - context_.set_line_cap(BUTT_CAP); - context_.set_miter_limit(4.0); - context_.set_line_width(1.0); - - if (mode == DEBUG_SYM_MODE_COLLISION) - { - typename detector_type::query_iterator itr = common_.detector_->begin(); - typename detector_type::query_iterator end = common_.detector_->end(); - for ( ;itr!=end; ++itr) - { - render_debug_box(context_, itr->box); - } - } - else if (mode == DEBUG_SYM_MODE_VERTEX) - { - for (auto const& geom : feature.paths()) - { - double x; - double y; - double z = 0; - geom.rewind(0); - unsigned cmd = 1; - while ((cmd = geom.vertex(&x, &y)) != mapnik::SEG_END) - { - if (cmd == SEG_CLOSE) continue; - prj_trans.backward(x,y,z); - common_.t_.forward(&x,&y); - context_.move_to(std::floor(x) - 0.5, std::floor(y) + 0.5); - context_.line_to(std::floor(x) + 1.5, std::floor(y) + 0.5); - context_.move_to(std::floor(x) + 0.5, std::floor(y) - 0.5); - context_.line_to(std::floor(x) + 0.5, std::floor(y) + 1.5); - context_.stroke(); - } - } - } -} - -template class cairo_renderer; template class cairo_renderer; } diff --git a/src/cairo/process_building_symbolizer.cpp b/src/cairo/process_building_symbolizer.cpp new file mode 100644 index 000000000..47f54b406 --- /dev/null +++ b/src/cairo/process_building_symbolizer.cpp @@ -0,0 +1,84 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +// mapnik symbolizer generics +#include + +// stl +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(building_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using path_type = coord_transform; + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + mapnik::color fill = get(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128)); + double opacity = get(sym, keys::fill_opacity, feature, common_.vars_, 1.0); + double height = get(sym, keys::height, feature, common_.vars_, 0.0); + + context_.set_operator(comp_op); + + render_building_symbolizer( + feature, height, + [&](geometry_type &faces) { + path_type faces_path(common_.t_, faces, prj_trans); + context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8 / 255.0, + fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0); + context_.add_path(faces_path); + context_.fill(); + }, + [&](geometry_type &frame) { + path_type path(common_.t_, frame, prj_trans); + context_.set_color(fill.red() * 0.8 / 255.0, fill.green() * 0.8/255.0, + fill.blue() * 0.8 / 255.0, fill.alpha() * opacity / 255.0); + context_.set_line_width(common_.scale_factor_); + context_.add_path(path); + context_.stroke(); + }, + [&](geometry_type &roof) { + path_type roof_path(common_.t_, roof, prj_trans); + context_.set_color(fill, opacity); + context_.add_path(roof_path); + context_.fill(); + }); +} + +template void cairo_renderer::process(building_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_debug_symbolizer.cpp b/src/cairo/process_debug_symbolizer.cpp new file mode 100644 index 000000000..bab726bec --- /dev/null +++ b/src/cairo/process_debug_symbolizer.cpp @@ -0,0 +1,110 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include + +namespace mapnik +{ + +namespace { + +// special implementation of the box drawing so that it's pixel-aligned +inline void render_debug_box(cairo_context &context, box2d const& b) +{ + cairo_save_restore guard(context); + double minx = std::floor(b.minx()) + 0.5; + double miny = std::floor(b.miny()) + 0.5; + double maxx = std::floor(b.maxx()) + 0.5; + double maxy = std::floor(b.maxy()) + 0.5; + context.move_to(minx, miny); + context.line_to(minx, maxy); + context.line_to(maxx, maxy); + context.line_to(maxx, miny); + context.close_path(); + context.stroke(); +} + +} // anonymous namespace + +template +void cairo_renderer::process(debug_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using detector_type = label_collision_detector4; + cairo_save_restore guard(context_); + + debug_symbolizer_mode_enum mode = get(sym, keys::mode, feature, common_.vars_, DEBUG_SYM_MODE_COLLISION); + + context_.set_operator(src_over); + context_.set_color(mapnik::color(255, 0, 0), 1.0); + context_.set_line_join(MITER_JOIN); + context_.set_line_cap(BUTT_CAP); + context_.set_miter_limit(4.0); + context_.set_line_width(1.0); + + if (mode == DEBUG_SYM_MODE_COLLISION) + { + typename detector_type::query_iterator itr = common_.detector_->begin(); + typename detector_type::query_iterator end = common_.detector_->end(); + for ( ;itr!=end; ++itr) + { + render_debug_box(context_, itr->box); + } + } + else if (mode == DEBUG_SYM_MODE_VERTEX) + { + for (auto const& geom : feature.paths()) + { + double x; + double y; + double z = 0; + geom.rewind(0); + unsigned cmd = 1; + while ((cmd = geom.vertex(&x, &y)) != mapnik::SEG_END) + { + if (cmd == SEG_CLOSE) continue; + prj_trans.backward(x,y,z); + common_.t_.forward(&x,&y); + context_.move_to(std::floor(x) - 0.5, std::floor(y) + 0.5); + context_.line_to(std::floor(x) + 1.5, std::floor(y) + 0.5); + context_.move_to(std::floor(x) + 0.5, std::floor(y) - 0.5); + context_.line_to(std::floor(x) + 0.5, std::floor(y) + 1.5); + context_.stroke(); + } + } + } +} + +template void cairo_renderer::process(debug_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_group_symbolizer.cpp b/src/cairo/process_group_symbolizer.cpp new file mode 100644 index 000000000..967fce270 --- /dev/null +++ b/src/cairo/process_group_symbolizer.cpp @@ -0,0 +1,126 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include + +// mapnik symbolizer generics +#include + +namespace mapnik +{ + +class feature_impl; +class proj_transform; +struct group_symbolizer; + +namespace { + +// Render a thunk which was frozen from a previous call to +// extract_bboxes. We should now have a new offset at which +// to render it, and the boxes themselves should already be +// in the detector from the placement_finder. +template +struct thunk_renderer : public boost::static_visitor<> +{ + using renderer_type = cairo_renderer; + + thunk_renderer(renderer_type & ren, + cairo_context & context, + cairo_face_manager & face_manager, + renderer_common & common, + pixel_position const& offset) + : ren_(ren), context_(context), face_manager_(face_manager), + common_(common), offset_(offset) + {} + + void operator()(point_render_thunk const &thunk) const + { + pixel_position new_pos(thunk.pos_.x + offset_.x, thunk.pos_.y + offset_.y); + ren_.render_marker(new_pos, *thunk.marker_, thunk.tr_, thunk.opacity_, + thunk.comp_op_); + } + + void operator()(text_render_thunk const &thunk) const + { + cairo_save_restore guard(context_); + context_.set_operator(thunk.comp_op_); + + render_offset_placements( + thunk.placements_, + offset_, + [&] (glyph_positions_ptr glyphs) + { + if (glyphs->marker()) + { + ren_.render_marker(glyphs->marker_pos(), + *(glyphs->marker()->marker), + glyphs->marker()->transform, + thunk.opacity_, thunk.comp_op_); + } + context_.add_text(glyphs, face_manager_, common_.font_manager_, src_over, src_over, common_.scale_factor_); + }); + } + + template + void operator()(T0 const &) const + { + // TODO: warning if unimplemented? + } + +private: + renderer_type & ren_; + cairo_context & context_; + cairo_face_manager & face_manager_; + renderer_common & common_; + pixel_position offset_; +}; + +} // anonymous namespace + +template +void cairo_renderer::process(group_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + render_group_symbolizer( + sym, feature, common_.vars_, prj_trans, common_.query_extent_, common_, + [&](render_thunk_list const& thunks, pixel_position const& render_offset) + { + thunk_renderer ren(*this, context_, face_manager_, common_, render_offset); + for (render_thunk_ptr const& thunk : thunks) + { + boost::apply_visitor(ren, *thunk); + } + }); +} + +template void cairo_renderer::process(group_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_line_pattern_symbolizer.cpp b/src/cairo/process_line_pattern_symbolizer.cpp new file mode 100644 index 000000000..4f1e1af60 --- /dev/null +++ b/src/cairo/process_line_pattern_symbolizer.cpp @@ -0,0 +1,141 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(line_pattern_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + + using conv_types = boost::mpl::vector; + + std::string filename = get(sym, keys::file, feature, common_.vars_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + bool clip = get(sym, keys::clip, feature, common_.vars_, false); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); + + boost::optional marker; + if ( !filename.empty() ) + { + marker = marker_cache::instance().find(filename, true); + } + if (!marker || !(*marker)) return; + + unsigned width = (*marker)->width(); + unsigned height = (*marker)->height(); + + cairo_save_restore guard(context_); + context_.set_operator(comp_op); + std::shared_ptr pattern; + image_ptr image = nullptr; + // TODO - re-implement at renderer level like polygon_pattern symbolizer + double opacity = get(sym, keys::opacity, feature, common_.vars_,1.0); + if ((*marker)->is_bitmap()) + { + pattern = std::make_unique(**((*marker)->get_bitmap_data())); + context_.set_line_width(height); + } + else + { + mapnik::rasterizer ras; + agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); + auto image_transform = get_optional(sym, keys::image_transform); + if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); + image = render_pattern(ras, **marker, image_tr, opacity); + pattern = std::make_unique(*image); + width = image->width(); + height = image->height(); + context_.set_line_width(height); + } + + pattern->set_extend(CAIRO_EXTEND_REPEAT); + pattern->set_filter(CAIRO_FILTER_BILINEAR); + + agg::trans_affine tr; + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } + + box2d clipping_extent = common_.query_extent_; + if (clip) + { + double padding = (double)(common_.query_extent_.width()/common_.width_); + double half_stroke = width/2.0; + if (half_stroke > 1) + padding *= half_stroke; + if (std::fabs(offset) > 0) + padding *= std::fabs(offset) * 1.2; + padding *= common_.scale_factor_; + clipping_extent.pad(padding); + } + + using rasterizer_type = line_pattern_rasterizer; + rasterizer_type ras(context_, *pattern, width, height); + vertex_converter, rasterizer_type, line_pattern_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> + converter(clipping_extent, ras, sym, common_.t_, prj_trans, tr, feature, common_.vars_, common_.scale_factor_); + + if (clip) converter.set(); // optional clip (default: true) + converter.set(); // always transform + if (std::fabs(offset) > 0.0) converter.set(); // parallel offset + converter.set(); // optional affine transform + if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter + if (smooth > 0.0) converter.set(); // optional smooth converter + + + for (auto & geom : feature.paths()) + { + if (geom.size() > 1) + { + converter.apply(geom); + } + } +} + +template void cairo_renderer::process(line_pattern_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_line_symbolizer.cpp b/src/cairo/process_line_symbolizer.cpp new file mode 100644 index 000000000..0b008cf57 --- /dev/null +++ b/src/cairo/process_line_symbolizer.cpp @@ -0,0 +1,116 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(line_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using conv_types = boost::mpl::vector; + + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + bool clip = get(sym, keys::clip, feature, common_.vars_, false); + double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); + + mapnik::color stroke = get(sym, keys::stroke, feature, common_.vars_, mapnik::color(0,0,0)); + double stroke_opacity = get(sym, keys::stroke_opacity, feature, common_.vars_, 1.0); + line_join_enum stroke_join = get(sym, keys::stroke_linejoin, feature, common_.vars_, MITER_JOIN); + line_cap_enum stroke_cap = get(sym, keys::stroke_linecap, feature, common_.vars_, BUTT_CAP); + auto dash = get_optional(sym, keys::stroke_dasharray, feature, common_.vars_); + double miterlimit = get(sym, keys::stroke_miterlimit, feature, common_.vars_, 4.0); + double width = get(sym, keys::stroke_width, feature, common_.vars_, 1.0); + + cairo_save_restore guard(context_); + context_.set_operator(comp_op); + context_.set_color(stroke, stroke_opacity); + context_.set_line_join(stroke_join); + context_.set_line_cap(stroke_cap); + context_.set_miter_limit(miterlimit); + context_.set_line_width(width * common_.scale_factor_); + if (dash) + { + context_.set_dash(*dash, common_.scale_factor_); + } + + agg::trans_affine tr; + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } + + box2d clipping_extent = common_.query_extent_; + if (clip) + { + double padding = (double)(common_.query_extent_.width()/common_.width_); + double half_stroke = width/2.0; + if (half_stroke > 1) + padding *= half_stroke; + if (std::fabs(offset) > 0) + padding *= std::fabs(offset) * 1.2; + padding *= common_.scale_factor_; + clipping_extent.pad(padding); + } + vertex_converter, cairo_context, line_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> + converter(clipping_extent,context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); + + if (clip) converter.set(); // optional clip (default: true) + converter.set(); // always transform + if (std::fabs(offset) > 0.0) converter.set(); // parallel offset + converter.set(); // optional affine transform + if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter + if (smooth > 0.0) converter.set(); // optional smooth converter + + for (geometry_type & geom : feature.paths()) + { + if (geom.size() > 1) + { + converter.apply(geom); + } + } + // stroke + context_.set_fill_rule(CAIRO_FILL_RULE_WINDING); + context_.stroke(); +} + +template void cairo_renderer::process(line_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_markers_symbolizer.cpp b/src/cairo/process_markers_symbolizer.cpp new file mode 100644 index 000000000..07bd142ee --- /dev/null +++ b/src/cairo/process_markers_symbolizer.cpp @@ -0,0 +1,224 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// agg +#include "agg/include/agg_array.h" // for pod_bvector +#include "agg/include/agg_trans_affine.h" // for trans_affine, etc + +namespace mapnik +{ + +class feature_impl; +class proj_transform; +namespace svg { struct path_attributes; } + +namespace detail { + +template +struct markers_dispatch : mapnik::noncopyable +{ + markers_dispatch(SvgPath & marker, + Attributes const& attributes, + box2d const& bbox, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + feature_impl const& feature, + mapnik::attributes const& vars, + bool snap_to_pixels, + RendererContext const& renderer_context) + :marker_(marker), + attributes_(attributes), + bbox_(bbox), + marker_trans_(marker_trans), + sym_(sym), + detector_(detector), + scale_factor_(scale_factor), + feature_(feature), + vars_(vars), + ctx_(std::get<0>(renderer_context)) + {} + + + template + void add_path(T & path) + { + marker_placement_enum placement_method = get( + sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); + coord2d center = bbox_.center(); + agg::trans_affine_translation recenter(-center.x, -center.y); + agg::trans_affine tr = recenter * marker_trans_; + markers_placement_finder placement_finder( + placement_method, + path, + bbox_, + tr, + detector_, + spacing * scale_factor_, + max_error, + allow_overlap); + double x, y, angle = .0; + while (placement_finder.get_point(x, y, angle, ignore_placement)) + { + agg::trans_affine matrix = tr; + matrix.rotate(angle); + matrix.translate(x, y); + render_vector_marker( + ctx_, + pixel_position(x, y), + marker_, + bbox_, + attributes_, + matrix, + opacity, + false); + } + } + + SvgPath & marker_; + Attributes const& attributes_; + box2d const& bbox_; + agg::trans_affine const& marker_trans_; + markers_symbolizer const& sym_; + Detector & detector_; + double scale_factor_; + feature_impl const& feature_; + attributes const& vars_; + cairo_context & ctx_; +}; + +template +struct raster_markers_dispatch : mapnik::noncopyable +{ + raster_markers_dispatch(mapnik::image_data_32 & src, + agg::trans_affine const& marker_trans, + markers_symbolizer const& sym, + Detector & detector, + double scale_factor, + feature_impl const& feature, + mapnik::attributes const& vars, + RendererContext const& renderer_context) + : src_(src), + detector_(detector), + sym_(sym), + marker_trans_(marker_trans), + scale_factor_(scale_factor), + feature_(feature), + vars_(vars), + ctx_(std::get<0>(renderer_context)) {} + + template + void add_path(T & path) + { + marker_placement_enum placement_method = get(sym_, keys::markers_placement_type, feature_, vars_, MARKER_POINT_PLACEMENT); + double opacity = get(sym_, keys::opacity, feature_, vars_, 1.0); + double spacing = get(sym_, keys::spacing, feature_, vars_, 100.0); + double max_error = get(sym_, keys::max_error, feature_, vars_, 0.2); + bool allow_overlap = get(sym_, keys::allow_overlap, feature_, vars_, false); + bool ignore_placement = get(sym_, keys::ignore_placement, feature_, vars_, false); + box2d bbox_(0,0, src_.width(),src_.height()); + markers_placement_finder placement_finder( + placement_method, + path, + bbox_, + marker_trans_, + detector_, + spacing * scale_factor_, + max_error, + allow_overlap); + double x, y, angle = .0; + while (placement_finder.get_point(x, y, angle, ignore_placement)) + { + agg::trans_affine matrix = marker_trans_; + matrix.rotate(angle); + matrix.translate(x, y); + ctx_.add_image(matrix, src_, opacity); + } + } + + image_data_32 & src_; + Detector & detector_; + markers_symbolizer const& sym_; + agg::trans_affine const& marker_trans_; + double scale_factor_; + feature_impl const& feature_; + attributes const& vars_; + cairo_context & ctx_; +}; + +} + +template +void cairo_renderer::process(markers_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using svg_attribute_type = agg::pod_bvector; + + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + context_.set_operator(comp_op); + box2d clip_box = common_.query_extent_; + + auto renderer_context = std::tie(context_); + + using RendererContextType = decltype(renderer_context); + using vector_dispatch_type = detail::markers_dispatch >, + svg_attribute_type,label_collision_detector4>; + + using raster_dispatch_type = detail::raster_markers_dispatch; + + + render_markers_symbolizer( + sym, feature, prj_trans, common_, clip_box, + renderer_context); +} + +template void cairo_renderer::process(markers_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_point_symbolizer.cpp b/src/cairo/process_point_symbolizer.cpp new file mode 100644 index 000000000..349a198f2 --- /dev/null +++ b/src/cairo/process_point_symbolizer.cpp @@ -0,0 +1,66 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include +#include +#include + +namespace agg { struct trans_affine; } + +namespace mapnik +{ + +class feature_impl; +class proj_transform; + +template +void cairo_renderer::process(point_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + + cairo_save_restore guard(context_); + context_.set_operator(comp_op); + + render_point_symbolizer( + sym, feature, prj_trans, common_, + [this](pixel_position const& pos, marker const& marker, + agg::trans_affine const& tr, double opacity) { + render_marker(pos, marker, tr, opacity); + }); +} + +template void cairo_renderer::process(point_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_polygon_pattern_symbolizer.cpp b/src/cairo/process_polygon_pattern_symbolizer.cpp new file mode 100644 index 000000000..3bea8c6b7 --- /dev/null +++ b/src/cairo/process_polygon_pattern_symbolizer.cpp @@ -0,0 +1,135 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(polygon_pattern_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + std::string filename = get(sym, keys::file, feature, common_.vars_); + bool clip = get(sym, keys::clip, feature, common_.vars_, false); + double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); + double smooth = get(sym, keys::smooth, feature, common_.vars_, 0.0); + + agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); + auto image_transform = get_optional(sym, keys::image_transform); + if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); + + cairo_save_restore guard(context_); + context_.set_operator(comp_op); + + boost::optional marker = mapnik::marker_cache::instance().find(filename,true); + if (!marker || !(*marker)) return; + + unsigned offset_x=0; + unsigned offset_y=0; + box2d const& clip_box = clipping_extent(common_); + pattern_alignment_enum alignment = get(sym, keys::alignment, feature, common_.vars_, GLOBAL_ALIGNMENT); + if (alignment == LOCAL_ALIGNMENT) + { + double x0 = 0.0; + double y0 = 0.0; + + if (feature.num_geometries() > 0) + { + using clipped_geometry_type = agg::conv_clip_polygon; + using path_type = coord_transform; + clipped_geometry_type clipped(feature.get_geometry(0)); + clipped.clip_box(clip_box.minx(), clip_box.miny(), + clip_box.maxx(), clip_box.maxy()); + path_type path(common_.t_, clipped, prj_trans); + path.vertex(&x0, &y0); + } + offset_x = std::abs(clip_box.width() - x0); + offset_y = std::abs(clip_box.height() - y0); + } + + if ((*marker)->is_bitmap()) + { + cairo_pattern pattern(**((*marker)->get_bitmap_data())); + pattern.set_extend(CAIRO_EXTEND_REPEAT); + pattern.set_origin(offset_x, offset_y); + context_.set_pattern(pattern); + } + else + { + mapnik::rasterizer ras; + double opacity = get(sym,keys::opacity, feature, common_.vars_, 1.0); + image_ptr image = render_pattern(ras, **marker, image_tr, opacity); + cairo_pattern pattern(*image); + pattern.set_extend(CAIRO_EXTEND_REPEAT); + pattern.set_origin(offset_x, offset_y); + context_.set_pattern(pattern); + } + + agg::trans_affine tr; + auto geom_transform = get_optional(sym, keys::geometry_transform); + if (geom_transform) { evaluate_transform(tr, feature, common_.vars_, *geom_transform, common_.scale_factor_); } + + using conv_types = boost::mpl::vector; + vertex_converter, cairo_context, polygon_pattern_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl> + converter(clip_box, context_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_); + + if (prj_trans.equal() && clip) converter.set(); //optional clip (default: true) + converter.set(); //always transform + converter.set(); + if (simplify_tolerance > 0.0) converter.set(); // optional simplify converter + if (smooth > 0.0) converter.set(); // optional smooth converter + + for ( geometry_type & geom : feature.paths()) + { + if (geom.size() > 2) + { + converter.apply(geom); + } + } + // fill polygon + context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); + context_.fill(); +} + +template void cairo_renderer::process(polygon_pattern_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_polygon_symbolizer.cpp b/src/cairo/process_polygon_symbolizer.cpp new file mode 100644 index 000000000..2680dafce --- /dev/null +++ b/src/cairo/process_polygon_symbolizer.cpp @@ -0,0 +1,66 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include +#include + +namespace mapnik +{ + + +template +void cairo_renderer::process(polygon_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + using conv_types = boost::mpl::vector; + using vertex_converter_type = vertex_converter, cairo_context, polygon_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, + conv_types, feature_impl>; + + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + context_.set_operator(comp_op); + + render_polygon_symbolizer( + sym, feature, prj_trans, common_, common_.query_extent_, context_, + [&](color const &fill, double opacity) { + context_.set_color(fill, opacity); + // fill polygon + context_.set_fill_rule(CAIRO_FILL_RULE_EVEN_ODD); + context_.fill(); + }); +} + +template void cairo_renderer::process(polygon_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_raster_symbolizer.cpp b/src/cairo/process_raster_symbolizer.cpp new file mode 100644 index 000000000..62f45353a --- /dev/null +++ b/src/cairo/process_raster_symbolizer.cpp @@ -0,0 +1,59 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include +#include + +// mapnik symbolizer generics +#include + +namespace mapnik +{ + +template +void cairo_renderer::process(raster_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + cairo_save_restore guard(context_); + render_raster_symbolizer( + sym, feature, prj_trans, common_, + [&](image_data_32 &target, composite_mode_e comp_op, double opacity, + int start_x, int start_y) { + context_.set_operator(comp_op); + context_.add_image(start_x, start_y, target, opacity); + } + ); +} + +template void cairo_renderer::process(raster_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/cairo/process_text_symbolizer.cpp b/src/cairo/process_text_symbolizer.cpp new file mode 100644 index 000000000..0948b4cce --- /dev/null +++ b/src/cairo/process_text_symbolizer.cpp @@ -0,0 +1,107 @@ +/***************************************************************************** + * + * This file is part of Mapnik (c++ mapping toolkit) + * + * Copyright (C) 2014 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 + * + *****************************************************************************/ + +#if defined(HAVE_CAIRO) + +// mapnik +#include +#include +#include + + +namespace mapnik +{ + +class feature_impl; +class proj_transform; + +template +void cairo_renderer::process(shield_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); + text_symbolizer_helper helper( + sym, feature, common_.vars_, prj_trans, + common_.width_, common_.height_, + common_.scale_factor_, + common_.t_, common_.font_manager_, *common_.detector_, + common_.query_extent_, tr); + + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + composite_mode_e halo_comp_op = get(sym, keys::halo_comp_op, feature, common_.vars_, src_over); + double opacity = get(sym,keys::opacity,feature, common_.vars_, 1.0); + + placements_list const &placements = helper.get(); + for (glyph_positions_ptr glyphs : placements) + { + if (glyphs->marker()) { + pixel_position pos = glyphs->marker_pos(); + render_marker(pos, + *(glyphs->marker()->marker), + glyphs->marker()->transform, + opacity); + } + context_.add_text(glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); + } +} + +template void cairo_renderer::process(shield_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +template +void cairo_renderer::process(text_symbolizer const& sym, + mapnik::feature_impl & feature, + proj_transform const& prj_trans) +{ + agg::trans_affine tr; + auto transform = get_optional(sym, keys::geometry_transform); + if (transform) evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_); + text_symbolizer_helper helper( + sym, feature, common_.vars_, prj_trans, + common_.width_, common_.height_, + common_.scale_factor_, + common_.t_, common_.font_manager_, *common_.detector_, + common_.query_extent_, tr); + + cairo_save_restore guard(context_); + composite_mode_e comp_op = get(sym, keys::comp_op, feature, common_.vars_, src_over); + composite_mode_e halo_comp_op = get(sym, keys::halo_comp_op, feature, common_.vars_, src_over); + + placements_list const& placements = helper.get(); + for (glyph_positions_ptr glyphs : placements) + { + context_.add_text(glyphs, face_manager_, common_.font_manager_, comp_op, halo_comp_op, common_.scale_factor_); + } +} + +template void cairo_renderer::process(text_symbolizer const&, + mapnik::feature_impl &, + proj_transform const&); + +} + +#endif // HAVE_CAIRO diff --git a/src/feature_style_processor.cpp b/src/feature_style_processor.cpp index 0d30c7682..a9af0dc5a 100644 --- a/src/feature_style_processor.cpp +++ b/src/feature_style_processor.cpp @@ -45,7 +45,6 @@ namespace mapnik #if defined(HAVE_CAIRO) template class feature_style_processor >; -template class feature_style_processor >; #endif #if defined(SVG_RENDERER) From 48078da22dd952801c520bb4b669962728bca2b7 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 20:35:23 -0700 Subject: [PATCH 91/92] debug font crash - refs #2341 --- .travis.yml | 3 +++ src/font_engine_freetype.cpp | 1 + 2 files changed, 4 insertions(+) diff --git a/.travis.yml b/.travis.yml index 96d7b2173..317dbe64e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -52,3 +52,6 @@ before_script: script: - if [[ ${BENCHMARK} != False ]]; then make bench; fi; + # install some exotic fonts to ensure we don't crash registering them + - sudo apt-get install ttf-* + - python -c "import mapnik;mapnik.logger.set_severity(mapnik.severity_type.Debug);mapnik.register_fonts('/usr/share/fonts/');mapnik.register_fonts('/usr/share/fonts/');print '\n'.join(list(mapnik.FontEngine.instance().face_names()))" diff --git a/src/font_engine_freetype.cpp b/src/font_engine_freetype.cpp index 87209f569..722b22959 100644 --- a/src/font_engine_freetype.cpp +++ b/src/font_engine_freetype.cpp @@ -132,6 +132,7 @@ bool freetype_engine::register_font(std::string const& file_name) bool freetype_engine::register_font_impl(std::string const& file_name, FT_LibraryRec_ * library) { + MAPNIK_LOG_DEBUG(font_engine_freetype) << "registering: " << file_name; #ifdef _WINDOWS FILE * file = _wfopen(mapnik::utf8_to_utf16(file_name).c_str(), L"rb"); #else From 4054b97984966e1b8e7374c4391424db8681db39 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Sun, 10 Aug 2014 20:56:13 -0700 Subject: [PATCH 92/92] fix font testing --- .travis.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 317dbe64e..e12580b01 100644 --- a/.travis.yml +++ b/.travis.yml @@ -53,5 +53,6 @@ before_script: script: - if [[ ${BENCHMARK} != False ]]; then make bench; fi; # install some exotic fonts to ensure we don't crash registering them - - sudo apt-get install ttf-* + - sudo apt-get install ttf-wqy-microhei + - source localize.sh - python -c "import mapnik;mapnik.logger.set_severity(mapnik.severity_type.Debug);mapnik.register_fonts('/usr/share/fonts/');mapnik.register_fonts('/usr/share/fonts/');print '\n'.join(list(mapnik.FontEngine.instance().face_names()))"

9T&`F-J;T$aL1^W6PbVMCv+1#rbVZqFldz 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 diff --git a/tests/visual_tests/images/line-pattern-symbolizer-opacity-512-512-1.0-cairo-reference.png b/tests/visual_tests/images/line-pattern-symbolizer-opacity-512-512-1.0-cairo-reference.png index f9b4d3de35779f44cd39d7b3b2a39601e6fc59ae..ea54754e6f5f77fdd07a5d1c08422c2383855804 100644 GIT binary patch literal 15983 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 literal 10328 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 literal 10328 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 Date: Tue, 5 Aug 2014 13:10:56 -0700 Subject: [PATCH 33/92] travis: give up on gcc (too often killed by travis oom) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c9151c92b..292b46842 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,7 +2,7 @@ language: cpp compiler: - clang - - gcc +# - gcc addons: postgresql: "9.3" From 2a7fc29e421593f9e8168629bf4cd59b1bd71d20 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Tue, 5 Aug 2014 13:48:40 -0700 Subject: [PATCH 34/92] add support for opacity with svgs in pattern symbolizers - refs #1010 --- .../mapnik/renderer_common/render_pattern.hpp | 5 +- src/agg/process_line_pattern_symbolizer.cpp | 5 +- .../process_polygon_pattern_symbolizer.cpp | 2 +- src/cairo/cairo_renderer.cpp | 7 +- src/load_map.cpp | 1 + src/renderer_common/render_pattern.cpp | 7 +- ...and-offset-500-100-1.0-grid-reference.json | 34 +++++ ...and-offset-512-512-1.0-grid-reference.json | 137 ++++++++++++++++++ ...h-and-offset-500-100-1.0-agg-reference.png | Bin 0 -> 8515 bytes ...and-offset-500-100-1.0-cairo-reference.png | Bin 0 -> 8594 bytes ...h-and-offset-500-100-2.0-agg-reference.png | Bin 0 -> 8201 bytes ...and-offset-500-100-2.0-cairo-reference.png | Bin 0 -> 9097 bytes ...h-and-offset-512-512-1.0-agg-reference.png | Bin 0 -> 30478 bytes ...and-offset-512-512-1.0-cairo-reference.png | Bin 0 -> 30913 bytes ...h-and-offset-512-512-2.0-agg-reference.png | Bin 0 -> 34059 bytes ...and-offset-512-512-2.0-cairo-reference.png | Bin 0 -> 36703 bytes .../styles/line-pattern-smooth-and-offset.xml | 24 +++ tests/visual_tests/test.py | 1 + 18 files changed, 215 insertions(+), 8 deletions(-) create mode 100644 tests/visual_tests/grids/line-pattern-smooth-and-offset-500-100-1.0-grid-reference.json create mode 100644 tests/visual_tests/grids/line-pattern-smooth-and-offset-512-512-1.0-grid-reference.json create mode 100644 tests/visual_tests/images/line-pattern-smooth-and-offset-500-100-1.0-agg-reference.png create mode 100644 tests/visual_tests/images/line-pattern-smooth-and-offset-500-100-1.0-cairo-reference.png create mode 100644 tests/visual_tests/images/line-pattern-smooth-and-offset-500-100-2.0-agg-reference.png create mode 100644 tests/visual_tests/images/line-pattern-smooth-and-offset-500-100-2.0-cairo-reference.png create mode 100644 tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-1.0-agg-reference.png create mode 100644 tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-1.0-cairo-reference.png create mode 100644 tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-2.0-agg-reference.png create mode 100644 tests/visual_tests/images/line-pattern-smooth-and-offset-512-512-2.0-cairo-reference.png create mode 100755 tests/visual_tests/styles/line-pattern-smooth-and-offset.xml diff --git a/include/mapnik/renderer_common/render_pattern.hpp b/include/mapnik/renderer_common/render_pattern.hpp index f40bef907..885d89c07 100644 --- a/include/mapnik/renderer_common/render_pattern.hpp +++ b/include/mapnik/renderer_common/render_pattern.hpp @@ -37,7 +37,10 @@ namespace mapnik { struct rasterizer; class marker; -std::shared_ptr render_pattern(rasterizer & ras, marker const& marker, agg::trans_affine const& tr); +std::shared_ptr render_pattern(rasterizer & ras, + marker const& marker, + agg::trans_affine const& tr, + double opacity); } // namespace mapnik diff --git a/src/agg/process_line_pattern_symbolizer.cpp b/src/agg/process_line_pattern_symbolizer.cpp index bddc9e476..2142d0dbe 100644 --- a/src/agg/process_line_pattern_symbolizer.cpp +++ b/src/agg/process_line_pattern_symbolizer.cpp @@ -106,6 +106,8 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, boost::optional marker_ptr = marker_cache::instance().find(filename, true); if (!marker_ptr || !(*marker_ptr)) return; boost::optional pat; + // TODO - re-implement at renderer level like polygon_pattern symbolizer + double opacity = get(sym, keys::opacity, feature, common_.vars_,1.0); if ((*marker_ptr)->is_bitmap()) { pat = (*marker_ptr)->get_bitmap_data(); @@ -115,13 +117,12 @@ void agg_renderer::process(line_pattern_symbolizer const& sym, agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym, keys::image_transform); if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); - pat = render_pattern(*ras_ptr, **marker_ptr, image_tr); + pat = render_pattern(*ras_ptr, **marker_ptr, image_tr, opacity); } if (!pat) return; bool clip = get(sym, keys::clip, feature, common_.vars_, false); - //double opacity = get(sym,keys::stroke_opacity,feature, 1.0); TODO double offset = get(sym, keys::offset, feature, common_.vars_, 0.0); double simplify_tolerance = get(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0); double smooth = get(sym, keys::smooth, feature, common_.vars_, false); diff --git a/src/agg/process_polygon_pattern_symbolizer.cpp b/src/agg/process_polygon_pattern_symbolizer.cpp index fb1a50d15..711ed63f4 100644 --- a/src/agg/process_polygon_pattern_symbolizer.cpp +++ b/src/agg/process_polygon_pattern_symbolizer.cpp @@ -74,7 +74,7 @@ void agg_renderer::process(polygon_pattern_symbolizer const& sym, agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym, keys::image_transform); if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); - pat = render_pattern(*ras_ptr, **marker_ptr, image_tr); + pat = render_pattern(*ras_ptr, **marker_ptr, image_tr, 1.0); } if (!pat) return; diff --git a/src/cairo/cairo_renderer.cpp b/src/cairo/cairo_renderer.cpp index a7ba32d30..fc60d6b81 100644 --- a/src/cairo/cairo_renderer.cpp +++ b/src/cairo/cairo_renderer.cpp @@ -631,6 +631,8 @@ void cairo_renderer_base::process(line_pattern_symbolizer const& sym, context_.set_operator(comp_op); std::shared_ptr pattern; image_ptr image = nullptr; + // TODO - re-implement at renderer level like polygon_pattern symbolizer + double opacity = get(sym, keys::opacity, feature, common_.vars_,1.0); if ((*marker)->is_bitmap()) { pattern = std::make_unique(**((*marker)->get_bitmap_data())); @@ -642,7 +644,7 @@ void cairo_renderer_base::process(line_pattern_symbolizer const& sym, agg::trans_affine image_tr = agg::trans_affine_scaling(common_.scale_factor_); auto image_transform = get_optional(sym, keys::image_transform); if (image_transform) evaluate_transform(image_tr, feature, common_.vars_, *image_transform); - image = render_pattern(ras, **marker, image_tr); + image = render_pattern(ras, **marker, image_tr, opacity); pattern = std::make_unique(*image); width = image->width(); height = image->height(); @@ -745,7 +747,8 @@ void cairo_renderer_base::process(polygon_pattern_symbolizer const& sym, else { mapnik::rasterizer ras; - image_ptr image = render_pattern(ras, **marker, image_tr); + double opacity = get(sym,keys::opacity, feature, common_.vars_, 1.0); + image_ptr image = render_pattern(ras, **marker, image_tr, opacity); cairo_pattern pattern(*image); pattern.set_extend(CAIRO_EXTEND_REPEAT); pattern.set_origin(offset_x, offset_y); diff --git a/src/load_map.cpp b/src/load_map.cpp index 195c25366..aa03500b8 100644 --- a/src/load_map.cpp +++ b/src/load_map.cpp @@ -1014,6 +1014,7 @@ void map_parser::parse_line_pattern_symbolizer(rule & rule, xml_node const & nod line_pattern_symbolizer symbol; parse_symbolizer_base(symbol, node); put(symbol, keys::file, parse_path(file)); + set_symbolizer_property(symbol, keys::opacity, node); // offset value optional offset = node.get_opt_attr("offset"); diff --git a/src/renderer_common/render_pattern.cpp b/src/renderer_common/render_pattern.cpp index b291a2871..f149c134a 100644 --- a/src/renderer_common/render_pattern.cpp +++ b/src/renderer_common/render_pattern.cpp @@ -35,7 +35,10 @@ namespace mapnik { -std::shared_ptr render_pattern(rasterizer & ras, marker const& marker, agg::trans_affine const& tr) +std::shared_ptr render_pattern(rasterizer & ras, + marker const& marker, + agg::trans_affine const& tr, + double opacity) { using pixfmt = agg::pixfmt_rgba32_pre; using renderer_base = agg::renderer_base; @@ -61,7 +64,7 @@ std::shared_ptr render_pattern(rasterizer & ras, marker const& ma agg::pixfmt_rgba32_pre > svg_renderer(svg_path, (*marker.get_vector_data())->attributes()); - svg_renderer.render(ras, sl, renb, mtx, 1.0, bbox); + svg_renderer.render(ras, sl, renb, mtx, opacity, bbox); return image; } diff --git a/tests/visual_tests/grids/line-pattern-smooth-and-offset-500-100-1.0-grid-reference.json b/tests/visual_tests/grids/line-pattern-smooth-and-offset-500-100-1.0-grid-reference.json new file mode 100644 index 000000000..bc60a27b1 --- /dev/null +++ b/tests/visual_tests/grids/line-pattern-smooth-and-offset-500-100-1.0-grid-reference.json @@ -0,0 +1,34 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " !! ! !! !!!!!!!!! !!!!!!!!! !! !!! ", + " !! !! !!!!!!!! !! !!!!! !!!!! !! !! ", + " !! !!!!!! !!! !!! !!!! !! !! ", + " !! ! !!!! !!! !!!!!!!! !!!! !! !! ", + " !! !! !!! !!!!!!!!!!!!!!! !!! !!! !! ", + " !! !!!!!! !!!!!!! !!!! !!! !!! !! !!! ", + " !! !!!!! !!!! !!!! !! !!!! !! !! ", + " !! !!!!!! !!!!!! !!!! !!!! !! !!!! !! ! ", + " !! !!!!!! !! !!! !!!!!!!!!!! !!!!!!!!!! ", + " !! !!!!! !! !!!!!!!! !! !! !! !!!! ", + " ! !! !!!!!! !! !! ! !! !! !! !!!! ! ", + " !!!!!!!! !! !!!!!!!! !!!!! !!! !! !! !! ", + " !!!! !!!!! !!!! ! !! !!! !!! !!! !! !! ", + " !!! !!!!! !!! !!!!!! !! !!!! !!! !! !! ", + " !! !!!!!!!! !! !!!!!! !!!!!!!!! !! ", + " !! !!! !! !!!! !!!! !! ! ", + " !! !!! !!!!! !!!! !!!! !! !! ", + " !! !!! !!! !!!!!! !! !!!! !! ", + " ! !!! !!!!!!!!!!! !! !!!! !! ", + " !! !!!!!!!!!!!!!!!!! !! !! ", + " ! !!!!! !!!!!! !!!! !! ", + " !!!!! !!! !! !! ! !! !! ", + " !! !!!!!!! ! !! !!!! ", + " !! !! !!!! ! !!!! !! ", + " !! !! !!!!! !! !! " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/grids/line-pattern-smooth-and-offset-512-512-1.0-grid-reference.json b/tests/visual_tests/grids/line-pattern-smooth-and-offset-512-512-1.0-grid-reference.json new file mode 100644 index 000000000..2d3c25756 --- /dev/null +++ b/tests/visual_tests/grids/line-pattern-smooth-and-offset-512-512-1.0-grid-reference.json @@ -0,0 +1,137 @@ +{ + "keys": [ + "", + "1" + ], + "data": {}, + "grid": [ + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " !!! !! ", + " !!!!!!!!! !!!!!!!! ", + " !!! !!!! !!!! !!! ", + " !!! !!!!! !!! !!! !!!!! !! ", + " !! !!!!!!!! !!! !!! !!!!!!!! !! ", + " !!!!! ! !! !! !!! !! !! !!! !! ", + " !! !! !!!!! !! !! !! !! !!!!! !!!!!! ", + " !! ! !!! !!!!! !! !! !! !!! !! !! !!! ", + " !! !! !!!!!!! !!!! !! !! !!!!!!!!! !! !! ", + " !! !!!!!!! !! !! !! !! !!!!!!!!!!!!!! !! !! ", + " !!!! !!!! !! ! !! !!!!!!!!! !!!!!! !! ", + " !! !! !!! !! !!!! !! !!!!! !!!!!!!!! ", + " !! ! !!! !!!!! ! !! !!!!!!!!!!!!!! !!!!! !!! ", + " !! !! !!! !!!!!!! !! !!!!!!!!!!! !!!!! !!!!! !! ", + " !! !!!!! !!!!!! !!!! !! !!!!!! !!!!!!!!! !! ", + " !!!! !! !! !!! !!!! !! !!!!! !!!! !!!!!!!! !! ", + " !! !! !! !! !!!!! !! !! !!!!! !!!!!!!!!! !!!! !!!!!! ", + " !! !!!! !!! !!! ! !! !!!!!!!!! !!! !!!! !!!! !! !!! ", + " !! !!!!! !! !!! !!!! !!! !!!!! !!! !!!! !!!!!! !! ", + " !! !!!! !! !! !!!!! !! !!! !!!!! !! !!! !!!!!!! !! ", + " !!!! !! !!! !!!! !!!!! !!! !!!! !!!!!!!! !!! !!!!!!! !! ", + " !! !!!!! !! !!! !!!!! !! !!!!!!! !!!!!!!!! !!! !!! !!!!!! ", + " !! !!!! !! !! !!!!! !! !! !!! !! !! !!! !!!!!! !!! ", + " !! !!!!! !! !! !! !!!!! !!! !!!!! !! !!!!!! !! ", + " !! !!!!!!! !!! !!!!! !! !!!! !!!!!! !! !!!!!!! !! ", + " !!!! !! !! !! !!!!! !!!!!!!! !!! !! !! !!!!!!! !! ", + " !! !!!!!!! !! !!!!!! !!!!! !!!!!! !!! !!!!!!!!!!", + " !! !!!! !! !!! ! !!! !!!! !! !! !!!!!!! !!", + " !! !! !!!! !! !!!!!! !!!! !! !! !!!!!!! !", + " !! !!!!!!! !! !!!! !!!!!!!!!!!!!!! !!!!!!!! !! ", + " !!!! !!!! !! !! !! !!!!!! !! !! !! !!!!!!!!", + " !! !! !!!! !! !!!! !! !! !!!!!!! !!", + " !! !!!! !! !! !! !! !!! !!! !! !! !! !", + " !! !! !!!! !! !! !!!! !!!!!!!! !! !!!!! ", + " !! !! !!!! !! !!!!!!!!!!! !! !! !! !!!", + " !! ! !! !! !! !! !! !!! !! !!!! !!!", + " !! !! !!!! !! !!!!!!!! !! !! !! !!", + " !! !! !!!! !! !!! !!! !! !!!! !!", + " ! !! !!!!! !! !!!! !!! !! !!!!", + " !! !! !!!! !! !!!!!! !!!! !", + " !! !! !!!! !! !! !!!", + " !! !! !!!!! !! !! !! ", + " !! !! !!!! !! !!!! ", + " ! !! !!!!! !! !! ", + " !! !! !!!!! !! ", + " !! !! !!!!!!! ", + " !! !! !!!!! !! ", + " !! !! !!!!! !! ", + " ! !! !!!!!!!! ", + " !! !! !!!!! !! ", + " !! !! !!!!! !! ", + " !! !! !!!!!!!! ", + " !!!!!!!! !! !! !!!!! !! ", + " !!!! !!!!! ! !! !!!!!! !! ", + " !!! !!!! !!!! !! !! !!!!!! ! ", + " !! !!!!!!!! !!!! !! !! ! !!! !! ", + " !! !!! !!!! !!!! !! !! !!!!!! !! ", + " !! !!! !!!!! !!!! !!!! !! !! !!!!!! ! ", + " !! !!! !!! !!!! !!!! !!!! !! !! !! !!!!!! ", + " !! !!! !! !!!!!!!! !!!! !!!! !! !! !!!!!! !! ", + " !! !!! !!!!!!!!!!!!!! !!!! !!! !!!! !! !!!! !! ", + "!! !!! !!!!! !!!!! !!!! !!! !! !! !! ! !!!! ", + "! !!! !!!! !!!!!!! !!!!!! !!! !! !! !! !!!!!! !! ", + " !!! !!! !!!!!!!!!! !!!!!! !! !!! !! !! !!!! !! ", + "!!! !!! !!!! !!! !! !!! !!!!! !! !!!! !!!! ", + "!! !!! !!! !!!!! !! !! !! !! !!!! !! !!!! !! ", + "! !!!! !! !!!!!!!! !! !! ! !! ! !! !! !!!! ! ", + " !!!! !! !!! !!! !! !!!!!! ! !!!! !! ! !! ", + "!!!! !! !!! !!! !! !!!!!! !! !! !!!! !! ", + "!!! !!! !! !!! !!!!!! !! !!!! !! !!!! ", + " !! !! !! !! !!!!!! !!!! !! !!!! !! ", + "!! !! !! !! !!!! !!!!! !!!! !! !! ", + "!!!! !!! !! !!!! !! !! !! !!!! ", + " !! !! !! !! !!!!! !!!!! !! !! ", + " ! !! !!!!!!! !!!!!! !!!!! ! ", + " !! !! !!!!! !!!!! !! ", + " ! !! !!!!! !!!!! !! ", + " !! !!!!!!!!!!! !!! ", + " !! !!!!!!!!! !!! ", + " !! !!! !!! !!! ", + " !! !!!!! !!! ", + " !! !!! ", + " !!!!!!! ", + " !!!! ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ] +} \ No newline at end of file diff --git a/tests/visual_tests/images/line-pattern-smooth-and-offset-500-100-1.0-agg-reference.png b/tests/visual_tests/images/line-pattern-smooth-and-offset-500-100-1.0-agg-reference.png new file mode 100644 index 0000000000000000000000000000000000000000..6da936da18be8354deaff6d276008c792b07b854 GIT binary patch literal 8515 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%0ARy0J2#;0l5 z@daF6SqgJ#8?dU2hoKXC5MzXMij;k?`j_;ais8z|O%e|`|K@>}Qb5_~^joSB zWxwD$7)MDg^h*piU(i65{Ys>RZ3Sn%cy?!PG2P!4G2eFco%|c9PBX;F!W^vZf^qb> zU@+=xgH&NJ{1iFx)5L-ok)Ro~8E5(X_qv`(AU&tHCDN5kDD+>04)of}%7Y==_)a&U zFzyu5{nhv;B0?^_WA+*LB5Ipv#2gD#E2@Qeq-%@9d|C@W0evn*0anMIciP?2_dwj= zGS^2$eoLe)mq_TZ_-ZxY0$Epc@@*s%VO#yaxU-h7()U5;)mneOzwJTO4I)i#E+dIr zB1OQ4GNYn^f;D(&uX-gW*Imu8=ae&0T5h(u%Au6eUp!GS#_wGy`vdLA36umvAE*b+ zgTW)RVr<^wtrDw&Wp_{JuWxK$2A78|+0B##yhifktgz~#1(N*Bz0jk34kG#q<4 zTqmLHh>JuI>6`Sa*vh^=<_QUs1VX=MH-*?voNSpepRQ#a?*KioR-M@gd$qlWGuGUY z++jLST2L6UiI#}oX)4dcb9lBsQK+6lqB3T%*?->H=QYC5ms`USuIw}2u3TazanN4| zkvOZc+t;%FQXL;|lTu)QecZitz;TB6^1v7MPlyaRDsjUctSZyCoM`MKM0=k%?sF@7 z9@~b%o~F%;3UOoT*-&Qu7{ZkO{LtscRT2h$059EfHrePYr70O;+e`6m-nKOcZYf*o zB#HVbL;?imN`yPDZ)P4`D09|&Z<MXYDJYl}^rb zmm#ESVX|GhL_vRrjl0wKcgoo*h)?G*P#ZWtGbU&xGta{lwdpvq5HUsv`(U!FtHZRR zH-Ai^FBSKvPtXh{{oA(=eNsFnQP3|T=FVE&n{=xnka|4~lN3#Z%;kfLXi7rqI1xu_ z)}##~`v`1(pLc1g7KU zMsZp{Z4fEA&Zlz<{XcUjWoHxW(v?F|TfuM*e6l4m(0h(S=0{`~w1mPO%#W!?*Csl!QRX zUYxUH=O$)e?J)0OGc?;+GDEjQS(Z6b#=Jm2#i%nVpf5lbhcVF$}g9j>|<@buLeEZ5&&kTl$@!EW zBo}PaJT|inSLv%b9+8A-`b!Y7IcXVX`KD7_)G}XuTOSd}S!PpuTh8rVHNSwcpEi5>mVMXljtIG9M)={PjEpRb zJv}{>5YHh$eQNae8O+41b$9kWjo{dgyd)|)Gw>^q+Ahfh*tk3Ebv4WvXqrugoL7y! z=t0vKTVM@*GIF&eefYW&gDQF`)EWwh&rZ*vl9QjAPH;2oSvd{#EE2w3y@hJL2UazD zQW95X>$!CVdU00~^HOQ_`(4au>>ace`C4)Gb<3G#u?6<9PV0h~2^$eu2saJGGQy$O z*49w-$_!h^r>7Ic&i={DohxE>tE}xpw-{q1(!a5^b`NO1`rN60$1@92wpV;D?6jJMM_5D;aef;>eG#fip z^YLTHGVEy?X=xK1Lh?2D=Ww_53CqipB2f&}R7l?6B=Wb_w#Z@&49IEIGTrQ|`D`<#-ReLm)SC}1{Wv#Q zLI>0{vN8np{QRYFz%4Wa?B347CkHyp%j}TG{rDivpJ?7%z64l#o~@sweP@d(wxAWL zE%s(t2Qo6IFIs<~q50v%hppi^%?(E@R?f<&L0L{#no2!uI)N^b6Zs5Mw_3IoI2ZS@ zB+0zD14mAJ?#er;A@k_wQEuibDPw@LGwO1o7~JXCU2Gw7HQh-dLg({EP?2+TCr!%E z%pttFF;}QhZ+Q4=hJ)Ni-7;JDEvM$h+v)eD?f3pvOzSc&Gq5-&^V6w13vuO&32WATOMPwrQX(B*QWbPlXU#<6fi*~DW&qxyA z*2K4v+9abmC0c88&io=4a%$qi_->c|?r2Xp(J0jj6n%0dPqT&&P`?Z)I;)ryU1!W8 z^t6c;c~lkYrNw#x?b`C!abQs#j~nox8Uq{}u~VBIGd z^fJ%AwRI&`;xtFoMO7t>sXE6!o(67E&e#Hw4(na1KmeOgl#iVK0hZEBP^{iZ`=)A1r=sICO{Q!;WLNrF}TdGq3(3Cyd zZ(x+3J6fzTWsXxgABuTO$^_TmpD?(S`#z%@=yg^s54E1<*%zVexx8qenaPP~*vdY! z;$et}^8E4oW0p!i|FecTkJE@svY`vXZ>aV%=HYoFJc7(QJ3g8OU?cQm1CVqTvtk zllKVp{=Ja8tg^VbXyz$*cY1CNV4@Gw;kvW=rb!_h;q?ymvC?~|s!oZ|t)MGe`b@f2 zhT3EC<}*EYZt6c?A^=Dz$#m#U~>iPL2Jv<{So`LSXk=EIMN!^uu7f8fhQ>jY>-#K`Yp2xGK zkuU+-kR$UiAAK}-{KSbL&zie*eZ|p+{|tS*Z`Kc{>mxKK@evO}x2&ecC@u3u;d&aK zd|NU7^7WX=jT1pSDzMS2YJ@sw>vKf{X6)Fp4L|)vU-igWrw-?K8)8iCbZ#Gk(TJaT z3Ob3_7fe|wLU$9t3Q=KBsG~hOWoU+0u#Fb!I@CTvtKIbV?P0sFl0l(=`V*1xyFedA z*;l^*P{dI@2HomEE<0a0$6($f8XBLVGK?_fXiktpI&6-kDOlDNcYs&NSx3zH3c|d( z)p{4`MA|pWu862I=;} z<}AKgg?jB!H{XFdkvA0@Z9n?%zi$G?v(WKd^2W&YIt{&K!#ad+TXK}R5mN#V(#5wc z*s2Ap>p8jkVsnYVAbn?D9-X%ZGLq*Lfe zX*G?NQPZyfaCXQfy7wiUB^QnuY1MgF(`-9qyZT|NNlQh*Px_urAo zbPh_pucAkcuo11`MO03{`CXE5AHIA*(64J0Hs003kN0{{R3M;S6t00072P)t-s0Du4m zf&~kO3loVG8;u)f0A6YUX(p2sCy004Fh zba?=N`Tzg`0Q-FaegFXfe*l30004jhfO-ykH=8&A1qB8M|9%XDeHVIz3xo>`|NjdM z{}%xN6BC9Qh!+?CN25oED24wt0RI~s|0gGsDwF$F04XW|Sgcr=Ihfm!0RJ{NH#h&` zjsWD70GLXc>6ZX!vuEX;0LQ!l>zx4qivUMQ|MZ*y%*O!#N=o#i0HjW(-T?ls7vtdo z;^YA2;sCB~ujSE;0C<^_nvi0QF9;@uYO>j3_;CU0;5?eYNi z>j3BH7xeT1;@&I$xHtcIclG)J=H)5+`T+X;0GP~}_`FL0{{XsQVO%Guc2>gc)u;j910$H>V4=Ho)aKmc4>&D^d>FMU>>FVU;>g?<5>*)08{{G4S_t)s^`~Tht#W>-F>V^Zohg z^!oJp^7!=h{r~jy^!oh&{Ph3-|BzOPF#rG{?@2^KRCt{2oryyeSN^~~QPKigv7mU= z>WaE*tw*hmtVdj=E*?wUm_n+Jwvp6SEhx5X>shO|rQ%Vqs(3*x(NP%~6yiu^$lvvQ z@6Eh7?>qAXSjpk9{q9yJnS^9M^S!_C&5(HJizZ9wh%_~RS{V%0*6FgZ*LePBIVU^l zt8R_wWhHyJtwU_`v+>kKN(+zP(PBa^JkM+0=gnK>d?PkQBmm&7}Osd zPe0y}Df^dh!u;KL z33=BizChqqo2otLp{GvOUj^uK3jN%tD=NHRUyz(ArWl8K=neEypy&(PTfHOXM(z7? z+eOkWx=5_o%w_iWU9-`P8T0Yed&r}`7i&Kt$gyDRANr7deM8lLO^d2$9CS_am>kxj z|5CAHwZ~H#AbN4tc(V5+j`>H=j7OnIzeV5as2JN?`orXb^OoOi2zOEKmrLeB(-&QPL;qiF=#J)c< zo^Rk4{Um+WO8(TdC{AeHk<6qA%pu25x=(+$1#v@#?=Xy-3eH&Q@^2Djs8Zw*hQ8ok z9sS}Dv9${NzJ7d$syhDThq$K2R85s7Ngd?#3M9jz$0SLyK89R+lVROgFJ0;*+~*a}WGFW72pT&lduxUH<5YWmX1CN|e1atg+@w+B>mlpvK z`fE(+H9?=b0Dsn5$_=BqnYN)tlyRFK;mOTZ2`}lvAmzVzcHw67U z3*fPQ;M-LfGP2Lw(5||=kl$BXc|wQY((>2PbcI+onOH&=%ssyN1NM2ffeOSNL0>_j z<9z3oqNr-LJ=*5xptCS;Hh