void grid_renderer<T>::process(building_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
    using color_type = typename grid_renderer_base_type::pixfmt_type::color_type;
    using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;
    using transform_path_type = transform_path_adapter<view_transform, vertex_adapter>;
    agg::scanline_bin sl;

    grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);
    pixfmt_type pixf(buf);

    grid_renderer_base_type renb(pixf);
    renderer_type ren(renb);

    ras_ptr->reset();

    double height = get<value_double>(sym, keys::height, feature, common_.vars_, 0.0);

    render_building_symbolizer(
        feature, height,
        [&](path_type const& faces)
        {
            vertex_adapter va(faces);
            transform_path_type faces_path (common_.t_,va,prj_trans);
            ras_ptr->add_path(faces_path);
            ren.color(color_type(feature.id()));
            agg::render_scanlines(*ras_ptr, sl, ren);
            ras_ptr->reset();
        },
        [&](path_type const& frame)
        {
            vertex_adapter va(frame);
            transform_path_type path(common_.t_,va,prj_trans);
            agg::conv_stroke<transform_path_type> stroke(path);
            ras_ptr->add_path(stroke);
            ren.color(color_type(feature.id()));
            agg::render_scanlines(*ras_ptr, sl, ren);
            ras_ptr->reset();
        },
        [&](path_type const& roof)
        {
            vertex_adapter va(roof);
            transform_path_type roof_path (common_.t_,va,prj_trans);
            ras_ptr->add_path(roof_path);
            ren.color(color_type(feature.id()));
            agg::render_scanlines(*ras_ptr, sl, ren);
        });

    pixmap_.add_feature(feature);
}
Пример #2
0
void render_raster_marker(RendererType ren,
                          RasterizerType & ras,
                          image_data_rgba8 & src,
                          mapnik::feature_impl const& feature,
                          agg::trans_affine const& marker_tr,
                          double opacity)
{
    using color_type = typename RendererType::color_type;
    agg::scanline_bin sl;
    double width  = src.width();
    double height = src.height();
    double p[8];
    p[0] = 0;     p[1] = 0;
    p[2] = width; p[3] = 0;
    p[4] = width; p[5] = height;
    p[6] = 0;     p[7] = height;
    marker_tr.transform(&p[0], &p[1]);
    marker_tr.transform(&p[2], &p[3]);
    marker_tr.transform(&p[4], &p[5]);
    marker_tr.transform(&p[6], &p[7]);
    ras.move_to_d(p[0],p[1]);
    ras.line_to_d(p[2],p[3]);
    ras.line_to_d(p[4],p[5]);
    ras.line_to_d(p[6],p[7]);
    ren.color(color_type(feature.id()));
    agg::render_scanlines(ras, sl, ren);
}
Пример #3
0
void
aggPixelPainter<pixel_fmt>::clear(const agg::rgba& bk)
{
    using color_type = typename pixel_fmt::color_type;
    agg::rgba bk_pre = bk;
    bk_pre.premultiply();
    rendBase.clear(color_type(bk_pre));
}
Пример #4
0
void progress_init(void)
{
	color_len = strlen(color_type(TUP_NODE_CMD)) +
		strlen(color_append_reverse()) +
		strlen(color_end());
	display_progress = tup_option_get_int("display.progress");
	display_job_numbers = tup_option_get_int("display.job_numbers");
	display_job_time = tup_option_get_int("display.job_time");
	timespan_start(&main_ts);
}
/**
 * \brief Apply the intensity and the opacities to a given color.
 * \param c The color.
 */
bear::visual::color_type
bear::visual::bitmap_rendering_attributes::convert_color
( const color_type& c ) const
{
  return
    color_type
    ( c.components.red * get_red_intensity(),
      c.components.green * get_green_intensity(),
      c.components.blue * get_blue_intensity(),
      c.components.alpha * get_opacity() );
} // bitmap_rendering_attributes::convert_color()
Пример #6
0
Файл: config.c Проект: 5kg/tup
/* Notes:
 * iserr=0 means stdout, for sub-processes that succeed
 * iserr=1 means stderr, for run-scripts
 * iserr=2 means stderr, for tup errors (eg: missing deps)
 * iserr=3 means stderr, for sub-processes that fail
 */
