From 32e35a02f9c0397cad7090014c1c2781a906ee62 Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Fri, 23 Dec 2022 19:57:52 +0100 Subject: [PATCH] LibWeb: Apply CSS text-transform during layout Previously we were doing this at the painting stage, which meant that layout potentially used the wrong glyphs when measuring text. This would lead to incorrect layout metrics and was visible on the HTML5Test score display, for example. :^) --- Userland/Libraries/LibWeb/Layout/TextNode.cpp | 12 +++++++++++- Userland/Libraries/LibWeb/Painting/PaintableBox.cpp | 6 ------ 2 files changed, 11 insertions(+), 7 deletions(-) diff --git a/Userland/Libraries/LibWeb/Layout/TextNode.cpp b/Userland/Libraries/LibWeb/Layout/TextNode.cpp index 4902339046..3d0512fd90 100644 --- a/Userland/Libraries/LibWeb/Layout/TextNode.cpp +++ b/Userland/Libraries/LibWeb/Layout/TextNode.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -31,10 +32,19 @@ static bool is_all_whitespace(StringView string) return true; } +static DeprecatedString apply_text_transform(DeprecatedString const& string, CSS::TextTransform text_transform) +{ + if (text_transform == CSS::TextTransform::Uppercase) + return Unicode::to_unicode_uppercase_full(string); + if (text_transform == CSS::TextTransform::Lowercase) + return Unicode::to_unicode_lowercase_full(string); + return string; +} + // NOTE: This collapses whitespace into a single ASCII space if collapse is true. void TextNode::compute_text_for_rendering(bool collapse) { - auto& data = dom_node().data(); + auto data = apply_text_transform(dom_node().data(), computed_values().text_transform()); if (dom_node().is_password_input()) { m_text_for_rendering = DeprecatedString::repeated('*', data.length()); diff --git a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp index 43a9092f86..478773ce4a 100644 --- a/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp +++ b/Userland/Libraries/LibWeb/Painting/PaintableBox.cpp @@ -513,13 +513,7 @@ static void paint_text_fragment(PaintContext& context, Layout::TextNode const& t if (text_node.document().inspected_node() == &text_node.dom_node()) context.painter().draw_rect(fragment_absolute_device_rect.to_type(), Color::Magenta); - // FIXME: text-transform should be done already in layout, since uppercase glyphs may be wider than lowercase, etc. auto text = text_node.text_for_rendering(); - auto text_transform = text_node.computed_values().text_transform(); - if (text_transform == CSS::TextTransform::Uppercase) - text = Unicode::to_unicode_uppercase_full(text_node.text_for_rendering()); - if (text_transform == CSS::TextTransform::Lowercase) - text = Unicode::to_unicode_lowercase_full(text_node.text_for_rendering()); DevicePixelPoint baseline_start { fragment_absolute_device_rect.x(), fragment_absolute_device_rect.y() + context.rounded_device_pixels(fragment.baseline()) }; Utf8View view { text.substring_view(fragment.start(), fragment.length()) };