Add line breaking.
Note: Text rendering is currently disabled.
This commit is contained in:
parent
d2918590b5
commit
b8a54e6a4f
5 changed files with 71 additions and 61 deletions
|
@ -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_;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Add table
Reference in a new issue