1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-24 15:17:45 +00:00

LibWeb: Use MediaFeatureIDs instead of Strings :^)

This commit is contained in:
Sam Atkins 2022-03-08 16:51:33 +00:00 committed by Andreas Kling
parent b7bb86462b
commit 12561327d6
5 changed files with 85 additions and 55 deletions

View file

@ -60,18 +60,18 @@ String MediaFeature::to_string() const
switch (m_type) { switch (m_type) {
case Type::IsTrue: case Type::IsTrue:
return serialize_an_identifier(m_name); return string_from_media_feature_id(m_id);
case Type::ExactValue: case Type::ExactValue:
return String::formatted("{}:{}", serialize_an_identifier(m_name), m_value->to_string()); return String::formatted("{}:{}", string_from_media_feature_id(m_id), m_value->to_string());
case Type::MinValue: case Type::MinValue:
return String::formatted("min-{}:{}", serialize_an_identifier(m_name), m_value->to_string()); return String::formatted("min-{}:{}", string_from_media_feature_id(m_id), m_value->to_string());
case Type::MaxValue: case Type::MaxValue:
return String::formatted("max-{}:{}", serialize_an_identifier(m_name), m_value->to_string()); return String::formatted("max-{}:{}", string_from_media_feature_id(m_id), m_value->to_string());
case Type::Range: case Type::Range:
if (!m_range->right_comparison.has_value()) if (!m_range->right_comparison.has_value())
return String::formatted("{} {} {}", m_range->left_value.to_string(), comparison_string(m_range->left_comparison), serialize_an_identifier(m_name)); return String::formatted("{} {} {}", m_range->left_value.to_string(), comparison_string(m_range->left_comparison), string_from_media_feature_id(m_id));
return String::formatted("{} {} {} {} {}", m_range->left_value.to_string(), comparison_string(m_range->left_comparison), serialize_an_identifier(m_name), comparison_string(*m_range->right_comparison), m_range->right_value->to_string()); return String::formatted("{} {} {} {} {}", m_range->left_value.to_string(), comparison_string(m_range->left_comparison), string_from_media_feature_id(m_id), comparison_string(*m_range->right_comparison), m_range->right_value->to_string());
} }
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
@ -79,7 +79,7 @@ String MediaFeature::to_string() const
bool MediaFeature::evaluate(HTML::Window const& window) const bool MediaFeature::evaluate(HTML::Window const& window) const
{ {
auto maybe_queried_value = window.query_media_feature(m_name); auto maybe_queried_value = window.query_media_feature(m_id);
if (!maybe_queried_value.has_value()) if (!maybe_queried_value.has_value())
return false; return false;
auto queried_value = maybe_queried_value.release_value(); auto queried_value = maybe_queried_value.release_value();

View file

@ -13,6 +13,7 @@
#include <AK/OwnPtr.h> #include <AK/OwnPtr.h>
#include <AK/RefCounted.h> #include <AK/RefCounted.h>
#include <LibWeb/CSS/GeneralEnclosed.h> #include <LibWeb/CSS/GeneralEnclosed.h>
#include <LibWeb/CSS/MediaFeatureID.h>
#include <LibWeb/CSS/Ratio.h> #include <LibWeb/CSS/Ratio.h>
#include <LibWeb/CSS/StyleValue.h> #include <LibWeb/CSS/StyleValue.h>
@ -101,25 +102,29 @@ public:
}; };
// Corresponds to `<mf-boolean>` grammar // Corresponds to `<mf-boolean>` grammar
static MediaFeature boolean(String const& name) static MediaFeature boolean(MediaFeatureID id)
{ {
return MediaFeature(Type::IsTrue, name); return MediaFeature(Type::IsTrue, id);
} }
// Corresponds to `<mf-plain>` grammar // Corresponds to `<mf-plain>` grammar
static MediaFeature plain(String const& name, MediaFeatureValue value) static MediaFeature plain(MediaFeatureID id, MediaFeatureValue value)
{ {
if (name.starts_with("min-", CaseSensitivity::CaseInsensitive)) return MediaFeature(Type::ExactValue, move(id), move(value));
return MediaFeature(Type::MinValue, name.substring_view(4), move(value)); }
if (name.starts_with("max-", CaseSensitivity::CaseInsensitive)) static MediaFeature min(MediaFeatureID id, MediaFeatureValue value)
return MediaFeature(Type::MaxValue, name.substring_view(4), move(value)); {
return MediaFeature(Type::ExactValue, move(name), move(value)); return MediaFeature(Type::MinValue, id, move(value));
}
static MediaFeature max(MediaFeatureID id, MediaFeatureValue value)
{
return MediaFeature(Type::MaxValue, id, move(value));
} }
// Corresponds to `<mf-range>` grammar, with a single comparison // Corresponds to `<mf-range>` grammar, with a single comparison
static MediaFeature half_range(MediaFeatureValue value, Comparison comparison, String const& name) static MediaFeature half_range(MediaFeatureValue value, Comparison comparison, MediaFeatureID id)
{ {
MediaFeature feature { Type::Range, name }; MediaFeature feature { Type::Range, id };
feature.m_range = Range { feature.m_range = Range {
.left_value = value, .left_value = value,
.left_comparison = comparison, .left_comparison = comparison,
@ -128,9 +133,9 @@ public:
} }
// Corresponds to `<mf-range>` grammar, with two comparisons // Corresponds to `<mf-range>` grammar, with two comparisons
static MediaFeature range(MediaFeatureValue left_value, Comparison left_comparison, String const& name, Comparison right_comparison, MediaFeatureValue right_value) static MediaFeature range(MediaFeatureValue left_value, Comparison left_comparison, MediaFeatureID id, Comparison right_comparison, MediaFeatureValue right_value)
{ {
MediaFeature feature { Type::Range, name }; MediaFeature feature { Type::Range, id };
feature.m_range = Range { feature.m_range = Range {
.left_value = left_value, .left_value = left_value,
.left_comparison = left_comparison, .left_comparison = left_comparison,
@ -152,9 +157,9 @@ private:
Range, Range,
}; };
MediaFeature(Type type, FlyString name, Optional<MediaFeatureValue> value = {}) MediaFeature(Type type, MediaFeatureID id, Optional<MediaFeatureValue> value = {})
: m_type(type) : m_type(type)
, m_name(move(name)) , m_id(move(id))
, m_value(move(value)) , m_value(move(value))
{ {
} }
@ -169,7 +174,7 @@ private:
}; };
Type m_type; Type m_type;
FlyString m_name; MediaFeatureID m_id;
Optional<MediaFeatureValue> m_value {}; Optional<MediaFeatureValue> m_value {};
Optional<Range> m_range {}; Optional<Range> m_range {};
}; };

