#include "catch.hpp" #include #include #include #include #include #include #include #include #include #include #include #include struct rendering_result { unsigned start_map_processing = 0; unsigned end_map_processing = 0; unsigned end_layer_processing = 0; unsigned start_style_processing = 0; unsigned end_style_processing = 0; std::vector> layer_query_extents; std::vector> geometries; }; class test_renderer : public mapnik::feature_style_processor { public: using processor_impl_type = test_renderer; test_renderer(mapnik::Map const& map, rendering_result& result) : mapnik::feature_style_processor(map) , result_(result) , painted_(false) , vars_() {} void start_map_processing(mapnik::Map const& map) { result_.start_map_processing++; } void end_map_processing(mapnik::Map const& map) { result_.end_map_processing++; } void start_layer_processing(mapnik::layer const& lay, mapnik::box2d const& query_extent) { result_.layer_query_extents.push_back(query_extent); } void end_layer_processing(mapnik::layer const& lay) { result_.end_layer_processing++; } void start_style_processing(mapnik::feature_type_style const& st) { result_.start_style_processing++; } void end_style_processing(mapnik::feature_type_style const& st) { result_.end_style_processing++; } template void process(Symbolizer const& sym, mapnik::feature_impl& feature, mapnik::proj_transform const& prj_trans) { result_.geometries.push_back(feature.get_geometry()); } bool process(mapnik::rule::symbolizers const&, mapnik::feature_impl&, mapnik::proj_transform const&) { return false; } double scale_factor() const { return 1; } mapnik::attributes const& variables() const { return vars_; } mapnik::eAttributeCollectionPolicy attribute_collection_policy() const { return mapnik::eAttributeCollectionPolicy::DEFAULT; } bool painted() const { return painted_; } void painted(bool painted) { painted_ = painted; } private: rendering_result& result_; bool painted_; mapnik::attributes vars_; }; std::shared_ptr prepare_datasource() { mapnik::parameters params; params["type"] = "memory"; using datasource_ptr = std::shared_ptr; datasource_ptr datasource = std::make_shared(params); mapnik::context_ptr ctx = std::make_shared(); { mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx, 1)); mapnik::geometry::point point(1, 2); feature->set_geometry(std::move(point)); datasource->push(feature); } { mapnik::feature_ptr feature(mapnik::feature_factory::create(ctx, 2)); mapnik::geometry::line_string path; path.emplace_back(-10, 0); path.emplace_back(0, 20); path.emplace_back(10, 0); path.emplace_back(15, 5); feature->set_geometry(std::move(path)); datasource->push(feature); } return datasource; } mapnik::Map prepare_map() { mapnik::Map map(256, 256); mapnik::feature_type_style lines_style; mapnik::rule rule; mapnik::line_symbolizer line_sym; rule.append(std::move(line_sym)); lines_style.add_rule(std::move(rule)); map.insert_style("lines", std::move(lines_style)); mapnik::layer lyr("layer"); lyr.set_datasource(prepare_datasource()); lyr.add_style("lines"); map.add_layer(lyr); map.zoom_all(); return map; } TEST_CASE("feature_style_processor") { SECTION("test_renderer") { mapnik::Map map(prepare_map()); rendering_result result; test_renderer renderer(map, result); renderer.apply(); REQUIRE(renderer.painted()); REQUIRE(result.start_map_processing == 1); REQUIRE(result.end_map_processing == 1); REQUIRE(result.end_layer_processing == 1); REQUIRE(result.start_style_processing == 1); REQUIRE(result.end_style_processing == 1); REQUIRE(result.layer_query_extents.size() == 1); const mapnik::box2d reference_query_extent(-10, 0, 15, 20); REQUIRE(result.layer_query_extents.front() == reference_query_extent); REQUIRE(result.geometries.size() == 2); REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point); REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString); } SECTION("test_renderer - apply() with single layer") { mapnik::Map map(prepare_map()); rendering_result result; test_renderer renderer(map, result); std::set attributes; mapnik::layer const& layer = map.get_layer(0); renderer.apply(layer, attributes); REQUIRE(renderer.painted()); REQUIRE(result.start_map_processing == 1); REQUIRE(result.end_map_processing == 1); REQUIRE(result.end_layer_processing == 1); REQUIRE(result.start_style_processing == 1); REQUIRE(result.end_style_processing == 1); REQUIRE(result.layer_query_extents.size() == 1); const mapnik::box2d reference_query_extent(-10, 0, 15, 20); REQUIRE(result.layer_query_extents.front() == reference_query_extent); REQUIRE(result.geometries.size() == 2); REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point); REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString); } SECTION("test_renderer - apply_to_layer") { mapnik::Map map(prepare_map()); rendering_result result; test_renderer renderer(map, result); std::set attributes; mapnik::projection map_proj(map.srs(), true); mapnik::layer const& layer = map.get_layer(0); renderer.apply_to_layer(layer, renderer, map_proj, map.scale(), map.scale_denominator(), map.width(), map.height(), map.get_current_extent(), 0, attributes); REQUIRE(renderer.painted()); REQUIRE(result.start_map_processing == 0); REQUIRE(result.end_map_processing == 0); REQUIRE(result.end_layer_processing == 1); REQUIRE(result.start_style_processing == 1); REQUIRE(result.end_style_processing == 1); REQUIRE(result.layer_query_extents.size() == 1); const mapnik::box2d reference_query_extent(-10, 0, 15, 20); REQUIRE(result.layer_query_extents.front() == reference_query_extent); REQUIRE(result.geometries.size() == 2); REQUIRE(mapnik::geometry::geometry_type(result.geometries[0]) == mapnik::geometry::geometry_types::Point); REQUIRE(mapnik::geometry::geometry_type(result.geometries[1]) == mapnik::geometry::geometry_types::LineString); } }