Fix label bounding box calculation to include glyph descenders [WIP] (ref #4308)

This commit is contained in:
Artem Pavlenko 2022-04-25 15:44:32 +01:00
parent 1ba1278b42
commit d26346f335
7 changed files with 29 additions and 17 deletions

View file

@ -360,7 +360,8 @@ struct harfbuzz_shaper
// Try next font in fontset // Try next font in fontset
continue; continue;
} }
double max_glyph_height = 0; double ymin = 0;
double ymax = 0;
for (auto const& c_id : clusters) for (auto const& c_id : clusters)
{ {
auto const& c = glyphinfos[c_id]; auto const& c = glyphinfos[c_id];
@ -382,19 +383,18 @@ struct harfbuzz_shaper
// Overwrite default advance with better value provided by HarfBuzz // Overwrite default advance with better value provided by HarfBuzz
g.unscaled_advance = gpos.x_advance; g.unscaled_advance = gpos.x_advance;
g.offset.set(gpos.x_offset * g.scale_multiplier, gpos.y_offset * g.scale_multiplier); g.offset.set(gpos.x_offset * g.scale_multiplier, gpos.y_offset * g.scale_multiplier);
double tmp_height = g.height(); ymin = std::min(ymin, g.ymin());
ymax = std::max(ymax, g.ymax());
if (g.face->is_color()) if (g.face->is_color())
{ {
tmp_height = g.ymax(); ymin = 0.0;
} }
if (tmp_height > max_glyph_height)
max_glyph_height = tmp_height;
width_map[char_index] += g.advance(); width_map[char_index] += g.advance();
line.add_glyph(std::move(g), scale_factor); line.add_glyph(std::move(g), scale_factor);
} }
} }
} }
line.update_max_char_height(max_glyph_height); line.update_max_char_height(ymin, ymax);
break; // When we reach this point the current font had all glyphs. break; // When we reach this point the current font had all glyphs.
} }
} }

View file

@ -93,7 +93,8 @@ struct icu_shaper
std::size_t num_chars = static_cast<std::size_t>(num_char); std::size_t num_chars = static_cast<std::size_t>(num_char);
shaped.releaseBuffer(length); shaped.releaseBuffer(length);
bool shaped_status = true; bool shaped_status = true;
double max_glyph_height = 0; double ymin = 0;
double ymax = 0;
if (U_SUCCESS(err) && (num_chars == length)) if (U_SUCCESS(err) && (num_chars == length))
{ {
unsigned char_index = 0; unsigned char_index = 0;
@ -113,9 +114,8 @@ struct icu_shaper
{ {
g.face = face; g.face = face;
g.scale_multiplier = size / face->get_face()->units_per_EM; g.scale_multiplier = size / face->get_face()->units_per_EM;
double tmp_height = g.height(); ymin = std::min(ymin, g.ymin());
if (tmp_height > max_glyph_height) ymax = std::max(ymax, g.ymax());
max_glyph_height = tmp_height;
width_map[char_index++] += g.advance(); width_map[char_index++] += g.advance();
line.add_glyph(std::move(g), scale_factor); line.add_glyph(std::move(g), scale_factor);
} }
@ -123,7 +123,7 @@ struct icu_shaper
} }
if (!shaped_status) if (!shaped_status)
continue; continue;
line.update_max_char_height(max_glyph_height); line.update_max_char_height(ymin, ymax);
return; return;
} }
} }

View file

@ -117,6 +117,7 @@ class text_layout
inline rotation const& orientation() const { return orientation_; } inline rotation const& orientation() const { return orientation_; }
inline pixel_position const& displacement() const { return displacement_; } inline pixel_position const& displacement() const { return displacement_; }
inline double base_ajustment() const { return baseline_adjustment_; }
inline box2d<double> const& bounds() const { return bounds_; } inline box2d<double> const& bounds() const { return bounds_; }
inline horizontal_alignment_e horizontal_alignment() const { return halign_; } inline horizontal_alignment_e horizontal_alignment() const { return halign_; }
pixel_position alignment_offset() const; pixel_position alignment_offset() const;
@ -173,6 +174,7 @@ class text_layout
bool repeat_wrap_char_ = false; bool repeat_wrap_char_ = false;
bool rotate_displacement_ = false; bool rotate_displacement_ = false;
double text_ratio_ = 0.0; double text_ratio_ = 0.0;
double baseline_adjustment_ = 0.0;
pixel_position displacement_ = {0, 0}; pixel_position displacement_ = {0, 0};
box2d<double> bounds_ = {0, 0, 0, 0}; box2d<double> bounds_ = {0, 0, 0, 0};

View file