View file

@ -877,20 +877,31 @@ Optional<MediaFeature> Parser::parse_media_feature(TokenStream<StyleComponentVal
tokens.skip_whitespace(); tokens.skip_whitespace();
// `<mf-name> = <ident>` // `<mf-name> = <ident>`
auto parse_mf_name = [](auto& tokens, bool allow_min_max_prefix) -> Optional<String> { struct MediaFeatureName {
enum Type {
Normal,
Min,
Max
} type;
MediaFeatureID id;
};
auto parse_mf_name = [](auto& tokens, bool allow_min_max_prefix) -> Optional<MediaFeatureName> {
auto& token = tokens.peek_token(); auto& token = tokens.peek_token();
if (token.is(Token::Type::Ident)) { if (token.is(Token::Type::Ident)) {
auto name = token.token().ident(); auto name = token.token().ident();
if (is_media_feature_name(name)) { if (auto id = media_feature_id_from_string(name); id.has_value()) {
tokens.next_token(); tokens.next_token();
return name; return MediaFeatureName { MediaFeatureName::Type::Normal, id.value() };
} }
if (allow_min_max_prefix && (name.starts_with("min-", CaseSensitivity::CaseInsensitive) || name.starts_with("max-", CaseSensitivity::CaseInsensitive))) { if (allow_min_max_prefix && (name.starts_with("min-", CaseSensitivity::CaseInsensitive) || name.starts_with("max-", CaseSensitivity::CaseInsensitive))) {
auto adjusted_name = name.substring_view(4); auto adjusted_name = name.substring_view(4);
if (is_media_feature_name(adjusted_name)) { if (auto id = media_feature_id_from_string(adjusted_name); id.has_value()) {
tokens.next_token(); tokens.next_token();
return name; return MediaFeatureName {
name.starts_with("min-", CaseSensitivity::CaseInsensitive) ? MediaFeatureName::Type::Min : MediaFeatureName::Type::Max,
id.value()
};
} }
} }
} }
@ -902,11 +913,10 @@ Optional<MediaFeature> Parser::parse_media_feature(TokenStream<StyleComponentVal
auto position = tokens.position(); auto position = tokens.position();
tokens.skip_whitespace(); tokens.skip_whitespace();
auto maybe_name = parse_mf_name(tokens, false); if (auto maybe_name = parse_mf_name(tokens, false); maybe_name.has_value()) {
if (maybe_name.has_value()) {
tokens.skip_whitespace(); tokens.skip_whitespace();
if (!tokens.has_next_token()) if (!tokens.has_next_token())
return MediaFeature::boolean(maybe_name.release_value()); return MediaFeature::boolean(maybe_name->id);
} }
tokens.rewind_to_position(position); tokens.rewind_to_position(position);
@ -924,8 +934,17 @@ Optional<MediaFeature> Parser::parse_media_feature(TokenStream<StyleComponentVal
tokens.skip_whitespace(); tokens.skip_whitespace();
if (auto maybe_value = parse_media_feature_value(tokens); maybe_value.has_value()) { if (auto maybe_value = parse_media_feature_value(tokens); maybe_value.has_value()) {
tokens.skip_whitespace(); tokens.skip_whitespace();
if (!tokens.has_next_token()) if (!tokens.has_next_token()) {
return MediaFeature::plain(maybe_name.release_value(), maybe_value.release_value()); switch (maybe_name->type) {
case MediaFeatureName::Type::Normal:
return MediaFeature::plain(maybe_name->id, maybe_value.release_value());
case MediaFeatureName::Type::Min:
return MediaFeature::min(maybe_name->id, maybe_value.release_value());
case MediaFeatureName::Type::Max:
return MediaFeature::max(maybe_name->id, maybe_value.release_value());
}
VERIFY_NOT_REACHED();
}
} }
} }
} }
@ -1016,7 +1035,7 @@ Optional<MediaFeature> Parser::parse_media_feature(TokenStream<StyleComponentVal
if (auto maybe_value = parse_media_feature_value(tokens); maybe_value.has_value()) { if (auto maybe_value = parse_media_feature_value(tokens); maybe_value.has_value()) {
tokens.skip_whitespace(); tokens.skip_whitespace();
if (!tokens.has_next_token() && !maybe_value->is_ident()) if (!tokens.has_next_token() && !maybe_value->is_ident())
return MediaFeature::half_range(maybe_value.release_value(), flip(maybe_comparison.release_value()), maybe_name.release_value()); return MediaFeature::half_range(maybe_value.release_value(), flip(maybe_comparison.release_value()), maybe_name->id);
} }
} }
} }
@ -1032,7 +1051,7 @@ Optional<MediaFeature> Parser::parse_media_feature(TokenStream<StyleComponentVal
tokens.skip_whitespace(); tokens.skip_whitespace();
if (!tokens.has_next_token()) if (!tokens.has_next_token())
return MediaFeature::half_range(maybe_left_value.release_value(), maybe_left_comparison.release_value(), maybe_name.release_value()); return MediaFeature::half_range(maybe_left_value.release_value(), maybe_left_comparison.release_value(), maybe_name->id);
if (auto maybe_right_comparison = parse_comparison(tokens); maybe_right_comparison.has_value()) { if (auto maybe_right_comparison = parse_comparison(tokens); maybe_right_comparison.has_value()) {
tokens.skip_whitespace(); tokens.skip_whitespace();
@ -1049,7 +1068,7 @@ Optional<MediaFeature> Parser::parse_media_feature(TokenStream<StyleComponentVal
&& comparisons_match(left_comparison, right_comparison) && comparisons_match(left_comparison, right_comparison)
&& left_comparison != MediaFeature::Comparison::Equal && left_comparison != MediaFeature::Comparison::Equal
&& !maybe_left_value->is_ident() && !maybe_right_value->is_ident()) { && !maybe_left_value->is_ident() && !maybe_right_value->is_ident()) {
return MediaFeature::range(maybe_left_value.release_value(), left_comparison, maybe_name.release_value(), right_comparison, maybe_right_value.release_value()); return MediaFeature::range(maybe_left_value.release_value(), left_comparison, maybe_name->id, right_comparison, maybe_right_value.release_value());
} }
} }
} }

