mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-15 23:09:05 +00:00
LibWeb/CSS: Allow calc() values in media queries
It was initially thought that the spec disallows them, but this turned out to be incorrect. This fixes several WPT tests.
This commit is contained in:
parent
ad3dd547b7
commit
8bec80ac47
Notes:
github-actions[bot]
2024-12-04 12:39:02 +00:00
Author: https://github.com/milotier
Commit: 8bec80ac47
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/2640
Reviewed-by: https://github.com/AtkinsSJ ✅
20 changed files with 439 additions and 52 deletions
|
@ -52,6 +52,13 @@ i64 IntegerOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue> const& c
|
||||||
return calculated->resolve_integer().value();
|
return calculated->resolve_integer().value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
i64 IntegerOrCalculated::resolved() const
|
||||||
|
{
|
||||||
|
if (is_calculated())
|
||||||
|
return calculated()->resolve_integer().value();
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> IntegerOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> IntegerOrCalculated::create_style_value() const
|
||||||
{
|
{
|
||||||
return IntegerStyleValue::create(value());
|
return IntegerStyleValue::create(value());
|
||||||
|
@ -99,6 +106,13 @@ Resolution ResolutionOrCalculated::resolve_calculated(NonnullRefPtr<CSSMathValue
|
||||||
return calculated->resolve_resolution().value();
|
return calculated->resolve_resolution().value();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Resolution ResolutionOrCalculated::resolved() const
|
||||||
|
{
|
||||||
|
if (is_calculated())
|
||||||
|
return calculated()->resolve_resolution().value();
|
||||||
|
return value();
|
||||||
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> ResolutionOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> ResolutionOrCalculated::create_style_value() const
|
||||||
{
|
{
|
||||||
return ResolutionStyleValue::create(value());
|
return ResolutionStyleValue::create(value());
|
||||||
|
|
|
@ -119,6 +119,8 @@ class IntegerOrCalculated : public CalculatedOr<i64> {
|
||||||
public:
|
public:
|
||||||
using CalculatedOr<i64>::CalculatedOr;
|
using CalculatedOr<i64>::CalculatedOr;
|
||||||
|
|
||||||
|
[[nodiscard]] i64 resolved() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual i64 resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
|
virtual i64 resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
|
@ -157,6 +159,8 @@ class ResolutionOrCalculated : public CalculatedOr<Resolution> {
|
||||||
public:
|
public:
|
||||||
using CalculatedOr<Resolution>::CalculatedOr;
|
using CalculatedOr<Resolution>::CalculatedOr;
|
||||||
|
|
||||||
|
[[nodiscard]] Resolution resolved() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Resolution resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
|
virtual Resolution resolve_calculated(NonnullRefPtr<CSSMathValue> const&, Layout::Node const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <LibWeb/DOM/Document.h>
|
#include <LibWeb/DOM/Document.h>
|
||||||
#include <LibWeb/HTML/BrowsingContext.h>
|
#include <LibWeb/HTML/BrowsingContext.h>
|
||||||
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
#include <LibWeb/HTML/HTMLHtmlElement.h>
|
||||||
|
#include <LibWeb/HTML/Window.h>
|
||||||
#include <LibWeb/Layout/Node.h>
|
#include <LibWeb/Layout/Node.h>
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
@ -131,6 +132,18 @@ CSSPixels Length::viewport_relative_length_to_px(CSSPixelRect const& viewport_re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Length::ResolutionContext Length::ResolutionContext::for_window(HTML::Window const& window)
|
||||||
|
{
|
||||||
|
auto const& initial_font = window.associated_document().style_computer().initial_font();
|
||||||
|
Gfx::FontPixelMetrics const& initial_font_metrics = initial_font.pixel_metrics();
|
||||||
|
Length::FontMetrics font_metrics { CSSPixels { initial_font.pixel_size() }, initial_font_metrics };
|
||||||
|
return Length::ResolutionContext {
|
||||||
|
.viewport_rect = window.page().web_exposed_screen_area(),
|
||||||
|
.font_metrics = font_metrics,
|
||||||
|
.root_font_metrics = font_metrics,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Node const& node)
|
Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Node const& node)
|
||||||
{
|
{
|
||||||
auto const* root_element = node.document().document_element();
|
auto const* root_element = node.document().document_element();
|
||||||
|
|
|
@ -158,6 +158,7 @@ public:
|
||||||
StringView unit_name() const;
|
StringView unit_name() const;
|
||||||
|
|
||||||
struct ResolutionContext {
|
struct ResolutionContext {
|
||||||
|
[[nodiscard]] static Length::ResolutionContext for_window(HTML::Window const&);
|
||||||
[[nodiscard]] static Length::ResolutionContext for_layout_node(Layout::Node const&);
|
[[nodiscard]] static Length::ResolutionContext for_layout_node(Layout::Node const&);
|
||||||
|
|
||||||
CSSPixelRect viewport_rect;
|
CSSPixelRect viewport_rect;
|
||||||
|
|
|
@ -26,20 +26,24 @@ String MediaFeatureValue::to_string() const
|
||||||
{
|
{
|
||||||
return m_value.visit(
|
return m_value.visit(
|
||||||
[](Keyword const& ident) { return MUST(String::from_utf8(string_from_keyword(ident))); },
|
[](Keyword const& ident) { return MUST(String::from_utf8(string_from_keyword(ident))); },
|
||||||
[](Length const& length) { return length.to_string(); },
|
[](LengthOrCalculated const& length) { return length.to_string(); },
|
||||||
[](Ratio const& ratio) { return ratio.to_string(); },
|
[](Ratio const& ratio) { return ratio.to_string(); },
|
||||||
[](Resolution const& resolution) { return resolution.to_string(); },
|
[](ResolutionOrCalculated const& resolution) { return resolution.to_string(); },
|
||||||
[](float number) { return String::number(number); });
|
[](IntegerOrCalculated const& integer) {
|
||||||
|
if (integer.is_calculated())
|
||||||
|
return integer.calculated()->to_string();
|
||||||
|
return String::number(integer.value());
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool MediaFeatureValue::is_same_type(MediaFeatureValue const& other) const
|
bool MediaFeatureValue::is_same_type(MediaFeatureValue const& other) const
|
||||||
{
|
{
|
||||||
return m_value.visit(
|
return m_value.visit(
|
||||||
[&](Keyword const&) { return other.is_ident(); },
|
[&](Keyword const&) { return other.is_ident(); },
|
||||||
[&](Length const&) { return other.is_length(); },
|
[&](LengthOrCalculated const&) { return other.is_length(); },
|
||||||
[&](Ratio const&) { return other.is_ratio(); },
|
[&](Ratio const&) { return other.is_ratio(); },
|
||||||
[&](Resolution const&) { return other.is_resolution(); },
|
[&](ResolutionOrCalculated const&) { return other.is_resolution(); },
|
||||||
[&](float) { return other.is_number(); });
|
[&](IntegerOrCalculated const&) { return other.is_integer(); });
|
||||||
}
|
}
|
||||||
|
|
||||||
String MediaFeature::to_string() const
|
String MediaFeature::to_string() const
|
||||||
|
@ -88,15 +92,18 @@ bool MediaFeature::evaluate(HTML::Window const& window) const
|
||||||
|
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case Type::IsTrue:
|
case Type::IsTrue:
|
||||||
if (queried_value.is_number())
|
if (queried_value.is_integer())
|
||||||
return queried_value.number() != 0;
|
return queried_value.integer().resolved() != 0;
|
||||||
if (queried_value.is_length())
|
if (queried_value.is_length()) {
|
||||||
return queried_value.length().raw_value() != 0;
|
auto resolution_context = Length::ResolutionContext::for_window(window);
|
||||||
|
auto length = queried_value.length().resolved(resolution_context);
|
||||||
|
return length.raw_value() != 0;
|
||||||
|
}
|
||||||
// FIXME: I couldn't figure out from the spec how ratios should be evaluated in a boolean context.
|
// FIXME: I couldn't figure out from the spec how ratios should be evaluated in a boolean context.
|
||||||
if (queried_value.is_ratio())
|
if (queried_value.is_ratio())
|
||||||
return !queried_value.ratio().is_degenerate();
|
return !queried_value.ratio().is_degenerate();
|
||||||
if (queried_value.is_resolution())
|
if (queried_value.is_resolution())
|
||||||
return queried_value.resolution().to_dots_per_pixel() != 0;
|
return queried_value.resolution().resolved().to_dots_per_pixel() != 0;
|
||||||
if (queried_value.is_ident()) {
|
if (queried_value.is_ident()) {
|
||||||
// NOTE: It is not technically correct to always treat `no-preference` as false, but every
|
// NOTE: It is not technically correct to always treat `no-preference` as false, but every
|
||||||
// media-feature that accepts it as a value treats it as false, so good enough. :^)
|
// media-feature that accepts it as a value treats it as false, so good enough. :^)
|
||||||
|
@ -141,18 +148,18 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left.is_number()) {
|
if (left.is_integer()) {
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
case Comparison::Equal:
|
case Comparison::Equal:
|
||||||
return left.number() == right.number();
|
return left.integer().resolved() == right.integer().resolved();
|
||||||
case Comparison::LessThan:
|
case Comparison::LessThan:
|
||||||
return left.number() < right.number();
|
return left.integer().resolved() < right.integer().resolved();
|
||||||
case Comparison::LessThanOrEqual:
|
case Comparison::LessThanOrEqual:
|
||||||
return left.number() <= right.number();
|
return left.integer().resolved() <= right.integer().resolved();
|
||||||
case Comparison::GreaterThan:
|
case Comparison::GreaterThan:
|
||||||
return left.number() > right.number();
|
return left.integer().resolved() > right.integer().resolved();
|
||||||
case Comparison::GreaterThanOrEqual:
|
case Comparison::GreaterThanOrEqual:
|
||||||
return left.number() >= right.number();
|
return left.integer().resolved() >= right.integer().resolved();
|
||||||
}
|
}
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -160,10 +167,13 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
|
||||||
if (left.is_length()) {
|
if (left.is_length()) {
|
||||||
CSSPixels left_px;
|
CSSPixels left_px;
|
||||||
CSSPixels right_px;
|
CSSPixels right_px;
|
||||||
|
auto resolution_context = Length::ResolutionContext::for_window(window);
|
||||||
|
auto left_length = left.length().resolved(resolution_context);
|
||||||
|
auto right_length = right.length().resolved(resolution_context);
|
||||||
// Save ourselves some work if neither side is a relative length.
|
// Save ourselves some work if neither side is a relative length.
|
||||||
if (left.length().is_absolute() && right.length().is_absolute()) {
|
if (left_length.is_absolute() && right_length.is_absolute()) {
|
||||||
left_px = left.length().absolute_length_to_px();
|
left_px = left_length.absolute_length_to_px();
|
||||||
right_px = right.length().absolute_length_to_px();
|
right_px = right_length.absolute_length_to_px();
|
||||||
} else {
|
} else {
|
||||||
auto viewport_rect = window.page().web_exposed_screen_area();
|
auto viewport_rect = window.page().web_exposed_screen_area();
|
||||||
|
|
||||||
|
@ -171,8 +181,8 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
|
||||||
Gfx::FontPixelMetrics const& initial_font_metrics = initial_font.pixel_metrics();
|
Gfx::FontPixelMetrics const& initial_font_metrics = initial_font.pixel_metrics();
|
||||||
Length::FontMetrics font_metrics { CSSPixels { initial_font.point_size() }, initial_font_metrics };
|
Length::FontMetrics font_metrics { CSSPixels { initial_font.point_size() }, initial_font_metrics };
|
||||||
|
|
||||||
left_px = left.length().to_px(viewport_rect, font_metrics, font_metrics);
|
left_px = left_length.to_px(viewport_rect, font_metrics, font_metrics);
|
||||||
right_px = right.length().to_px(viewport_rect, font_metrics, font_metrics);
|
right_px = right_length.to_px(viewport_rect, font_metrics, font_metrics);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
|
@ -211,8 +221,8 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left.is_resolution()) {
|
if (left.is_resolution()) {
|
||||||
auto left_dppx = left.resolution().to_dots_per_pixel();
|
auto left_dppx = left.resolution().resolved().to_dots_per_pixel();
|
||||||
auto right_dppx = right.resolution().to_dots_per_pixel();
|
auto right_dppx = right.resolution().resolved().to_dots_per_pixel();
|
||||||
|
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
case Comparison::Equal:
|
case Comparison::Equal:
|
||||||
|
|
|
@ -10,11 +10,10 @@
|
||||||
#include <AK/Optional.h>
|
#include <AK/Optional.h>
|
||||||
#include <AK/OwnPtr.h>
|
#include <AK/OwnPtr.h>
|
||||||
#include <AK/RefCounted.h>
|
#include <AK/RefCounted.h>
|
||||||
|
#include <LibWeb/CSS/CalculatedOr.h>
|
||||||
#include <LibWeb/CSS/GeneralEnclosed.h>
|
#include <LibWeb/CSS/GeneralEnclosed.h>
|
||||||
#include <LibWeb/CSS/Length.h>
|
|
||||||
#include <LibWeb/CSS/MediaFeatureID.h>
|
#include <LibWeb/CSS/MediaFeatureID.h>
|
||||||
#include <LibWeb/CSS/Ratio.h>
|
#include <LibWeb/CSS/Ratio.h>
|
||||||
#include <LibWeb/CSS/Resolution.h>
|
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
|
@ -26,7 +25,7 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit MediaFeatureValue(Length length)
|
explicit MediaFeatureValue(LengthOrCalculated length)
|
||||||
: m_value(move(length))
|
: m_value(move(length))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -36,23 +35,28 @@ public:
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit MediaFeatureValue(Resolution resolution)
|
explicit MediaFeatureValue(ResolutionOrCalculated resolution)
|
||||||
: m_value(move(resolution))
|
: m_value(move(resolution))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
explicit MediaFeatureValue(float number)
|
explicit MediaFeatureValue(IntegerOrCalculated integer)
|
||||||
: m_value(number)
|
: m_value(move(integer))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
explicit MediaFeatureValue(i64 integer)
|
||||||
|
: m_value(IntegerOrCalculated(integer))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
String to_string() const;
|
String to_string() const;
|
||||||
|
|
||||||
bool is_ident() const { return m_value.has<Keyword>(); }
|
bool is_ident() const { return m_value.has<Keyword>(); }
|
||||||
bool is_length() const { return m_value.has<Length>(); }
|
bool is_length() const { return m_value.has<LengthOrCalculated>(); }
|
||||||
bool is_number() const { return m_value.has<float>(); }
|
bool is_integer() const { return m_value.has<IntegerOrCalculated>(); }
|
||||||
bool is_ratio() const { return m_value.has<Ratio>(); }
|
bool is_ratio() const { return m_value.has<Ratio>(); }
|
||||||
bool is_resolution() const { return m_value.has<Resolution>(); }
|
bool is_resolution() const { return m_value.has<ResolutionOrCalculated>(); }
|
||||||
bool is_same_type(MediaFeatureValue const& other) const;
|
bool is_same_type(MediaFeatureValue const& other) const;
|
||||||
|
|
||||||
Keyword const& ident() const
|
Keyword const& ident() const
|
||||||
|
@ -61,10 +65,10 @@ public:
|
||||||
return m_value.get<Keyword>();
|
return m_value.get<Keyword>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Length const& length() const
|
LengthOrCalculated const& length() const
|
||||||
{
|
{
|
||||||
VERIFY(is_length());
|
VERIFY(is_length());
|
||||||
return m_value.get<Length>();
|
return m_value.get<LengthOrCalculated>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ratio const& ratio() const
|
Ratio const& ratio() const
|
||||||
|
@ -73,20 +77,20 @@ public:
|
||||||
return m_value.get<Ratio>();
|
return m_value.get<Ratio>();
|
||||||
}
|
}
|
||||||
|
|
||||||
Resolution const& resolution() const
|
ResolutionOrCalculated const& resolution() const
|
||||||
{
|
{
|
||||||
VERIFY(is_resolution());
|
VERIFY(is_resolution());
|
||||||
return m_value.get<Resolution>();
|
return m_value.get<ResolutionOrCalculated>();
|
||||||
}
|
}
|
||||||
|
|
||||||
float number() const
|
IntegerOrCalculated integer() const
|
||||||
{
|
{
|
||||||
VERIFY(is_number());
|
VERIFY(is_integer());
|
||||||
return m_value.get<float>();
|
return m_value.get<IntegerOrCalculated>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Variant<Keyword, Length, Ratio, Resolution, float> m_value;
|
Variant<Keyword, LengthOrCalculated, Ratio, ResolutionOrCalculated, IntegerOrCalculated> m_value;
|
||||||
};
|
};
|
||||||
|
|
||||||
// https://www.w3.org/TR/mediaqueries-4/#mq-features
|
// https://www.w3.org/TR/mediaqueries-4/#mq-features
|
||||||
|
|
|
@ -551,8 +551,6 @@ OwnPtr<MediaCondition> Parser::parse_media_in_parens(TokenStream<ComponentValue>
|
||||||
// `<mf-value>`, https://www.w3.org/TR/mediaqueries-4/#typedef-mf-value
|
// `<mf-value>`, https://www.w3.org/TR/mediaqueries-4/#typedef-mf-value
|
||||||
Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID media_feature, TokenStream<ComponentValue>& tokens)
|
Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID media_feature, TokenStream<ComponentValue>& tokens)
|
||||||
{
|
{
|
||||||
// NOTE: Calculations are not allowed for media feature values, at least in the current spec, so we reject them.
|
|
||||||
|
|
||||||
// Identifiers
|
// Identifiers
|
||||||
if (tokens.next_token().is(Token::Type::Ident)) {
|
if (tokens.next_token().is(Token::Type::Ident)) {
|
||||||
auto transaction = tokens.begin_transaction();
|
auto transaction = tokens.begin_transaction();
|
||||||
|
@ -570,11 +568,11 @@ Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID med
|
||||||
if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Boolean)) {
|
if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Boolean)) {
|
||||||
auto transaction = tokens.begin_transaction();
|
auto transaction = tokens.begin_transaction();
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
if (auto integer = parse_integer(tokens); integer.has_value() && !integer->is_calculated()) {
|
if (auto integer = parse_integer(tokens); integer.has_value()) {
|
||||||
auto integer_value = integer->value();
|
auto integer_value = integer.value().resolved();
|
||||||
if (integer_value == 0 || integer_value == 1) {
|
if (integer_value == 0 || integer_value == 1) {
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
return MediaFeatureValue(integer_value);
|
return MediaFeatureValue(integer.release_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -582,9 +580,9 @@ Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID med
|
||||||
// Integer
|
// Integer
|
||||||
if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Integer)) {
|
if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Integer)) {
|
||||||
auto transaction = tokens.begin_transaction();
|
auto transaction = tokens.begin_transaction();
|
||||||
if (auto integer = parse_integer(tokens); integer.has_value() && !integer->is_calculated()) {
|
if (auto integer = parse_integer(tokens); integer.has_value()) {
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
return MediaFeatureValue(integer->value());
|
return MediaFeatureValue(integer.release_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -592,9 +590,9 @@ Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID med
|
||||||
if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Length)) {
|
if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Length)) {
|
||||||
auto transaction = tokens.begin_transaction();
|
auto transaction = tokens.begin_transaction();
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
if (auto length = parse_length(tokens); length.has_value() && !length->is_calculated()) {
|
if (auto length = parse_length(tokens); length.has_value()) {
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
return MediaFeatureValue(length->value());
|
return MediaFeatureValue(length.release_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -612,9 +610,9 @@ Optional<MediaFeatureValue> Parser::parse_media_feature_value(MediaFeatureID med
|
||||||
if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Resolution)) {
|
if (media_feature_accepts_type(media_feature, MediaFeatureValueType::Resolution)) {
|
||||||
auto transaction = tokens.begin_transaction();
|
auto transaction = tokens.begin_transaction();
|
||||||
tokens.discard_whitespace();
|
tokens.discard_whitespace();
|
||||||
if (auto resolution = parse_resolution(tokens); resolution.has_value() && !resolution->is_calculated()) {
|
if (auto resolution = parse_resolution(tokens); resolution.has_value()) {
|
||||||
transaction.commit();
|
transaction.commit();
|
||||||
return MediaFeatureValue(resolution->value());
|
return MediaFeatureValue(resolution.release_value());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test: support for calc in Media Queries</title>
|
||||||
|
<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="calc can be used in Media Queries">
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
@media (min-width: calc(1px - 1px)){
|
||||||
|
div { background-color: green; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test: evaluation of em in calc in Media Queries</title>
|
||||||
|
<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="The size in pixels of the 'em' unit used in calc inside a media query does not depend on declarations and use the initial value.">
|
||||||
|
<style>
|
||||||
|
:root { font-size: 30000px; }
|
||||||
|
p { font-size: 16px; }
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
@media (min-width: calc(1em)){
|
||||||
|
div { background-color: green; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
||||||
|
<script>
|
||||||
|
document.body.offsetTop;
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
@media (min-width: calc(1em)){
|
||||||
|
div { background-color: green; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,35 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test: evaluation of ex in calc in Media Queries</title>
|
||||||
|
<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="The size in pixels of the 'ex' unit used in calc inside a media query does not depend on declarations and use the initial value.">
|
||||||
|
<style>
|
||||||
|
:root { font-size: 30000px; }
|
||||||
|
p { font-size: 16px; }
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
@media (min-width: calc(1ex)){
|
||||||
|
div { background-color: green; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
||||||
|
<script>
|
||||||
|
document.body.offsetTop;
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
@media (min-width: calc(1ex)){
|
||||||
|
div { background-color: green; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test: evaluation of ch in calc in Media Queries</title>
|
||||||
|
<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="The size in pixels of the 'ch' unit used in calc inside a media query does not depend on declarations and use the initial value.">
|
||||||
|
<style>
|
||||||
|
:root { font-size: 30000px; }
|
||||||
|
p { font-size: 16px; }
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
||||||
|
<script>
|
||||||
|
document.body.offsetTop;
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
@media (min-width: calc(1ch)){
|
||||||
|
div { background-color: green; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,32 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test: evaluation of rem in calc in Media Queries</title>
|
||||||
|
<link rel="author" title="Florian Rivoal" href="http://florian.rivoal.net/">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="The size in pixels of the 'rem' unit used in calc inside a media query does not depend on declarations and use the initial value.">
|
||||||
|
<style>
|
||||||
|
:root { font-size: 30000px; }
|
||||||
|
p { font-size: 16px; }
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
||||||
|
<script>
|
||||||
|
document.body.offsetTop;
|
||||||
|
</script>
|
||||||
|
<style>
|
||||||
|
@media (min-width: calc(1rem)){
|
||||||
|
div { background-color: green; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<link rel="author" title="Xiaocheng Hu" href="xiaochengh@chromium.org">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="https://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="The 'in' unit used in calc is not mistaken as 'px'.">
|
||||||
|
<style>
|
||||||
|
p { font-size: 16px; }
|
||||||
|
#target {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
@media (min-width: calc(100in)) {
|
||||||
|
/* Should not be selected */
|
||||||
|
#target { background-color: red }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div id=target></div>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Test: evaluation of mixed-unit calc in Media Queries</title>
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-values-4/#calc-func">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/mediaqueries-4/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<style>
|
||||||
|
:root { font-size: 30000px; }
|
||||||
|
p { font-size: 16px; }
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
@media (min-width: calc(1px + 1rem)) {
|
||||||
|
div { background-color: green; }
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div>
|
||||||
|
</div>
|
|
@ -0,0 +1,28 @@
|
||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Test: support for calc in Media Queries</title>
|
||||||
|
<link rel="author" title="Romain Menke" href="https://github.com/romainmenke">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="https://drafts.csswg.org/css-values-4/#ratios">
|
||||||
|
<link rel="help" href="https://github.com/w3c/csswg-drafts/issues/3757">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="calc can be used in Media Queries">
|
||||||
|
<style>
|
||||||
|
div {
|
||||||
|
background-color: red;
|
||||||
|
height: 100px;
|
||||||
|
width: 100px;
|
||||||
|
}
|
||||||
|
@media screen and (min-aspect-ratio: calc(59/79)) {
|
||||||
|
div {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
||||||
|
</body>
|
||||||
|
</html>
|
|
@ -0,0 +1,20 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<title>Test: support for calc resolution in Media Queries</title>
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<meta name="assert" content="calc resolution can be used in Media Queries">
|
||||||
|
<style>
|
||||||
|
#test {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (resolution >= calc(2x - 96dpi)){
|
||||||
|
#test {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div id="test"></div>
|
|
@ -0,0 +1,25 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Test: support for calc with sign() in Media Queries</title>
|
||||||
|
<link rel="author" title="Daniil Sakhapov" href="mailto:sakhapov@chromium.org">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width > calc(1px * (1 + sign(16px - 1rem)))) {
|
||||||
|
div {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Test: support for calc with sign() in Media Queries</title>
|
||||||
|
<link rel="author" title="Daniil Sakhapov" href="mailto:sakhapov@chromium.org">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (width > calc(-1px * sign(15px - 1rem))) {
|
||||||
|
div {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Test: support for calc with sign() in Media Queries</title>
|
||||||
|
<link rel="author" title="Daniil Sakhapov" href="mailto:sakhapov@chromium.org">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (resolution > calc(-1dppx * sign(17px - 1rem))) {
|
||||||
|
div {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
|
@ -0,0 +1,24 @@
|
||||||
|
<!doctype html>
|
||||||
|
<title>Test: support for calc with sign() in Media Queries</title>
|
||||||
|
<link rel="author" title="Daniil Sakhapov" href="mailto:sakhapov@chromium.org">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-values/#calc-notation">
|
||||||
|
<link rel="help" href="http://www.w3.org/TR/css3-mediaqueries/#units">
|
||||||
|
<link rel="match" href="../../../../expected/wpt-import/css/mediaqueries/../reference/ref-filled-green-100px-square.xht">
|
||||||
|
<style>
|
||||||
|
:root {
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
div {
|
||||||
|
width: 100px;
|
||||||
|
height: 100px;
|
||||||
|
background-color: red;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media (grid: calc(2 * sign(16px - 1rem))) {
|
||||||
|
div {
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<p>Test passes if there is a filled green square and <strong>no red</strong>.</p>
|
||||||
|
<div></div>
|
Loading…
Add table
Add a link
Reference in a new issue