@ -65,7 +65,11 @@ class MAPNIK_DECL text_line : util::noncopyable
double max_char_height() const { return max_char_height_; } double max_char_height() const { return max_char_height_; }
// Called for each font/style to update the maximum height of this line. // Called for each font/style to update the maximum height of this line.
void update_max_char_height(double max_char_height); void update_max_char_height(double ymin, double ymax);
// Verticall adjustment
double baseline_adjustment() const { return baseline_adjustment_;}
// Line height including line spacing. // Line height including line spacing.
double line_height() const { return line_height_; } double line_height() const { return line_height_; }
@ -88,6 +92,7 @@ class MAPNIK_DECL text_line : util::noncopyable
glyph_vector glyphs_; glyph_vector glyphs_;
double line_height_; // Includes line spacing (returned by freetype) double line_height_; // Includes line spacing (returned by freetype)
double max_char_height_; // Max height of any glyphs in line - calculated by shaper double max_char_height_; // Max height of any glyphs in line - calculated by shaper
double baseline_adjustment_; // Adjustment to (0,0) origin
double width_; double width_;
double glyphs_width_; double glyphs_width_;
unsigned first_char_; unsigned first_char_;

View file

@ -172,7 +172,6 @@ bool placement_finder::find_point_placement(pixel_position const& pos)
// Find text origin. // Find text origin.
pixel_position layout_center = pos + layout.displacement(); pixel_position layout_center = pos + layout.displacement();
if (!base_point_set) if (!base_point_set)
{ {
glyphs->set_base_point(layout_center); glyphs->set_base_point(layout_center);
@ -180,9 +179,10 @@ bool placement_finder::find_point_placement(pixel_position const& pos)
} }
box2d<double> bbox = layout.bounds(); box2d<double> bbox = layout.bounds();
bbox.re_center(layout_center.x, layout_center.y);
/* For point placements it is faster to just check the bounding box. */ bbox.re_center(layout_center.x, layout_center.y - layout.base_ajustment());
// For point placements it is faster to just check the bounding box.
if (collision(bbox, layouts_.text(), false)) if (collision(bbox, layouts_.text(), false))
return false; return false;

View file

@ -210,6 +210,7 @@ void text_layout::layout()
displacement_ = scale_factor_ * displacement_ + alignment_offset(); displacement_ = scale_factor_ * displacement_ + alignment_offset();
if (rotate_displacement_) if (rotate_displacement_)
displacement_ = displacement_.rotate(!orientation_); displacement_ = displacement_.rotate(!orientation_);
// Find layout bounds, expanded for rotation // Find layout bounds, expanded for rotation
rotated_box2d(bounds_, orientation_, displacement_, width_, height_); rotated_box2d(bounds_, orientation_, displacement_, width_, height_);
} }
@ -436,6 +437,7 @@ void text_layout::add_line(text_line&& line)
line.set_first_line(true); line.set_first_line(true);
} }
height_ += line.height(); height_ += line.height();
baseline_adjustment_ = line.baseline_adjustment();
glyphs_count_ += line.size(); glyphs_count_ += line.size();
width_ = std::max(width_, line.width()); width_ = std::max(width_, line.width());
lines_.emplace_back(std::move(line)); lines_.emplace_back(std::move(line));

View file

@ -30,6 +30,7 @@ text_line::text_line(unsigned first_char, unsigned last_char)
: glyphs_() : glyphs_()
, line_height_(0.0) , line_height_(0.0)
, max_char_height_(0.0) , max_char_height_(0.0)
, baseline_adjustment_(0.0)
, width_(0.0) , width_(0.0)
, glyphs_width_(0.0) , glyphs_width_(0.0)
, first_char_(first_char) , first_char_(first_char)
@ -42,6 +43,7 @@ text_line::text_line(text_line&& rhs)
: glyphs_(std::move(rhs.glyphs_)) : glyphs_(std::move(rhs.glyphs_))
, line_height_(std::move(rhs.line_height_)) , line_height_(std::move(rhs.line_height_))
, max_char_height_(std::move(rhs.max_char_height_)) , max_char_height_(std::move(rhs.max_char_height_))
, baseline_adjustment_(std::move(baseline_adjustment_))
, width_(std::move(rhs.width_)) , width_(std::move(rhs.width_))
, glyphs_width_(std::move(rhs.glyphs_width_)) , glyphs_width_(std::move(rhs.glyphs_width_))
, first_char_(std::move(rhs.first_char_)) , first_char_(std::move(rhs.first_char_))
@ -92,9 +94,10 @@ double text_line::height() const
return line_height_; return line_height_;
} }
void text_line::update_max_char_height(double max_char_height) void text_line::update_max_char_height(double ymin, double ymax)
{ {
max_char_height_ = std::max(max_char_height_, max_char_height); max_char_height_ = std::max(max_char_height_, ymax - ymin);
baseline_adjustment_ = ymin;
} }
void text_line::set_first_line(bool first_line) void text_line::set_first_line(bool first_line)