diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 43d4d23bd..51e166efb 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -28,6 +28,8 @@ #include #include #include +#include +#include #include #include #include @@ -36,12 +38,17 @@ #include // agg +#include "agg_basics.h" +#include "agg_rendering_buffer.h" +#include "agg_pixfmt_rgba.h" #include "agg_rasterizer_scanline_aa.h" -#include "agg_renderer_scanline.h" -#include "agg_scanline_bin.h" +#include "agg_scanline_u.h" #include "agg_path_storage.h" -#include "agg_ellipse.h" -#include "agg_conv_stroke.h" +#include "agg_conv_clip_polyline.h" +#include "agg_conv_transform.h" + +// boost +#include // stl #include @@ -54,59 +61,68 @@ void grid_renderer::process(markers_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - typedef coord_transform path_type; - typedef agg::renderer_base ren_base; - typedef agg::renderer_scanline_bin_solid renderer; - agg::scanline_bin sl; + typedef agg::conv_clip_polyline clipped_geometry_type; + typedef coord_transform path_type; + typedef agg::conv_transform transformed_path_type; + typedef agg::renderer_base renderer_base; + typedef agg::renderer_scanline_bin_solid renderer_type; - grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray32 pixf(buf); - - ren_base renb(pixf); - renderer ren(renb); - - ras_ptr->reset(); - - agg::trans_affine tr; - evaluate_transform(tr, feature, sym.get_image_transform()); - unsigned int res = pixmap_.get_resolution(); - tr = agg::trans_affine_scaling(scale_factor_*(1.0/res)) * tr; std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature); marker_placement_e placement_method = sym.get_marker_placement(); if (!filename.empty()) { boost::optional mark = mapnik::marker_cache::instance()->find(filename, true); - if (mark && *mark && (*mark)->is_vector()) + if (mark && *mark) { + if (!(*mark)->is_vector()) + { + MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: markers_symbolizer does not yet support non-SVG markers"; + return; + } + + agg::scanline_bin sl; + grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); + mapnik::pixfmt_gray32 pixf(buf); + ras_ptr->reset(); + renderer_base renb(pixf); + renderer_type ren(renb); + + agg::trans_affine geom_tr; + evaluate_transform(geom_tr, feature, sym.get_transform()); + boost::optional marker = (*mark)->get_vector_data(); box2d const& bbox = (*marker)->bounding_box(); - double x1 = bbox.minx(); - double y1 = bbox.miny(); - double x2 = bbox.maxx(); - double y2 = bbox.maxy(); - double w = (*mark)->width(); - double h = (*mark)->height(); - // clamp sizes - w = std::max(w,4.0); - h = std::max(w,4.0); - agg::trans_affine recenter = agg::trans_affine_translation(-0.5*(x1+x2),-0.5*(y1+y2)); - tr.transform(&x1,&y1); - tr.transform(&x2,&y2); - box2d extent(x1,y1,x2,y2); + agg::trans_affine tr; + setup_label_transform(tr, bbox, feature, sym); + tr = agg::trans_affine_scaling(scale_factor_*(1.0/pixmap_.get_resolution())) * tr; + // - clamp sizes to >= 4 pixels of interativity + if (tr.scale() < .25) + tr.scale(.25); + + coord2d center = bbox.center(); + agg::trans_affine_translation recenter(-center.x, -center.y); + agg::trans_affine marker_trans = recenter * tr; + using namespace mapnik::svg; vertex_stl_adapter stl_storage((*marker)->source()); svg_path_adapter svg_path(stl_storage); + + agg::pod_bvector attributes; + bool result = push_explicit_style( (*marker)->attributes(), attributes, sym); + svg_renderer, - renderer, - mapnik::pixfmt_gray32 > svg_renderer(svg_path,(*marker)->attributes()); + agg::pod_bvector, + renderer_type, + mapnik::pixfmt_gray32 > svg_renderer(svg_path, result ? attributes : (*marker)->attributes()); + + marker_placement_e placement_method = sym.get_marker_placement(); bool placed = false; - for (unsigned i=0; i::process(markers_symbolizer const& sym, geom.label_interior_position(&x, &y); prj_trans.backward(x,y,z); t_.forward(&x,&y); - extent.re_center(x,y); + geom_tr.transform(&x,&y); + agg::trans_affine matrix = marker_trans; + matrix.translate(x,y); + box2d transformed_bbox = bbox * matrix; if (sym.get_allow_overlap() || - detector_.has_placement(extent)) + detector_.has_placement(transformed_bbox)) { + placed = true; + svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), matrix, sym.get_opacity(), bbox); + if (/* DEBUG */ 0) + { + //debug_draw_box(buf, transformed_bbox, 0, 0, 0.0); + } - render_marker(feature, - pixmap_.get_resolution(), - pixel_position(x - 0.5 * w, y - 0.5 * h), - **mark, - tr, - sym.get_opacity()); + if (!sym.get_ignore_placement()) + detector_.insert(transformed_bbox); } } - - path_type path(t_,geom,prj_trans); - markers_placement placement(path, bbox, recenter, detector_, - sym.get_spacing() * scale_factor_, - sym.get_max_error(), - sym.get_allow_overlap()); - double x, y, angle; - while (placement.get_point(x, y, angle)) + else { - placed = true; - agg::trans_affine matrix = recenter * tr *agg::trans_affine_rotation(angle) * agg::trans_affine_translation(x, y); - svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), matrix, sym.get_opacity(),bbox); + clipped_geometry_type clipped(geom); + clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); + path_type path(t_,clipped,prj_trans); + transformed_path_type path_transformed(path,geom_tr); + markers_placement placement(path_transformed, bbox, marker_trans, detector_, + sym.get_spacing() * scale_factor_, + sym.get_max_error(), + sym.get_allow_overlap()); + double x, y, angle; + while (placement.get_point(x, y, angle)) + { + placed = true; + agg::trans_affine matrix = marker_trans; + matrix.rotate(angle); + matrix.translate(x, y); + svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), matrix, sym.get_opacity(), bbox); + + if (/* DEBUG */ 0) + { + //debug_draw_box(buf, bbox*matrix, 0, 0, 0.0); + } + } } } if (placed) + { pixmap_.add_feature(feature); + } } } }