int display_output(int fd, int iserr, const char *name, int display_name, FILE *f)
{
	if(fd != -1) {
		char buf[1024];
		int rc;
		int displayed = 0;
		FILE *out = stdout;

		if(iserr)
			out = stderr;
		if(f)
			out = f;

		while(1) {
			rc = read(fd, buf, sizeof(buf));
			if(rc < 0) {
				perror("display_output: read");
				fprintf(stderr, "tup internal error: Unable to display output from a sub-process.\n");
				return -1;
			}
			if(rc == 0)
				break;
			if(!displayed) {
				displayed = 1;
				clear_active(out);
				if(iserr == 2) {
					/* For tup errors (eg: missing deps) */
					fprintf(out, " *** tup errors ***\n");
				}
				if(iserr == 1) {
					/* This is for run-scripts */
					if(display_name) {
						color_set(stderr);
						fprintf(out, " *** tup: stderr from command '%s%s%s%s' ***\n", color_type(TUP_NODE_CMD), color_append_normal(), name, color_end());
					}
				}
			}
			fprintf(out, "%.*s", rc, buf);
		}
	}
	return 0;
}
Пример #7
0
 void render_raster_marker(agg::trans_affine const& marker_tr)
 {
     agg::scanline_bin sl_;
     double width  = src_.width();
     double height = src_.height();
     double p[8];
     p[0] = 0;     p[1] = 0;
     p[2] = width; p[3] = 0;
     p[4] = width; p[5] = height;
     p[6] = 0;     p[7] = height;
     marker_tr.transform(&p[0], &p[1]);
     marker_tr.transform(&p[2], &p[3]);
     marker_tr.transform(&p[4], &p[5]);
     marker_tr.transform(&p[6], &p[7]);
     ras_.move_to_d(p[0],p[1]);
     ras_.line_to_d(p[2],p[3]);
     ras_.line_to_d(p[4],p[5]);
     ras_.line_to_d(p[6],p[7]);
     RendererType ren(renb_);
     ren.color(color_type(feature_.id()));
     agg::render_scanlines(ras_, sl_, ren);
 }
