add text attribute horizontal-alignment="adjust"
This commit is contained in:
parent
d59529d22f
commit
31607cb3f4
8 changed files with 92 additions and 4 deletions
|
@ -158,6 +158,7 @@ enum horizontal_alignment_enum
|
|||
H_MIDDLE,
|
||||
H_RIGHT,
|
||||
H_AUTO,
|
||||
H_ADJUST,
|
||||
horizontal_alignment_enum_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -67,6 +67,8 @@ bool placement_finder::find_line_placements(T & path, bool points)
|
|||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
layouts_.adjust(pp.length(), scale_factor_);
|
||||
}
|
||||
|
||||
double spacing = get_spacing(pp.length(), points ? 0. : layouts_.width());
|
||||
|
@ -74,7 +76,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;
|
||||
}
|
||||
|
|
|
@ -110,6 +110,10 @@ public:
|
|||
|
||||
void evaluate_properties(feature_impl const& feature, attributes const& attr);
|
||||
|
||||
text_line const& longest_line() const;
|
||||
|
||||
void set_character_spacing(double spacing, double scale_factor);
|
||||
|
||||
private:
|
||||
void break_line(text_line & line, double wrap_width, unsigned text_ratio, bool wrap_before);
|
||||
void break_line(text_line & line, char wrap_char,
|
||||
|
@ -186,6 +190,8 @@ public:
|
|||
inline double width() const { return bounds_.width(); }
|
||||
inline double height() const { return bounds_.height(); }
|
||||
|
||||
void adjust(double width, double scale_factor);
|
||||
|
||||
private:
|
||||
text_layout_vector layouts_;
|
||||
|
||||
|
|
|
@ -52,6 +52,8 @@ public:
|
|||
// Iterator beyond last glyph.
|
||||
const_iterator end() const;
|
||||
|
||||
// Width of all glyphs without character spacing.
|
||||
double glyphs_width() const { return glyphs_width_; }
|
||||
// Width of all glyphs including character spacing.
|
||||
double width() const { return width_; }
|
||||
// Real line height. For first line: max_char_height(), for all others: line_height().
|
||||
|
@ -75,14 +77,21 @@ public:
|
|||
|
||||
// Number of glyphs.
|
||||
unsigned size() const;
|
||||
|
||||
unsigned space_count() const { return space_count_; }
|
||||
|
||||
void set_character_spacing(double character_spacing, double scale_factor);
|
||||
|
||||
private:
|
||||
glyph_vector glyphs_;
|
||||
double line_height_; // Includes line spacing (returned by freetype)
|
||||
double max_char_height_; // Height of 'X' character of the largest font in this run. //TODO: Initialize this!
|
||||
double width_;
|
||||
double glyphs_width_;
|
||||
unsigned first_char_;
|
||||
unsigned last_char_;
|
||||
bool first_line_;
|
||||
unsigned space_count_;
|
||||
};
|
||||
|
||||
} //namespace mapnik
|
||||
|
|
|
@ -137,6 +137,7 @@ static const char * horizontal_alignment_strings[] = {
|
|||
"middle",
|
||||
"right",
|
||||
"auto",
|
||||
"adjust",
|
||||
""
|
||||
};
|
||||
|
||||
|
|
|
@ -36,6 +36,7 @@
|
|||
|
||||
// stl
|
||||
#include <vector>
|
||||
#include <functional>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
|
@ -192,6 +193,7 @@ 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();
|
||||
bool move_by_length = layout.horizontal_alignment() == H_ADJUST;
|
||||
|
||||
for (auto const& line : layout)
|
||||
{
|
||||
|
@ -209,12 +211,14 @@ bool placement_finder::single_line_placement(vertex_cache &pp, text_upright_e or
|
|||
double angle;
|
||||
rotation rot;
|
||||
double last_glyph_spacing = 0.;
|
||||
std::function<bool(double)> glyph_move_method = std::bind(
|
||||
move_by_length ? &vertex_cache::move : &vertex_cache::move_to_distance, &off_pp, std::placeholders::_1);
|
||||
|
||||
for (auto const& glyph : line)
|
||||
{
|
||||
if (current_cluster != static_cast<int>(glyph.char_index))
|
||||
{
|
||||
if (!off_pp.move_to_distance(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing)))
|
||||
if (!glyph_move_method(sign * (layout.cluster_width(current_cluster) + last_glyph_spacing)))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -415,6 +415,31 @@ double text_layout::jalign_offset(double line_width) const
|
|||
return 0;
|
||||
}
|
||||
|
||||
text_line const& text_layout::longest_line() const
|
||||
{
|
||||
if (lines_.empty())
|
||||
{
|
||||
throw std::runtime_error("longest_line: Text layout has no lines.");
|
||||
}
|
||||
text_layout::const_iterator longest = lines_.begin();
|
||||
for (text_layout::const_iterator line = longest + 1; line != lines_.end(); ++line)
|
||||
{
|
||||
if (line->glyphs_width() > longest->glyphs_width())
|
||||
{
|
||||
longest = line;
|
||||
}
|
||||
}
|
||||
return *longest;
|
||||
}
|
||||
|
||||
void text_layout::set_character_spacing(double spacing, double scale_factor)
|
||||
{
|
||||
for (auto & line : lines_)
|
||||
{
|
||||
line.set_character_spacing(spacing, scale_factor);
|
||||
}
|
||||
}
|
||||
|
||||
void layout_container::add(text_layout_ptr layout)
|
||||
{
|
||||
text_ += layout->text();
|
||||
|
@ -461,5 +486,20 @@ void layout_container::clear()
|
|||
line_count_ = 0;
|
||||
}
|
||||
|
||||
|
||||
void layout_container::adjust(double width, double scale_factor)
|
||||
{
|
||||
for (auto & layout_ptr : layouts_)
|
||||
{
|
||||
text_layout & layout = *layout_ptr;
|
||||
if (layout.horizontal_alignment() == H_ADJUST)
|
||||
{
|
||||
text_line const& longest_line = layout.longest_line();
|
||||
double character_spacing = ((width - longest_line.glyphs_width()) / longest_line.space_count()) / scale_factor;
|
||||
if (character_spacing >= .0)
|
||||
{
|
||||
layout.set_character_spacing(character_spacing, scale_factor);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} //ns mapnik
|
||||
|
|
|
@ -31,9 +31,11 @@ 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)
|
||||
{}
|
||||
|
||||
void text_line::add_glyph(glyph_info const& glyph, double scale_factor_)
|
||||
|
@ -43,11 +45,15 @@ void text_line::add_glyph(glyph_info const& 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_.push_back(glyph);
|
||||
}
|
||||
|
@ -99,4 +105,23 @@ unsigned text_line::size() const
|
|||
return glyphs_.size();
|
||||
}
|
||||
|
||||
void text_line::set_character_spacing(double character_spacing, double scale_factor)
|
||||
{
|
||||
bool first = true;
|
||||
for (auto const& glyph : glyphs_)
|
||||
{
|
||||
glyph.format->character_spacing = character_spacing;
|
||||
double advance = glyph.advance();
|
||||
if (first)
|
||||
{
|
||||
width_ = advance;
|
||||
first = false;
|
||||
}
|
||||
else if (advance)
|
||||
{
|
||||
width_ += advance + character_spacing * scale_factor;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // end namespace mapnik
|
||||
|
|
Loading…
Add table
Reference in a new issue