Add line breaking.

Note: Text rendering is currently disabled.
This commit is contained in:
Hermann Kraus 2012-07-21 04:17:58 +02:00
parent d2918590b5
commit b8a54e6a4f
5 changed files with 71 additions and 61 deletions

View file

@ -38,27 +38,27 @@
namespace mapnik
{
#if 0
/** This class stores all format_runs in a line in left to right order.
/** This class stores all glyphs of a line in left to right order.
*
* It can be used for rendering but no text processing (like line breaking)
* should be done!
* Glyphs are stored in runs with the same format.
*/
class text_line
{
public:
text_line();
std::vector<format_run_ptr> const& runs() const { return runs_; }
void add_run(format_run_ptr run);
typedef std::vector<glyph_info> glyph_vector;
glyph_vector const& get_glyphs() const { return glyphs_; }
void add_glyph(glyph_info const& glyph);
void reserve(glyph_vector::size_type length);
private:
std::vector<format_run_ptr> runs_;
double max_line_height; //Includes line spacing
double max_text_height; //Height of the largest format run in this run.
glyph_vector glyphs_;
double line_height_; //Includes line spacing
double text_height_; //Height of the largest format run in this run.
double width_;
};
typedef boost::shared_ptr<text_line> text_line_ptr;
#endif
class text_layout
{
@ -69,27 +69,26 @@ public:
itemizer.add_text(str, format);
}
void break_lines(double break_width);
void shape_text();
void clear();
unsigned size() const { return glyphs_.size(); }
void layout(double break_width);
typedef std::vector<glyph_info> glyph_vector;
glyph_vector const& get_glyphs() const { return glyphs_; }
/** Get the text width. Returns 0 if shape_text() wasn't called before.
* If break_lines was already called the width of the longest line is returned.
**/
double get_width() const { return width_; }
void clear();
private:
void break_line(text_line_ptr line, double break_width);
void shape_text(text_line_ptr line, unsigned start, unsigned end);
//input
face_manager_freetype &font_manager_;
//processing
text_itemizer itemizer;
// std::vector<text_line_ptr> lines_;
/// Maps char index (UTF-16) to width. If multiple glyphs map to the same char the sum of all widths is used
std::map<unsigned, double> width_map;
glyph_vector glyphs_;
face_manager_freetype &font_manager_;
double total_width_;
double width_;
//output
std::vector<text_line_ptr> lines_;
};
}

View file

