Merge pull request #2523 from mapycz/halign-adjust-immutable

halign adjust with immutability of style objects in mind
This commit is contained in:
Dane Springmeyer 2014-10-13 18:47:37 -07:00
commit 09f91a24a0
10 changed files with 63 additions and 14 deletions

View file

@ -158,6 +158,7 @@ enum horizontal_alignment_enum
H_MIDDLE,
H_RIGHT,
H_AUTO,
H_ADJUST,
horizontal_alignment_enum_MAX
};

View file

@ -74,7 +74,7 @@ bool placement_finder::find_line_placements(T & path, bool points)
//horizontal_alignment_e halign = layouts_.back()->horizontal_alignment();
// halign == H_LEFT -> don't move
if (horizontal_alignment_ == H_MIDDLE || horizontal_alignment_ == H_AUTO)
if (horizontal_alignment_ == H_MIDDLE || horizontal_alignment_ == H_AUTO || horizontal_alignment_ == H_ADJUST)
{
if (!pp.forward(spacing / 2.0)) continue;
}

View file

@ -123,6 +123,8 @@ public:
double jalign_offset(double line_width) const;
evaluated_format_properties_ptr & new_child_format_ptr(evaluated_format_properties_ptr const& p);
const_iterator longest_line() const;
private:
void break_line(std::pair<unsigned, unsigned> && line_limits);
void break_line_icu(std::pair<unsigned, unsigned> && line_limits);

View file

@ -57,6 +57,8 @@ public:
// Width of all glyphs including character spacing.
double width() const { return width_; }
// Width of all glyphs without character spacing.
double glyphs_width() const { return glyphs_width_; }
// Real line height. For first line: max_char_height(), for all others: line_height().
double height() const;
@ -81,14 +83,18 @@ public:
// Number of glyphs.
unsigned size() const;
unsigned space_count() const { return space_count_; }
private:
glyph_vector glyphs_;
double line_height_; // Includes line spacing (returned by freetype)
double max_char_height_; // Max height of any glyphs in line - calculated by shaper
double width_;
double glyphs_width_;
unsigned first_char_;
unsigned last_char_;
bool first_line_;
unsigned space_count_;
};
} //namespace mapnik

View file

@ -137,6 +137,7 @@ static const char * horizontal_alignment_strings[] = {
"middle",
"right",
"auto",
"adjust",
""
};

View file

