Implement line placements.

This commit is contained in:
Hermann Kraus 2012-08-04 23:14:32 +02:00
parent 5cb7cb8c59
commit 53fa3ff1e1
3 changed files with 90 additions and 5 deletions

View file

@ -43,6 +43,7 @@ typedef label_collision_detector4 DetectorType;
class feature_impl; class feature_impl;
typedef feature_impl Feature; typedef feature_impl Feature;
class vertex_cache;
class placement_finder_ng : boost::noncopyable class placement_finder_ng : boost::noncopyable
{ {
@ -69,6 +70,8 @@ public:
private: private:
void init_alignment(); void init_alignment();
pixel_position alignment_offset() const; pixel_position alignment_offset() const;
bool single_line_placement(vertex_cache &pp, signed orientation);
Feature const& feature_; Feature const& feature_;
DetectorType &detector_; DetectorType &detector_;
box2d<double> const& extent_; box2d<double> const& extent_;

View file

@ -27,7 +27,7 @@
#include <mapnik/debug.hpp> #include <mapnik/debug.hpp>
#include <mapnik/label_collision_detector.hpp> #include <mapnik/label_collision_detector.hpp>
#include <mapnik/ctrans.hpp> #include <mapnik/ctrans.hpp>
#include <mapnik/path_processor.hpp> #include <mapnik/vertex_cache.hpp>
#include <mapnik/expression_evaluator.hpp> #include <mapnik/expression_evaluator.hpp>
//boost //boost
@ -244,8 +244,8 @@ bool placement_finder_ng::find_point_placement(pixel_position pos)
template <typename T> template <typename T>
bool placement_finder_ng::find_point_on_line_placements(T & path) bool placement_finder_ng::find_point_on_line_placements(T & path)
{ {
path_processor<T> pp(path);
if (!layout_.size()) return true; if (!layout_.size()) return true;
vertex_cache pp(path);
bool success = false; bool success = false;
while (pp.next_subpath()) while (pp.next_subpath())
{ {
@ -277,8 +277,90 @@ bool placement_finder_ng::find_point_on_line_placements(T & path)
template <typename T> template <typename T>
bool placement_finder_ng::find_line_placements(T & path) bool placement_finder_ng::find_line_placements(T & path)
{ {
path_processor<T> pp(path); if (!layout_.size()) return true;
return false; vertex_cache pp(path);
bool success = false;
while (pp.next_subpath())
{
if ((pp.length() < info_->properties.minimum_path_length)
||
(pp.length() < layout_.width())) continue;
int num_labels = 1;
if (info_->properties.label_spacing > 0)
num_labels = static_cast<int> (floor(pp.length() / info_->properties.label_spacing * scale_factor_));
if (info_->properties.force_odd_labels && num_labels % 2 == 0)
num_labels--;
if (num_labels <= 0)
num_labels = 1;
double spacing = pp.length() / num_labels;
pp.forward(spacing/2.-layout_.width()/2.); // first label should be placed at half the spacing
do
{
vertex_cache::state s = pp.save_state();
success = single_line_placement(pp, 0) || success;
pp.restore_state(s);
} while (pp.forward(spacing));
}
return success;
}
bool placement_finder_ng::single_line_placement(vertex_cache &pp, signed orientation)
{
std::cout << "single_line" << pp.current_position().x << ", " << pp.current_position().y << "\n";
double base_offset = alignment_offset().y + info_->properties.displacement.y;
glyph_positions_ptr glyphs = boost::make_shared<glyph_positions>();
// glyphs->set_base_point(pixel_position(0, 0));
/* IMPORTANT NOTE:
x and y are relative to the center of the text
coordinate system:
x: grows from left to right
y: grows from bottom to top (all values are negative!)
*/
double offset = base_offset + layout_.height();
text_layout::const_iterator line_itr = layout_.begin(), line_end = layout_.end();
for (; line_itr != line_end; line_itr++)
{
double char_height = (*line_itr)->max_char_height();
offset -= (*line_itr)->height();
// reset to begining of line position
text_line::const_iterator glyph_itr = (*line_itr)->begin(), glyph_end = (*line_itr)->end();
for (; glyph_itr != glyph_end; glyph_itr++)
{
double angle = pp.angle();
std::cout << "angle:" << angle / (2 * M_PI) * 360 << "\n";
double sina = sin(angle);
double cosa = cos(angle);
pixel_position pos = pp.current_position();
//Center the text on the line
pos.y = -pos.y - char_height/2.0*cosa;
pos.x = pos.x - char_height/2.0*sina;
// if (orientation < 0)
// {
// // rotate in place
// render_x += cwidth*cosa - char_height*sina;
// render_y -= cwidth*sina + char_height*cosa;
// render_angle += M_PI;
// }
glyphs->push_back(*glyph_itr, pos, -angle); //TODO: Store cosa, sina instead
if (glyph_itr->width)
{
//Only advance if glyph is not part of a multiple glyph sequence
pp.forward(glyph_itr->width + glyph_itr->format->character_spacing);
}
}
}
placements_.push_back(glyphs);
return true;
} }

View file

@ -102,7 +102,7 @@ void text_renderer<T>::render(glyph_positions_ptr pos)
pixel_position const& base_point = pos->get_base_point(); pixel_position const& base_point = pos->get_base_point();
start.x = static_cast<FT_Pos>(base_point.x * (1 << 6)); start.x = static_cast<FT_Pos>(base_point.x * (1 << 6));
start.y = static_cast<FT_Pos>((height - base_point.y) * (1 << 6)); //TODO: Why is this inverted coordinate system used? start.y = static_cast<FT_Pos>((height - base_point.y) * (1 << 6));
//render halo //render halo
typename boost::ptr_vector<glyph_t>::iterator itr; typename boost::ptr_vector<glyph_t>::iterator itr;