diff options
author | Timothy Flynn <trflynn89@pm.me> | 2023-03-03 14:40:56 -0500 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-03-03 22:49:12 +0100 |
commit | 4463de3d109ce953e420c6347a863285fa7c83a2 (patch) | |
tree | 865e48bf6a2188b0c6f870cdda855028f87650bc /Userland/Libraries/LibGUI | |
parent | c7736ef41017288b2bb8d41cf51f2b1366ed5a35 (diff) | |
download | serenity-4463de3d109ce953e420c6347a863285fa7c83a2.zip |
LibGUI: Compute syntax-highlighted visual text spans using float rects
For vector fonts in particular, we need to take care to compute offsets
using floating point math. For example, with Berkeley Mono at font size
16, with syntax highlighting enabled, we are currently truncating these
offsets to integers. This results in a leftward-drift when we paint the
text.
This changes the rect in which we paint syntax-highlighted text spans to
a float rect. As we traverse the spans, we now no longer truncate any of
the text offsets, and we draw the text in the correct positions.
This is likely not a complete solution. TextEditor blindly casts ints to
floats all over, and we will want to make all of these (hundred+) float-
aware. But this should be a step in the right direction and makes vector
fonts immediately more comfortable to use.
Diffstat (limited to 'Userland/Libraries/LibGUI')
-rw-r--r-- | Userland/Libraries/LibGUI/TextEditor.cpp | 28 |
1 files changed, 23 insertions, 5 deletions
diff --git a/Userland/Libraries/LibGUI/TextEditor.cpp b/Userland/Libraries/LibGUI/TextEditor.cpp index 75c4399c3d..3f801aa1c9 100644 --- a/Userland/Libraries/LibGUI/TextEditor.cpp +++ b/Userland/Libraries/LibGUI/TextEditor.cpp @@ -497,17 +497,35 @@ void TextEditor::paint_event(PaintEvent& event) // NOTE: This lambda and TextEditor::text_width_for_font() are used to substitute all glyphs with m_substitution_code_point if necessary. // Painter::draw_text() and Gfx::Font::width() should not be called directly, but using this lambda and TextEditor::text_width_for_font(). - auto draw_text = [&](Gfx::IntRect const& rect, auto const& raw_text, Gfx::Font const& font, Gfx::TextAlignment alignment, Gfx::TextAttributes attributes, bool substitute = true) { + auto draw_text = [&](auto const& rect, auto const& raw_text, Gfx::Font const& font, Gfx::TextAlignment alignment, Gfx::TextAttributes attributes, bool substitute = true) { if (m_substitution_code_point.has_value() && substitute) { painter.draw_text(rect, substitution_code_point_view(raw_text.length()), font, alignment, attributes.color); } else { painter.draw_text(rect, raw_text, font, alignment, attributes.color); } if (attributes.underline) { + auto bottom_left = [&]() { + auto point = rect.bottom_left().translated(0, 1); + + if constexpr (IsSame<RemoveCVReference<decltype(rect)>, Gfx::IntRect>) + return point; + else + return point.template to_type<int>(); + }; + + auto bottom_right = [&]() { + auto point = rect.bottom_right().translated(0, 1); + + if constexpr (IsSame<RemoveCVReference<decltype(rect)>, Gfx::IntRect>) + return point; + else + return point.template to_type<int>(); + }; + if (attributes.underline_style == Gfx::TextAttributes::UnderlineStyle::Solid) - painter.draw_line(rect.bottom_left().translated(0, 1), rect.bottom_right().translated(0, 1), attributes.underline_color.value_or(attributes.color)); + painter.draw_line(bottom_left(), bottom_right(), attributes.underline_color.value_or(attributes.color)); if (attributes.underline_style == Gfx::TextAttributes::UnderlineStyle::Wavy) - painter.draw_triangle_wave(rect.bottom_left().translated(0, 1), rect.bottom_right().translated(0, 1), attributes.underline_color.value_or(attributes.color), 2); + painter.draw_triangle_wave(bottom_left(), bottom_right(), attributes.underline_color.value_or(attributes.color), 2); } }; @@ -651,7 +669,7 @@ void TextEditor::paint_event(PaintEvent& event) draw_text(visual_line_rect, visual_line_text, font(), m_text_alignment, unspanned_text_attributes); } else { size_t next_column = 0; - Gfx::IntRect span_rect = { visual_line_rect.location(), { 0, line_height() } }; + Gfx::FloatRect span_rect = { visual_line_rect.location(), { 0, line_height() } }; auto draw_text_helper = [&](size_t start, size_t end, Gfx::Font const& font, Gfx::TextAttributes text_attributes) { size_t length = end - start; @@ -660,7 +678,7 @@ void TextEditor::paint_event(PaintEvent& event) auto text = visual_line_text.substring_view(start, length); span_rect.set_width(font.width(text) + font.glyph_spacing()); if (text_attributes.background_color.has_value()) { - painter.fill_rect(span_rect, text_attributes.background_color.value()); + painter.fill_rect(span_rect.to_type<int>(), text_attributes.background_color.value()); } draw_text(span_rect, text, font, m_text_alignment, text_attributes); span_rect.translate_by(span_rect.width(), 0); |