@ -206,16 +206,30 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or
pixel_position const& layout_displacement = layout.displacement();
double sign = (real_orientation == UPRIGHT_LEFT) ? -1 : 1;
double offset = layout_displacement.y + 0.5 * sign * layout.height();
double adjust_character_spacing = .0;
double layout_width = layout.width();
bool adjust = layout.horizontal_alignment() == H_ADJUST;
if (adjust)
{
text_layout::const_iterator longest_line = layout.longest_line();
if (longest_line != layout.end())
{
adjust_character_spacing = (pp.length() - longest_line->glyphs_width()) / longest_line->space_count();
layout_width = longest_line->glyphs_width() + longest_line->space_count() * adjust_character_spacing;
}
}
for (auto const& line : layout)
{
// Only subtract half the line height here and half at the end because text is automatically
// centered on the line
offset -= sign * line.height()/2;
vertex_cache & off_pp = pp.get_offseted(offset, sign*layout.width());
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 is done
double line_width = adjust ? (line.glyphs_width() + line.space_count() * adjust_character_spacing) : line.width();
if (!off_pp.move(sign * layout.jalign_offset(line.width()) - align_offset.x)) return false;
if (!off_pp.move(sign * layout.jalign_offset(line_width) - align_offset.x)) return false;
double last_cluster_angle = 999;
int current_cluster = -1;
@ -228,11 +242,19 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or
{
if (current_cluster != static_cast<int>(glyph.char_index))
{
if (!off_pp.move_to_distance(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing)))
return false;
if (adjust)
{
if (!off_pp.move(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing)))
return false;
last_glyph_spacing = adjust_character_spacing;
}
else
{
if (!off_pp.move_to_distance(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing)))
return false;
last_glyph_spacing = glyph.format->character_spacing * scale_factor_;
}
current_cluster = glyph.char_index;
last_glyph_spacing = glyph.format->character_spacing * scale_factor_;
// Only calculate new angle at the start of each cluster!
angle = normalize_angle(off_pp.angle(sign * layout.cluster_width(current_cluster)));
rot.init(angle);
@ -312,7 +334,7 @@ double placement_finder::normalize_angle(double angle)
double placement_finder::get_spacing(double path_length, double layout_width) const
{
int num_labels = 1;
if (text_props_->label_spacing > 0)
if (horizontal_alignment_ != H_ADJUST && text_props_->label_spacing > 0)
{
num_labels = static_cast<int>(std::floor(
path_length / (text_props_->label_spacing * scale_factor_ + layout_width)));

View file

@ -31,6 +31,7 @@
// ICU
#include <unicode/brkiter.h>
#include <algorithm>
namespace mapnik
{
@ -489,6 +490,15 @@ double text_layout::jalign_offset(double line_width) const
return 0;
}
text_layout::const_iterator text_layout::longest_line() const
{
return std::max_element(lines_.begin(), lines_.end(),
[](text_line const& line1, text_line const& line2)
{
return line1.glyphs_width() < line2.glyphs_width();
});
}
void layout_container::add(text_layout_ptr layout)
{
text_ += layout->text();

View file

@ -31,19 +31,23 @@ text_line::text_line(unsigned first_char, unsigned last_char)
line_height_(0.0),
max_char_height_(0.0),
width_(0.0),
glyphs_width_(0.0),
first_char_(first_char),
last_char_(last_char),
first_line_(false)
first_line_(false),
space_count_(0)
{}
text_line::text_line( text_line && rhs)
text_line::text_line(text_line && rhs)
: glyphs_(std::move(rhs.glyphs_)),
line_height_(std::move(rhs.line_height_)),
max_char_height_(std::move(rhs.max_char_height_)),
width_(std::move(rhs.width_)),
glyphs_width_(std::move(rhs.glyphs_width_)),
first_char_(std::move(rhs.first_char_)),
last_char_(std::move(rhs.last_char_)),
first_line_(std::move(rhs.first_line_)) {}
first_line_(std::move(rhs.first_line_)),
space_count_(std::move(rhs.space_count_)) {}
void text_line::add_glyph(glyph_info && glyph, double scale_factor_)
{
@ -52,11 +56,15 @@ void text_line::add_glyph(glyph_info && glyph, double scale_factor_)
if (glyphs_.empty())
{
width_ = advance;
glyphs_width_ = advance;
space_count_ = 0;
}
else if (advance)
{
// Only add character spacing if the character is not a zero-width part of a cluster.
width_ += advance + glyphs_.back().format->character_spacing * scale_factor_;
glyphs_width_ += advance;
space_count_++;
}
glyphs_.emplace_back(std::move(glyph));
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 30 KiB

View file

@ -185,9 +185,8 @@ files = {
'text-bug2037': {'sizes': [(800, 300)], 'bbox': default_text_box},
'text-expressionformat-color': {'sizes': [(800, 100)], 'bbox': default_text_box},
'text-halign': {'sizes': [(800,800)], 'bbox': default_text_box},
# disabled: https://github.com/mapnik/mapnik/pull/2426#issuecomment-58771864
#'text-halign-adjust': {'sizes': [(800,800)], 'bbox': default_text_box},
#'text-halign-adjust-multiline': {'sizes': [(800,800)], 'bbox': default_text_box},
'text-halign-adjust': {'sizes': [(800,800)], 'bbox': default_text_box},
'text-halign-adjust-multiline': {'sizes': [(800,800)], 'bbox': default_text_box},
'text-vertical-alignment': {'sizes': [(800,800)], 'bbox': default_text_box},
'text-malayalam': {'sizes': [(800, 100)], 'bbox': default_text_box},
'text-bengali': {'sizes': [(800, 100)], 'bbox': default_text_box},