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
|
// mapnik
|
||||||
#include <mapnik/pixel_position.hpp>
|
#include <mapnik/pixel_position.hpp>
|
||||||
#include <mapnik/debug.hpp>
|
#include <mapnik/debug.hpp>
|
||||||
|
#include <mapnik/offset_converter.hpp>
|
||||||
|
|
||||||
// agg
|
// agg
|
||||||
#include "agg_basics.h"
|
#include "agg_basics.h"
|
||||||
|
@ -32,10 +33,18 @@
|
||||||
// stl
|
// stl
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
|
//boost
|
||||||
|
#include <boost/shared_ptr.hpp>
|
||||||
|
#include <boost/make_shared.hpp>
|
||||||
|
|
||||||
namespace mapnik
|
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. */
|
/** Caches all path points and their lengths. Allows easy moving in both directions. */
|
||||||
class vertex_cache
|
class vertex_cache
|
||||||
{
|
{
|
||||||
|
@ -62,6 +71,7 @@ public:
|
||||||
double position_in_segment;
|
double position_in_segment;
|
||||||
pixel_position current_position;
|
pixel_position current_position;
|
||||||
pixel_position segment_starting_point;
|
pixel_position segment_starting_point;
|
||||||
|
double position_;
|
||||||
friend class vertex_cache;
|
friend class vertex_cache;
|
||||||
public:
|
public:
|
||||||
pixel_position const& position() const { return current_position; }
|
pixel_position const& position() const { return current_position; }
|
||||||
|
@ -91,7 +101,7 @@ public:
|
||||||
bool next_subpath();
|
bool next_subpath();
|
||||||
|
|
||||||
/** Moves all positions to a parallel line in the specified distance. */
|
/** 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.
|
/** Skip a certain amount of space.
|
||||||
|
@ -125,8 +135,11 @@ private:
|
||||||
double position_in_segment_;
|
double position_in_segment_;
|
||||||
mutable double angle_;
|
mutable double angle_;
|
||||||
mutable bool angle_valid_;
|
mutable bool angle_valid_;
|
||||||
|
vertex_cache_ptr offseted_line_;
|
||||||
|
double position_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
vertex_cache::vertex_cache(T &path)
|
vertex_cache::vertex_cache(T &path)
|
||||||
: current_position_(),
|
: current_position_(),
|
||||||
|
@ -139,7 +152,9 @@ vertex_cache::vertex_cache(T &path)
|
||||||
first_subpath_(true),
|
first_subpath_(true),
|
||||||
position_in_segment_(0.),
|
position_in_segment_(0.),
|
||||||
angle_(0.),
|
angle_(0.),
|
||||||
angle_valid_(false)
|
angle_valid_(false),
|
||||||
|
offseted_line_(),
|
||||||
|
position_(0.)
|
||||||
{
|
{
|
||||||
path.rewind(0);
|
path.rewind(0);
|
||||||
unsigned cmd;
|
unsigned cmd;
|
||||||
|
@ -248,9 +263,22 @@ bool vertex_cache::previous_segment()
|
||||||
return true;
|
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)
|
bool vertex_cache::forward(double length)
|
||||||
|
@ -275,6 +303,7 @@ bool vertex_cache::backward(double length)
|
||||||
|
|
||||||
bool vertex_cache::move(double length)
|
bool vertex_cache::move(double length)
|
||||||
{
|
{
|
||||||
|
position_ += length;
|
||||||
length += position_in_segment_;
|
length += position_in_segment_;
|
||||||
while (length >= current_segment_->length)
|
while (length >= current_segment_->length)
|
||||||
{
|
{
|
||||||
|
@ -300,6 +329,7 @@ void vertex_cache::rewind_subpath()
|
||||||
position_in_segment_ = 0;
|
position_in_segment_ = 0;
|
||||||
segment_starting_point_ = current_position_;
|
segment_starting_point_ = current_position_;
|
||||||
angle_valid_ = false;
|
angle_valid_ = false;
|
||||||
|
position_ = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void vertex_cache::rewind(unsigned)
|
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.position_in_segment = position_in_segment_;
|
||||||
s.current_position = current_position_;
|
s.current_position = current_position_;
|
||||||
s.segment_starting_point = segment_starting_point_;
|
s.segment_starting_point = segment_starting_point_;
|
||||||
|
s.position_ = position_;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,6 +371,7 @@ void vertex_cache::restore_state(state const& s)
|
||||||
position_in_segment_ = s.position_in_segment;
|
position_in_segment_ = s.position_in_segment;
|
||||||
current_position_ = s.current_position;
|
current_position_ = s.current_position;
|
||||||
segment_starting_point_ = s.segment_starting_point;
|
segment_starting_point_ = s.segment_starting_point;
|
||||||
|
position_ = s.position_;
|
||||||
angle_valid_ = false;
|
angle_valid_ = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ void font_face::glyph_dimensions(glyph_info &glyph) const
|
||||||
matrix.yx = (FT_Fixed)( 0 * 0x10000L );
|
matrix.yx = (FT_Fixed)( 0 * 0x10000L );
|
||||||
matrix.yy = (FT_Fixed)( 1 * 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_Load_Glyph (face_, glyph.glyph_index, FT_LOAD_NO_HINTING)) return;
|
||||||
if (FT_Get_Glyph(face_->glyph, &image)) return;
|
if (FT_Get_Glyph(face_->glyph, &image)) return;
|
||||||
|
|
|
@ -218,12 +218,12 @@ void text_layout::clear()
|
||||||
|
|
||||||
double text_layout::height() const
|
double text_layout::height() const
|
||||||
{
|
{
|
||||||
return height_; //TODO
|
return height_;
|
||||||
}
|
}
|
||||||
|
|
||||||
double text_layout::width() const
|
double text_layout::width() const
|
||||||
{
|
{
|
||||||
return width_; //TODO
|
return width_;
|
||||||
}
|
}
|
||||||
|
|
||||||
text_layout::const_iterator text_layout::begin() const
|
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;
|
double base_offset = alignment_offset().y + info_->properties.displacement.y;
|
||||||
glyph_positions_ptr glyphs = boost::make_shared<glyph_positions>();
|
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;
|
unsigned upside_down_glyph_count = 0;
|
||||||
|
|
||||||
std::vector<box2d<double> > bboxes;
|
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++)
|
for (; line_itr != line_end; line_itr++)
|
||||||
{
|
{
|
||||||
double char_height = (*line_itr)->max_char_height();
|
double char_height = (*line_itr)->max_char_height();
|
||||||
offset -= (*line_itr)->height();
|
//Only subtract half the line height here and half at the end because text is automatically
|
||||||
pp.set_offset(offset);
|
//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;
|
double last_cluster_angle = 999;
|
||||||
signed current_cluster = -1;
|
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;
|
glyph_info const& glyph = *glyph_itr;
|
||||||
if (current_cluster != glyph.char_index)
|
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;
|
current_cluster = glyph.char_index;
|
||||||
//Only calculate new angle at the start of each cluster!
|
//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);
|
rot.init(angle);
|
||||||
if ((info_->properties.max_char_angle_delta > 0) && (last_cluster_angle != 999) &&
|
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)
|
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++;
|
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
|
//Center the text on the line
|
||||||
pos.y = -pos.y - char_height/2.0*rot.cos;
|
pos.y = -pos.y - char_height/2.0*rot.cos;
|
||||||
pos.x = pos.x + char_height/2.0*rot.sin;
|
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);
|
bboxes.push_back(bbox);
|
||||||
glyphs->push_back(glyph, pos, rot);
|
glyphs->push_back(glyph, pos, rot);
|
||||||
}
|
}
|
||||||
|
//See comment above
|
||||||
|
offset -= (*line_itr)->height()/2;
|
||||||
}
|
}
|
||||||
s.restore();
|
s.restore();
|
||||||
if (orientation == UPRIGHT_AUTO && (upside_down_glyph_count > layout_.get_text().length()/2))
|
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)
|
(0/ymin) (width/ymin)
|
||||||
Add glyph offset in y direction, but not in x direction (as we use the full cluster width anyways)!
|
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);
|
double width = layout_.cluster_width(glyph.char_index);
|
||||||
if (glyph.width <= 0) width = -width;
|
if (glyph.width <= 0) width = -width;
|
||||||
pixel_position tmp, tmp2;
|
pixel_position tmp, tmp2;
|
||||||
|
|
Loading…
Add table
Reference in a new issue