From d2ade9800f205d3cbb01d51af768423a9f1c1d58 Mon Sep 17 00:00:00 2001 From: Sam Atkins Date: Tue, 15 Feb 2022 16:12:22 +0000 Subject: [PATCH] LibWeb: Implement relative lengths in media queries :^) As noted, this is not entirely right, since we are using the computed font's metrics instead of the initial font's metrics, but we do not have a good way to obtain the latter. --- Userland/Libraries/LibWeb/CSS/MediaQuery.cpp | 37 +++++++++++++------- Userland/Libraries/LibWeb/CSS/MediaQuery.h | 2 +- 2 files changed, 25 insertions(+), 14 deletions(-) diff --git a/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp b/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp index 847cd85dd0..83a00ef6ab 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp +++ b/Userland/Libraries/LibWeb/CSS/MediaQuery.cpp @@ -91,20 +91,20 @@ bool MediaFeature::evaluate(DOM::Window const& window) const return false; case Type::ExactValue: - return compare(*m_value, Comparison::Equal, queried_value); + return compare(window, *m_value, Comparison::Equal, queried_value); case Type::MinValue: - return compare(queried_value, Comparison::GreaterThanOrEqual, *m_value); + return compare(window, queried_value, Comparison::GreaterThanOrEqual, *m_value); case Type::MaxValue: - return compare(queried_value, Comparison::LessThanOrEqual, *m_value); + return compare(window, queried_value, Comparison::LessThanOrEqual, *m_value); case Type::Range: - if (!compare(m_range->left_value, m_range->left_comparison, queried_value)) + if (!compare(window, m_range->left_value, m_range->left_comparison, queried_value)) return false; if (m_range->right_comparison.has_value()) - if (!compare(queried_value, *m_range->right_comparison, *m_range->right_value)) + if (!compare(window, queried_value, *m_range->right_comparison, *m_range->right_value)) return false; return true; @@ -113,7 +113,7 @@ bool MediaFeature::evaluate(DOM::Window const& window) const VERIFY_NOT_REACHED(); } -bool MediaFeature::compare(MediaFeatureValue left, Comparison comparison, MediaFeatureValue right) +bool MediaFeature::compare(DOM::Window const& window, MediaFeatureValue left, Comparison comparison, MediaFeatureValue right) { if (!left.is_same_type(right)) return false; @@ -141,14 +141,25 @@ bool MediaFeature::compare(MediaFeatureValue left, Comparison comparison, MediaF } if (left.is_length()) { - // FIXME: Handle relative lengths. https://www.w3.org/TR/mediaqueries-4/#ref-for-relative-length - if (!left.length().is_absolute() || !right.length().is_absolute()) { - dbgln("TODO: Support relative lengths in media queries!"); - return false; - } - auto left_px = left.length().absolute_length_to_px(); - auto right_px = right.length().absolute_length_to_px(); + float left_px; + float right_px; + // Save ourselves some work if neither side is a relative length. + if (left.length().is_absolute() && right.length().is_absolute()) { + left_px = left.length().absolute_length_to_px(); + right_px = right.length().absolute_length_to_px(); + } else { + Gfx::IntRect viewport_rect { 0, 0, window.inner_width(), window.inner_height() }; + + // FIXME: This isn't right - we want to query the initial-value font, which is the one used + // if no author styles are defined. + auto const& font = window.associated_document().root().layout_node()->font(); + Gfx::FontMetrics const& font_metrics = font.metrics('M'); + float root_font_size = font.presentation_size(); + + left_px = left.length().to_px(viewport_rect, font_metrics, root_font_size); + right_px = right.length().to_px(viewport_rect, font_metrics, root_font_size); + } switch (comparison) { case Comparison::Equal: diff --git a/Userland/Libraries/LibWeb/CSS/MediaQuery.h b/Userland/Libraries/LibWeb/CSS/MediaQuery.h index 73581c6b68..ed8adbfa43 100644 --- a/Userland/Libraries/LibWeb/CSS/MediaQuery.h +++ b/Userland/Libraries/LibWeb/CSS/MediaQuery.h @@ -135,7 +135,7 @@ private: { } - static bool compare(MediaFeatureValue left, Comparison comparison, MediaFeatureValue right); + static bool compare(DOM::Window const& window, MediaFeatureValue left, Comparison comparison, MediaFeatureValue right); struct Range { MediaFeatureValue left_value;