mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-08-09 09:39:39 +00:00
LibWeb/CSS: Update CalculatedOr API to use CalculationResolutionContext
To be properly compatible with calc(), the resolved() methods all need: - A length resolution context - To return an Optional, as the calculation might not be resolvable A bonus of this is that we can get rid of the overloads of `resolved()` as they now all behave the same way. A downside is a scattering of `value_or()` wherever these are used. It might be the case that all unresolvable calculations have been rejected before this point, but I'm not confident, and so I'll leave it like this for now.
This commit is contained in:
parent
1d71662f31
commit
385c3d273a
Notes:
github-actions[bot]
2025-01-30 18:33:51 +00:00
Author: https://github.com/AtkinsSJ
Commit: 385c3d273a
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3383
11 changed files with 98 additions and 100 deletions
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
|
* Copyright (c) 2023-2025, Sam Atkins <sam@ladybird.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -17,9 +17,9 @@
|
||||||
|
|
||||||
namespace Web::CSS {
|
namespace Web::CSS {
|
||||||
|
|
||||||
Angle AngleOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<Angle> AngleOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_angle({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_angle(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> AngleOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> AngleOrCalculated::create_style_value() const
|
||||||
|
@ -27,9 +27,9 @@ NonnullRefPtr<CSSStyleValue> AngleOrCalculated::create_style_value() const
|
||||||
return AngleStyleValue::create(value());
|
return AngleStyleValue::create(value());
|
||||||
}
|
}
|
||||||
|
|
||||||
Flex FlexOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<Flex> FlexOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_flex({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_flex(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> FlexOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> FlexOrCalculated::create_style_value() const
|
||||||
|
@ -37,9 +37,9 @@ NonnullRefPtr<CSSStyleValue> FlexOrCalculated::create_style_value() const
|
||||||
return FlexStyleValue::create(value());
|
return FlexStyleValue::create(value());
|
||||||
}
|
}
|
||||||
|
|
||||||
Frequency FrequencyOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<Frequency> FrequencyOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_frequency({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_frequency(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> FrequencyOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> FrequencyOrCalculated::create_style_value() const
|
||||||
|
@ -47,16 +47,9 @@ NonnullRefPtr<CSSStyleValue> FrequencyOrCalculated::create_style_value() const
|
||||||
return FrequencyStyleValue::create(value());
|
return FrequencyStyleValue::create(value());
|
||||||
}
|
}
|
||||||
|
|
||||||
i64 IntegerOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<i64> IntegerOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_integer({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_integer(context);
|
||||||
}
|
|
||||||
|
|
||||||
i64 IntegerOrCalculated::resolved(Length::ResolutionContext const& context) const
|
|
||||||
{
|
|
||||||
if (is_calculated())
|
|
||||||
return calculated()->resolve_integer({ .length_resolution_context = context }).value();
|
|
||||||
return value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> IntegerOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> IntegerOrCalculated::create_style_value() const
|
||||||
|
@ -64,16 +57,9 @@ NonnullRefPtr<CSSStyleValue> IntegerOrCalculated::create_style_value() const
|
||||||
return IntegerStyleValue::create(value());
|
return IntegerStyleValue::create(value());
|
||||||
}
|
}
|
||||||
|
|
||||||
Length LengthOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<Length> LengthOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_length({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_length(context);
|
||||||
}
|
|
||||||
|
|
||||||
Length LengthOrCalculated::resolved(Length::ResolutionContext const& context) const
|
|
||||||
{
|
|
||||||
if (is_calculated())
|
|
||||||
return calculated()->resolve_length({ .length_resolution_context = context }).value();
|
|
||||||
return value();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> LengthOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> LengthOrCalculated::create_style_value() const
|
||||||
|
@ -81,9 +67,9 @@ NonnullRefPtr<CSSStyleValue> LengthOrCalculated::create_style_value() const
|
||||||
return LengthStyleValue::create(value());
|
return LengthStyleValue::create(value());
|
||||||
}
|
}
|
||||||
|
|
||||||
double NumberOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<double> NumberOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_number({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_number(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> NumberOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> NumberOrCalculated::create_style_value() const
|
||||||
|
@ -91,9 +77,9 @@ NonnullRefPtr<CSSStyleValue> NumberOrCalculated::create_style_value() const
|
||||||
return NumberStyleValue::create(value());
|
return NumberStyleValue::create(value());
|
||||||
}
|
}
|
||||||
|
|
||||||
Percentage PercentageOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<Percentage> PercentageOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_percentage({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_percentage(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> PercentageOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> PercentageOrCalculated::create_style_value() const
|
||||||
|
@ -101,16 +87,9 @@ NonnullRefPtr<CSSStyleValue> PercentageOrCalculated::create_style_value() const
|
||||||
return PercentageStyleValue::create(value());
|
return PercentageStyleValue::create(value());
|
||||||
}
|
}
|
||||||
|
|
||||||
Resolution ResolutionOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<Resolution> ResolutionOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_resolution({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_resolution(context);
|
||||||
}
|
|
||||||
|
|
||||||
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
|
||||||
|
@ -118,9 +97,9 @@ NonnullRefPtr<CSSStyleValue> ResolutionOrCalculated::create_style_value() const
|
||||||
return ResolutionStyleValue::create(value());
|
return ResolutionStyleValue::create(value());
|
||||||
}
|
}
|
||||||
|
|
||||||
Time TimeOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
Optional<Time> TimeOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return calculated->resolve_time({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
return calculated->resolve_time(context);
|
||||||
}
|
}
|
||||||
|
|
||||||
NonnullRefPtr<CSSStyleValue> TimeOrCalculated::create_style_value() const
|
NonnullRefPtr<CSSStyleValue> TimeOrCalculated::create_style_value() const
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2023, Sam Atkins <atkinssj@serenityos.org>
|
* Copyright (c) 2023-2025, Sam Atkins <sam@ladybird.org>
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: BSD-2-Clause
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
*/
|
*/
|
||||||
|
@ -54,14 +54,14 @@ public:
|
||||||
return m_value.template get<NonnullRefPtr<CalculatedStyleValue>>();
|
return m_value.template get<NonnullRefPtr<CalculatedStyleValue>>();
|
||||||
}
|
}
|
||||||
|
|
||||||
T resolved(Layout::Node const& layout_node) const
|
Optional<T> resolved(CalculationResolutionContext const& context) const
|
||||||
{
|
{
|
||||||
return m_value.visit(
|
return m_value.visit(
|
||||||
[&](T const& t) {
|
[&](T const& t) -> Optional<T> {
|
||||||
return t;
|
return t;
|
||||||
},
|
},
|
||||||
[&](NonnullRefPtr<CalculatedStyleValue> const& calculated) {
|
[&](NonnullRefPtr<CalculatedStyleValue> const& calculated) {
|
||||||
return resolve_calculated(calculated, layout_node);
|
return resolve_calculated(calculated, context);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual T resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const = 0;
|
virtual Optional<T> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const = 0;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const = 0;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const = 0;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -93,7 +93,7 @@ public:
|
||||||
using CalculatedOr<Angle>::CalculatedOr;
|
using CalculatedOr<Angle>::CalculatedOr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Angle resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<Angle> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -102,7 +102,7 @@ public:
|
||||||
using CalculatedOr<Flex>::CalculatedOr;
|
using CalculatedOr<Flex>::CalculatedOr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Flex resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<Flex> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ public:
|
||||||
using CalculatedOr<Frequency>::CalculatedOr;
|
using CalculatedOr<Frequency>::CalculatedOr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Frequency resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<Frequency> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -119,10 +119,8 @@ class IntegerOrCalculated : public CalculatedOr<i64> {
|
||||||
public:
|
public:
|
||||||
using CalculatedOr<i64>::CalculatedOr;
|
using CalculatedOr<i64>::CalculatedOr;
|
||||||
|
|
||||||
[[nodiscard]] i64 resolved(Length::ResolutionContext const&) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual i64 resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<i64> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -130,10 +128,8 @@ class LengthOrCalculated : public CalculatedOr<Length> {
|
||||||
public:
|
public:
|
||||||
using CalculatedOr<Length>::CalculatedOr;
|
using CalculatedOr<Length>::CalculatedOr;
|
||||||
|
|
||||||
[[nodiscard]] Length resolved(Length::ResolutionContext const&) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Length resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<Length> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -142,7 +138,7 @@ public:
|
||||||
using CalculatedOr<double>::CalculatedOr;
|
using CalculatedOr<double>::CalculatedOr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual double resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<double> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -151,7 +147,7 @@ public:
|
||||||
using CalculatedOr<Percentage>::CalculatedOr;
|
using CalculatedOr<Percentage>::CalculatedOr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Percentage resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<Percentage> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -159,10 +155,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<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<Resolution> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -171,7 +165,7 @@ public:
|
||||||
using CalculatedOr<Time>::CalculatedOr;
|
using CalculatedOr<Time>::CalculatedOr;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual Time resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, Layout::Node const&) const override;
|
virtual Optional<Time> resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const&, CalculationResolutionContext const&) const override;
|
||||||
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
virtual NonnullRefPtr<CSSStyleValue> create_style_value() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -90,20 +90,22 @@ bool MediaFeature::evaluate(HTML::Window const& window) const
|
||||||
return false;
|
return false;
|
||||||
auto queried_value = maybe_queried_value.release_value();
|
auto queried_value = maybe_queried_value.release_value();
|
||||||
|
|
||||||
auto resolution_context = Length::ResolutionContext::for_window(window);
|
CalculationResolutionContext calculation_context {
|
||||||
|
.length_resolution_context = Length::ResolutionContext::for_window(window),
|
||||||
|
};
|
||||||
switch (m_type) {
|
switch (m_type) {
|
||||||
case Type::IsTrue:
|
case Type::IsTrue:
|
||||||
if (queried_value.is_integer())
|
if (queried_value.is_integer())
|
||||||
return queried_value.integer().resolved(resolution_context) != 0;
|
return queried_value.integer().resolved(calculation_context) != 0;
|
||||||
if (queried_value.is_length()) {
|
if (queried_value.is_length()) {
|
||||||
auto length = queried_value.length().resolved(resolution_context);
|
auto length = queried_value.length().resolved(calculation_context);
|
||||||
return length.raw_value() != 0;
|
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().resolved().to_dots_per_pixel() != 0;
|
return queried_value.resolution().resolved(calculation_context).map([](auto& it) { return it.to_dots_per_pixel(); }).value_or(0) != 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. :^)
|
||||||
|
@ -148,19 +150,22 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CalculationResolutionContext calculation_context {
|
||||||
|
.length_resolution_context = Length::ResolutionContext::for_window(window),
|
||||||
|
};
|
||||||
|
|
||||||
if (left.is_integer()) {
|
if (left.is_integer()) {
|
||||||
auto resolution_context = Length::ResolutionContext::for_window(window);
|
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
case Comparison::Equal:
|
case Comparison::Equal:
|
||||||
return left.integer().resolved(resolution_context) == right.integer().resolved(resolution_context);
|
return left.integer().resolved(calculation_context).value_or(0) == right.integer().resolved(calculation_context).value_or(0);
|
||||||
case Comparison::LessThan:
|
case Comparison::LessThan:
|
||||||
return left.integer().resolved(resolution_context) < right.integer().resolved(resolution_context);
|
return left.integer().resolved(calculation_context).value_or(0) < right.integer().resolved(calculation_context).value_or(0);
|
||||||
case Comparison::LessThanOrEqual:
|
case Comparison::LessThanOrEqual:
|
||||||
return left.integer().resolved(resolution_context) <= right.integer().resolved(resolution_context);
|
return left.integer().resolved(calculation_context).value_or(0) <= right.integer().resolved(calculation_context).value_or(0);
|
||||||
case Comparison::GreaterThan:
|
case Comparison::GreaterThan:
|
||||||
return left.integer().resolved(resolution_context) > right.integer().resolved(resolution_context);
|
return left.integer().resolved(calculation_context).value_or(0) > right.integer().resolved(calculation_context).value_or(0);
|
||||||
case Comparison::GreaterThanOrEqual:
|
case Comparison::GreaterThanOrEqual:
|
||||||
return left.integer().resolved(resolution_context) >= right.integer().resolved(resolution_context);
|
return left.integer().resolved(calculation_context).value_or(0) >= right.integer().resolved(calculation_context).value_or(0);
|
||||||
}
|
}
|
||||||
VERIFY_NOT_REACHED();
|
VERIFY_NOT_REACHED();
|
||||||
}
|
}
|
||||||
|
@ -168,9 +173,8 @@ 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(calculation_context).value_or(Length::make_px(0));
|
||||||
auto left_length = left.length().resolved(resolution_context);
|
auto right_length = right.length().resolved(calculation_context).value_or(Length::make_px(0));
|
||||||
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();
|
||||||
|
@ -222,8 +226,8 @@ bool MediaFeature::compare(HTML::Window const& window, MediaFeatureValue left, C
|
||||||
}
|
}
|
||||||
|
|
||||||
if (left.is_resolution()) {
|
if (left.is_resolution()) {
|
||||||
auto left_dppx = left.resolution().resolved().to_dots_per_pixel();
|
auto left_dppx = left.resolution().resolved(calculation_context).map([](auto& it) { return it.to_dots_per_pixel(); }).value_or(0);
|
||||||
auto right_dppx = right.resolution().resolved().to_dots_per_pixel();
|
auto right_dppx = right.resolution().resolved(calculation_context).map([](auto& it) { return it.to_dots_per_pixel(); }).value_or(0);
|
||||||
|
|
||||||
switch (comparison) {
|
switch (comparison) {
|
||||||
case Comparison::Equal:
|
case Comparison::Equal:
|
||||||
|
|
|
@ -16,7 +16,7 @@ namespace Web::CSS {
|
||||||
float FilterOperation::Blur::resolved_radius(Layout::Node const& node) const
|
float FilterOperation::Blur::resolved_radius(Layout::Node const& node) const
|
||||||
{
|
{
|
||||||
if (radius.has_value())
|
if (radius.has_value())
|
||||||
return radius->resolved(Length::ResolutionContext::for_layout_node(node)).to_px(node).to_float();
|
return radius->resolved({ .length_resolution_context = Length::ResolutionContext::for_layout_node(node) })->to_px(node).to_float();
|
||||||
|
|
||||||
// Default value when omitted is 0px.
|
// Default value when omitted is 0px.
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -27,7 +27,7 @@ float FilterOperation::HueRotate::angle_degrees(Layout::Node const& node) const
|
||||||
// Default value when omitted is 0deg.
|
// Default value when omitted is 0deg.
|
||||||
if (!angle.has_value())
|
if (!angle.has_value())
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
return angle->visit([&](AngleOrCalculated const& a) { return a.resolved(node).to_degrees(); }, [&](Zero) { return 0.0; });
|
return angle->visit([&](AngleOrCalculated const& a) { return a.resolved({ .length_resolution_context = Length::ResolutionContext::for_layout_node(node) })->to_degrees(); }, [&](Zero) { return 0.0; });
|
||||||
}
|
}
|
||||||
|
|
||||||
float FilterOperation::Color::resolved_amount() const
|
float FilterOperation::Color::resolved_amount() const
|
||||||
|
|
|
@ -20,8 +20,14 @@ ErrorOr<Gfx::FloatMatrix4x4> Transformation::to_matrix(Optional<Painting::Painta
|
||||||
{
|
{
|
||||||
auto count = m_values.size();
|
auto count = m_values.size();
|
||||||
auto value = [&](size_t index, CSSPixels const& reference_length = 0) -> ErrorOr<float> {
|
auto value = [&](size_t index, CSSPixels const& reference_length = 0) -> ErrorOr<float> {
|
||||||
|
CalculationResolutionContext context {};
|
||||||
|
if (paintable_box.has_value())
|
||||||
|
context.length_resolution_context = Length::ResolutionContext::for_layout_node(paintable_box->layout_node());
|
||||||
|
|
||||||
return m_values[index].visit(
|
return m_values[index].visit(
|
||||||
[&](CSS::LengthPercentage const& value) -> ErrorOr<float> {
|
[&](CSS::LengthPercentage const& value) -> ErrorOr<float> {
|
||||||
|
context.percentage_basis = Length::make_px(reference_length);
|
||||||
|
|
||||||
if (paintable_box.has_value())
|
if (paintable_box.has_value())
|
||||||
return value.resolved(paintable_box->layout_node(), reference_length).to_px(paintable_box->layout_node()).to_float();
|
return value.resolved(paintable_box->layout_node(), reference_length).to_px(paintable_box->layout_node()).to_float();
|
||||||
if (value.is_length()) {
|
if (value.is_length()) {
|
||||||
|
@ -31,8 +37,8 @@ ErrorOr<Gfx::FloatMatrix4x4> Transformation::to_matrix(Optional<Painting::Painta
|
||||||
return Error::from_string_literal("Transform contains non absolute units");
|
return Error::from_string_literal("Transform contains non absolute units");
|
||||||
},
|
},
|
||||||
[&](CSS::AngleOrCalculated const& value) -> ErrorOr<float> {
|
[&](CSS::AngleOrCalculated const& value) -> ErrorOr<float> {
|
||||||
if (paintable_box.has_value())
|
if (auto resolved = value.resolved(context); resolved.has_value())
|
||||||
return value.resolved(paintable_box->layout_node()).to_radians();
|
return resolved->to_radians();
|
||||||
if (!value.is_calculated())
|
if (!value.is_calculated())
|
||||||
return value.value().to_radians();
|
return value.value().to_radians();
|
||||||
return Error::from_string_literal("Transform contains non absolute units");
|
return Error::from_string_literal("Transform contains non absolute units");
|
||||||
|
|
|
@ -909,13 +909,17 @@ void CanvasRenderingContext2D::set_filter(String filter)
|
||||||
},
|
},
|
||||||
[&](CSS::FilterOperation::DropShadow const& drop_shadow) {
|
[&](CSS::FilterOperation::DropShadow const& drop_shadow) {
|
||||||
auto resolution_context = CSS::Length::ResolutionContext::for_layout_node(*layout_node);
|
auto resolution_context = CSS::Length::ResolutionContext::for_layout_node(*layout_node);
|
||||||
|
CSS::CalculationResolutionContext calculation_context {
|
||||||
|
.length_resolution_context = resolution_context,
|
||||||
|
};
|
||||||
|
auto zero_px = CSS::Length::make_px(0);
|
||||||
|
|
||||||
float offset_x = static_cast<float>(drop_shadow.offset_x.resolved(resolution_context).to_px(resolution_context));
|
float offset_x = static_cast<float>(drop_shadow.offset_x.resolved(calculation_context).value_or(zero_px).to_px(resolution_context));
|
||||||
float offset_y = static_cast<float>(drop_shadow.offset_y.resolved(resolution_context).to_px(resolution_context));
|
float offset_y = static_cast<float>(drop_shadow.offset_y.resolved(calculation_context).value_or(zero_px).to_px(resolution_context));
|
||||||
|
|
||||||
float radius = 0.0f;
|
float radius = 0.0f;
|
||||||
if (drop_shadow.radius.has_value()) {
|
if (drop_shadow.radius.has_value()) {
|
||||||
radius = static_cast<float>(drop_shadow.radius->resolved(resolution_context).to_px(resolution_context));
|
radius = static_cast<float>(drop_shadow.radius->resolved(calculation_context).value_or(zero_px).to_px(resolution_context));
|
||||||
};
|
};
|
||||||
|
|
||||||
auto color = drop_shadow.color.value_or(Gfx::Color { 0, 0, 0, 255 });
|
auto color = drop_shadow.color.value_or(Gfx::Color { 0, 0, 0, 255 });
|
||||||
|
|
|
@ -404,8 +404,8 @@ void SourceSet::normalize_source_densities(DOM::Element const& element)
|
||||||
// FIXME: We should have a way to build a LengthResolutionContext for any DOM node without going through the layout tree.
|
// FIXME: We should have a way to build a LengthResolutionContext for any DOM node without going through the layout tree.
|
||||||
const_cast<DOM::Document&>(element.document()).update_layout();
|
const_cast<DOM::Document&>(element.document()).update_layout();
|
||||||
if (element.layout_node()) {
|
if (element.layout_node()) {
|
||||||
auto context = CSS::Length::ResolutionContext::for_layout_node(*element.layout_node());
|
CSS::CalculationResolutionContext context { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*element.layout_node()) };
|
||||||
return m_source_size.resolved(context);
|
return m_source_size.resolved(context).value_or(CSS::Length::make_auto());
|
||||||
}
|
}
|
||||||
// FIXME: This is wrong, but we don't have a better way to resolve lengths without a layout node yet.
|
// FIXME: This is wrong, but we don't have a better way to resolve lengths without a layout node yet.
|
||||||
return CSS::Length::make_auto();
|
return CSS::Length::make_auto();
|
||||||
|
|
|
@ -437,12 +437,12 @@ Gfx::ShapeFeatures InlineLevelIterator::create_and_merge_font_features() const
|
||||||
// FIXME 4. Feature settings determined by properties other than ‘font-variant’ or ‘font-feature-settings’. For example, setting a non-default value for the ‘letter-spacing’ property disables common ligatures.
|
// FIXME 4. Feature settings determined by properties other than ‘font-variant’ or ‘font-feature-settings’. For example, setting a non-default value for the ‘letter-spacing’ property disables common ligatures.
|
||||||
|
|
||||||
// 5. Font features implied by the value of ‘font-feature-settings’ property.
|
// 5. Font features implied by the value of ‘font-feature-settings’ property.
|
||||||
auto resolution_context = CSS::Length::ResolutionContext::for_layout_node(*m_current_node.ptr());
|
CSS::CalculationResolutionContext calculation_context { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*m_current_node.ptr()) };
|
||||||
auto font_feature_settings = computed_values.font_feature_settings();
|
auto font_feature_settings = computed_values.font_feature_settings();
|
||||||
if (font_feature_settings.has_value()) {
|
if (font_feature_settings.has_value()) {
|
||||||
auto const& feature_settings = font_feature_settings.value();
|
auto const& feature_settings = font_feature_settings.value();
|
||||||
for (auto const& [key, feature_value] : feature_settings) {
|
for (auto const& [key, feature_value] : feature_settings) {
|
||||||
merged_features.set(key, feature_value.resolved(resolution_context));
|
merged_features.set(key, feature_value.resolved(calculation_context).value_or(0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -497,9 +497,9 @@ Optional<InlineLevelIterator::Item> InlineLevelIterator::next_without_lookahead(
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
auto resolution_context = CSS::Length::ResolutionContext::for_layout_node(text_node);
|
CSS::CalculationResolutionContext calculation_context { .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(text_node) };
|
||||||
auto letter_spacing = text_node.computed_values().letter_spacing().resolved(resolution_context).to_px(text_node);
|
auto letter_spacing = text_node.computed_values().letter_spacing().resolved(calculation_context).map([&](auto& it) { return it.to_px(text_node); }).value_or(0);
|
||||||
auto word_spacing = text_node.computed_values().word_spacing().resolved(resolution_context).to_px(text_node);
|
auto word_spacing = text_node.computed_values().word_spacing().resolved(calculation_context).map([&](auto& it) { return it.to_px(text_node); }).value_or(0);
|
||||||
|
|
||||||
auto x = 0.0f;
|
auto x = 0.0f;
|
||||||
if (chunk.has_breaking_tab) {
|
if (chunk.has_breaking_tab) {
|
||||||
|
@ -513,15 +513,15 @@ Optional<InlineLevelIterator::Item> InlineLevelIterator::next_without_lookahead(
|
||||||
|
|
||||||
// https://drafts.csswg.org/css-text/#tab-size-property
|
// https://drafts.csswg.org/css-text/#tab-size-property
|
||||||
auto tab_size = text_node.computed_values().tab_size();
|
auto tab_size = text_node.computed_values().tab_size();
|
||||||
auto resolution_context = CSS::Length::ResolutionContext::for_layout_node(text_node);
|
|
||||||
CSSPixels tab_width;
|
CSSPixels tab_width;
|
||||||
tab_width = tab_size.visit(
|
tab_width = tab_size.visit(
|
||||||
[&](CSS::LengthOrCalculated const& t) -> CSSPixels {
|
[&](CSS::LengthOrCalculated const& t) -> CSSPixels {
|
||||||
auto value = t.resolved(resolution_context);
|
return t.resolved(calculation_context)
|
||||||
return value.to_px(text_node);
|
.map([&](auto& it) { return it.to_px(text_node); })
|
||||||
|
.value_or(0);
|
||||||
},
|
},
|
||||||
[&](CSS::NumberOrCalculated const& n) -> CSSPixels {
|
[&](CSS::NumberOrCalculated const& n) -> CSSPixels {
|
||||||
auto tab_number = n.resolved(text_node);
|
auto tab_number = n.resolved(calculation_context).value_or(0);
|
||||||
|
|
||||||
return CSSPixels::nearest_value_for(tab_number * (chunk.font->glyph_width(' ') + word_spacing.to_float() + letter_spacing.to_float()));
|
return CSSPixels::nearest_value_for(tab_number * (chunk.font->glyph_width(' ') + word_spacing.to_float() + letter_spacing.to_float()));
|
||||||
});
|
});
|
||||||
|
|
|
@ -581,13 +581,18 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
|
||||||
.radius = blur.resolved_radius(*this) });
|
.radius = blur.resolved_radius(*this) });
|
||||||
},
|
},
|
||||||
[&](CSS::FilterOperation::DropShadow const& drop_shadow) {
|
[&](CSS::FilterOperation::DropShadow const& drop_shadow) {
|
||||||
auto context = CSS::Length::ResolutionContext::for_layout_node(*this);
|
CSS::CalculationResolutionContext context {
|
||||||
|
.length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*this),
|
||||||
|
};
|
||||||
|
auto to_px = [&](CSS::LengthOrCalculated const& length) {
|
||||||
|
return static_cast<float>(length.resolved(context).map([&](auto& it) { return it.to_px(*this).to_double(); }).value_or(0.0));
|
||||||
|
};
|
||||||
// The default value for omitted values is missing length values set to 0
|
// The default value for omitted values is missing length values set to 0
|
||||||
// and the missing used color is taken from the color property.
|
// and the missing used color is taken from the color property.
|
||||||
resolved_filter.append(Gfx::DropShadowFilter {
|
resolved_filter.append(Gfx::DropShadowFilter {
|
||||||
.offset_x = static_cast<float>(drop_shadow.offset_x.resolved(context).to_px(*this).to_double()),
|
.offset_x = to_px(drop_shadow.offset_x),
|
||||||
.offset_y = static_cast<float>(drop_shadow.offset_y.resolved(context).to_px(*this).to_double()),
|
.offset_y = to_px(drop_shadow.offset_y),
|
||||||
.radius = static_cast<float>(drop_shadow.radius.has_value() ? drop_shadow.radius->resolved(context).to_px(*this).to_double() : 0.0),
|
.radius = drop_shadow.radius.has_value() ? to_px(*drop_shadow.radius) : 0.0f,
|
||||||
.color = drop_shadow.color.has_value() ? *drop_shadow.color : this->computed_values().color() });
|
.color = drop_shadow.color.has_value() ? *drop_shadow.color : this->computed_values().color() });
|
||||||
},
|
},
|
||||||
[&](CSS::FilterOperation::Color const& color_operation) {
|
[&](CSS::FilterOperation::Color const& color_operation) {
|
||||||
|
|
|
@ -154,7 +154,10 @@ void SVGPathPaintable::paint(PaintContext& context, PaintPhase phase) const
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto miter_limit = graphics_element.stroke_miterlimit().value_or(CSS::InitialValues::stroke_miterlimit()).resolved(layout_node());
|
CSS::CalculationResolutionContext calculation_context {
|
||||||
|
.length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(layout_node()),
|
||||||
|
};
|
||||||
|
auto miter_limit = graphics_element.stroke_miterlimit().value_or(CSS::InitialValues::stroke_miterlimit()).resolved(calculation_context).value_or(0);
|
||||||
|
|
||||||
auto stroke_opacity = graphics_element.stroke_opacity().value_or(1);
|
auto stroke_opacity = graphics_element.stroke_opacity().value_or(1);
|
||||||
|
|
||||||
|
|
|
@ -306,7 +306,10 @@ Vector<float> SVGGraphicsElement::stroke_dasharray() const
|
||||||
dasharray.append(resolve_relative_to_viewport_size(length_percentage));
|
dasharray.append(resolve_relative_to_viewport_size(length_percentage));
|
||||||
},
|
},
|
||||||
[&](CSS::NumberOrCalculated const& number_or_calculated) {
|
[&](CSS::NumberOrCalculated const& number_or_calculated) {
|
||||||
dasharray.append(number_or_calculated.resolved(*layout_node()));
|
CSS::CalculationResolutionContext calculation_context {
|
||||||
|
.length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*layout_node()),
|
||||||
|
};
|
||||||
|
dasharray.append(number_or_calculated.resolved(calculation_context).value_or(0));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue