diff options
author | Sam Atkins <atkinssj@serenityos.org> | 2023-06-01 17:01:09 +0100 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2023-06-01 21:04:21 +0200 |
commit | 1160d8186b555bdf7ec46839c8117ab4a6dba7b3 (patch) | |
tree | 80ed18d5f96b079b51d595be8c95d7eee298a787 /Userland | |
parent | ad8565011c9a2bab2ce0eb1ed1df7faf0c29960b (diff) | |
download | serenity-1160d8186b555bdf7ec46839c8117ab4a6dba7b3.zip |
LibWeb: Implement IntegerStyleValue, for holding `<integer>`
Having one StyleValue for `<number>` and `<integer>` is making user code
more complicated than it needs to be. We know based on the property
being parsed, whether it wants a `<number>` or an `<integer>`, so we
can use separate StyleValue types for these.
Diffstat (limited to 'Userland')
-rw-r--r-- | Userland/Libraries/LibWeb/CMakeLists.txt | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp | 40 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 3 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleProperties.cpp | 14 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleValue.cpp | 11 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleValue.h | 4 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp | 16 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h | 36 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Forward.h | 1 | ||||
-rw-r--r-- | Userland/Libraries/LibWeb/Layout/Node.cpp | 2 |
10 files changed, 105 insertions, 23 deletions
diff --git a/Userland/Libraries/LibWeb/CMakeLists.txt b/Userland/Libraries/LibWeb/CMakeLists.txt index 0f1a285b9c..61f8ebfcbf 100644 --- a/Userland/Libraries/LibWeb/CMakeLists.txt +++ b/Userland/Libraries/LibWeb/CMakeLists.txt @@ -96,6 +96,7 @@ set(SOURCES CSS/StyleValues/GridTrackSizeListStyleValue.cpp CSS/StyleValues/IdentifierStyleValue.cpp CSS/StyleValues/ImageStyleValue.cpp + CSS/StyleValues/IntegerStyleValue.cpp CSS/StyleValues/LengthStyleValue.cpp CSS/StyleValues/LinearGradientStyleValue.cpp CSS/StyleValues/ListStyleStyleValue.cpp diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index d386f7df66..21e05cb054 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -62,6 +62,7 @@ #include <LibWeb/CSS/StyleValues/ImageStyleValue.h> #include <LibWeb/CSS/StyleValues/InheritStyleValue.h> #include <LibWeb/CSS/StyleValues/InitialStyleValue.h> +#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h> #include <LibWeb/CSS/StyleValues/LengthStyleValue.h> #include <LibWeb/CSS/StyleValues/LinearGradientStyleValue.h> #include <LibWeb/CSS/StyleValues/ListStyleStyleValue.h> @@ -3811,13 +3812,23 @@ ErrorOr<RefPtr<StyleValue>> Parser::parse_dimension_value(ComponentValue const& VERIFY_NOT_REACHED(); } -ErrorOr<RefPtr<StyleValue>> Parser::parse_numeric_value(ComponentValue const& component_value) +ErrorOr<RefPtr<StyleValue>> Parser::parse_integer_value(TokenStream<ComponentValue>& tokens) { - if (component_value.is(Token::Type::Number)) { - auto const& number = component_value.token(); - if (number.number().is_integer()) - return NumberStyleValue::create_integer(number.to_integer()); - return NumberStyleValue::create_float(number.number_value()); + auto peek_token = tokens.peek_token(); + if (peek_token.is(Token::Type::Number) && peek_token.token().number().is_integer()) { + (void)tokens.next_token(); + return IntegerStyleValue::create(peek_token.token().number().integer_value()); + } + + return nullptr; +} + +ErrorOr<RefPtr<StyleValue>> Parser::parse_number_value(TokenStream<ComponentValue>& tokens) +{ + auto peek_token = tokens.peek_token(); + if (peek_token.is(Token::Type::Number)) { + (void)tokens.next_token(); + return NumberStyleValue::create_float(peek_token.token().number().value()); } return nullptr; @@ -6313,7 +6324,9 @@ ErrorOr<RefPtr<StyleValue>> Parser::parse_transform_value(Vector<ComponentValue> if (maybe_calc_value && maybe_calc_value->resolves_to_number()) { values.append(maybe_calc_value.release_nonnull()); } else { - auto number = TRY(parse_numeric_value(value)); + // FIXME: Remove this reconsume once all parsing functions are TokenStream-based. + argument_tokens.reconsume_current_input_token(); + auto number = TRY(parse_number_value(argument_tokens)); if (!number) return nullptr; values.append(number.release_nonnull()); @@ -7436,11 +7449,14 @@ ErrorOr<Parser::PropertyAndValue> Parser::parse_css_value_for_properties(Readonl bool property_accepts_numeric = property_accepting_integer.has_value() || property_accepting_number.has_value(); if (peek_token.is(Token::Type::Number) && property_accepts_numeric) { - auto numeric = TRY(parse_numeric_value(peek_token)); - (void)tokens.next_token(); - if (numeric->as_number().has_integer() && property_accepting_integer.has_value()) - return PropertyAndValue { *property_accepting_integer, numeric }; - return PropertyAndValue { property_accepting_integer.value_or(property_accepting_number.value()), numeric }; + if (property_accepting_integer.has_value()) { + if (auto integer = TRY(parse_integer_value(tokens))) + return PropertyAndValue { *property_accepting_integer, integer }; + } + if (property_accepting_number.has_value()) { + if (auto number = TRY(parse_number_value(tokens))) + return PropertyAndValue { *property_accepting_number, number }; + } } if (peek_token.is(Token::Type::Percentage)) { diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h index 51cf8cd7a0..43c3a5d86a 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.h +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.h @@ -290,7 +290,8 @@ private: ErrorOr<RefPtr<StyleValue>> parse_dynamic_value(ComponentValue const&); ErrorOr<RefPtr<CalculatedStyleValue>> parse_calculated_value(Vector<ComponentValue> const&); ErrorOr<RefPtr<StyleValue>> parse_dimension_value(ComponentValue const&); - ErrorOr<RefPtr<StyleValue>> parse_numeric_value(ComponentValue const&); + ErrorOr<RefPtr<StyleValue>> parse_integer_value(TokenStream<ComponentValue>&); + ErrorOr<RefPtr<StyleValue>> parse_number_value(TokenStream<ComponentValue>&); ErrorOr<RefPtr<StyleValue>> parse_identifier_value(ComponentValue const&); ErrorOr<RefPtr<StyleValue>> parse_color_value(ComponentValue const&); ErrorOr<RefPtr<StyleValue>> parse_rect_value(ComponentValue const&); diff --git a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp index d20cb9d87b..53ab1e0afd 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleProperties.cpp @@ -15,6 +15,7 @@ #include <LibWeb/CSS/StyleValues/GridTemplateAreaStyleValue.h> #include <LibWeb/CSS/StyleValues/GridTrackPlacementStyleValue.h> #include <LibWeb/CSS/StyleValues/GridTrackSizeListStyleValue.h> +#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h> #include <LibWeb/CSS/StyleValues/LengthStyleValue.h> #include <LibWeb/CSS/StyleValues/NumberStyleValue.h> #include <LibWeb/CSS/StyleValues/PercentageStyleValue.h> @@ -244,13 +245,12 @@ Optional<int> StyleProperties::z_index() const auto value = property(CSS::PropertyID::ZIndex); if (value->has_auto()) return {}; - if (value->is_number() && value->as_number().has_integer()) { + if (value->is_integer()) { // Clamp z-index to the range of a signed 32-bit integer for consistency with other engines. - // NOTE: Casting between 32-bit float and 32-bit integer is finicky here, since INT32_MAX is not representable as a 32-bit float! - auto integer = value->as_number().integer(); - if (integer >= static_cast<float>(NumericLimits<int>::max())) + auto integer = value->as_integer().integer(); + if (integer >= NumericLimits<int>::max()) return NumericLimits<int>::max(); - if (integer <= static_cast<float>(NumericLimits<int>::min())) + if (integer <= NumericLimits<int>::min()) return NumericLimits<int>::min(); return static_cast<int>(integer); } @@ -362,9 +362,9 @@ float StyleProperties::flex_shrink() const int StyleProperties::order() const { auto value = property(CSS::PropertyID::Order); - if (!value->is_number() || !value->as_number().has_integer()) + if (!value->is_integer()) return 0; - return value->as_number().integer(); + return value->as_integer().integer(); } Optional<CSS::ImageRendering> StyleProperties::image_rendering() const diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index ff3e7f9bc6..f67c7008bc 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -40,6 +40,7 @@ #include <LibWeb/CSS/StyleValues/ImageStyleValue.h> #include <LibWeb/CSS/StyleValues/InheritStyleValue.h> #include <LibWeb/CSS/StyleValues/InitialStyleValue.h> +#include <LibWeb/CSS/StyleValues/IntegerStyleValue.h> #include <LibWeb/CSS/StyleValues/LengthStyleValue.h> #include <LibWeb/CSS/StyleValues/LinearGradientStyleValue.h> #include <LibWeb/CSS/StyleValues/ListStyleStyleValue.h> @@ -248,6 +249,12 @@ InitialStyleValue const& StyleValue::as_initial() const return static_cast<InitialStyleValue const&>(*this); } +IntegerStyleValue const& StyleValue::as_integer() const +{ + VERIFY(is_integer()); + return static_cast<IntegerStyleValue const&>(*this); +} + LengthStyleValue const& StyleValue::as_length() const { VERIFY(is_length()); @@ -409,8 +416,8 @@ int StyleValue::to_font_weight() const return Gfx::FontWeight::Regular; } } - if (is_number() && as_number().has_integer()) { - return as_number().integer(); + if (is_number()) { + return round_to<int>(as_number().number()); } if (is_calculated()) { auto maybe_weight = const_cast<CalculatedStyleValue&>(as_calculated()).resolve_integer(); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index c84b8e7e6b..dae517ba76 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -117,6 +117,7 @@ public: Image, Inherit, Initial, + Integer, Length, LinearGradient, ListStyle, @@ -172,6 +173,7 @@ public: bool is_image() const { return type() == Type::Image; } bool is_inherit() const { return type() == Type::Inherit; } bool is_initial() const { return type() == Type::Initial; } + bool is_integer() const { return type() == Type::Integer; } bool is_length() const { return type() == Type::Length; } bool is_linear_gradient() const { return type() == Type::LinearGradient; } bool is_list_style() const { return type() == Type::ListStyle; } @@ -226,6 +228,7 @@ public: ImageStyleValue const& as_image() const; InheritStyleValue const& as_inherit() const; InitialStyleValue const& as_initial() const; + IntegerStyleValue const& as_integer() const; LengthStyleValue const& as_length() const; LinearGradientStyleValue const& as_linear_gradient() const; ListStyleStyleValue const& as_list_style() const; @@ -277,6 +280,7 @@ public: ImageStyleValue& as_image() { return const_cast<ImageStyleValue&>(const_cast<StyleValue const&>(*this).as_image()); } InheritStyleValue& as_inherit() { return const_cast<InheritStyleValue&>(const_cast<StyleValue const&>(*this).as_inherit()); } InitialStyleValue& as_initial() { return const_cast<InitialStyleValue&>(const_cast<StyleValue const&>(*this).as_initial()); } + IntegerStyleValue& as_integer() { return const_cast<IntegerStyleValue&>(const_cast<StyleValue const&>(*this).as_integer()); } LengthStyleValue& as_length() { return const_cast<LengthStyleValue&>(const_cast<StyleValue const&>(*this).as_length()); } LinearGradientStyleValue& as_linear_gradient() { return const_cast<LinearGradientStyleValue&>(const_cast<StyleValue const&>(*this).as_linear_gradient()); } ListStyleStyleValue& as_list_style() { return const_cast<ListStyleStyleValue&>(const_cast<StyleValue const&>(*this).as_list_style()); } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp new file mode 100644 index 0000000000..a8ae8beaa2 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#include "IntegerStyleValue.h" + +namespace Web::CSS { + +ErrorOr<String> IntegerStyleValue::to_string() const +{ + return String::number(m_value); +} + +} diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h new file mode 100644 index 0000000000..f47fbe3be0 --- /dev/null +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org> + * + * SPDX-License-Identifier: BSD-2-Clause + */ + +#pragma once + +#include <LibWeb/CSS/StyleValue.h> + +namespace Web::CSS { + +class IntegerStyleValue : public StyleValueWithDefaultOperators<IntegerStyleValue> { +public: + static ErrorOr<ValueComparingNonnullRefPtr<IntegerStyleValue>> create(i64 value) + { + return adopt_nonnull_ref_or_enomem(new (nothrow) IntegerStyleValue(value)); + } + + i64 integer() const { return m_value; } + + virtual ErrorOr<String> to_string() const override; + + bool properties_equal(IntegerStyleValue const& other) const { return m_value == other.m_value; } + +private: + explicit IntegerStyleValue(i64 value) + : StyleValueWithDefaultOperators(Type::Integer) + , m_value(value) + { + } + + i64 m_value { 0 }; +}; + +} diff --git a/Userland/Libraries/LibWeb/Forward.h b/Userland/Libraries/LibWeb/Forward.h index 276a73eae6..d1f2f97aa7 100644 --- a/Userland/Libraries/LibWeb/Forward.h +++ b/Userland/Libraries/LibWeb/Forward.h @@ -117,6 +117,7 @@ class IdentifierStyleValue; class ImageStyleValue; class InheritStyleValue; class InitialStyleValue; +class IntegerStyleValue; class Length; class LengthBox; class LengthOrCalculated; diff --git a/Userland/Libraries/LibWeb/Layout/Node.cpp b/Userland/Libraries/LibWeb/Layout/Node.cpp index d1fffbf080..bb87ac1882 100644 --- a/Userland/Libraries/LibWeb/Layout/Node.cpp +++ b/Userland/Libraries/LibWeb/Layout/Node.cpp @@ -295,7 +295,7 @@ void NodeWithStyle::apply_style(const CSS::StyleProperties& computed_style) // That's why it has to be set before everything else. m_font = computed_style.computed_font(); computed_values.set_font_size(computed_style.property(CSS::PropertyID::FontSize)->as_length().length().to_px(*this).value()); - computed_values.set_font_weight(computed_style.property(CSS::PropertyID::FontWeight)->as_number().integer()); + computed_values.set_font_weight(round_to<int>(computed_style.property(CSS::PropertyID::FontWeight)->as_number().number())); m_line_height = computed_style.line_height(*this); computed_values.set_vertical_align(computed_style.vertical_align()); |