From 957c40f7631edfa1902f6e62e3198d9362fefe76 Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Wed, 6 Jun 2012 16:36:38 -0700 Subject: [PATCH] move to int32 for grid rendering buffer - closes #1196 --- include/mapnik/grid/grid.hpp | 2 +- include/mapnik/grid/grid_pixel.hpp | 137 ++++++++++++++++++ include/mapnik/grid/grid_pixfmt.hpp | 6 + include/mapnik/grid/grid_view.hpp | 2 +- include/mapnik/svg/svg_renderer.hpp | 2 +- src/grid/grid_renderer.cpp | 7 +- src/grid/process_building_symbolizer.cpp | 10 +- src/grid/process_line_pattern_symbolizer.cpp | 6 +- src/grid/process_line_symbolizer.cpp | 6 +- src/grid/process_markers_symbolizer.cpp | 8 +- .../process_polygon_pattern_symbolizer.cpp | 6 +- src/grid/process_polygon_symbolizer.cpp | 6 +- tests/python_tests/render_grid_test.py | 45 ++++++ 13 files changed, 215 insertions(+), 28 deletions(-) diff --git a/include/mapnik/grid/grid.hpp b/include/mapnik/grid/grid.hpp index 95073a15b..c0fcf306d 100644 --- a/include/mapnik/grid/grid.hpp +++ b/include/mapnik/grid/grid.hpp @@ -329,7 +329,7 @@ public: }; -typedef MAPNIK_DECL hit_grid grid; +typedef MAPNIK_DECL hit_grid grid; } #endif //MAPNIK_GRID_HPP diff --git a/include/mapnik/grid/grid_pixel.hpp b/include/mapnik/grid/grid_pixel.hpp index 451fad349..23588472f 100644 --- a/include/mapnik/grid/grid_pixel.hpp +++ b/include/mapnik/grid/grid_pixel.hpp @@ -165,6 +165,143 @@ struct gray16 static self_type no_color() { return self_type(0,0); } }; +//==================================================================gray16 +struct gray32 +{ + typedef agg::int32 value_type; + typedef agg::int64u calc_type; + typedef agg::int64 long_type; + enum base_scale_e + { + base_shift = 32, + base_scale = 1 << base_shift, + base_mask = base_scale - 1 + }; + typedef gray32 self_type; + + value_type v; + value_type a; + + //-------------------------------------------------------------------- + gray32() {} + + //-------------------------------------------------------------------- + gray32(unsigned v_, unsigned a_=base_mask) : + v(agg::int32(v_)), a(agg::int32(a_)) {} + + //-------------------------------------------------------------------- + gray32(const self_type& c, unsigned a_) : + v(c.v), a(value_type(a_)) {} + + //-------------------------------------------------------------------- + void clear() + { + v = a = 0; + } + + //-------------------------------------------------------------------- + const self_type& transparent() + { + a = 0; + return *this; + } + + //-------------------------------------------------------------------- + void opacity(double a_) + { + if(a_ < 0.0) a_ = 0.0; + if(a_ > 1.0) a_ = 1.0; + a = (value_type)agg::uround(a_ * double(base_mask)); + } + + //-------------------------------------------------------------------- + double opacity() const + { + return double(a) / double(base_mask); + } + + + //-------------------------------------------------------------------- + const self_type& premultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + v = value_type((calc_type(v) * a) >> base_shift); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& premultiply(unsigned a_) + { + if(a == base_mask && a_ >= base_mask) return *this; + if(a == 0 || a_ == 0) + { + v = a = 0; + return *this; + } + calc_type v_ = (calc_type(v) * a_) / a; + v = value_type((v_ > a_) ? a_ : v_); + a = value_type(a_); + return *this; + } + + //-------------------------------------------------------------------- + const self_type& demultiply() + { + if(a == base_mask) return *this; + if(a == 0) + { + v = 0; + return *this; + } + calc_type v_ = (calc_type(v) * base_mask) / a; + v = value_type((v_ > base_mask) ? base_mask : v_); + return *this; + } + + //-------------------------------------------------------------------- + self_type gradient(self_type c, double k) const + { + self_type ret; + calc_type ik = agg::uround(k * base_scale); + ret.v = value_type(calc_type(v) + (((calc_type(c.v) - v) * ik) >> base_shift)); + ret.a = value_type(calc_type(a) + (((calc_type(c.a) - a) * ik) >> base_shift)); + return ret; + } + + //-------------------------------------------------------------------- + AGG_INLINE void add(const self_type& c, unsigned cover) + { + calc_type cv, ca; + if(cover == agg::cover_mask) + { + if(c.a == base_mask) + { + *this = c; + } + else + { + cv = v + c.v; v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; + ca = a + c.a; a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + else + { + cv = v + ((c.v * cover + agg::cover_mask/2) >> agg::cover_shift); + ca = a + ((c.a * cover + agg::cover_mask/2) >> agg::cover_shift); + v = (cv > calc_type(base_mask)) ? calc_type(base_mask) : cv; + a = (ca > calc_type(base_mask)) ? calc_type(base_mask) : ca; + } + } + + //-------------------------------------------------------------------- + static self_type no_color() { return self_type(0,0); } +}; + } #endif diff --git a/include/mapnik/grid/grid_pixfmt.hpp b/include/mapnik/grid/grid_pixfmt.hpp index 53f73a19f..55dc6751d 100644 --- a/include/mapnik/grid/grid_pixfmt.hpp +++ b/include/mapnik/grid/grid_pixfmt.hpp @@ -634,6 +634,12 @@ typedef blender_gray blender_gray16; typedef pixfmt_alpha_blend_gray pixfmt_gray16; //----pixfmt_gray16 + +typedef blender_gray blender_gray32; + +typedef pixfmt_alpha_blend_gray pixfmt_gray32; //----pixfmt_gray16 + } #endif diff --git a/include/mapnik/grid/grid_view.hpp b/include/mapnik/grid/grid_view.hpp index dfa636255..7e18050db 100644 --- a/include/mapnik/grid/grid_view.hpp +++ b/include/mapnik/grid/grid_view.hpp @@ -201,7 +201,7 @@ private: feature_type const& features_; }; -typedef hit_grid_view > grid_view; +typedef hit_grid_view > grid_view; } diff --git a/include/mapnik/svg/svg_renderer.hpp b/include/mapnik/svg/svg_renderer.hpp index 666bbacb1..d375f4834 100644 --- a/include/mapnik/svg/svg_renderer.hpp +++ b/include/mapnik/svg/svg_renderer.hpp @@ -379,7 +379,7 @@ public: curved_.approximation_scale(scl); curved_.angle_tolerance(0.0); - mapnik::gray16 color(feature_id); + mapnik::gray32 color(feature_id); if (attr.fill_flag || attr.fill_gradient.get_gradient_type() != NO_GRADIENT) { diff --git a/src/grid/grid_renderer.cpp b/src/grid/grid_renderer.cpp index 16e4c8e1c..3907fcd28 100644 --- a/src/grid/grid_renderer.cpp +++ b/src/grid/grid_renderer.cpp @@ -105,12 +105,12 @@ void grid_renderer::render_marker(mapnik::feature_ptr const& feature, unsigne if (marker.is_vector()) { typedef coord_transform path_type; - typedef agg::renderer_base ren_base; + typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray16 pixf(buf); + mapnik::pixfmt_gray32 pixf(buf); ren_base renb(pixf); renderer ren(renb); @@ -132,7 +132,7 @@ void grid_renderer::render_marker(mapnik::feature_ptr const& feature, unsigne svg_renderer, renderer, - mapnik::pixfmt_gray16> svg_renderer(svg_path, + mapnik::pixfmt_gray32> svg_renderer(svg_path, (*marker.get_vector_data())->attributes()); svg_renderer.render_id(*ras_ptr, sl, renb, feature->id(), mtx, opacity, bbox); @@ -161,7 +161,6 @@ void grid_renderer::render_marker(mapnik::feature_ptr const& feature, unsigne pixmap_.add_feature(feature); } -template class hit_grid; template class grid_renderer; } diff --git a/src/grid/process_building_symbolizer.cpp b/src/grid/process_building_symbolizer.cpp index 52b1edd69..e7203cd61 100644 --- a/src/grid/process_building_symbolizer.cpp +++ b/src/grid/process_building_symbolizer.cpp @@ -47,12 +47,12 @@ void grid_renderer::process(building_symbolizer const& sym, proj_transform const& prj_trans) { typedef coord_transform path_type; - typedef agg::renderer_base ren_base; + typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray16 pixf(buf); + mapnik::pixfmt_gray32 pixf(buf); ren_base renb(pixf); renderer ren(renb); @@ -108,7 +108,7 @@ void grid_renderer::process(building_symbolizer const& sym, path_type faces_path (t_,*faces,prj_trans); ras_ptr->add_path(faces_path); - ren.color(mapnik::gray16(feature->id())); + ren.color(mapnik::gray32(feature->id())); agg::render_scanlines(*ras_ptr, sl, ren); ras_ptr->reset(); @@ -135,13 +135,13 @@ void grid_renderer::process(building_symbolizer const& sym, path_type path(t_,*frame,prj_trans); agg::conv_stroke stroke(path); ras_ptr->add_path(stroke); - ren.color(mapnik::gray16(feature->id())); + ren.color(mapnik::gray32(feature->id())); agg::render_scanlines(*ras_ptr, sl, ren); ras_ptr->reset(); path_type roof_path (t_,*roof,prj_trans); ras_ptr->add_path(roof_path); - ren.color(mapnik::gray16(feature->id())); + ren.color(mapnik::gray32(feature->id())); agg::render_scanlines(*ras_ptr, sl, ren); } } diff --git a/src/grid/process_line_pattern_symbolizer.cpp b/src/grid/process_line_pattern_symbolizer.cpp index 2ab1ad8a5..92f9407a7 100644 --- a/src/grid/process_line_pattern_symbolizer.cpp +++ b/src/grid/process_line_pattern_symbolizer.cpp @@ -46,12 +46,12 @@ void grid_renderer::process(line_pattern_symbolizer const& sym, proj_transform const& prj_trans) { typedef coord_transform path_type; - typedef agg::renderer_base ren_base; + typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray16 pixf(buf); + mapnik::pixfmt_gray32 pixf(buf); ren_base renb(pixf); renderer ren(renb); @@ -75,7 +75,7 @@ void grid_renderer::process(line_pattern_symbolizer const& sym, } // render id - ren.color(mapnik::gray16(feature->id())); + ren.color(mapnik::gray32(feature->id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache diff --git a/src/grid/process_line_symbolizer.cpp b/src/grid/process_line_symbolizer.cpp index be3519586..d836ed75d 100644 --- a/src/grid/process_line_symbolizer.cpp +++ b/src/grid/process_line_symbolizer.cpp @@ -46,12 +46,12 @@ void grid_renderer::process(line_symbolizer const& sym, proj_transform const& prj_trans) { typedef coord_transform path_type; - typedef agg::renderer_base ren_base; + typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray16 pixf(buf); + mapnik::pixfmt_gray32 pixf(buf); ren_base renb(pixf); renderer ren(renb); @@ -134,7 +134,7 @@ void grid_renderer::process(line_symbolizer const& sym, } // render id - ren.color(mapnik::gray16(feature->id())); + ren.color(mapnik::gray32(feature->id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 4d83e521a..62154a8e6 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -56,12 +56,12 @@ void grid_renderer::process(markers_symbolizer const& sym, proj_transform const& prj_trans) { typedef coord_transform path_type; - typedef agg::renderer_base ren_base; + typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray16 pixf(buf); + mapnik::pixfmt_gray32 pixf(buf); ren_base renb(pixf); renderer ren(renb); @@ -104,7 +104,7 @@ void grid_renderer::process(markers_symbolizer const& sym, svg_renderer, renderer, - mapnik::pixfmt_gray16 > svg_renderer(svg_path,(*marker)->attributes()); + mapnik::pixfmt_gray32 > svg_renderer(svg_path,(*marker)->attributes()); bool placed = false; for (unsigned i=0; inum_geometries(); ++i) @@ -285,7 +285,7 @@ void grid_renderer::process(markers_symbolizer const& sym, } } - ren.color(mapnik::gray16(feature->id())); + ren.color(mapnik::gray32(feature->id())); agg::render_scanlines(*ras_ptr, sl, ren); pixmap_.add_feature(feature); } diff --git a/src/grid/process_polygon_pattern_symbolizer.cpp b/src/grid/process_polygon_pattern_symbolizer.cpp index 855694df4..3f71f0c88 100644 --- a/src/grid/process_polygon_pattern_symbolizer.cpp +++ b/src/grid/process_polygon_pattern_symbolizer.cpp @@ -45,12 +45,12 @@ void grid_renderer::process(polygon_pattern_symbolizer const& sym, proj_transform const& prj_trans) { typedef coord_transform path_type; - typedef agg::renderer_base ren_base; + typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray16 pixf(buf); + mapnik::pixfmt_gray32 pixf(buf); ren_base renb(pixf); renderer ren(renb); @@ -68,7 +68,7 @@ void grid_renderer::process(polygon_pattern_symbolizer const& sym, } // render id - ren.color(mapnik::gray16(feature->id())); + ren.color(mapnik::gray32(feature->id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache diff --git a/src/grid/process_polygon_symbolizer.cpp b/src/grid/process_polygon_symbolizer.cpp index 649366bd8..c353fdee9 100644 --- a/src/grid/process_polygon_symbolizer.cpp +++ b/src/grid/process_polygon_symbolizer.cpp @@ -45,12 +45,12 @@ void grid_renderer::process(polygon_symbolizer const& sym, proj_transform const& prj_trans) { typedef coord_transform path_type; - typedef agg::renderer_base ren_base; + typedef agg::renderer_base ren_base; typedef agg::renderer_scanline_bin_solid renderer; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray16 pixf(buf); + mapnik::pixfmt_gray32 pixf(buf); ren_base renb(pixf); renderer ren(renb); @@ -67,7 +67,7 @@ void grid_renderer::process(polygon_symbolizer const& sym, } // render id - ren.color(mapnik::gray16(feature->id())); + ren.color(mapnik::gray32(feature->id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache diff --git a/tests/python_tests/render_grid_test.py b/tests/python_tests/render_grid_test.py index 140f97c9d..0525f71c5 100644 --- a/tests/python_tests/render_grid_test.py +++ b/tests/python_tests/render_grid_test.py @@ -186,5 +186,50 @@ def test_render_grid3(): eq_(resolve(utf5,38,10),{"Name": "South West"}) eq_(resolve(utf5,38,46),{"Name": "South East"}) + +def gen_grid_for_id(pixel_key): + ds = mapnik.MemoryDatasource() + context = mapnik.Context() + context.push('Name') + f = mapnik.Feature(context,pixel_key) + f['Name'] = str(pixel_key) + f.add_geometries_from_wkt('POLYGON ((0 0, 0 256, 256 256, 256 0, 0 0))') + ds.add_feature(f) + s = mapnik.Style() + r = mapnik.Rule() + symb = mapnik.PolygonSymbolizer() + r.symbols.append(symb) + s.rules.append(r) + lyr = mapnik.Layer('Places') + lyr.datasource = ds + lyr.styles.append('places_labels') + width,height = 256,256 + m = mapnik.Map(width,height) + m.append_style('places_labels',s) + m.layers.append(lyr) + m.zoom_all() + grid = mapnik.Grid(m.width,m.height,key='__id__') + mapnik.render_layer(m,grid,layer=0,fields=['__id__','Name']) + return grid + +def test_negative_id(): + grid = gen_grid_for_id(-1) + eq_(grid.get_pixel(128,128),-1) + utf1 = grid.encode('utf',resolution=4) + eq_(utf1['keys'],['-1']) + +def test_32bit_int_id(): + int32 = 2147483647 + grid = gen_grid_for_id(int32) + eq_(grid.get_pixel(128,128),int32) + utf1 = grid.encode('utf',resolution=4) + eq_(utf1['keys'],[str(int32)]) + + max_neg = -(int32+1) + grid = gen_grid_for_id(max_neg) + eq_(grid.get_pixel(128,128),max_neg) + utf1 = grid.encode('utf',resolution=4) + eq_(utf1['keys'],[str(max_neg)]) + if __name__ == "__main__": [eval(run)() for run in dir() if 'test_' in run]