summaryrefslogtreecommitdiff
path: root/Userland
diff options
context:
space:
mode:
authorSam Atkins <atkinssj@serenityos.org>2023-06-01 17:01:09 +0100
committerAndreas Kling <kling@serenityos.org>2023-06-01 21:04:21 +0200
commit1160d8186b555bdf7ec46839c8117ab4a6dba7b3 (patch)
tree80ed18d5f96b079b51d595be8c95d7eee298a787 /Userland
parentad8565011c9a2bab2ce0eb1ed1df7faf0c29960b (diff)
downloadserenity-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.txt1
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp40
-rw-r--r--Userland/Libraries/LibWeb/CSS/Parser/Parser.h3
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleProperties.cpp14
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleValue.cpp11
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleValue.h4
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.cpp16
-rw-r--r--Userland/Libraries/LibWeb/CSS/StyleValues/IntegerStyleValue.h36
-rw-r--r--Userland/Libraries/LibWeb/Forward.h1
-rw-r--r--Userland/Libraries/LibWeb/Layout/Node.cpp2
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());