From d2be12bb076b3857f321b37692a1a89af12b5fbd Mon Sep 17 00:00:00 2001 From: Megamouse Date: Wed, 13 Jul 2022 22:18:13 +0200 Subject: [PATCH] overlays: find missing characters lost during wrapped rendering --- rpcs3/Emu/RSX/Overlays/overlay_fonts.cpp | 201 ++++++++++------------- 1 file changed, 90 insertions(+), 111 deletions(-) diff --git a/rpcs3/Emu/RSX/Overlays/overlay_fonts.cpp b/rpcs3/Emu/RSX/Overlays/overlay_fonts.cpp index a635d6b14f..c0c8a9ed80 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_fonts.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_fonts.cpp @@ -294,128 +294,107 @@ namespace rsx return; } - usz i = 0u; - bool skip_whitespace = false; - - while (true) + // Render as many characters as possible as glyphs. + for (usz i = 0u, begin_of_word = 0u; i < char_limit; i++) { - if (auto c = text[i++]; c && (i <= char_limit)) + switch (const auto& c = text[i]) { - switch (c) + case '\0': + { + // We're done. + return; + } + case '\n': + { + // Reset x to 0 and increase y to advance to the new line. + x_advance = 0.f; + y_advance += size_px + 2.f; + begin_of_word = result.size(); + continue; + } + case '\r': + { + // Reset x to 0. + x_advance = 0.f; + begin_of_word = result.size(); + continue; + } + default: + { + const bool is_whitespace = c == ' '; + stbtt_aligned_quad quad{}; + + if (is_whitespace) { - case '\n': - { - y_advance += size_px + 2.f; - x_advance = 0.f; - continue; - } - case '\r': - { - x_advance = 0.f; - continue; - } - default: - { - stbtt_aligned_quad quad; - if (skip_whitespace && text[i - 1] == ' ') + // Skip whitespace if we are at the start of a line. + if (x_advance > 0.f) { - quad = {}; + // Get the glyph size. + quad = get_char(c, x_advance, y_advance); + + // Reset the result if the glyph would protrude out of the given space anyway. + if (x_advance > max_width) + { + quad = {}; + } + } + } + else + { + // No whitespace. Get the glyph size. + quad = get_char(c, x_advance, y_advance); + } + + // Add the glyph's vertices. + result.emplace_back(quad.x0, quad.y0, quad.s0, quad.t0); + result.emplace_back(quad.x1, quad.y0, quad.s1, quad.t0); + result.emplace_back(quad.x0, quad.y1, quad.s0, quad.t1); + result.emplace_back(quad.x1, quad.y1, quad.s1, quad.t1); + + // The next word will begin after any whitespaces. + if (is_whitespace) + { + begin_of_word = result.size(); + } + + // Check if we reached the end of the available space. + if (x_advance > max_width) + { + // Try to wrap the protruding text + if (wrap) + { + // Increase y to advance to the next line. + y_advance += size_px + 2.f; + + // We can just reset x and move on to the next character if this is a whitespace. + if (is_whitespace) + { + x_advance = 0.f; + break; + } + + // Get the leftmost offset of the current word. + const f32 base_x = result[begin_of_word].x(); + + // Move all characters of the current word one line down and to the left. + for (usz n = begin_of_word; n < result.size(); ++n) + { + result[n].x() -= base_x; + result[n].y() += size_px + 2.f; + } + + // Set x offset to the rightmost position of the current word + x_advance = result.back().x(); } else { - quad = get_char(c, x_advance, y_advance); - skip_whitespace = false; + // TODO: Ellipsize } - - if (x_advance > max_width) - { - bool wrapped = false; - bool non_whitespace_break = false; - - if (wrap) - { - // scan previous chars - for (usz j = i - 1, nb_chars = 0; j > 0; j--, nb_chars++) - { - if (text[j] == '\n') - break; - - if (text[j] == ' ') - { - non_whitespace_break = true; - continue; - } - - if (non_whitespace_break) - { - if (nb_chars > 1) - { - nb_chars--; - - auto first_affected = result.size() - (nb_chars * 4); - f32 base_x = result[first_affected].values[0]; - - for (usz n = first_affected; n < result.size(); ++n) - { - auto char_index = n / 4; - if (text[char_index] == ' ') - { - // Skip character - result[n++].vec2(0.f, 0.f); - result[n++].vec2(0.f, 0.f); - result[n++].vec2(0.f, 0.f); - result[n].vec2(0.f, 0.f); - continue; - } - - result[n].values[0] -= base_x; - result[n].values[1] += size_px + 2.f; - } - - x_advance = result.back().values[0]; - } - else - { - x_advance = 0.f; - } - - wrapped = true; - y_advance += size_px + 2.f; - - if (text[i - 1] == ' ') - { - quad = {}; - skip_whitespace = true; - } - else - { - quad = get_char(c, x_advance, y_advance); - } - - break; - } - } - } - - if (!wrapped) - { - // TODO: Ellipsize - break; - } - } - - result.emplace_back(quad.x0, quad.y0, quad.s0, quad.t0); - result.emplace_back(quad.x1, quad.y0, quad.s1, quad.t0); - result.emplace_back(quad.x0, quad.y1, quad.s0, quad.t1); - result.emplace_back(quad.x1, quad.y1, quad.s1, quad.t1); - break; } - } // switch - } - else - { + break; } + } // switch } }