From fdc15e12c4a6211bbe25fc0231de764779aeaf44 Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 13 Jul 2022 20:53:46 +0200 Subject: [PATCH] overlays: properly calculate offsets for wrapped text --- rpcs3/Emu/RSX/Overlays/overlay_controls.cpp | 63 ++++++++++++++++----- rpcs3/Emu/RSX/Overlays/overlay_controls.h | 2 +- rpcs3/Emu/RSX/Overlays/overlay_utils.h | 20 +++++++ 3 files changed, 69 insertions(+), 16 deletions(-) diff --git a/rpcs3/Emu/RSX/Overlays/overlay_controls.cpp b/rpcs3/Emu/RSX/Overlays/overlay_controls.cpp index c4507243a9..853de28b1e 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_controls.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_controls.cpp @@ -355,17 +355,17 @@ namespace rsx return font_ref ? font_ref : fontmgr::get("Arial", 12); } - std::vector overlay_element::render_text(const char32_t *string, f32 x, f32 y) + std::vector overlay_element::render_text(const char32_t* string, f32 x, f32 y) { auto renderer = get_font(); f32 text_extents_w = 0.f; - u16 clip_width = clip_text ? w : umax; + const u16 clip_width = clip_text ? w : umax; std::vector result = renderer->render_text(string, clip_width, wrap_text); if (!result.empty()) { - for (auto &v : result) + for (vertex& v : result) { // Check for real text region extent // TODO: Ellipsis @@ -397,30 +397,63 @@ namespace rsx continue; default: ctr += 4; + break; } } lines.emplace_back(line_begin, ctr); - const auto max_region_w = std::max(text_extents_w, w); + const f32 max_region_w = std::max(text_extents_w, w); 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) - 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; + const f32 line_length = result[end - 1].x() - result[begin].x(); if (line_length < max_region_w) { 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; + } } } } diff --git a/rpcs3/Emu/RSX/Overlays/overlay_controls.h b/rpcs3/Emu/RSX/Overlays/overlay_controls.h index 6570379ba8..f348b3d52c 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_controls.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_controls.h @@ -189,7 +189,7 @@ namespace rsx virtual void align_text(text_align align); virtual void set_wrap_text(bool state); virtual font* get_font() const; - virtual std::vector render_text(const char32_t *string, f32 x, f32 y); + virtual std::vector render_text(const char32_t* string, f32 x, f32 y); virtual compiled_resource& get_compiled(); void measure_text(u16& width, u16& height, bool ignore_word_wrap = false) const; }; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_utils.h b/rpcs3/Emu/RSX/Overlays/overlay_utils.h index 2c828ba293..cab0e1a598 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_utils.h +++ b/rpcs3/Emu/RSX/Overlays/overlay_utils.h @@ -36,6 +36,26 @@ struct vertex 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) { values[0] = x;