Пример #8
0
void grid_renderer<T>::process(polygon_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;
    using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
    using color_type = typename grid_renderer_base_type::pixfmt_type::color_type;
    using vertex_converter_type = vertex_converter<transform2_tag,
                                                   clip_poly_tag,
                                                   transform_tag,
                                                   affine_transform_tag,
                                                   simplify_tag,
                                                   smooth_tag,
                                                   contour_tag>;

    ras_ptr->reset();

    grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);

    render_polygon_symbolizer<vertex_converter_type>(
      sym, feature, prj_trans, common_, common_.query_extent_, *ras_ptr,
      [&](color const &, double) {
        pixfmt_type pixf(buf);

        grid_renderer_base_type renb(pixf);
        renderer_type ren(renb);

        // render id
        ren.color(color_type(feature.id()));
        agg::scanline_bin sl;
        ras_ptr->filling_rule(agg::fill_non_zero);
        agg::render_scanlines(*ras_ptr, sl, ren);

        // add feature properties to grid cache
        pixmap_.add_feature(feature);
      });
}
Пример #9
0
void show_progress(int active, enum TUP_NODE_TYPE type)
{
	int console_width = tup_option_get_int("display.width");
	if(total && display_progress && console_width >= 10) {
		/* -3 for the [] and leading space, and -6 for the " 100% " at
		 * the end.
		 */
		int max = console_width - 9;
		int fill;
		char buf[console_width + color_len + 1];
		int num_infos = 0;
		int i = 0;
		int x;
		int tmpmax;
		int offset;

		if(max > total)
			max = total;
		if(got_error)
			type = TUP_NODE_ROOT;

		clear_active(stdout);

		fill = max * sum / total;

		if(color_len) {
			memset(buf, ' ', sizeof(buf));
		} else {
			memset(buf, '.', fill);
			memset(buf+fill, ' ', sizeof(buf) - fill);
		}

		for(x=0; x<ARRAY_SIZE(infos); x++) {
			infos[x].len = 0;
		}

		if(total_time != -1) {
			infos[i].len = get_time_remaining(infos[i].text, sizeof(infos[i].text), job_time, total_time, 0);
		} else {
			infos[i].len = get_time_remaining(infos[i].text, sizeof(infos[i].text), sum, total, 1);
		}
		i++;

		infos[i].len = snprintf(infos[i].text, sizeof(infos[i].text), "Remaining=%i", total-sum);
		i++;

		if(active != -1) {
			infos[i].len = snprintf(infos[i].text, sizeof(infos[i].text), "Active=%i", active);
		} else {
			/* Override maxlen to disable "Active..." */
			infos[i].maxlen = 0;
		}
		i++;

		tmpmax = max;
		for(x=0; x<ARRAY_SIZE(infos); x++) {
			int spacing = 0;
			if(x)
				spacing = 1;
			if(tmpmax >= infos[x].maxlen + spacing) {
				tmpmax -= infos[x].maxlen + spacing;
				num_infos++;
			} else {
				break;
			}
		}
		offset = tmpmax / 2;
		for(x=0; x<num_infos; x++) {
			if(x)
				offset++;
			memcpy(buf + offset, infos[x].text, infos[x].len);
			offset += infos[x].maxlen;
		}

		color_set(stdout);
		printf(" [%s%s%.*s%s%.*s] %3i%%", color_type(type), color_append_reverse(), fill, buf, color_end(), max-fill, buf+fill, percent_complete());
		is_active = 1;
		fflush(stdout);
	}
}
void grid_renderer<T>::process(line_pattern_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
    if (filename.empty()) return;
    std::shared_ptr<mapnik::marker const> mark = marker_cache::instance().find(filename, true);
    if (mark->is<mapnik::marker_null>()) return;

    if (!mark->is<mapnik::marker_rgba8>())
    {
        MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer";
        return;
    }

    value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_);
    value_double offset = get<value_double, keys::offset>(sym, feature, common_.vars_);
    value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
    value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);

    using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
    using color_type = typename grid_renderer_base_type::pixfmt_type::color_type;
    using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;

    agg::scanline_bin sl;

    grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);
    pixfmt_type pixf(buf);

    grid_renderer_base_type renb(pixf);
    renderer_type ren(renb);

    ras_ptr->reset();

    line_pattern_enum pattern = get<line_pattern_enum, keys::line_pattern>(sym, feature, common_.vars_);
    std::size_t stroke_width = (pattern == LINE_PATTERN_WARP) ? mark->width() :
        get<value_double, keys::stroke_width>(sym, feature, common_.vars_);

    agg::trans_affine tr;
    auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (transform)
    {
        evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
    }

    box2d<double> clipping_extent = common_.query_extent_;
    if (clip)
    {
        double pad_per_pixel = static_cast<double>(common_.query_extent_.width()/common_.width_);
        double pixels = std::ceil(std::max(stroke_width / 2.0 + std::fabs(offset),
                                          (std::fabs(offset) * offset_converter_default_threshold)));
        double padding = pad_per_pixel * pixels * common_.scale_factor_;

        clipping_extent.pad(padding);
    }

    // to avoid the complexity of using an agg pattern filter instead
    // we create a line_symbolizer in order to fake the pattern
    line_symbolizer line;
    put<value_double>(line, keys::stroke_width, value_double(stroke_width));
    // TODO: really should pass the offset to the fake line too, but
    // this wasn't present in the previous version and makes the test
    // fail - in this case, probably the test should be updated.
    //put<value_double>(line, keys::offset, value_double(offset));
    put<value_double>(line, keys::simplify_tolerance, value_double(simplify_tolerance));
    put<value_double>(line, keys::smooth, value_double(smooth));

    using vertex_converter_type = vertex_converter<clip_line_tag, transform_tag,
                                                   affine_transform_tag,
                                                   simplify_tag,smooth_tag,
                                                   offset_transform_tag,stroke_tag>;
    vertex_converter_type converter(clipping_extent,line,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);
    if (clip) converter.set<clip_line_tag>();
    converter.set<transform_tag>(); // always transform
    if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
    converter.set<affine_transform_tag>(); // optional affine transform
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
    converter.set<stroke_tag>(); //always stroke
    using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type,grid_rasterizer>;
    using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
    apply_vertex_converter_type apply(converter, *ras_ptr);
    mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry());

    // render id
    ren.color(color_type(feature.id()));
    agg::render_scanlines(*ras_ptr, sl, ren);

    // add feature properties to grid cache
    pixmap_.add_feature(feature);

}
Пример #11
0
void scene_renderer_t::render_and_filter_shape( const shape_t& s, int bbox_index)
{
	RAMEN_ASSERT( bbox_index >= 0 && bbox_index <= filtered_bboxes_.size());
	
	boost::gil::fill_pixels( boost::gil::view( buf_), image::gray_pixel_t( 0));
	boost::gil::fill_pixels( boost::gil::view( tmp_), image::gray_pixel_t( 0));
	
    ren_base_type ren_base;
    agg::scanline_u8 sl;
    agg::rasterizer_scanline_aa<> ras;
    renderer_type ren;

    ren_base.set_view( boost::gil::view( buf_));
    ren.attach( ren_base);
    ras.gamma( agg::gamma_none());
	
	convert_to_path( s, path_, filtered_bboxes_[bbox_index].min, subsample_);
    agg::conv_curve<agg::path_storage> cpath( path_);
    ras.add_path( cpath);
    ras.filling_rule( agg::fill_non_zero);
    ren.color( color_type( 1.0f, 1.0f));
    agg::render_scanlines( ras, sl, ren);

	image::gray_image_view_t buf_view( boost::gil::view( buf_));
	
	float g = s.grow();
	if( g != 0.0f)
	{
		/*
		image::gray_image_view_t subbuf_view( boost::gil::subimage_view( buf_view, 
																		 bboxes_[bbox_index].min.x - filtered_bboxes_[bbox_index].min.x,
																		 bboxes_[bbox_index].min.y - filtered_bboxes_[bbox_index].min.y,
																		 bboxes_[bbox_index].size().x + 1, bboxes_[bbox_index].size().y + 1));
		
		image::dilate( subbuf_view, boost::gil::view( tmp_), subbuf_view, g / aspect_ / subsample_, g / subsample_);
		*/
		boost::gil::fill_pixels( boost::gil::view( tmp_), image::gray_pixel_t( 0));
		image::dilate( buf_view, boost::gil::view( tmp_), buf_view, g / aspect_ / subsample_, g / subsample_);
	}

	Imath::V2f blur = s.blur();
	if( blur.x != 0.0f || blur.y != 0.0f)
	{
		boost::gil::fill_pixels( boost::gil::view( tmp_), image::gray_pixel_t( 0));
		image::box_blur_gray( buf_view, boost::gil::view( tmp_), buf_view, blur.x / aspect_ / subsample_, blur.y / subsample_, 1);
	}
	
	Imath::Box2i common_area = ImathExt::intersect( area_, filtered_bboxes_[bbox_index]);
	
	if( !common_area.isEmpty())
	{
		
		image::gray_image_view_t bg_view( boost::gil::subimage_view( boost::gil::view( pixels_), 
																	 common_area.min.x - area_.min.x, 
																	 common_area.min.y - area_.min.y, 
																	 common_area.size().x, 
																	 common_area.size().y));
		
		boost::gil::tbb_transform2_pixels( boost::gil::subimage_view( buf_view, 
																	  common_area.min.x - filtered_bboxes_[bbox_index].min.x, 
																	  common_area.min.y - filtered_bboxes_[bbox_index].min.y, 
																	  common_area.size().x, 
																	  common_area.size().y),
										   bg_view, bg_view, composite_layer( s.color(), s.opacity()));
	}
}
Пример #12
0
void grid_renderer<T>::process(line_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
    using color_type = typename grid_renderer_base_type::pixfmt_type::color_type;
    using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;

    agg::scanline_bin sl;

    grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);
    pixfmt_type pixf(buf);

    grid_renderer_base_type renb(pixf);
    renderer_type ren(renb);

    ras_ptr->reset();

    agg::trans_affine tr;
    auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (transform)
    {
        evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
    }

    box2d<double> clipping_extent = common_.query_extent_;

    bool clip = get<value_bool>(sym, keys::clip, feature, common_.vars_, false);
    double width = get<value_double>(sym, keys::stroke_width, feature, common_.vars_,1.0);
    double offset = get<value_double>(sym, keys::offset, feature, common_.vars_,0.0);
    double simplify_tolerance = get<value_double>(sym, keys::simplify_tolerance, feature, common_.vars_,0.0);
    double smooth = get<value_double>(sym, keys::smooth, feature, common_.vars_,false);
    bool has_dash = has_key(sym, keys::stroke_dasharray);

    if (clip)
    {
        double padding = (double)(common_.query_extent_.width()/pixmap_.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 vertex_converter_type = vertex_converter<clip_line_tag, clip_poly_tag, transform_tag,
                                                   affine_transform_tag,
                                                   simplify_tag, smooth_tag,
                                                   offset_transform_tag,
                                                   dash_tag, stroke_tag>;

    vertex_converter_type converter(clipping_extent,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);
    if (clip)
    {
        geometry::geometry_types type = geometry::geometry_type(feature.get_geometry());
        if (type == geometry::geometry_types::Polygon || type == geometry::geometry_types::MultiPolygon)
            converter.template set<clip_poly_tag>();
        else if (type == geometry::geometry_types::LineString || type == geometry::geometry_types::MultiLineString)
            converter.template set<clip_line_tag>();
    }
    converter.set<transform_tag>(); // always transform
    if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
    converter.set<affine_transform_tag>(); // optional affine transform
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
    if (has_dash) converter.set<dash_tag>();
    converter.set<stroke_tag>(); //always stroke

    using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, grid_rasterizer>;
    using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
    apply_vertex_converter_type apply(converter, *ras_ptr);
    mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry());

    // render id
    ren.color(color_type(feature.id()));
    ras_ptr->filling_rule(agg::fill_non_zero);
    agg::render_scanlines(*ras_ptr, sl, ren);

    // add feature properties to grid cache
    pixmap_.add_feature(feature);

}
void grid_renderer<T>::process(polygon_pattern_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    std::string filename = get<std::string>(sym, keys::file, feature, common_.vars_);
    if (filename.empty()) return;
    boost::optional<mapnik::marker_ptr> mark = marker_cache::instance().find(filename, true);
    if (!mark) return;

    if (!(*mark)->is_bitmap())
    {
        MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer";
        return;
    }

    boost::optional<image_ptr> pat = (*mark)->get_bitmap_data();
    if (!pat) return;

    ras_ptr->reset();

    bool clip = get<value_bool>(sym, keys::clip, feature, common_.vars_, true);
    double simplify_tolerance = get<value_double>(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0);
    double smooth = get<value_double>(sym, keys::smooth, feature, common_.vars_, false);

    agg::trans_affine tr;
    auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (transform)
    {
        evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
    }

    using conv_types = boost::mpl::vector<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag>;
    vertex_converter<box2d<double>, grid_rasterizer, polygon_pattern_symbolizer,
                     CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl>
        converter(common_.query_extent_,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);

    if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
    converter.set<transform_tag>(); //always transform
    converter.set<affine_transform_tag>();
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

    for ( geometry_type & geom : feature.paths())
    {
        if (geom.size() > 2)
        {
            converter.apply(geom);
        }
    }
    using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
    using color_type = typename grid_renderer_base_type::pixfmt_type::color_type;
    using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;

    grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);
    pixfmt_type pixf(buf);

    grid_renderer_base_type renb(pixf);
    renderer_type ren(renb);

    // render id
    ren.color(color_type(feature.id()));
    agg::scanline_bin sl;
    ras_ptr->filling_rule(agg::fill_even_odd);
    agg::render_scanlines(*ras_ptr, sl, ren);

    // add feature properties to grid cache
    pixmap_.add_feature(feature);
}
void grid_renderer<T>::process(line_pattern_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    std::string filename = get<std::string>(sym, keys::file, feature, common_.vars_);
    if (filename.empty()) return;
    boost::optional<mapnik::marker_ptr> mark = marker_cache::instance().find(filename, true);
    if (!mark) return;

    if (!(*mark)->is_bitmap())
    {
        MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer";
        return;
    }

    boost::optional<image_ptr> pat = (*mark)->get_bitmap_data();
    if (!pat) return;

    bool clip = get<value_bool>(sym, keys::clip, feature, common_.vars_, true);
    double offset = get<value_double>(sym, keys::offset, feature, common_.vars_, 0.0);
    double simplify_tolerance = get<value_double>(sym, keys::simplify_tolerance, feature, common_.vars_, 0.0);
    double smooth = get<value_double>(sym, keys::smooth, feature, common_.vars_, false);

    using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
    using color_type = typename grid_renderer_base_type::pixfmt_type::color_type;
    using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;
    using conv_types = boost::mpl::vector<clip_line_tag, transform_tag,
                                          offset_transform_tag, affine_transform_tag,
                                          simplify_tag, smooth_tag, stroke_tag>;
    agg::scanline_bin sl;

    grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);
    pixfmt_type pixf(buf);

    grid_renderer_base_type renb(pixf);
    renderer_type ren(renb);

    ras_ptr->reset();

    int stroke_width = (*pat)->width();

    agg::trans_affine tr;
    auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (transform)
    {
        evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
    }

    box2d<double> clipping_extent = common_.query_extent_;
    if (clip)
    {
        double padding = (double)(common_.query_extent_.width()/pixmap_.width());
        double half_stroke = 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);
    }

    // to avoid the complexity of using an agg pattern filter instead
    // we create a line_symbolizer in order to fake the pattern
    line_symbolizer line;
    put<value_double>(line, keys::stroke_width, value_double(stroke_width));
    // TODO: really should pass the offset to the fake line too, but
    // this wasn't present in the previous version and makes the test
    // fail - in this case, probably the test should be updated.
    //put<value_double>(line, keys::offset, value_double(offset));
    put<value_double>(line, keys::simplify_tolerance, value_double(simplify_tolerance));
    put<value_double>(line, keys::smooth, value_double(smooth));

    vertex_converter<box2d<double>, grid_rasterizer, line_symbolizer,
                     CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl>
        converter(clipping_extent,*ras_ptr,line,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);
    if (clip) converter.set<clip_line_tag>(); // optional clip (default: true)
    converter.set<transform_tag>(); // always transform
    if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
    converter.set<affine_transform_tag>(); // optional affine transform
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
    converter.set<stroke_tag>(); //always stroke

    for (geometry_type & geom : feature.paths())
    {
        if (geom.size() > 1)
        {
            converter.apply(geom);
        }
    }

    // render id
    ren.color(color_type(feature.id()));
    agg::render_scanlines(*ras_ptr, sl, ren);

    // add feature properties to grid cache
    pixmap_.add_feature(feature);

}
void grid_renderer<T>::process(polygon_pattern_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    std::string filename = get<std::string, keys::file>(sym, feature, common_.vars_);
    if (filename.empty()) return;
    mapnik::marker const& mark = marker_cache::instance().find(filename, true);
    if (mark.is<mapnik::marker_null>()) return;

    if (!mark.is<mapnik::marker_rgba8>())
    {
        MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: Only images (not '" << filename << "') are supported in the line_pattern_symbolizer";
        return;
    }

    ras_ptr->reset();

    value_bool clip = get<value_bool, keys::clip>(sym, feature, common_.vars_);
    value_double simplify_tolerance = get<value_double, keys::simplify_tolerance>(sym, feature, common_.vars_);
    value_double smooth = get<value_double, keys::smooth>(sym, feature, common_.vars_);

    agg::trans_affine tr;
    auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (transform)
    {
        evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
    }

    using vertex_converter_type = vertex_converter<clip_poly_tag,transform_tag,affine_transform_tag,smooth_tag>;
    vertex_converter_type converter(common_.query_extent_,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);

    if (prj_trans.equal() && clip) converter.set<clip_poly_tag>(); //optional clip (default: true)
    converter.set<transform_tag>(); //always transform
    converter.set<affine_transform_tag>();
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter

    using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type, grid_rasterizer>;
    using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>;
    apply_vertex_converter_type apply(converter, *ras_ptr);
    mapnik::util::apply_visitor(vertex_processor_type(apply),feature.get_geometry());

    using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
    using color_type = typename grid_renderer_base_type::pixfmt_type::color_type;
    using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;

    grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);
    pixfmt_type pixf(buf);

    grid_renderer_base_type renb(pixf);
    renderer_type ren(renb);

    // render id
    ren.color(color_type(feature.id()));
    agg::scanline_bin sl;
    ras_ptr->filling_rule(agg::fill_even_odd);
    agg::render_scanlines(*ras_ptr, sl, ren);

    // add feature properties to grid cache
    pixmap_.add_feature(feature);
}
void grid_renderer<T>::process(line_symbolizer const& sym,
                               mapnik::feature_impl & feature,
                               proj_transform const& prj_trans)
{
    using pixfmt_type = typename grid_renderer_base_type::pixfmt_type;
    using color_type = typename grid_renderer_base_type::pixfmt_type::color_type;
    using renderer_type = agg::renderer_scanline_bin_solid<grid_renderer_base_type>;
    using conv_types = boost::mpl::vector<clip_line_tag, transform_tag,
                                          offset_transform_tag, affine_transform_tag,
                                          simplify_tag, smooth_tag, dash_tag, stroke_tag>;
    agg::scanline_bin sl;

    grid_rendering_buffer buf(pixmap_.raw_data(), common_.width_, common_.height_, common_.width_);
    pixfmt_type pixf(buf);

    grid_renderer_base_type renb(pixf);
    renderer_type ren(renb);

    ras_ptr->reset();

    agg::trans_affine tr;
    auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
    if (transform)
    {
        evaluate_transform(tr, feature, common_.vars_, *transform, common_.scale_factor_);
    }

    box2d<double> clipping_extent = common_.query_extent_;

    bool clip = get<value_bool>(sym, keys::clip, feature, common_.vars_, true);
    double width = get<value_double>(sym, keys::stroke_width, feature, common_.vars_,1.0);
    double offset = get<value_double>(sym, keys::offset, feature, common_.vars_,0.0);
    double simplify_tolerance = get<value_double>(sym, keys::simplify_tolerance, feature, common_.vars_,0.0);
    double smooth = get<value_double>(sym, keys::smooth, feature, common_.vars_,false);
    bool has_dash = has_key<dash_array>(sym, keys::stroke_dasharray);

    if (clip)
    {
        double padding = (double)(common_.query_extent_.width()/pixmap_.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<box2d<double>, grid_rasterizer, line_symbolizer,
                     CoordTransform, proj_transform, agg::trans_affine, conv_types, feature_impl>
        converter(clipping_extent,*ras_ptr,sym,common_.t_,prj_trans,tr,feature,common_.vars_,common_.scale_factor_);
    if (clip) converter.set<clip_line_tag>(); // optional clip (default: true)
    converter.set<transform_tag>(); // always transform
    if (std::fabs(offset) > 0.0) converter.set<offset_transform_tag>(); // parallel offset
    converter.set<affine_transform_tag>(); // optional affine transform
    if (simplify_tolerance > 0.0) converter.set<simplify_tag>(); // optional simplify converter
    if (smooth > 0.0) converter.set<smooth_tag>(); // optional smooth converter
    if (has_dash) converter.set<dash_tag>();
    converter.set<stroke_tag>(); //always stroke

    for ( geometry_type & geom : feature.paths())
    {
        if (geom.size() > 1)
        {
            converter.apply(geom);
        }
    }

    // render id
    ren.color(color_type(feature.id()));
    ras_ptr->filling_rule(agg::fill_non_zero);
    agg::render_scanlines(*ras_ptr, sl, ren);

    // add feature properties to grid cache
    pixmap_.add_feature(feature);

}