LibWeb/CSS: Wrap calc()-resolution data in a struct

Initially I added this to the existing CalculationContext, but in
reality, we have some data at parse-time and different data at
resolve-time, so it made more sense to keep those separate.

Instead of needing a variety of methods for resolving a Foo, depending
on whether we have a Layout::Node available, or a percentage basis, or
a length resolution context... put those in a
CalculationResolutionContext, and just pass that one thing to these
methods. This also removes the need for separate resolve_*_percentage()
methods, because we can just pass the percentage basis in to the regular
resolve_foo() method.

This also corrects the issue that *any* calculation may need to resolve
lengths, but we previously only passed a length resolution context to
specific types in some situations. Now, they can all have one available,
though it's up to the caller to provide it.
This commit is contained in:
Sam Atkins 2025-01-22 16:05:32 +00:00 committed by Andreas Kling
commit 1d71662f31
Notes: github-actions[bot] 2025-01-30 18:33:58 +00:00
18 changed files with 256 additions and 309 deletions

View file

@ -42,7 +42,7 @@ Optional<double> CSSColorValue::resolve_hue(CSSStyleValue const& style_value)
return normalized(style_value.as_angle().angle().to_degrees());
if (style_value.is_calculated() && style_value.as_calculated().resolves_to_angle())
return normalized(style_value.as_calculated().resolve_angle().value().to_degrees());
return normalized(style_value.as_calculated().resolve_angle({}).value().to_degrees());
if (style_value.is_keyword() && style_value.to_keyword() == Keyword::None)
return 0;
@ -65,10 +65,11 @@ Optional<double> CSSColorValue::resolve_with_reference_value(CSSStyleValue const
if (style_value.is_calculated()) {
auto const& calculated = style_value.as_calculated();
CalculationResolutionContext context {};
if (calculated.resolves_to_number())
return calculated.resolve_number().value();
return calculated.resolve_number(context).value();
if (calculated.resolves_to_percentage())
return normalize_percentage(calculated.resolve_percentage().value());
return normalize_percentage(calculated.resolve_percentage(context).value());
}
if (style_value.is_keyword() && style_value.to_keyword() == Keyword::None)
@ -94,10 +95,11 @@ Optional<double> CSSColorValue::resolve_alpha(CSSStyleValue const& style_value)
if (style_value.is_calculated()) {
auto const& calculated = style_value.as_calculated();
CalculationResolutionContext context {};
if (calculated.resolves_to_number())
return normalized(calculated.resolve_number().value());
return normalized(calculated.resolve_number(context).value());
if (calculated.resolves_to_percentage())
return normalized(calculated.resolve_percentage().value().as_fraction());
return normalized(calculated.resolve_percentage(context).value().as_fraction());
}
if (style_value.is_keyword() && style_value.to_keyword() == Keyword::None)

View file

@ -32,10 +32,11 @@ Color CSSRGB::to_color(Optional<Layout::NodeWithStyle const&>) const
if (style_value.is_calculated()) {
auto const& calculated = style_value.as_calculated();
CalculationResolutionContext context {};
if (calculated.resolves_to_number())
return normalized(calculated.resolve_number().value());
return normalized(calculated.resolve_number(context).value());
if (calculated.resolves_to_percentage())
return normalized(calculated.resolve_percentage().value().value() * 255 / 100);
return normalized(calculated.resolve_percentage(context).value().value() * 255 / 100);
}
if (style_value.is_keyword() && style_value.to_keyword() == Keyword::None)

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -198,23 +198,23 @@ bool NumericCalculationNode::contains_percentage() const
return m_value.has<Percentage>();
}
CalculatedStyleValue::CalculationResult NumericCalculationNode::resolve(Optional<Length::ResolutionContext const&> resolution_context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult NumericCalculationNode::resolve(CalculationResolutionContext const& context) const
{
if (m_value.has<Percentage>()) {
// NOTE: Depending on whether percentage_basis is set, the caller of resolve() is expecting a raw percentage or
// resolved type.
return percentage_basis.visit(
return context.percentage_basis.visit(
[&](Empty const&) {
VERIFY(numeric_type_from_calculated_style_value(m_value, {}) == numeric_type());
return CalculatedStyleValue::CalculationResult::from_value(m_value, resolution_context, numeric_type());
return CalculatedStyleValue::CalculationResult::from_value(m_value, context, numeric_type());
},
[&](auto const& value) {
auto const calculated_value = value.percentage_of(m_value.get<Percentage>());
return CalculatedStyleValue::CalculationResult::from_value(calculated_value, resolution_context, numeric_type_from_calculated_style_value(calculated_value, {}));
return CalculatedStyleValue::CalculationResult::from_value(calculated_value, context, numeric_type_from_calculated_style_value(calculated_value, {}));
});
}
return CalculatedStyleValue::CalculationResult::from_value(m_value, resolution_context, numeric_type());
return CalculatedStyleValue::CalculationResult::from_value(m_value, context, numeric_type());
}
void NumericCalculationNode::dump(StringBuilder& builder, int indent) const
@ -272,17 +272,17 @@ bool SumCalculationNode::contains_percentage() const
return false;
}
CalculatedStyleValue::CalculationResult SumCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult SumCalculationNode::resolve(CalculationResolutionContext const& context) const
{
Optional<CalculatedStyleValue::CalculationResult> total;
for (auto& additional_product : m_values) {
auto additional_value = additional_product->resolve(context, percentage_basis);
auto additional_value = additional_product->resolve(context);
if (!total.has_value()) {
total = additional_value;
continue;
}
total->add(additional_value, context, percentage_basis);
total->add(additional_value);
}
return total.value();
@ -350,17 +350,17 @@ bool ProductCalculationNode::contains_percentage() const
return false;
}
CalculatedStyleValue::CalculationResult ProductCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult ProductCalculationNode::resolve(CalculationResolutionContext const& context) const
{
Optional<CalculatedStyleValue::CalculationResult> total;
for (auto& additional_product : m_values) {
auto additional_value = additional_product->resolve(context, percentage_basis);
auto additional_value = additional_product->resolve(context);
if (!total.has_value()) {
total = additional_value;
continue;
}
total->multiply_by(additional_value, context);
total->multiply_by(additional_value);
}
return total.value();
@ -412,9 +412,9 @@ bool NegateCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult NegateCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult NegateCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto child_value = m_value->resolve(context, percentage_basis);
auto child_value = m_value->resolve(context);
child_value.negate();
return child_value;
}
@ -464,9 +464,9 @@ bool InvertCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult InvertCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult InvertCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto child_value = m_value->resolve(context, percentage_basis);
auto child_value = m_value->resolve(context);
child_value.invert();
return child_value;
}
@ -525,13 +525,13 @@ bool MinCalculationNode::contains_percentage() const
return false;
}
CalculatedStyleValue::CalculationResult MinCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult MinCalculationNode::resolve(CalculationResolutionContext const& context) const
{
CalculatedStyleValue::CalculationResult smallest_node = m_values.first()->resolve(context, percentage_basis);
CalculatedStyleValue::CalculationResult smallest_node = m_values.first()->resolve(context);
auto smallest_value = smallest_node.value();
for (size_t i = 1; i < m_values.size(); i++) {
auto child_resolved = m_values[i]->resolve(context, percentage_basis);
auto child_resolved = m_values[i]->resolve(context);
auto child_value = child_resolved.value();
if (child_value < smallest_value) {
@ -604,13 +604,13 @@ bool MaxCalculationNode::contains_percentage() const
return false;
}
CalculatedStyleValue::CalculationResult MaxCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult MaxCalculationNode::resolve(CalculationResolutionContext const& context) const
{
CalculatedStyleValue::CalculationResult largest_node = m_values.first()->resolve(context, percentage_basis);
CalculatedStyleValue::CalculationResult largest_node = m_values.first()->resolve(context);
auto largest_value = largest_node.value();
for (size_t i = 1; i < m_values.size(); i++) {
auto child_resolved = m_values[i]->resolve(context, percentage_basis);
auto child_resolved = m_values[i]->resolve(context);
auto child_value = child_resolved.value();
if (child_value > largest_value) {
@ -680,11 +680,11 @@ bool ClampCalculationNode::contains_percentage() const
return m_min_value->contains_percentage() || m_center_value->contains_percentage() || m_max_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult ClampCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult ClampCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto min_node = m_min_value->resolve(context, percentage_basis);
auto center_node = m_center_value->resolve(context, percentage_basis);
auto max_node = m_max_value->resolve(context, percentage_basis);
auto min_node = m_min_value->resolve(context);
auto center_node = m_center_value->resolve(context);
auto max_node = m_max_value->resolve(context);
auto min_value = min_node.value();
auto center_value = center_node.value();
@ -750,9 +750,9 @@ bool AbsCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult AbsCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult AbsCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
if (node_a.value() < 0)
node_a.negate();
return node_a;
@ -801,9 +801,9 @@ bool SignCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult SignCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult SignCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto node_a_value = node_a.value();
if (node_a_value < 0)
@ -864,7 +864,7 @@ String ConstantCalculationNode::to_string() const
VERIFY_NOT_REACHED();
}
CalculatedStyleValue::CalculationResult ConstantCalculationNode::resolve([[maybe_unused]] Optional<Length::ResolutionContext const&> context, [[maybe_unused]] CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult ConstantCalculationNode::resolve(CalculationResolutionContext const&) const
{
switch (m_constant) {
case ConstantType::E:
@ -925,9 +925,9 @@ bool SinCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult SinCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult SinCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto node_a_value = AK::to_radians(node_a.value());
auto result = sin(node_a_value);
@ -977,9 +977,9 @@ bool CosCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult CosCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult CosCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto node_a_value = AK::to_radians(node_a.value());
auto result = cos(node_a_value);
@ -1029,9 +1029,9 @@ bool TanCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult TanCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult TanCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto node_a_value = AK::to_radians(node_a.value());
auto result = tan(node_a_value);
@ -1081,9 +1081,9 @@ bool AsinCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult AsinCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult AsinCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto result = AK::to_degrees(asin(node_a.value()));
return { result, CSSNumericType { CSSNumericType::BaseType::Angle, 1 } };
}
@ -1131,9 +1131,9 @@ bool AcosCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult AcosCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult AcosCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto result = AK::to_degrees(acos(node_a.value()));
return { result, CSSNumericType { CSSNumericType::BaseType::Angle, 1 } };
}
@ -1181,9 +1181,9 @@ bool AtanCalculationNode::contains_percentage() const
return m_value->contains_percentage();
}
CalculatedStyleValue::CalculationResult AtanCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult AtanCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto result = AK::to_degrees(atan(node_a.value()));
return { result, CSSNumericType { CSSNumericType::BaseType::Angle, 1 } };
}
@ -1234,10 +1234,10 @@ bool Atan2CalculationNode::contains_percentage() const
return m_y->contains_percentage() || m_x->contains_percentage();
}
CalculatedStyleValue::CalculationResult Atan2CalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult Atan2CalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_y->resolve(context, percentage_basis);
auto node_b = m_x->resolve(context, percentage_basis);
auto node_a = m_y->resolve(context);
auto node_b = m_x->resolve(context);
auto result = AK::to_degrees(atan2(node_a.value(), node_b.value()));
return { result, CSSNumericType { CSSNumericType::BaseType::Angle, 1 } };
}
@ -1284,10 +1284,10 @@ String PowCalculationNode::to_string() const
return MUST(builder.to_string());
}
CalculatedStyleValue::CalculationResult PowCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult PowCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_x->resolve(context, percentage_basis);
auto node_b = m_y->resolve(context, percentage_basis);
auto node_a = m_x->resolve(context);
auto node_b = m_y->resolve(context);
auto result = pow(node_a.value(), node_b.value());
return { result, CSSNumericType {} };
}
@ -1331,9 +1331,9 @@ String SqrtCalculationNode::to_string() const
return MUST(builder.to_string());
}
CalculatedStyleValue::CalculationResult SqrtCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult SqrtCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto result = sqrt(node_a.value());
return { result, CSSNumericType {} };
}
@ -1391,13 +1391,13 @@ bool HypotCalculationNode::contains_percentage() const
return false;
}
CalculatedStyleValue::CalculationResult HypotCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult HypotCalculationNode::resolve(CalculationResolutionContext const& context) const
{
double square_sum = 0.0;
Optional<CSSNumericType> result_type;
for (auto const& value : m_values) {
auto child_resolved = value->resolve(context, percentage_basis);
auto child_resolved = value->resolve(context);
auto child_value = child_resolved.value();
square_sum += child_value * child_value;
@ -1459,10 +1459,10 @@ String LogCalculationNode::to_string() const
return MUST(builder.to_string());
}
CalculatedStyleValue::CalculationResult LogCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult LogCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_x->resolve(context, percentage_basis);
auto node_b = m_y->resolve(context, percentage_basis);
auto node_a = m_x->resolve(context);
auto node_b = m_y->resolve(context);
auto result = log2(node_a.value()) / log2(node_b.value());
return { result, CSSNumericType {} };
}
@ -1506,9 +1506,9 @@ String ExpCalculationNode::to_string() const
return MUST(builder.to_string());
}
CalculatedStyleValue::CalculationResult ExpCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult ExpCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_value->resolve(context, percentage_basis);
auto node_a = m_value->resolve(context);
auto result = exp(node_a.value());
return { result, CSSNumericType {} };
}
@ -1563,10 +1563,10 @@ bool RoundCalculationNode::contains_percentage() const
return m_x->contains_percentage() || m_y->contains_percentage();
}
CalculatedStyleValue::CalculationResult RoundCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult RoundCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_x->resolve(context, percentage_basis);
auto node_b = m_y->resolve(context, percentage_basis);
auto node_a = m_x->resolve(context);
auto node_b = m_y->resolve(context);
auto node_a_value = node_a.value();
auto node_b_value = node_b.value();
@ -1650,10 +1650,10 @@ bool ModCalculationNode::contains_percentage() const
return m_x->contains_percentage() || m_y->contains_percentage();
}
CalculatedStyleValue::CalculationResult ModCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult ModCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_x->resolve(context, percentage_basis);
auto node_b = m_y->resolve(context, percentage_basis);
auto node_a = m_x->resolve(context);
auto node_b = m_y->resolve(context);
auto node_a_value = node_a.value();
auto node_b_value = node_b.value();
@ -1711,10 +1711,10 @@ bool RemCalculationNode::contains_percentage() const
return m_x->contains_percentage() || m_y->contains_percentage();
}
CalculatedStyleValue::CalculationResult RemCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
CalculatedStyleValue::CalculationResult RemCalculationNode::resolve(CalculationResolutionContext const& context) const
{
auto node_a = m_x->resolve(context, percentage_basis);
auto node_b = m_y->resolve(context, percentage_basis);
auto node_a = m_x->resolve(context);
auto node_b = m_y->resolve(context);
auto value = fmod(node_a.value(), node_b.value());
return { value, node_a.type() };
}
@ -1734,7 +1734,7 @@ bool RemCalculationNode::equals(CalculationNode const& other) const
&& m_y->equals(*static_cast<RemCalculationNode const&>(other).m_y);
}
CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult::from_value(Value const& value, Optional<Length::ResolutionContext const&> context, Optional<CSSNumericType> numeric_type)
CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult::from_value(Value const& value, CalculationResolutionContext const& context, Optional<CSSNumericType> numeric_type)
{
auto const expected_numeric_type = numeric_type_from_calculated_style_value(value, {});
if (numeric_type.has_value()) {
@ -1755,12 +1755,12 @@ CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult:
return length.absolute_length_to_px().to_double();
// If we don't have a context, we cant resolve the length, so return NAN
if (!context.has_value()) {
if (!context.length_resolution_context.has_value()) {
dbgln("Failed to resolve length, likely due to calc() being used with relative units and a property not taking it into account");
return AK::NaN<double>;
}
return length.to_px(*context).to_double();
return length.to_px(context.length_resolution_context.value()).to_double();
},
[](Resolution const& resolution) { return resolution.to_dots_per_pixel(); },
[](Time const& time) { return time.to_seconds(); },
@ -1769,25 +1769,25 @@ CalculatedStyleValue::CalculationResult CalculatedStyleValue::CalculationResult:
return CalculationResult { number, numeric_type };
}
void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other, Optional<Length::ResolutionContext const&>, PercentageBasis const&)
void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other)
{
m_value = m_value + other.m_value;
m_type = m_type.has_value() && other.m_type.has_value() ? m_type->added_to(*other.m_type) : OptionalNone {};
}
void CalculatedStyleValue::CalculationResult::subtract(CalculationResult const& other, Optional<Length::ResolutionContext const&>, PercentageBasis const&)
void CalculatedStyleValue::CalculationResult::subtract(CalculationResult const& other)
{
m_value = m_value - other.m_value;
m_type = m_type.has_value() && other.m_type.has_value() ? m_type->added_to(*other.m_type) : OptionalNone {};
}
void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult const& other, Optional<Length::ResolutionContext const&>)
void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult const& other)
{
m_value = m_value * other.m_value;
m_type = m_type.has_value() && other.m_type.has_value() ? m_type->multiplied_by(*other.m_type) : OptionalNone {};
}
void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const& other, Optional<Length::ResolutionContext const&>)
void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const& other)
{
auto other_copy = other;
other_copy.invert();
@ -1822,164 +1822,78 @@ bool CalculatedStyleValue::equals(CSSStyleValue const& other) const
return m_calculation->equals(*other.as_calculated().m_calculation);
}
Optional<Angle> CalculatedStyleValue::resolve_angle() const
Optional<Angle> CalculatedStyleValue::resolve_angle(CalculationResolutionContext const& context) const
{
auto result = m_calculation->resolve({}, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_angle(m_context.percentages_resolve_as))
return Angle::make_degrees(result.value());
return {};
}
Optional<Angle> CalculatedStyleValue::resolve_angle(Layout::Node const& layout_node) const
Optional<Flex> CalculatedStyleValue::resolve_flex(CalculationResolutionContext const& context) const
{
return resolve_angle(Length::ResolutionContext::for_layout_node(layout_node));
}
Optional<Angle> CalculatedStyleValue::resolve_angle(Length::ResolutionContext const& context) const
{
auto result = m_calculation->resolve(context, {});
if (result.type().has_value() && result.type()->matches_angle(m_context.percentages_resolve_as))
return Angle::make_degrees(result.value());
return {};
}
Optional<Angle> CalculatedStyleValue::resolve_angle_percentage(Angle const& percentage_basis) const
{
auto result = m_calculation->resolve({}, percentage_basis);
if (result.type().has_value() && result.type()->matches_angle(m_context.percentages_resolve_as))
return Angle::make_degrees(result.value());
return {};
}
Optional<Flex> CalculatedStyleValue::resolve_flex() const
{
auto result = m_calculation->resolve({}, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_flex(m_context.percentages_resolve_as))
return Flex::make_fr(result.value());
return {};
}
Optional<Frequency> CalculatedStyleValue::resolve_frequency() const
Optional<Frequency> CalculatedStyleValue::resolve_frequency(CalculationResolutionContext const& context) const
{
auto result = m_calculation->resolve({}, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_frequency(m_context.percentages_resolve_as))
return Frequency::make_hertz(result.value());
return {};
}
Optional<Frequency> CalculatedStyleValue::resolve_frequency_percentage(Frequency const& percentage_basis) const
Optional<Length> CalculatedStyleValue::resolve_length(CalculationResolutionContext const& context) const
{
auto result = m_calculation->resolve({}, percentage_basis);
if (result.type().has_value() && result.type()->matches_frequency(m_context.percentages_resolve_as))
return Frequency::make_hertz(result.value());
return {};
}
Optional<Length> CalculatedStyleValue::resolve_length(Length::ResolutionContext const& context) const
{
auto result = m_calculation->resolve(context, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_length(m_context.percentages_resolve_as))
return Length::make_px(CSSPixels { result.value() });
return {};
}
Optional<Length> CalculatedStyleValue::resolve_length(Layout::Node const& layout_node) const
Optional<Percentage> CalculatedStyleValue::resolve_percentage(CalculationResolutionContext const& context) const
{
return resolve_length(Length::ResolutionContext::for_layout_node(layout_node));
}
Optional<Length> CalculatedStyleValue::resolve_length_percentage(Layout::Node const& layout_node, Length const& percentage_basis) const
{
return resolve_length_percentage(Length::ResolutionContext::for_layout_node(layout_node), percentage_basis);
}
Optional<Length> CalculatedStyleValue::resolve_length_percentage(Layout::Node const& layout_node, CSSPixels percentage_basis) const
{
return resolve_length_percentage(Length::ResolutionContext::for_layout_node(layout_node), Length::make_px(percentage_basis));
}
Optional<Length> CalculatedStyleValue::resolve_length_percentage(Length::ResolutionContext const& resolution_context, Length const& percentage_basis) const
{
auto result = m_calculation->resolve(resolution_context, percentage_basis);
if (result.type().has_value() && result.type()->matches_length(m_context.percentages_resolve_as))
return Length::make_px(CSSPixels { result.value() });
return {};
}
Optional<Percentage> CalculatedStyleValue::resolve_percentage() const
{
auto result = m_calculation->resolve({}, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_percentage())
return Percentage { result.value() };
return {};
}
Optional<Resolution> CalculatedStyleValue::resolve_resolution() const
Optional<Resolution> CalculatedStyleValue::resolve_resolution(CalculationResolutionContext const& context) const
{
auto result = m_calculation->resolve({}, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_resolution(m_context.percentages_resolve_as))
return Resolution::make_dots_per_pixel(result.value());
return {};
}
Optional<Time> CalculatedStyleValue::resolve_time() const
Optional<Time> CalculatedStyleValue::resolve_time(CalculationResolutionContext const& context) const
{
auto result = m_calculation->resolve({}, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_time(m_context.percentages_resolve_as))
return Time::make_seconds(result.value());
return {};
}
Optional<Time> CalculatedStyleValue::resolve_time_percentage(Time const& percentage_basis) const
Optional<double> CalculatedStyleValue::resolve_number(CalculationResolutionContext const& context) const
{
auto result = m_calculation->resolve({}, percentage_basis);
if (result.type().has_value() && result.type()->matches_time(m_context.percentages_resolve_as))
return Time::make_seconds(result.value());
return {};
}
Optional<double> CalculatedStyleValue::resolve_number() const
{
auto result = m_calculation->resolve({}, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_number(m_context.percentages_resolve_as))
return result.value();
return {};
}
Optional<double> CalculatedStyleValue::resolve_number(Length::ResolutionContext const& context) const
Optional<i64> CalculatedStyleValue::resolve_integer(CalculationResolutionContext const& context) const
{
auto result = m_calculation->resolve(context, {});
if (result.type().has_value() && result.type()->matches_number(m_context.percentages_resolve_as))
return result.value();
return {};
}
Optional<double> CalculatedStyleValue::resolve_number(Layout::Node const& layout_node) const
{
return resolve_number(Length::ResolutionContext::for_layout_node(layout_node));
}
Optional<i64> CalculatedStyleValue::resolve_integer() const
{
auto result = m_calculation->resolve({}, {});
auto result = m_calculation->resolve(context);
if (result.type().has_value() && result.type()->matches_number(m_context.percentages_resolve_as))
return llround(result.value());
return {};
}
Optional<i64> CalculatedStyleValue::resolve_integer(Length::ResolutionContext const& context) const
{
auto result = m_calculation->resolve(context, {});
if (result.type().has_value() && result.type()->matches_number(m_context.percentages_resolve_as))
return llround(result.value());
return {};
}
Optional<i64> CalculatedStyleValue::resolve_integer(Layout::Node const& layout_node) const
{
return resolve_integer(Length::ResolutionContext::for_layout_node(layout_node));
}
bool CalculatedStyleValue::contains_percentage() const
{
return m_calculation->contains_percentage();

View file

@ -1,7 +1,7 @@
/*
* Copyright (c) 2018-2020, Andreas Kling <andreas@ladybird.org>
* Copyright (c) 2021, Tobias Christiansen <tobyase@serenityos.org>
* Copyright (c) 2021-2024, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2021-2025, Sam Atkins <sam@ladybird.org>
* Copyright (c) 2022-2023, MacDue <macdue@dueutil.tech>
*
* SPDX-License-Identifier: BSD-2-Clause
@ -25,18 +25,22 @@ namespace Web::CSS {
class CalculationNode;
// https://drafts.csswg.org/css-values-4/#ref-for-calc-calculation%E2%91%A2%E2%91%A7
// Contains the context available at parse-time.
struct CalculationContext {
Optional<ValueType> percentages_resolve_as {};
};
// Contains the context for resolving the calculation.
struct CalculationResolutionContext {
Variant<Empty, Angle, Frequency, Length, Time> percentage_basis {};
Optional<Length::ResolutionContext> length_resolution_context;
};
class CalculatedStyleValue : public CSSStyleValue {
public:
using PercentageBasis = Variant<Empty, Angle, Frequency, Length, Time>;
class CalculationResult {
public:
using Value = Variant<Number, Angle, Flex, Frequency, Length, Percentage, Resolution, Time>;
static CalculationResult from_value(Value const&, Optional<Length::ResolutionContext const&>, Optional<CSSNumericType>);
static CalculationResult from_value(Value const&, CalculationResolutionContext const&, Optional<CSSNumericType>);
CalculationResult(double value, Optional<CSSNumericType> type)
: m_value(value)
@ -44,10 +48,10 @@ public:
{
}
void add(CalculationResult const& other, Optional<Length::ResolutionContext const&>, PercentageBasis const& percentage_basis);
void subtract(CalculationResult const& other, Optional<Length::ResolutionContext const&>, PercentageBasis const& percentage_basis);
void multiply_by(CalculationResult const& other, Optional<Length::ResolutionContext const&>);
void divide_by(CalculationResult const& other, Optional<Length::ResolutionContext const&>);
void add(CalculationResult const& other);
void subtract(CalculationResult const& other);
void multiply_by(CalculationResult const& other);
void divide_by(CalculationResult const& other);
void negate();
void invert();
@ -71,45 +75,32 @@ public:
bool resolves_to_angle() const { return m_resolved_type.matches_angle(m_context.percentages_resolve_as); }
bool resolves_to_angle_percentage() const { return m_resolved_type.matches_angle_percentage(m_context.percentages_resolve_as); }
Optional<Angle> resolve_angle() const;
Optional<Angle> resolve_angle(Layout::Node const& layout_node) const;
Optional<Angle> resolve_angle(Length::ResolutionContext const& context) const;
Optional<Angle> resolve_angle_percentage(Angle const& percentage_basis) const;
Optional<Angle> resolve_angle(CalculationResolutionContext const&) const;
bool resolves_to_flex() const { return m_resolved_type.matches_flex(m_context.percentages_resolve_as); }
Optional<Flex> resolve_flex() const;
Optional<Flex> resolve_flex(CalculationResolutionContext const&) const;
bool resolves_to_frequency() const { return m_resolved_type.matches_frequency(m_context.percentages_resolve_as); }
bool resolves_to_frequency_percentage() const { return m_resolved_type.matches_frequency_percentage(m_context.percentages_resolve_as); }
Optional<Frequency> resolve_frequency() const;
Optional<Frequency> resolve_frequency_percentage(Frequency const& percentage_basis) const;
Optional<Frequency> resolve_frequency(CalculationResolutionContext const&) const;
bool resolves_to_length() const { return m_resolved_type.matches_length(m_context.percentages_resolve_as); }
bool resolves_to_length_percentage() const { return m_resolved_type.matches_length_percentage(m_context.percentages_resolve_as); }
Optional<Length> resolve_length(Length::ResolutionContext const&) const;
Optional<Length> resolve_length(Layout::Node const& layout_node) const;
Optional<Length> resolve_length_percentage(Layout::Node const&, Length const& percentage_basis) const;
Optional<Length> resolve_length_percentage(Layout::Node const&, CSSPixels percentage_basis) const;
Optional<Length> resolve_length_percentage(Length::ResolutionContext const&, Length const& percentage_basis) const;
Optional<Length> resolve_length(CalculationResolutionContext const&) const;
bool resolves_to_percentage() const { return m_resolved_type.matches_percentage(); }
Optional<Percentage> resolve_percentage() const;
Optional<Percentage> resolve_percentage(CalculationResolutionContext const&) const;
bool resolves_to_resolution() const { return m_resolved_type.matches_resolution(m_context.percentages_resolve_as); }
Optional<Resolution> resolve_resolution() const;
Optional<Resolution> resolve_resolution(CalculationResolutionContext const&) const;
bool resolves_to_time() const { return m_resolved_type.matches_time(m_context.percentages_resolve_as); }
bool resolves_to_time_percentage() const { return m_resolved_type.matches_time_percentage(m_context.percentages_resolve_as); }
Optional<Time> resolve_time() const;
Optional<Time> resolve_time_percentage(Time const& percentage_basis) const;
Optional<Time> resolve_time(CalculationResolutionContext const&) const;
bool resolves_to_number() const { return m_resolved_type.matches_number(m_context.percentages_resolve_as); }
Optional<double> resolve_number() const;
Optional<double> resolve_number(Length::ResolutionContext const&) const;
Optional<double> resolve_number(Layout::Node const& layout_node) const;
Optional<i64> resolve_integer() const;
Optional<i64> resolve_integer(Length::ResolutionContext const&) const;
Optional<i64> resolve_integer(Layout::Node const& layout_node) const;
Optional<double> resolve_number(CalculationResolutionContext const&) const;
Optional<i64> resolve_integer(CalculationResolutionContext const&) const;
bool resolves_to_dimension() const { return m_resolved_type.matches_dimension(); }
@ -249,7 +240,7 @@ public:
virtual String to_string() const = 0;
Optional<CSSNumericType> const& numeric_type() const { return m_numeric_type; }
virtual bool contains_percentage() const = 0;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const = 0;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const = 0;
virtual void dump(StringBuilder&, int indent) const = 0;
virtual bool equals(CalculationNode const&) const = 0;
@ -269,7 +260,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -286,7 +277,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -303,7 +294,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -320,7 +311,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -337,7 +328,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -354,7 +345,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -371,7 +362,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -388,7 +379,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -407,7 +398,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -424,7 +415,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -441,7 +432,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override { return false; }
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -458,7 +449,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -475,7 +466,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -492,7 +483,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -509,7 +500,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -526,7 +517,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -543,7 +534,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -560,7 +551,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -578,7 +569,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override { return false; }
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -596,7 +587,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override { return false; }
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -613,7 +604,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -630,7 +621,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override { return false; }
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -648,7 +639,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override { return false; }
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -665,7 +656,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -684,7 +675,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;
@ -702,7 +693,7 @@ public:
virtual String to_string() const override;
virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual CalculatedStyleValue::CalculationResult resolve(CalculationResolutionContext const&) const override;
virtual void dump(StringBuilder&, int indent) const override;
virtual bool equals(CalculationNode const&) const override;

View file

@ -43,11 +43,12 @@ float FilterOperation::Color::resolved_amount() const
return amount->percentage().as_fraction();
if (amount->is_calculated()) {
CalculationResolutionContext context {};
if (amount->calculated()->resolves_to_number())
return amount->calculated()->resolve_number().value();
return amount->calculated()->resolve_number(context).value();
if (amount->calculated()->resolves_to_percentage())
return amount->calculated()->resolve_percentage()->as_fraction();
return amount->calculated()->resolve_percentage(context)->as_fraction();
}
VERIFY_NOT_REACHED();

View file

@ -70,7 +70,7 @@ String TransformationStyleValue::to_string(SerializationMode mode) const
if (value->is_number())
return value->as_number().number();
if (value->is_calculated() && value->as_calculated().resolves_to_number())
return value->as_calculated().resolve_number();
return value->as_calculated().resolve_number({});
VERIFY_NOT_REACHED();
};