void feature_style_processor<Processor>::apply_to_layer(layer const& lay,
                                                        Processor & p,
                                                        projection const& proj0,
                                                        double scale,
                                                        double scale_denom,
                                                        unsigned width,
                                                        unsigned height,
                                                        box2d<double> const& extent,
                                                        int buffer_size,
                                                        std::set<std::string>& names)
{
    feature_style_context_map ctx_map;
    layer_rendering_material  mat(lay, proj0);

    prepare_layer(mat,
                  ctx_map,
                  p,
                  scale,
                  scale_denom,
                  width,
                  height,
                  extent,
                  buffer_size,
                  names);

    prepare_layers(mat, lay.layers(), ctx_map, p, scale_denom);

    if (!mat.active_styles_.empty())
    {
        render_material(mat,p);
        render_submaterials(mat, p);
    }
}
void feature_style_processor<Processor>::prepare_layers(layer_rendering_material & parent_mat,
                                                        std::vector<layer> const & layers,
                                                        feature_style_context_map & ctx_map,
                                                        Processor & p,
                                                        double scale_denom)
{
    for (layer const& lyr : layers)
    {
        if (lyr.visible(scale_denom))
        {
            std::set<std::string> names;
            layer_rendering_material mat(lyr, parent_mat.proj0_);

            prepare_layer(mat,
                          ctx_map,
                          p,
                          m_.scale(),
                          scale_denom,
                          m_.width(),
                          m_.height(),
                          m_.get_current_extent(),
                          m_.buffer_size(),
                          names);

            // Store active material
            if (!mat.active_styles_.empty())
            {
                prepare_layers(mat, lyr.layers(), ctx_map, p, scale_denom);
                parent_mat.materials_.emplace_back(std::move(mat));
            }
        }
    }
}
void feature_style_processor<Processor>::apply(double scale_denom)
{
    Processor & p = static_cast<Processor&>(*this);
    p.start_map_processing(m_);

    projection proj(m_.srs(),true);
    if (scale_denom <= 0.0)
        scale_denom = mapnik::scale_denominator(m_.scale(),proj.is_geographic());
    scale_denom *= p.scale_factor();

    // Asynchronous query supports:
    // This is a two steps process,
    // first we setup all queries at layer level
    // in a second time, we fetch the results and
    // do the actual rendering

    std::vector<layer_rendering_material_ptr> mat_list;

    // Define processing context map used by datasources
    // implementing asynchronous queries
    feature_style_context_map ctx_map;

    for ( layer const& lyr : m_.layers() )
    {
        if (lyr.visible(scale_denom))
        {
            std::set<std::string> names;
            layer_rendering_material_ptr mat = std::make_shared<layer_rendering_material>(lyr, proj);

            prepare_layer(*mat,
                          ctx_map,
                          p,
                          m_.scale(),
                          scale_denom,
                          m_.width(),
                          m_.height(),
                          m_.get_current_extent(),
                          m_.buffer_size(),
                          names);

            // Store active material
            if (!mat->active_styles_.empty())
            {
                mat_list.push_back(mat);
            }
        }
    }

    for ( layer_rendering_material_ptr mat : mat_list )
    {
        if (!mat->active_styles_.empty())
        {
            render_material(*mat,p);
        }
    }

    p.end_map_processing(m_);
}