View file

@ -372,52 +372,53 @@ NonnullRefPtr<CSS::MediaQueryList> Window::match_media(String media)
return media_query_list; return media_query_list;
} }
Optional<CSS::MediaFeatureValue> Window::query_media_feature(FlyString const& name) const Optional<CSS::MediaFeatureValue> Window::query_media_feature(CSS::MediaFeatureID media_feature) const
{ {
// FIXME: Many of these should be dependent on the hardware // FIXME: Many of these should be dependent on the hardware
// MEDIAQUERIES-4 properties - https://www.w3.org/TR/mediaqueries-4/#media-descriptor-table // MEDIAQUERIES-4 properties - https://www.w3.org/TR/mediaqueries-4/#media-descriptor-table
if (name.equals_ignoring_case("any-hover"sv)) switch (media_feature) {
case CSS::MediaFeatureID::AnyHover:
return CSS::MediaFeatureValue("hover"); return CSS::MediaFeatureValue("hover");
if (name.equals_ignoring_case("any-pointer"sv)) case CSS::MediaFeatureID::AnyPointer:
return CSS::MediaFeatureValue("fine"); return CSS::MediaFeatureValue("fine");
if (name.equals_ignoring_case("aspect-ratio"sv)) case CSS::MediaFeatureID::AspectRatio:
return CSS::MediaFeatureValue(CSS::Ratio(inner_width(), inner_height())); return CSS::MediaFeatureValue(CSS::Ratio(inner_width(), inner_height()));
if (name.equals_ignoring_case("color"sv)) case CSS::MediaFeatureID::Color:
return CSS::MediaFeatureValue(8); return CSS::MediaFeatureValue(8);
if (name.equals_ignoring_case("color-gamut"sv)) case CSS::MediaFeatureID::ColorGamut:
return CSS::MediaFeatureValue("srgb"); return CSS::MediaFeatureValue("srgb");
if (name.equals_ignoring_case("color-index"sv)) case CSS::MediaFeatureID::ColorIndex:
return CSS::MediaFeatureValue(0); return CSS::MediaFeatureValue(0);
// FIXME: device-aspect-ratio // FIXME: device-aspect-ratio
// FIXME: device-height // FIXME: device-height
// FIXME: device-width // FIXME: device-width
if (name.equals_ignoring_case("grid"sv)) case CSS::MediaFeatureID::Grid:
return CSS::MediaFeatureValue(0); return CSS::MediaFeatureValue(0);
if (name.equals_ignoring_case("height"sv)) case CSS::MediaFeatureID::Height:
return CSS::MediaFeatureValue(CSS::Length::make_px(inner_height())); return CSS::MediaFeatureValue(CSS::Length::make_px(inner_height()));
if (name.equals_ignoring_case("hover"sv)) case CSS::MediaFeatureID::Hover:
return CSS::MediaFeatureValue("hover"); return CSS::MediaFeatureValue("hover");
if (name.equals_ignoring_case("monochrome"sv)) case CSS::MediaFeatureID::Monochrome:
return CSS::MediaFeatureValue(0); return CSS::MediaFeatureValue(0);
if (name.equals_ignoring_case("orientation"sv)) case CSS::MediaFeatureID::Orientation:
return CSS::MediaFeatureValue(inner_height() >= inner_width() ? "portrait" : "landscape"); return CSS::MediaFeatureValue(inner_height() >= inner_width() ? "portrait" : "landscape");
if (name.equals_ignoring_case("overflow-block"sv)) case CSS::MediaFeatureID::OverflowBlock:
return CSS::MediaFeatureValue("scroll"); return CSS::MediaFeatureValue("scroll");
if (name.equals_ignoring_case("overflow-inline"sv)) case CSS::MediaFeatureID::OverflowInline:
return CSS::MediaFeatureValue("scroll"); return CSS::MediaFeatureValue("scroll");
if (name.equals_ignoring_case("pointer"sv)) case CSS::MediaFeatureID::Pointer:
return CSS::MediaFeatureValue("fine"); return CSS::MediaFeatureValue("fine");
// FIXME: resolution // FIXME: resolution
if (name.equals_ignoring_case("scan"sv)) case CSS::MediaFeatureID::Scan:
return CSS::MediaFeatureValue("progressive"); return CSS::MediaFeatureValue("progressive");
if (name.equals_ignoring_case("update"sv)) case CSS::MediaFeatureID::Update:
return CSS::MediaFeatureValue("fast"); return CSS::MediaFeatureValue("fast");
if (name.equals_ignoring_case("width"sv)) case CSS::MediaFeatureID::Width:
return CSS::MediaFeatureValue(CSS::Length::make_px(inner_width())); return CSS::MediaFeatureValue(CSS::Length::make_px(inner_width()));
// MEDIAQUERIES-5 properties - https://www.w3.org/TR/mediaqueries-5/#media-descriptor-table // MEDIAQUERIES-5 properties - https://www.w3.org/TR/mediaqueries-5/#media-descriptor-table
if (name.equals_ignoring_case("prefers-color-scheme")) { case CSS::MediaFeatureID::PrefersColorScheme: {
if (auto* page = this->page()) { if (auto* page = this->page()) {
switch (page->preferred_color_scheme()) { switch (page->preferred_color_scheme()) {
case CSS::PreferredColorScheme::Light: case CSS::PreferredColorScheme::Light:
@ -429,6 +430,11 @@ Optional<CSS::MediaFeatureValue> Window::query_media_feature(FlyString const& na
return CSS::MediaFeatureValue(page->palette().is_dark() ? "dark" : "light"); return CSS::MediaFeatureValue(page->palette().is_dark() ? "dark" : "light");
} }
} }
return CSS::MediaFeatureValue(CSS::ValueID::Light);
}
default:
break;
} }
return {}; return {};

View file

@ -89,7 +89,7 @@ public:
NonnullRefPtr<CSS::CSSStyleDeclaration> get_computed_style(DOM::Element&) const; NonnullRefPtr<CSS::CSSStyleDeclaration> get_computed_style(DOM::Element&) const;
NonnullRefPtr<CSS::MediaQueryList> match_media(String); NonnullRefPtr<CSS::MediaQueryList> match_media(String);
Optional<CSS::MediaFeatureValue> query_media_feature(FlyString const&) const; Optional<CSS::MediaFeatureValue> query_media_feature(CSS::MediaFeatureID) const;
float scroll_x() const; float scroll_x() const;
float scroll_y() const; float scroll_y() const;