Change glyph_positions interface to be easier to use.

This commit is contained in:
Hermann Kraus 2012-07-22 21:47:07 +02:00
parent 9408f2e169
commit c0180d59ed
4 changed files with 59 additions and 66 deletions

View file

@ -29,7 +29,7 @@
#include <mapnik/text/char_properties_ptr.hpp>
//stl
#include <list>
#include <vector>
//boost
#include <boost/utility.hpp>
@ -47,33 +47,42 @@ typedef feature_impl Feature;
class text_layout;
typedef boost::shared_ptr<text_layout> text_layout_ptr;
struct glyph_position
{
glyph_position(glyph_info const& glyph, pixel_position const& pos, double angle)
: glyph(&glyph), pos(pos), angle(angle) { }
glyph_info const* glyph;
pixel_position pos;
double angle;
};
/** Stores positions of glphys.
*
* The actual glyphs and their format is stored in text_layout.
* For point placements only the base point is stored, glyph positions
* are defined by information in text_layout.
*/
class glyph_positions
{
public:
glyph_positions(text_layout_ptr layout);
void point_placement(pixel_position base_point);
bool is_point_placement() const { return point_; }
bool next();
void rewind();
glyph_info const& get_glyph() const;
pixel_position get_position() const;
double get_angle() const;
typedef std::vector<glyph_position>::const_iterator const_iterator;
glyph_positions();
const_iterator begin() const;
const_iterator end() const;
void push_back(glyph_info const& glyph, pixel_position offset, double angle);
/** Is each character rotated by the same angle?
* This function is used to avoid costly trigonometric function calls when not necessary. */
bool is_constant_angle() const;
double get_angle() const;
pixel_position const& get_base_point() const;
void set_base_point(pixel_position base_point);
private:
std::vector<glyph_position> data_;
pixel_position base_point_;
bool point_;
text_layout_ptr layout_;
signed current_;
pixel_position current_position_;
double angle_;
bool const_angle_;
};
typedef boost::shared_ptr<glyph_positions> glyph_positions_ptr;
@ -85,11 +94,14 @@ public:
box2d<double> const& extent);
/** Try to place a single label at the given point. */
glyph_positions_ptr find_point_placement(text_layout_ptr layout, double pos_x, double pos_y, double angle=0.0);
glyph_positions_ptr find_point_placement(text_layout_ptr layout, double pos_x, double pos_y);
void set_angle(double angle);
private:
Feature const& feature_;
DetectorType const& detector_;
box2d<double> const& extent_;
double angle_;
};
}//ns mapnik

View file

@ -123,7 +123,7 @@ glyph_positions_ptr text_symbolizer_helper<FaceManagerT, DetectorT>::next_point_
continue; //Reexecute size check
}
glyph_positions_ptr glyphs = finder_.find_point_placement(
layout_, point_itr_->first, point_itr_->second, angle_);
layout_, point_itr_->first, point_itr_->second);
if (glyphs)
{
//Found a placement
@ -272,6 +272,7 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_placement()
} else {
angle_ = 0.0;
}
finder_.set_angle(angle_);
#if 0
if (writer_.first) finder_->set_collect_extents(true);
@ -324,7 +325,7 @@ bool shield_symbolizer_helper<FaceManagerT, DetectorT>::next_point_placement()
double label_x = point_itr_->first + shield_pos.first;
double label_y = point_itr_->second + shield_pos.second;
glyph_positions_ptr glyphs = finder_.find_point_placement(layout_, label_x, label_y, angle_);
glyph_positions_ptr glyphs = finder_.find_point_placement(layout_, label_x, label_y);
if (!glyphs)
{
//No placement for this point. Keep it in points_ for next try.

View file

@ -35,71 +35,52 @@ placement_finder_ng::placement_finder_ng( Feature const& feature, DetectorType &
{
}
glyph_positions_ptr placement_finder_ng::find_point_placement(text_layout_ptr layout, double pos_x, double pos_y, double angle)
glyph_positions_ptr placement_finder_ng::find_point_placement(text_layout_ptr layout, double pos_x, double pos_y)
{
glyph_positions_ptr glyphs = boost::make_shared<glyph_positions>(layout);
glyphs->point_placement(pixel_position(pos_x, pos_y));
glyph_positions_ptr glyphs = boost::make_shared<glyph_positions>();
// glyphs->point_placement(pixel_position(pos_x, pos_y));
//TODO: angle
//TODO: Check for placement
return glyphs;
}
glyph_positions::glyph_positions(text_layout_ptr layout)
: base_point_(), point_(true), layout_(layout), current_(0)
glyph_positions::glyph_positions()
: base_point_(), const_angle_(true)
{
}
void glyph_positions::point_placement(pixel_position base_point)
glyph_positions::const_iterator glyph_positions::begin() const
{
base_point_ = base_point;
point_ = true;
return data_.begin();
}
bool glyph_positions::next()
glyph_positions::const_iterator glyph_positions::end() const
{
return false;
#if 0
if (current_ == -1)
return data_.end();
}
void glyph_positions::push_back(const glyph_info &glyph, pixel_position offset, double angle)
{
if (data_.empty())
{
current_ = 0;
return (bool)layout_->size();
angle_ = angle;
} else
{
if (angle != angle_) const_angle_ = false;
}
if (current_ >= layout_->size()) return false;
glyph_info glyph = layout_->get_glyphs()[current_];
current_position_.x += glyph.width + glyph.format->character_spacing;
current_++;
if (current_ >= layout_->size()) return false;
return true;
#endif
data_.push_back(glyph_position(glyph, offset, angle));
}
void glyph_positions::rewind()
{
current_ = -1;
current_position_ = pixel_position(0, 0);
}
glyph_info const& glyph_positions::get_glyph() const
bool glyph_positions::is_constant_angle() const
{
// assert(layout_);
// assert(current_ < layout_->size());
// return layout_->get_glyphs()[current_];
}
pixel_position glyph_positions::get_position() const
{
return current_position_;
return const_angle_;
}
double glyph_positions::get_angle() const
{
return 0;
}
bool glyph_positions::is_constant_angle() const
{
return point_;
return angle_;
}
const pixel_position &glyph_positions::get_base_point() const

View file

@ -26,7 +26,6 @@ void text_renderer<T>::prepare_glyphs(glyph_positions_ptr pos)
FT_Vector pen;
FT_Error error;
pos->rewind();
bool constant_angle = pos->is_constant_angle();
if (constant_angle)
{
@ -38,18 +37,18 @@ void text_renderer<T>::prepare_glyphs(glyph_positions_ptr pos)
matrix.yx = (FT_Fixed)( sina * 0x10000L);
matrix.yy = (FT_Fixed)( cosa * 0x10000L);
}
while (pos->next())
glyph_positions::const_iterator itr = pos->begin(), end = pos->end();
for (; itr != end; itr++)
{
glyph_info const& glyph = pos->get_glyph();
glyph_info const& glyph = *(itr->glyph);
glyph.face->set_character_sizes(glyph.format->text_size * scale_factor_); //TODO: Optimize this?
pixel_position p = pos->get_position();
pen.x = int((p.x +glyph.offset_x) * 64);
pen.y = int((p.y + glyph.offset_y) * 64);
pen.x = int((itr->pos.x + glyph.offset_x) * 64);
pen.y = int((itr->pos.y + glyph.offset_y) * 64);
if (!constant_angle)
{
double angle = pos->get_angle();
double angle = itr->angle;
double cosa = cos(angle);
double sina = sin(angle);
matrix.xx = (FT_Fixed)( cosa * 0x10000L);