From dcc2c8a12545762746d2f14a3cb4781c7b75b9d1 Mon Sep 17 00:00:00 2001 From: Jakob-Niklas See Date: Tue, 8 Sep 2020 20:39:09 +0200 Subject: [PATCH] LibWeb: Add support for viewport-relative length units (#3433) We can now use vh, vw, vmax and vmin as length units in CSS. --- Libraries/LibWeb/CSS/Length.cpp | 23 +++++++++++++++++++++++ Libraries/LibWeb/CSS/Length.h | 15 ++++++++++++++- Libraries/LibWeb/CSS/Parser/CSSParser.cpp | 12 ++++++++++++ 3 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Libraries/LibWeb/CSS/Length.cpp b/Libraries/LibWeb/CSS/Length.cpp index 2df30f1a38..154d3a19b1 100644 --- a/Libraries/LibWeb/CSS/Length.cpp +++ b/Libraries/LibWeb/CSS/Length.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace Web::CSS { @@ -39,6 +40,20 @@ float Length::relative_length_to_px(const LayoutNode& layout_node) const return m_value * layout_node.font_size(); case Type::Rem: return m_value * layout_node.document().document_element()->layout_node()->font_size(); + case Type::Vw: + return layout_node.document().frame()->viewport_rect().width() * (m_value / 100); + case Type::Vh: + return layout_node.document().frame()->viewport_rect().height() * (m_value / 100); + case Type::Vmin: { + auto viewport = layout_node.document().frame()->viewport_rect(); + + return min(viewport.width(), viewport.height()) * (m_value / 100); + } + case Type::Vmax: { + auto viewport = layout_node.document().frame()->viewport_rect(); + + return max(viewport.width(), viewport.height()) * (m_value / 100); + } default: ASSERT_NOT_REACHED(); } @@ -63,6 +78,14 @@ const char* Length::unit_name() const return "%"; case Type::Undefined: return "undefined"; + case Type::Vh: + return "vh"; + case Type::Vw: + return "vw"; + case Type::Vmax: + return "vmax"; + case Type::Vmin: + return "vmin"; } ASSERT_NOT_REACHED(); } diff --git a/Libraries/LibWeb/CSS/Length.h b/Libraries/LibWeb/CSS/Length.h index 38efb16b4d..9ed6a696ab 100644 --- a/Libraries/LibWeb/CSS/Length.h +++ b/Libraries/LibWeb/CSS/Length.h @@ -42,6 +42,10 @@ public: Ex, Em, Rem, + Vh, + Vw, + Vmax, + Vmin, }; Length() { } @@ -85,7 +89,16 @@ public: bool is_percentage() const { return m_type == Type::Percentage; } bool is_auto() const { return m_type == Type::Auto; } bool is_absolute() const { return m_type == Type::Px || m_type == Type::Pt; } - bool is_relative() const { return m_type == Type::Ex || m_type == Type::Em || m_type == Type::Rem; } + bool is_relative() const + { + return m_type == Type::Ex + || m_type == Type::Em + || m_type == Type::Rem + || m_type == Type::Vh + || m_type == Type::Vw + || m_type == Type::Vmax + || m_type == Type::Vmin; + } float raw_value() const { return m_value; } ALWAYS_INLINE float to_px(const LayoutNode& layout_node) const diff --git a/Libraries/LibWeb/CSS/Parser/CSSParser.cpp b/Libraries/LibWeb/CSS/Parser/CSSParser.cpp index 0a9dd97adc..60883cf35b 100644 --- a/Libraries/LibWeb/CSS/Parser/CSSParser.cpp +++ b/Libraries/LibWeb/CSS/Parser/CSSParser.cpp @@ -292,6 +292,18 @@ static CSS::Length parse_length(const CSS::ParsingContext& context, const String } else if (view.ends_with("ex", CaseSensitivity::CaseInsensitive)) { type = CSS::Length::Type::Ex; value = try_parse_float(view.substring_view(0, view.length() - 2)); + } else if (view.ends_with("vw", CaseSensitivity::CaseInsensitive)) { + type = CSS::Length::Type::Vw; + value = try_parse_float(view.substring_view(0, view.length() - 2)); + } else if (view.ends_with("vh", CaseSensitivity::CaseInsensitive)) { + type = CSS::Length::Type::Vh; + value = try_parse_float(view.substring_view(0, view.length() - 2)); + } else if (view.ends_with("vmax", CaseSensitivity::CaseInsensitive)) { + type = CSS::Length::Type::Vmax; + value = try_parse_float(view.substring_view(0, view.length() - 4)); + } else if (view.ends_with("vmin", CaseSensitivity::CaseInsensitive)) { + type = CSS::Length::Type::Vmin; + value = try_parse_float(view.substring_view(0, view.length() - 4)); } else if (view == "0") { type = CSS::Length::Type::Px; value = 0;