Start work on new symbolizer helpers.
This commit is contained in:
parent
2eb3662d87
commit
3b887972b8
2 changed files with 159 additions and 27 deletions
138
include/mapnik/symbolizer_helpers.hpp
Normal file
138
include/mapnik/symbolizer_helpers.hpp
Normal file
|
@ -0,0 +1,138 @@
|
|||
/*****************************************************************************
|
||||
*
|
||||
* This file is part of Mapnik (c++ mapping toolkit)
|
||||
*
|
||||
* Copyright (C) 2012 Artem Pavlenko
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*
|
||||
*****************************************************************************/
|
||||
#ifndef SYMBOLIZER_HELPERS_HPP
|
||||
#define SYMBOLIZER_HELPERS_HPP
|
||||
|
||||
#include <mapnik/text_symbolizer.hpp>
|
||||
#include <mapnik/text_processing.hpp>
|
||||
#include <mapnik/placement_finder.hpp>
|
||||
#include <mapnik/expression_evaluator.hpp>
|
||||
#include <mapnik/feature.hpp>
|
||||
|
||||
#include <boost/shared_ptr.hpp>
|
||||
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
template <typename FaceManagerT, typename DetectorT>
|
||||
class text_symbolizer_helper
|
||||
{
|
||||
public:
|
||||
text_symbolizer_helper(unsigned width,
|
||||
unsigned height,
|
||||
double scale_factor,
|
||||
CoordTransform const &t,
|
||||
FaceManagerT &font_manager,
|
||||
DetectorT &detector) :
|
||||
width_(width),
|
||||
height_(height),
|
||||
scale_factor_(scale_factor),
|
||||
t_(t),
|
||||
font_manager_(font_manager),
|
||||
detector_(detector),
|
||||
text_()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
text_placement_info_ptr get_placement(text_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
private:
|
||||
bool initialize_geometries(text_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
|
||||
unsigned width_;
|
||||
unsigned height_;
|
||||
double scale_factor_;
|
||||
CoordTransform const &t_;
|
||||
FaceManagerT &font_manager_;
|
||||
DetectorT &detector_;
|
||||
boost::shared_ptr<processed_text> text_; /*TODO: Use shared pointers for text placement so we don't need to keep a reference here! */
|
||||
// Use a boost::ptr_vector here instread of std::vector?
|
||||
std::vector<geometry_type*> geometries_to_process_;
|
||||
};
|
||||
|
||||
|
||||
template <typename FaceManagerT, typename DetectorT>
|
||||
text_placement_info_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::get_placement(
|
||||
text_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
if (!initialize_geometries(sym, feature, prj_trans)) return text_placement_info_ptr();
|
||||
|
||||
text_ = boost::shared_ptr<processed_text>(new processed_text(font_manager_, scale_factor_));
|
||||
metawriter_with_properties writer = sym.get_metawriter();
|
||||
|
||||
box2d<double> dims(0, 0, width_, height_);
|
||||
|
||||
// typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
text_placement_info_ptr placement = sym.get_placement_options()->get_placement_info();
|
||||
placement->init(scale_factor_, width_, height_);
|
||||
if (writer.first)
|
||||
placement->collect_extents = true;
|
||||
|
||||
while (placement->next())
|
||||
{
|
||||
text_processor &processor = placement->properties.processor;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename FaceManagerT, typename DetectorT>
|
||||
bool text_symbolizer_helper<FaceManagerT, DetectorT>::initialize_geometries(
|
||||
text_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
unsigned num_geom = feature.num_geometries();
|
||||
for (unsigned i=0; i<num_geom; ++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
|
||||
// don't bother with empty geometries
|
||||
if (geom.num_points() == 0) continue;
|
||||
|
||||
if ((geom.type() == Polygon) && sym.get_minimum_path_length() > 0)
|
||||
{
|
||||
// TODO - find less costly method than fetching full envelope
|
||||
box2d<double> gbox = t_.forward(geom.envelope(),prj_trans);
|
||||
if (gbox.width() < sym.get_minimum_path_length())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// TODO - calculate length here as well
|
||||
geometries_to_process_.push_back(const_cast<geometry_type*>(&geom));
|
||||
}
|
||||
|
||||
if (!geometries_to_process_.size() > 0)
|
||||
{
|
||||
// early return to avoid significant overhead of rendering setup
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
#endif // SYMBOLIZER_HELPERS_HPP
|
|
@ -24,7 +24,7 @@
|
|||
// mapnik
|
||||
#include <mapnik/agg_renderer.hpp>
|
||||
#include <mapnik/agg_rasterizer.hpp>
|
||||
#include <mapnik/expression_evaluator.hpp>
|
||||
#include <mapnik/symbolizer_helpers.hpp>
|
||||
|
||||
namespace mapnik {
|
||||
|
||||
|
@ -33,33 +33,27 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
#if 0
|
||||
// Use a boost::ptr_vector here instread of std::vector?
|
||||
std::vector<geometry_type*> geometries_to_process;
|
||||
unsigned num_geom = feature.num_geometries();
|
||||
for (unsigned i=0; i<num_geom; ++i)
|
||||
{
|
||||
geometry_type const& geom = feature.get_geometry(i);
|
||||
|
||||
if (geom.num_points() == 0) continue; // don't bother with empty geometries
|
||||
|
||||
if ((geom.type() == Polygon) && sym.get_minimum_path_length() > 0)
|
||||
{
|
||||
// TODO - find less costly method than fetching full envelope
|
||||
box2d<double> gbox = t_.forward(geom.envelope(),prj_trans);
|
||||
if (gbox.width() < sym.get_minimum_path_length())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
// TODO - calculate length here as well
|
||||
geometries_to_process.push_back(const_cast<geometry_type*>(&geom));
|
||||
}
|
||||
|
||||
if (!geometries_to_process.size() > 0)
|
||||
return; // early return to avoid significant overhead of rendering setup
|
||||
/* This could also be a member of the renderer class, but I would have
|
||||
to check if any of the variables changes and notify the helper.
|
||||
It could be done at a later point, but for now keep the code simple.
|
||||
*/
|
||||
text_symbolizer_helper<face_manager<freetype_engine>, boost::shared_ptr<label_collision_detector4> > helper(width_, height_, scale_factor_, t_, font_manager_, detector_);
|
||||
|
||||
text_placement_info_ptr placement = helper.get_placement(sym, feature, prj_trans);
|
||||
|
||||
if (!placement) return;
|
||||
|
||||
text_renderer<T> ren(pixmap_, font_manager_, *(font_manager_.get_stroker()));
|
||||
for (unsigned int ii = 0; ii < placement->placements.size(); ++ii)
|
||||
{
|
||||
double x = placement->placements[ii].starting_x;
|
||||
double y = placement->placements[ii].starting_y;
|
||||
ren.prepare_glyphs(&(placement->placements[ii]));
|
||||
ren.render(x, y);
|
||||
}
|
||||
|
||||
#if 0
|
||||
|
||||
typedef coord_transform2<CoordTransform,geometry_type> path_type;
|
||||
|
||||
bool placement_found = false;
|
||||
text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info();
|
||||
|
|
Loading…
Reference in a new issue