From e6c0cb5a7f56a270339c78a0b3517184245d4c2a Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Mon, 9 Aug 2021 14:54:40 +0100 Subject: [PATCH] LibWeb: Implement and use OverflowStyleValue Also added a test page for the `overflow` properties. They apparently don't work, but at least they do parse. --- Base/res/html/misc/overflow.html | 180 ++++++++++++++++++ Base/res/html/misc/welcome.html | 1 + .../Libraries/LibWeb/CSS/Parser/Parser.cpp | 45 +++++ Userland/Libraries/LibWeb/CSS/Parser/Parser.h | 1 + .../Libraries/LibWeb/CSS/StyleResolver.cpp | 13 +- Userland/Libraries/LibWeb/CSS/StyleValue.h | 30 +++ 6 files changed, 268 insertions(+), 2 deletions(-) create mode 100644 Base/res/html/misc/overflow.html diff --git a/Base/res/html/misc/overflow.html b/Base/res/html/misc/overflow.html new file mode 100644 index 00000000000..60a8e99a16b --- /dev/null +++ b/Base/res/html/misc/overflow.html @@ -0,0 +1,180 @@ + + + + + CSS Overflow Test + + + +

Single-value 'overflow' property

+ +

Overflow: inherit

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: initial

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: auto

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: clip

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: hidden

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: scroll

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: visible

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Two-value 'overflow' property

+ +

Overflow: auto hidden

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: hidden auto

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: scroll clip

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: clip scroll

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Overflow: visible hidden

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

Separate 'overflow-x' / 'overflow-y' property

+ +

overflow-x: auto, overflow-y: hidden

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

overflow-x: hidden, overflow-y: auto

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

overflow-x: scroll, overflow-y: clip

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

overflow-y: scroll

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ +

overflow-x: visible

+
+

Heading extends outside the box!

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+

Hello this is some text

+
+ + diff --git a/Base/res/html/misc/welcome.html b/Base/res/html/misc/welcome.html index d958d22bc21..50f717bc8ee 100644 --- a/Base/res/html/misc/welcome.html +++ b/Base/res/html/misc/welcome.html @@ -105,6 +105,7 @@
  • Floating boxes
  • Floating boxes with overflow=hidden
  • Float clearing
  • +
  • Overflow
  • Features

  • Basic functionality
  • css colors
  • diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 0240cfc3225..6f82f9755b4 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -2503,6 +2503,47 @@ RefPtr Parser::parse_list_style_value(ParsingContext const& context, return ListStyleStyleValue::create(list_position.release_nonnull(), list_image.release_nonnull(), list_type.release_nonnull()); } +RefPtr Parser::parse_overflow_value(ParsingContext const& context, Vector const& component_values) +{ + auto is_overflow = [](StyleValue const& value) -> bool { + switch (value.to_identifier()) { + case ValueID::Auto: + case ValueID::Clip: + case ValueID::Hidden: + case ValueID::Scroll: + case ValueID::Visible: + return true; + default: + return false; + } + }; + + if (component_values.size() == 1) { + auto maybe_value = parse_css_value(context, PropertyID::Overflow, component_values.first()); + if (!maybe_value) + return nullptr; + auto value = maybe_value.release_nonnull(); + if (is_overflow(*value)) + return OverflowStyleValue::create(value, value); + return nullptr; + } + + if (component_values.size() == 2) { + auto maybe_x_value = parse_css_value(context, PropertyID::OverflowX, component_values[0]); + auto maybe_y_value = parse_css_value(context, PropertyID::OverflowY, component_values[1]); + + if (!maybe_x_value || !maybe_y_value) + return nullptr; + auto x_value = maybe_x_value.release_nonnull(); + auto y_value = maybe_y_value.release_nonnull(); + if (!is_overflow(x_value) || !is_overflow(y_value)) + return nullptr; + return OverflowStyleValue::create(x_value, y_value); + } + + return nullptr; +} + RefPtr Parser::parse_text_decoration_value(ParsingContext const& context, Vector const& component_values) { auto is_text_decoration_line = [](StyleValue const& value) -> bool { @@ -2650,6 +2691,10 @@ RefPtr Parser::parse_css_value(PropertyID property_id, TokenStream parse_flex_flow_value(ParsingContext const&, Vector const&); static RefPtr parse_font_value(ParsingContext const&, Vector const&); static RefPtr parse_list_style_value(ParsingContext const&, Vector const&); + static RefPtr parse_overflow_value(ParsingContext const&, Vector const&); static RefPtr parse_text_decoration_value(ParsingContext const&, Vector const&); // calc() parsing, according to https://www.w3.org/TR/css-values-3/#calc-syntax diff --git a/Userland/Libraries/LibWeb/CSS/StyleResolver.cpp b/Userland/Libraries/LibWeb/CSS/StyleResolver.cpp index 669f6842b70..3d6181741fb 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleResolver.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleResolver.cpp @@ -220,8 +220,17 @@ static void set_property_expanding_shorthands(StyleProperties& style, CSS::Prope } if (property_id == CSS::PropertyID::Overflow) { - style.set_property(CSS::PropertyID::OverflowX, value); - style.set_property(CSS::PropertyID::OverflowY, value); + if (value.is_overflow()) { + auto& overflow = static_cast(value); + style.set_property(CSS::PropertyID::OverflowX, overflow.overflow_x()); + style.set_property(CSS::PropertyID::OverflowY, overflow.overflow_y()); + return; + } + if (value.is_builtin()) { + style.set_property(CSS::PropertyID::OverflowX, value); + style.set_property(CSS::PropertyID::OverflowY, value); + return; + } return; } diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 66e1dd3f093..4a190f5e762 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -237,6 +237,7 @@ public: FlexFlow, Font, ListStyle, + Overflow, TextDecoration, }; @@ -262,6 +263,7 @@ public: bool is_flex_flow() const { return type() == Type::FlexFlow; } bool is_font() const { return type() == Type::Font; } bool is_list_style() const { return type() == Type::ListStyle; } + bool is_overflow() const { return type() == Type::Overflow; } bool is_text_decoration() const { return type() == Type::TextDecoration; } bool is_builtin() const { return is_inherit() || is_initial(); } @@ -902,6 +904,34 @@ private: NonnullRefPtr m_style_type; }; +class OverflowStyleValue final : public StyleValue { +public: + static NonnullRefPtr create(NonnullRefPtr overflow_x, NonnullRefPtr overflow_y) + { + return adopt_ref(*new OverflowStyleValue(overflow_x, overflow_y)); + } + virtual ~OverflowStyleValue() override { } + + NonnullRefPtr overflow_x() const { return m_overflow_x; } + NonnullRefPtr overflow_y() const { return m_overflow_y; } + + virtual String to_string() const override + { + return String::formatted("{} {}", m_overflow_x->to_string(), m_overflow_y->to_string()); + } + +private: + OverflowStyleValue(NonnullRefPtr overflow_x, NonnullRefPtr overflow_y) + : StyleValue(Type::Overflow) + , m_overflow_x(overflow_x) + , m_overflow_y(overflow_y) + { + } + + NonnullRefPtr m_overflow_x; + NonnullRefPtr m_overflow_y; +}; + class TextDecorationStyleValue final : public StyleValue { public: static NonnullRefPtr create(