Implement offsets and multiline rendering.
This commit is contained in:
parent
14891379d0
commit
37a5552bbd
4 changed files with 50 additions and 14 deletions
|
@ -25,6 +25,7 @@
|
|||
// mapnik
|
||||
#include <mapnik/pixel_position.hpp>
|
||||
#include <mapnik/debug.hpp>
|
||||
#include <mapnik/offset_converter.hpp>
|
||||
|
||||
// agg
|
||||
#include "agg_basics.h"
|
||||
|
@ -32,10 +33,18 @@
|
|||
// stl
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <cmath>
|
||||
|
||||
//boost
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/make_shared.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
||||
class vertex_cache;
|
||||
typedef boost::shared_ptr<vertex_cache> vertex_cache_ptr;
|
||||
|
||||
/** Caches all path points and their lengths. Allows easy moving in both directions. */
|
||||
class vertex_cache
|
||||
{
|
||||
|
@ -62,6 +71,7 @@ public:
|
|||
double position_in_segment;
|
||||
pixel_position current_position;
|
||||
pixel_position segment_starting_point;
|
||||
double position_;
|
||||
friend class vertex_cache;
|
||||
public:
|
||||
pixel_position const& position() const { return current_position; }
|
||||
|
@ -91,7 +101,7 @@ public:
|
|||
bool next_subpath();
|
||||
|
||||
/** Moves all positions to a parallel line in the specified distance. */
|
||||
void set_offset(double offset);
|
||||
vertex_cache &get_offseted(double offset, double region_width);
|
||||
|
||||
|
||||
/** Skip a certain amount of space.
|
||||
|
@ -125,8 +135,11 @@ private:
|
|||
double position_in_segment_;
|
||||
mutable double angle_;
|
||||
mutable bool angle_valid_;
|
||||
vertex_cache_ptr offseted_line_;
|
||||
double position_;
|
||||
};
|
||||
|
||||
|
||||
template <typename T>
|
||||
vertex_cache::vertex_cache(T &path)
|
||||
: current_position_(),
|
||||
|
@ -139,7 +152,9 @@ vertex_cache::vertex_cache(T &path)
|
|||
first_subpath_(true),
|
||||
position_in_segment_(0.),
|
||||
angle_(0.),
|
||||
angle_valid_(false)
|
||||
angle_valid_(false),
|
||||
offseted_line_(),
|
||||
position_(0.)
|
||||
{
|
||||
path.rewind(0);
|
||||
unsigned cmd;
|
||||
|
@ -248,9 +263,22 @@ bool vertex_cache::previous_segment()
|
|||
return true;
|
||||
}
|
||||
|
||||
void vertex_cache::set_offset(double offset)
|
||||
vertex_cache & vertex_cache::get_offseted(double offset, double region_width)
|
||||
{
|
||||
MAPNIK_LOG_DEBUG(vertex_cache) << "set_offset: unimplemented\n";
|
||||
if (fabs(offset) < 0.01)
|
||||
{
|
||||
return *this;
|
||||
}
|
||||
//TODO: Cache offseted lines
|
||||
offset_converter<vertex_cache> converter(*this);
|
||||
converter.set_offset(offset);
|
||||
offseted_line_ = vertex_cache_ptr(new vertex_cache(converter));
|
||||
offseted_line_->rewind_subpath(); //TODO: Multiple subpath support
|
||||
double seek = (position_ + region_width/2.) * offseted_line_->length() / length() - region_width/2.;
|
||||
if (seek < 0) seek = 0;
|
||||
if (seek > offseted_line_->length()) seek = offseted_line_->length();
|
||||
offseted_line_->move(seek);
|
||||
return *offseted_line_;
|
||||
}
|
||||
|
||||
bool vertex_cache::forward(double length)
|
||||
|
@ -275,6 +303,7 @@ bool vertex_cache::backward(double length)
|
|||
|
||||
bool vertex_cache::move(double length)
|
||||
{
|
||||
position_ += length;
|
||||
length += position_in_segment_;
|
||||
while (length >= current_segment_->length)
|
||||
{
|
||||
|
@ -300,6 +329,7 @@ void vertex_cache::rewind_subpath()
|
|||
position_in_segment_ = 0;
|
||||
segment_starting_point_ = current_position_;
|
||||
angle_valid_ = false;
|
||||
position_ = 0;
|
||||
}
|
||||
|
||||
void vertex_cache::rewind(unsigned)
|
||||
|
@ -331,6 +361,7 @@ vertex_cache::state vertex_cache::save_state() const
|
|||
s.position_in_segment = position_in_segment_;
|
||||
s.current_position = current_position_;
|
||||
s.segment_starting_point = segment_starting_point_;
|
||||
s.position_ = position_;
|
||||
return s;
|
||||
}
|
||||
|
||||
|
@ -340,6 +371,7 @@ void vertex_cache::restore_state(state const& s)
|
|||
position_in_segment_ = s.position_in_segment;
|
||||
current_position_ = s.current_position;
|
||||
segment_starting_point_ = s.segment_starting_point;
|
||||
position_ = s.position_;
|
||||
angle_valid_ = false;
|
||||
}
|
||||
|
||||
|
|
|
@ -78,7 +78,7 @@ void font_face::glyph_dimensions(glyph_info &glyph) const
|
|||
matrix.yx = (FT_Fixed)( 0 * 0x10000L );
|
||||
matrix.yy = (FT_Fixed)( 1 * 0x10000L );
|
||||
|
||||
FT_Set_Transform(face_, &matrix, &pen); //TODO: Matrix is always only set to the identity matrix. This seems to be useless.
|
||||
FT_Set_Transform(face_, &matrix, &pen);
|
||||
|
||||
if (FT_Load_Glyph (face_, glyph.glyph_index, FT_LOAD_NO_HINTING)) return;
|
||||
if (FT_Get_Glyph(face_->glyph, &image)) return;
|
||||
|
|
|
@ -218,12 +218,12 @@ void text_layout::clear()
|
|||
|
||||
double text_layout::height() const
|
||||
{
|
||||
return height_; //TODO
|
||||
return height_;
|
||||
}
|
||||
|
||||
double text_layout::width() const
|
||||
{
|
||||
return width_; //TODO
|
||||
return width_;
|
||||
}
|
||||
|
||||
text_layout::const_iterator text_layout::begin() const
|
||||
|
|
|
@ -296,7 +296,7 @@ bool placement_finder_ng::single_line_placement(vertex_cache &pp, text_upright_e
|
|||
double base_offset = alignment_offset().y + info_->properties.displacement.y;
|
||||
glyph_positions_ptr glyphs = boost::make_shared<glyph_positions>();
|
||||
|
||||
double offset = base_offset + layout_.height();
|
||||
double offset = base_offset + layout_.height()/2.;
|
||||
unsigned upside_down_glyph_count = 0;
|
||||
|
||||
std::vector<box2d<double> > bboxes;
|
||||
|
@ -306,8 +306,11 @@ bool placement_finder_ng::single_line_placement(vertex_cache &pp, text_upright_e
|
|||
for (; line_itr != line_end; line_itr++)
|
||||
{
|
||||
double char_height = (*line_itr)->max_char_height();
|
||||
offset -= (*line_itr)->height();
|
||||
pp.set_offset(offset);
|
||||
//Only subtract half the line height here and half at the end because text is automatically
|
||||
//centered on the line
|
||||
offset -= (*line_itr)->height()/2;
|
||||
vertex_cache &off_pp = pp.get_offseted(offset, sign*layout_.width());
|
||||
vertex_cache::scoped_state off_state(off_pp); //TODO: Remove this when a clean implementation in vertex_cache::get_offseted was done
|
||||
|
||||
double last_cluster_angle = 999;
|
||||
signed current_cluster = -1;
|
||||
|
@ -321,10 +324,10 @@ bool placement_finder_ng::single_line_placement(vertex_cache &pp, text_upright_e
|
|||
glyph_info const& glyph = *glyph_itr;
|
||||
if (current_cluster != glyph.char_index)
|
||||
{
|
||||
if (!pp.move(sign * layout_.cluster_width(current_cluster))) return false;
|
||||
if (!off_pp.move(sign * layout_.cluster_width(current_cluster))) return false;
|
||||
current_cluster = glyph.char_index;
|
||||
//Only calculate new angle at the start of each cluster!
|
||||
angle = normalize_angle(pp.angle(sign * layout_.cluster_width(current_cluster)));
|
||||
angle = normalize_angle(off_pp.angle(sign * layout_.cluster_width(current_cluster)));
|
||||
rot.init(angle);
|
||||
if ((info_->properties.max_char_angle_delta > 0) && (last_cluster_angle != 999) &&
|
||||
fabs(normalize_angle(angle-last_cluster_angle)) > info_->properties.max_char_angle_delta)
|
||||
|
@ -336,7 +339,7 @@ bool placement_finder_ng::single_line_placement(vertex_cache &pp, text_upright_e
|
|||
}
|
||||
if (abs(angle) > M_PI/2) upside_down_glyph_count++;
|
||||
|
||||
pixel_position pos = pp.current_position() + cluster_offset;
|
||||
pixel_position pos = off_pp.current_position() + cluster_offset;
|
||||
//Center the text on the line
|
||||
pos.y = -pos.y - char_height/2.0*rot.cos;
|
||||
pos.x = pos.x + char_height/2.0*rot.sin;
|
||||
|
@ -349,6 +352,8 @@ bool placement_finder_ng::single_line_placement(vertex_cache &pp, text_upright_e
|
|||
bboxes.push_back(bbox);
|
||||
glyphs->push_back(glyph, pos, rot);
|
||||
}
|
||||
//See comment above
|
||||
offset -= (*line_itr)->height()/2;
|
||||
}
|
||||
s.restore();
|
||||
if (orientation == UPRIGHT_AUTO && (upside_down_glyph_count > layout_.get_text().length()/2))
|
||||
|
@ -429,7 +434,6 @@ box2d<double> placement_finder_ng::get_bbox(glyph_info const& glyph, pixel_posit
|
|||
(0/ymin) (width/ymin)
|
||||
Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)!
|
||||
*/
|
||||
std::cout << glyph.offset << glyph.width << "," << glyph.ymin << glyph.ymax << "\n";
|
||||
double width = layout_.cluster_width(glyph.char_index);
|
||||
if (glyph.width <= 0) width = -width;
|
||||
pixel_position tmp, tmp2;
|
||||
|
|
Loading…
Reference in a new issue