@ -37,10 +37,10 @@ extern "C"
namespace mapnik
{
/** This class is a thin wrapper around HarfBuzz. */
class text_shaping
{
public:
//TODO: Get font file from font name
text_shaping(FT_Face face);
~text_shaping();

View file

@ -262,8 +262,7 @@ bool text_symbolizer_helper<FaceManagerT, DetectorT>::next_placement()
return false;
}
placement_->properties.process(*layout_, feature_);
layout_->shape_text();
layout_->break_lines(placement_->properties.wrap_width);
layout_->layout(placement_->properties.wrap_width);
//TODO
// info_ = &(text_.get_string_info());

View file

@ -32,8 +32,10 @@
// ICU
#include <unicode/brkiter.h>
// boost
#include <boost/make_shared.hpp>
/* TODO: Remove unused classes:
* processed_text
* string_info
* text_path
* char_info
@ -46,9 +48,21 @@ text_layout::text_layout(face_manager_freetype &font_manager)
{
}
void text_layout::break_lines(double break_width)
void text_layout::layout(double break_width)
{
if (total_width_ < break_width || !break_width) return;
text_line_ptr line = boost::make_shared<text_line>();
shape_text(line, 0, itemizer.get_text().length()); //Process full text
break_line(line, break_width); //Break line if neccessary
}
void text_layout::break_line(text_line_ptr line, double break_width)
{
if (total_width_ < break_width || !break_width)
{
lines_.push_back(line);
return;
}
UnicodeString const& text = itemizer.get_text();
Locale locale; //TODO: Is the default constructor correct?
UErrorCode status = U_ZERO_ERROR;
@ -76,28 +90,30 @@ void text_layout::break_lines(double break_width)
break_position = breakitr->following(i);
std::cout << "Line overflow!\n";
}
//TODO: Add line
std::cout << "Line to long ("<< current_line_length << ") at "<< i << " going to " << break_position << ". Last break was at " << last_break_position << "\n";
text_line_ptr new_line = boost::make_shared<text_line>();
shape_text(line, last_break_position, break_position);
last_break_position = break_position;
i = break_position - 1;
current_line_length = 0;
}
}
}
void text_layout::shape_text()
void text_layout::shape_text(text_line_ptr line, unsigned start, unsigned end)
{
UnicodeString const& text = itemizer.get_text();
glyphs_.reserve(text.length()); //Preallocate memory
size_t length = end - start;
line->reserve(length); //Preallocate memory
total_width_ = 0.0;
std::list<text_item> const& list = itemizer.itemize();
std::list<text_item>::const_iterator itr = list.begin(), end = list.end();
for (;itr!=end; itr++)
std::list<text_item> const& list = itemizer.itemize(start, end);
std::list<text_item>::const_iterator itr = list.begin(), list_end = list.end();
for (; itr != list_end; itr++)
{
face_set_ptr face_set = font_manager_.get_face_set(itr->format->face_name, itr->format->fontset);
face_set->set_character_sizes(itr->format->text_size);
@ -130,7 +146,7 @@ void text_layout::shape_text()
width_map[glyphs[i].cluster] += tmp.width;
total_width_ += tmp.width;
glyphs_.push_back(tmp);
line->add_glyph(tmp);
// std::cout << "glyph:" << glyphs[i].mask << " xa:" << positions[i].x_advance << " ya:" << positions[i].y_advance << " xo:" << positions[i].x_offset << " yo:" << positions[i].y_offset << "\n";
}
}
@ -150,33 +166,26 @@ void text_layout::shape_text()
void text_layout::clear()
{
itemizer.clear();
glyphs_.clear();
}
#if 0
format_run::format_run(char_properties_ptr properties, double text_height)
: properties_(properties), glyphs_(), width_(0), text_height_(text_height), line_height_(0)
{
}
void format_run::add_glyph(const glyph_info &info)
{
glyphs_.push_back(info);
width_ += info.width;
line_height_ = info.line_height; //Same value for all characters with the same format
lines_.clear();
}
text_line::text_line()
: max_line_height(0), max_text_height(0)
: glyphs_(), line_height_(0.), text_height_(0.), width_(0.)
{
}
void text_line::add_run(format_run_ptr run)
void text_line::add_glyph(const glyph_info &glyph)
{
max_line_height = std::max(max_line_height, run->line_height());
max_text_height = std::max(max_text_height, run->text_height());
runs_.push_back(run);
glyphs_.push_back(glyph);
line_height_ = std::max(line_height_, glyph.line_height);
text_height_ = std::max(text_height_, glyph.height());
width_ += glyph.width + glyph.format->character_spacing;
}
void text_line::reserve(glyph_vector::size_type length)
{
glyphs_.reserve(length);
}
#endif
} //ns mapnik

View file

@ -58,10 +58,12 @@ void glyph_positions::point_placement(pixel_position base_point)
bool glyph_positions::next()
{
return false;
#if 0
if (current_ == -1)
{
current_ = 0;
return layout_->size();
return (bool)layout_->size();
}
if (current_ >= layout_->size()) return false;
glyph_info glyph = layout_->get_glyphs()[current_];
@ -69,6 +71,7 @@ bool glyph_positions::next()
current_++;
if (current_ >= layout_->size()) return false;
return true;
#endif
}
void glyph_positions::rewind()
@ -79,9 +82,9 @@ void glyph_positions::rewind()
glyph_info const& glyph_positions::get_glyph() const
{
assert(layout_);
assert(current_ < layout_->size());
return layout_->get_glyphs()[current_];
// assert(layout_);
// assert(current_ < layout_->size());
// return layout_->get_glyphs()[current_];
}
pixel_position glyph_positions::get_position() const