overlays: properly calculate offsets for wrapped text

This commit is contained in:
Megamouse 2022-07-13 20:53:46 +02:00
parent e548743cbf
commit fdc15e12c4
3 changed files with 69 additions and 16 deletions

View file

@ -355,17 +355,17 @@ namespace rsx
return font_ref ? font_ref : fontmgr::get("Arial", 12); return font_ref ? font_ref : fontmgr::get("Arial", 12);
} }
std::vector<vertex> overlay_element::render_text(const char32_t *string, f32 x, f32 y) std::vector<vertex> overlay_element::render_text(const char32_t* string, f32 x, f32 y)
{ {
auto renderer = get_font(); auto renderer = get_font();
f32 text_extents_w = 0.f; f32 text_extents_w = 0.f;
u16 clip_width = clip_text ? w : umax; const u16 clip_width = clip_text ? w : umax;
std::vector<vertex> result = renderer->render_text(string, clip_width, wrap_text); std::vector<vertex> result = renderer->render_text(string, clip_width, wrap_text);
if (!result.empty()) if (!result.empty())
{ {
for (auto &v : result) for (vertex& v : result)
{ {
// Check for real text region extent // Check for real text region extent
// TODO: Ellipsis // TODO: Ellipsis
@ -397,30 +397,63 @@ namespace rsx
continue; continue;
default: default:
ctr += 4; ctr += 4;
break;
} }
} }
lines.emplace_back(line_begin, ctr); lines.emplace_back(line_begin, ctr);
const auto max_region_w = std::max<f32>(text_extents_w, w); const f32 max_region_w = std::max<f32>(text_extents_w, w);
const f32 offset_extent = (alignment == text_align::center ? 0.5f : 1.0f); const f32 offset_extent = (alignment == text_align::center ? 0.5f : 1.0f);
const f32 size_px = renderer->get_size_px() * 0.5f;
for (auto p : lines) // Moves all glyphs of a line by the correct amount to get a nice alignment.
const auto move_line = [&result, &max_region_w, &offset_extent](u32 begin, u32 end)
{ {
if (p.first >= p.second) const f32 line_length = result[end - 1].x() - result[begin].x();
continue;
const f32 line_length = result[p.second - 1].values[0] - result[p.first].values[0];
const bool wrapped = std::fabs(result[p.second - 1].values[1] - result[p.first + 3].values[1]) >= (renderer->get_size_px() * 0.5f);
if (wrapped)
continue;
if (line_length < max_region_w) if (line_length < max_region_w)
{ {
const f32 offset = (max_region_w - line_length) * offset_extent; const f32 offset = (max_region_w - line_length) * offset_extent;
for (auto n = p.first; n < p.second; ++n) for (auto n = begin; n < end; ++n)
{ {
result[n].values[0] += offset; result[n].x() += offset;
}
}
};
for (const auto& [begin, end] : lines)
{
if (begin >= end)
continue;
// Check if there's any wrapped text
if (std::fabs(result[end - 1].y() - result[begin + 3].y()) < size_px)
{
// No wrapping involved. We can just move the entire line.
move_line(begin, end);
continue;
}
// Wrapping involved. We have to search for the line breaks and move each line seperately.
for (u32 i_begin = begin, i_next = begin + 4;; i_next += 4)
{
// Check if this is the last glyph in the line of text.
const bool is_last_glyph = i_next >= end;
// The line may be wrapped, so we need to check if the next glyph's position is below the current position.
if (is_last_glyph || (std::fabs(result[i_next - 1].y() - result[i_begin + 3].y()) >= size_px))
{
// Whenever we reached the end of a visual line we need to move its glyphs accordingly.
const u32 i_end = i_next - (is_last_glyph ? 0 : 4);
move_line(i_begin, i_end);
i_begin = i_end;
if (is_last_glyph)
{
break;
}
} }
} }
} }

View file

@ -189,7 +189,7 @@ namespace rsx
virtual void align_text(text_align align); virtual void align_text(text_align align);
virtual void set_wrap_text(bool state); virtual void set_wrap_text(bool state);
virtual font* get_font() const; virtual font* get_font() const;
virtual std::vector<vertex> render_text(const char32_t *string, f32 x, f32 y); virtual std::vector<vertex> render_text(const char32_t* string, f32 x, f32 y);
virtual compiled_resource& get_compiled(); virtual compiled_resource& get_compiled();
void measure_text(u16& width, u16& height, bool ignore_word_wrap = false) const; void measure_text(u16& width, u16& height, bool ignore_word_wrap = false) const;
}; };

View file

@ -36,6 +36,26 @@ struct vertex
return values[index]; return values[index];
} }
float& x()
{
return values[0];
}
float& y()
{
return values[1];
}
float& z()
{
return values[2];
}
float& w()
{
return values[3];
}
void vec2(float x, float y) void vec2(float x, float y)
{ {
values[0] = x; values[0] = x;