From 1d8867d9ae9de1312fe6624bf9040dde12bfa9df Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Fri, 27 Sep 2024 17:11:05 +0100 Subject: [PATCH] LibWeb/CSS: Parse and propagate the font-language-override property --- .../css/getComputedStyle-print-all.txt | 3 +- .../Libraries/LibWeb/CSS/ComputedValues.h | 3 ++ .../Libraries/LibWeb/CSS/Parser/Parser.cpp | 49 +++++++++++++++++++ Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 1 + Userland/Libraries/LibWeb/CSS/Properties.json | 12 +++++ .../Libraries/LibWeb/CSS/StyleProperties.cpp | 8 +++ .../Libraries/LibWeb/CSS/StyleProperties.h | 1 + Userland/Libraries/LibWeb/Layout/Node.cpp | 3 +- 8 files changed, 78 insertions(+), 2 deletions(-) diff --git a/Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt b/Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt index 5b97bbc89b4..a0cc5ee5425 100644 --- a/Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt +++ b/Tests/LibWeb/Text/expected/css/getComputedStyle-print-all.txt @@ -11,6 +11,7 @@ fill: rgb(0, 0, 0) fill-opacity: 1 fill-rule: nonzero font-family: serif +font-language-override: normal font-size: 16px font-style: normal font-variant: normal @@ -116,7 +117,7 @@ grid-row-start: auto grid-template-areas: grid-template-columns: grid-template-rows: -height: 2006px +height: 2023px inline-size: auto inset-block-end: auto inset-block-start: auto diff --git a/Userland/Libraries/LibWeb/CSS/ComputedValues.h b/Userland/Libraries/LibWeb/CSS/ComputedValues.h index 638cff0c096..b12daab5561 100644 --- a/Userland/Libraries/LibWeb/CSS/ComputedValues.h +++ b/Userland/Libraries/LibWeb/CSS/ComputedValues.h @@ -485,6 +485,7 @@ public: CSSPixels font_size() const { return m_inherited.font_size; } int font_weight() const { return m_inherited.font_weight; } CSS::FontVariant font_variant() const { return m_inherited.font_variant; } + Optional font_language_override() const { return m_inherited.font_language_override; } CSSPixels line_height() const { return m_inherited.line_height; } CSS::Time transition_delay() const { return m_noninherited.transition_delay; } @@ -516,6 +517,7 @@ protected: CSSPixels font_size { InitialValues::font_size() }; int font_weight { InitialValues::font_weight() }; CSS::FontVariant font_variant { InitialValues::font_variant() }; + Optional font_language_override; CSSPixels line_height { InitialValues::line_height() }; CSS::BorderCollapse border_collapse { InitialValues::border_collapse() }; CSS::Length border_spacing_horizontal { InitialValues::border_spacing() }; @@ -672,6 +674,7 @@ public: void set_font_size(CSSPixels font_size) { m_inherited.font_size = font_size; } void set_font_weight(int font_weight) { m_inherited.font_weight = font_weight; } void set_font_variant(CSS::FontVariant font_variant) { m_inherited.font_variant = font_variant; } + void set_font_language_override(Optional font_language_override) { m_inherited.font_language_override = font_language_override; } void set_line_height(CSSPixels line_height) { m_inherited.line_height = line_height; } void set_border_spacing_horizontal(CSS::Length border_spacing_horizontal) { m_inherited.border_spacing_horizontal = border_spacing_horizontal; } void set_border_spacing_vertical(CSS::Length border_spacing_vertical) { m_inherited.border_spacing_vertical = border_spacing_vertical; } diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index cfb1aba1761..199efbc3930 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -5447,6 +5447,51 @@ RefPtr Parser::parse_font_family_value(TokenStream Parser::parse_font_language_override_value(TokenStream& tokens) +{ + // https://drafts.csswg.org/css-fonts/#propdef-font-language-override + // This is `normal | ` but with the constraint that the string has to be 4 characters long: + // Shorter strings are right-padded with spaces, and longer strings are invalid. + + { + auto transaction = tokens.begin_transaction(); + tokens.skip_whitespace(); + if (auto keyword = parse_keyword_value(tokens); keyword->to_keyword() == Keyword::Normal) { + tokens.skip_whitespace(); + if (tokens.has_next_token()) { + dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Failed to parse font-language-override: unexpected trailing tokens"); + return nullptr; + } + transaction.commit(); + return keyword; + } + } + + { + auto transaction = tokens.begin_transaction(); + tokens.skip_whitespace(); + if (auto string = parse_string_value(tokens)) { + auto string_value = string->as_string().string_value(); + tokens.skip_whitespace(); + if (tokens.has_next_token()) { + dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Failed to parse font-language-override: unexpected trailing tokens"); + return nullptr; + } + auto length = string_value.code_points().length(); + if (length > 4) { + dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Failed to parse font-language-override: value \"{}\" is too long", string_value); + return nullptr; + } + transaction.commit(); + if (length < 4) + return StringStyleValue::create(MUST(String::formatted("{<4}", string_value))); + return string; + } + } + + return nullptr; +} + JS::GCPtr Parser::parse_font_face_rule(TokenStream& tokens) { auto declarations_and_at_rules = parse_a_list_of_declarations(tokens); @@ -7528,6 +7573,10 @@ Parser::ParseErrorOr> Parser::parse_css_value(Prope if (auto parsed_value = parse_font_family_value(tokens); parsed_value && !tokens.has_next_token()) return parsed_value.release_nonnull(); return ParseError::SyntaxError; + case PropertyID::FontLanguageOverride: + if (auto parsed_value = parse_font_language_override_value(tokens); parsed_value && !tokens.has_next_token()) + return parsed_value.release_nonnull(); + return ParseError::SyntaxError; case PropertyID::GridArea: if (auto parsed_value = parse_grid_area_shorthand_value(tokens); parsed_value && !tokens.has_next_token()) return parsed_value.release_nonnull(); diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 0e30f68f533..58bd47b89cc 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -305,6 +305,7 @@ private: RefPtr parse_flex_flow_value(TokenStream&); RefPtr parse_font_value(TokenStream&); RefPtr parse_font_family_value(TokenStream&); + RefPtr parse_font_language_override_value(TokenStream&); RefPtr parse_list_style_value(TokenStream&); RefPtr parse_math_depth_value(TokenStream&); RefPtr parse_overflow_value(TokenStream&); diff --git a/Userland/Libraries/LibWeb/CSS/Properties.json b/Userland/Libraries/LibWeb/CSS/Properties.json index 674a3abdb6f..ac37c7b4e19 100644 --- a/Userland/Libraries/LibWeb/CSS/Properties.json +++ b/Userland/Libraries/LibWeb/CSS/Properties.json @@ -1145,6 +1145,7 @@ "font": { "inherited": true, "initial": "normal medium serif", + "__comment": "FIXME: Handle properties that are reset implicitly. https://drafts.csswg.org/css-fonts/#reset-implicitly", "longhands": [ "font-family", "font-size", @@ -1164,6 +1165,17 @@ "string" ] }, + "font-language-override": { + "animation-type": "discrete", + "inherited": true, + "initial": "normal", + "valid-types": [ + "string" + ], + "valid-identifiers": [ + "normal" + ] + }, "font-size": { "animation-type": "by-computed-value", "inherited": true, diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index d8763620cd5..97f8e7f7b92 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -1000,6 +1000,14 @@ Optional StyleProperties::font_variant() const return keyword_to_font_variant(value->to_keyword()); } +Optional StyleProperties::font_language_override() const +{ + auto value = property(CSS::PropertyID::FontLanguageOverride); + if (value->is_string()) + return value->as_string().string_value(); + return {}; +} + CSS::GridTrackSizeList StyleProperties::grid_auto_columns() const { auto value = property(CSS::PropertyID::GridAutoColumns); diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.h b/Userland/Libraries/LibWeb/CSS/StyleProperties.h index 3272ab28ac4..e0e1a9e25e1 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.h +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.h @@ -147,6 +147,7 @@ public: Optional pointer_events() const; Variant vertical_align() const; Optional font_variant() const; + Optional font_language_override() const; CSS::GridTrackSizeList grid_auto_columns() const; CSS::GridTrackSizeList grid_auto_rows() const; CSS::GridTrackSizeList grid_template_columns() const; diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index 2d317d446c0..6019a86af48 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -469,8 +469,9 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style) if (auto maybe_font_variant = computed_style.font_variant(); maybe_font_variant.has_value()) computed_values.set_font_variant(maybe_font_variant.release_value()); + if (auto maybe_font_language_override = computed_style.font_language_override(); maybe_font_language_override.has_value()) + computed_values.set_font_language_override(maybe_font_language_override.release_value()); - // FIXME: BorderXRadius properties are now BorderRadiusStyleValues, so make use of that. auto border_bottom_left_radius = computed_style.property(CSS::PropertyID::BorderBottomLeftRadius); if (border_bottom_left_radius->is_border_radius()) { computed_values.set_border_bottom_left_radius(