1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-26 02:27:43 +00:00

LibWeb: Add a way to resolve calc() values without a layout node

Instead of a layout node, you can pass a new Length::ResolutionContext
struct which contains everything needed to resolve calc() lengths.
This commit is contained in:
Andreas Kling 2023-06-02 12:39:39 +02:00
parent 2ade229f27
commit df8a96ee00
5 changed files with 107 additions and 75 deletions

View file

@ -144,6 +144,23 @@ CSSPixels Length::viewport_relative_length_to_px(CSSPixelRect const& viewport_re
} }
} }
Length::ResolutionContext Length::ResolutionContext::for_layout_node(Layout::Node const& node)
{
auto const* root_element = node.document().document_element();
VERIFY(root_element);
VERIFY(root_element->layout_node());
return Length::ResolutionContext {
.viewport_rect = node.browsing_context().viewport_rect(),
.font_metrics = { node.computed_values().font_size(), node.font().pixel_metrics(), node.line_height() },
.root_font_metrics = { root_element->layout_node()->computed_values().font_size(), root_element->layout_node()->font().pixel_metrics(), root_element->layout_node()->line_height() },
};
}
CSSPixels Length::to_px(ResolutionContext const& context) const
{
return to_px(context.viewport_rect, context.font_metrics, context.root_font_metrics);
}
CSSPixels Length::to_px(Layout::Node const& layout_node) const CSSPixels Length::to_px(Layout::Node const& layout_node) const
{ {
if (is_auto()) { if (is_auto()) {

View file

@ -9,6 +9,7 @@
#include <AK/String.h> #include <AK/String.h>
#include <LibGfx/Forward.h> #include <LibGfx/Forward.h>
#include <LibGfx/Rect.h>
#include <LibWeb/Forward.h> #include <LibWeb/Forward.h>
#include <LibWeb/PixelUnits.h> #include <LibWeb/PixelUnits.h>
@ -156,6 +157,16 @@ public:
Type type() const { return m_type; } Type type() const { return m_type; }
double raw_value() const { return m_value; } double raw_value() const { return m_value; }
struct ResolutionContext {
[[nodiscard]] static Length::ResolutionContext for_layout_node(Layout::Node const&);
CSSPixelRect viewport_rect;
FontMetrics font_metrics;
FontMetrics root_font_metrics;
};
[[nodiscard]] CSSPixels to_px(ResolutionContext const&) const;
CSSPixels to_px(Layout::Node const&) const; CSSPixels to_px(Layout::Node const&) const;
ALWAYS_INLINE CSSPixels to_px(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const ALWAYS_INLINE CSSPixels to_px(CSSPixelRect const& viewport_rect, FontMetrics const& font_metrics, FontMetrics const& root_font_metrics) const

View file

@ -8022,7 +8022,7 @@ public:
virtual ErrorOr<String> to_string() const override { VERIFY_NOT_REACHED(); } virtual ErrorOr<String> to_string() const override { VERIFY_NOT_REACHED(); }
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override { VERIFY_NOT_REACHED(); } virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override { VERIFY_NOT_REACHED(); }
virtual bool contains_percentage() const override { VERIFY_NOT_REACHED(); } virtual bool contains_percentage() const override { VERIFY_NOT_REACHED(); }
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override { VERIFY_NOT_REACHED(); } virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override { VERIFY_NOT_REACHED(); }
virtual ErrorOr<void> dump(StringBuilder& builder, int indent) const override virtual ErrorOr<void> dump(StringBuilder& builder, int indent) const override
{ {

View file

@ -24,13 +24,13 @@ static bool is_dimension(CalculatedStyleValue::ResolvedType type)
&& type != CalculatedStyleValue::ResolvedType::Percentage; && type != CalculatedStyleValue::ResolvedType::Percentage;
} }
static double resolve_value(CalculatedStyleValue::CalculationResult::Value value, Layout::Node const* layout_node) static double resolve_value(CalculatedStyleValue::CalculationResult::Value value, Optional<Length::ResolutionContext const&> context)
{ {
return value.visit( return value.visit(
[](Number const& number) { return number.value(); }, [](Number const& number) { return number.value(); },
[](Angle const& angle) { return angle.to_degrees(); }, [](Angle const& angle) { return angle.to_degrees(); },
[](Frequency const& frequency) { return frequency.to_hertz(); }, [](Frequency const& frequency) { return frequency.to_hertz(); },
[layout_node](Length const& length) { return length.to_px(*layout_node).value(); }, [&context](Length const& length) { return length.to_px(*context).value(); },
[](Percentage const& percentage) { return percentage.value(); }, [](Percentage const& percentage) { return percentage.value(); },
[](Time const& time) { return time.to_seconds(); }); [](Time const& time) { return time.to_seconds(); });
}; };
@ -76,7 +76,7 @@ bool NumericCalculationNode::contains_percentage() const
return m_value.has<Percentage>(); return m_value.has<Percentage>();
} }
CalculatedStyleValue::CalculationResult NumericCalculationNode::resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const CalculatedStyleValue::CalculationResult NumericCalculationNode::resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const
{ {
return m_value; return m_value;
} }
@ -164,17 +164,17 @@ bool SumCalculationNode::contains_percentage() const
return false; return false;
} }
CalculatedStyleValue::CalculationResult SumCalculationNode::resolve(Layout::Node const* layout_node, CalculatedStyleValue::PercentageBasis const& percentage_basis) const CalculatedStyleValue::CalculationResult SumCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
{ {
Optional<CalculatedStyleValue::CalculationResult> total; Optional<CalculatedStyleValue::CalculationResult> total;
for (auto& additional_product : m_values) { for (auto& additional_product : m_values) {
auto additional_value = additional_product->resolve(layout_node, percentage_basis); auto additional_value = additional_product->resolve(context, percentage_basis);
if (!total.has_value()) { if (!total.has_value()) {
total = additional_value; total = additional_value;
continue; continue;
} }
total->add(additional_value, layout_node, percentage_basis); total->add(additional_value, context, percentage_basis);
} }
return total.value(); return total.value();
@ -266,17 +266,17 @@ bool ProductCalculationNode::contains_percentage() const
return false; return false;
} }
CalculatedStyleValue::CalculationResult ProductCalculationNode::resolve(Layout::Node const* layout_node, CalculatedStyleValue::PercentageBasis const& percentage_basis) const CalculatedStyleValue::CalculationResult ProductCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
{ {
Optional<CalculatedStyleValue::CalculationResult> total; Optional<CalculatedStyleValue::CalculationResult> total;
for (auto& additional_product : m_values) { for (auto& additional_product : m_values) {
auto additional_value = additional_product->resolve(layout_node, percentage_basis); auto additional_value = additional_product->resolve(context, percentage_basis);
if (!total.has_value()) { if (!total.has_value()) {
total = additional_value; total = additional_value;
continue; continue;
} }
total->multiply_by(additional_value, layout_node); total->multiply_by(additional_value, context);
} }
return total.value(); return total.value();
@ -328,9 +328,9 @@ bool NegateCalculationNode::contains_percentage() const
return m_value->contains_percentage(); return m_value->contains_percentage();
} }
CalculatedStyleValue::CalculationResult NegateCalculationNode::resolve(Layout::Node const* layout_node, CalculatedStyleValue::PercentageBasis const& percentage_basis) const CalculatedStyleValue::CalculationResult NegateCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
{ {
auto child_value = m_value->resolve(layout_node, percentage_basis); auto child_value = m_value->resolve(context, percentage_basis);
child_value.negate(); child_value.negate();
return child_value; return child_value;
} }
@ -380,9 +380,9 @@ bool InvertCalculationNode::contains_percentage() const
return m_value->contains_percentage(); return m_value->contains_percentage();
} }
CalculatedStyleValue::CalculationResult InvertCalculationNode::resolve(Layout::Node const* layout_node, CalculatedStyleValue::PercentageBasis const& percentage_basis) const CalculatedStyleValue::CalculationResult InvertCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
{ {
auto child_value = m_value->resolve(layout_node, percentage_basis); auto child_value = m_value->resolve(context, percentage_basis);
child_value.invert(); child_value.invert();
return child_value; return child_value;
} }
@ -443,14 +443,14 @@ bool MinCalculationNode::contains_percentage() const
return false; return false;
} }
CalculatedStyleValue::CalculationResult MinCalculationNode::resolve(Layout::Node const* layout_node, CalculatedStyleValue::PercentageBasis const& percentage_basis) const CalculatedStyleValue::CalculationResult MinCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
{ {
CalculatedStyleValue::CalculationResult smallest_node = m_values.first()->resolve(layout_node, percentage_basis); CalculatedStyleValue::CalculationResult smallest_node = m_values.first()->resolve(context, percentage_basis);
auto smallest_value = resolve_value(smallest_node.value(), layout_node); auto smallest_value = resolve_value(smallest_node.value(), context);
for (size_t i = 1; i < m_values.size(); i++) { for (size_t i = 1; i < m_values.size(); i++) {
auto child_resolved = m_values[i]->resolve(layout_node, percentage_basis); auto child_resolved = m_values[i]->resolve(context, percentage_basis);
auto child_value = resolve_value(child_resolved.value(), layout_node); auto child_value = resolve_value(child_resolved.value(), context);
if (child_value < smallest_value) { if (child_value < smallest_value) {
smallest_value = child_value; smallest_value = child_value;
@ -521,14 +521,14 @@ bool MaxCalculationNode::contains_percentage() const
return false; return false;
} }
CalculatedStyleValue::CalculationResult MaxCalculationNode::resolve(Layout::Node const* layout_node, CalculatedStyleValue::PercentageBasis const& percentage_basis) const CalculatedStyleValue::CalculationResult MaxCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
{ {
CalculatedStyleValue::CalculationResult largest_node = m_values.first()->resolve(layout_node, percentage_basis); CalculatedStyleValue::CalculationResult largest_node = m_values.first()->resolve(context, percentage_basis);
auto largest_value = resolve_value(largest_node.value(), layout_node); auto largest_value = resolve_value(largest_node.value(), context);
for (size_t i = 1; i < m_values.size(); i++) { for (size_t i = 1; i < m_values.size(); i++) {
auto child_resolved = m_values[i]->resolve(layout_node, percentage_basis); auto child_resolved = m_values[i]->resolve(context, percentage_basis);
auto child_value = resolve_value(child_resolved.value(), layout_node); auto child_value = resolve_value(child_resolved.value(), context);
if (child_value > largest_value) { if (child_value > largest_value) {
largest_value = child_value; largest_value = child_value;
@ -596,15 +596,15 @@ bool ClampCalculationNode::contains_percentage() const
return m_min_value->contains_percentage() || m_center_value->contains_percentage() || m_max_value->contains_percentage(); return m_min_value->contains_percentage() || m_center_value->contains_percentage() || m_max_value->contains_percentage();
} }
CalculatedStyleValue::CalculationResult ClampCalculationNode::resolve(Layout::Node const* layout_node, CalculatedStyleValue::PercentageBasis const& percentage_basis) const CalculatedStyleValue::CalculationResult ClampCalculationNode::resolve(Optional<Length::ResolutionContext const&> context, CalculatedStyleValue::PercentageBasis const& percentage_basis) const
{ {
auto min_node = m_min_value->resolve(layout_node, percentage_basis); auto min_node = m_min_value->resolve(context, percentage_basis);
auto center_node = m_center_value->resolve(layout_node, percentage_basis); auto center_node = m_center_value->resolve(context, percentage_basis);
auto max_node = m_max_value->resolve(layout_node, percentage_basis); auto max_node = m_max_value->resolve(context, percentage_basis);
auto min_value = resolve_value(min_node.value(), layout_node); auto min_value = resolve_value(min_node.value(), context);
auto center_value = resolve_value(center_node.value(), layout_node); auto center_value = resolve_value(center_node.value(), context);
auto max_value = resolve_value(max_node.value(), layout_node); auto max_value = resolve_value(max_node.value(), context);
// NOTE: The value should be returned as "max(MIN, min(VAL, MAX))" // NOTE: The value should be returned as "max(MIN, min(VAL, MAX))"
auto chosen_value = max(min_value, min(center_value, max_value)); auto chosen_value = max(min_value, min(center_value, max_value));
@ -639,17 +639,17 @@ ErrorOr<void> ClampCalculationNode::dump(StringBuilder& builder, int indent) con
return {}; return {};
} }
void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other, Layout::Node const* layout_node, PercentageBasis const& percentage_basis) void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other, Optional<Length::ResolutionContext const&> context, PercentageBasis const& percentage_basis)
{ {
add_or_subtract_internal(SumOperation::Add, other, layout_node, percentage_basis); add_or_subtract_internal(SumOperation::Add, other, context, percentage_basis);
} }
void CalculatedStyleValue::CalculationResult::subtract(CalculationResult const& other, Layout::Node const* layout_node, PercentageBasis const& percentage_basis) void CalculatedStyleValue::CalculationResult::subtract(CalculationResult const& other, Optional<Length::ResolutionContext const&> context, PercentageBasis const& percentage_basis)
{ {
add_or_subtract_internal(SumOperation::Subtract, other, layout_node, percentage_basis); add_or_subtract_internal(SumOperation::Subtract, other, context, percentage_basis);
} }
void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const* layout_node, PercentageBasis const& percentage_basis) void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperation op, CalculationResult const& other, Optional<Length::ResolutionContext const&> context, PercentageBasis const& percentage_basis)
{ {
// We know from validation when resolving the type, that "both sides have the same type, or that one side is a <number> and the other is an <integer>". // We know from validation when resolving the type, that "both sides have the same type, or that one side is a <number> and the other is an <integer>".
// Though, having the same type may mean that one side is a <dimension> and the other a <percentage>. // Though, having the same type may mean that one side is a <dimension> and the other a <percentage>.
@ -701,9 +701,9 @@ void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperat
} }
}, },
[&](Length const& length) { [&](Length const& length) {
auto this_px = length.to_px(*layout_node); auto this_px = length.to_px(*context);
if (other.m_value.has<Length>()) { if (other.m_value.has<Length>()) {
auto other_px = other.m_value.get<Length>().to_px(*layout_node); auto other_px = other.m_value.get<Length>().to_px(*context);
if (op == SumOperation::Add) if (op == SumOperation::Add)
m_value = Length::make_px(this_px + other_px); m_value = Length::make_px(this_px + other_px);
else else
@ -711,7 +711,7 @@ void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperat
} else { } else {
VERIFY(percentage_basis.has<Length>()); VERIFY(percentage_basis.has<Length>());
auto other_px = percentage_basis.get<Length>().percentage_of(other.m_value.get<Percentage>()).to_px(*layout_node); auto other_px = percentage_basis.get<Length>().percentage_of(other.m_value.get<Percentage>()).to_px(*context);
if (op == SumOperation::Add) if (op == SumOperation::Add)
m_value = Length::make_px(this_px + other_px); m_value = Length::make_px(this_px + other_px);
else else
@ -748,18 +748,18 @@ void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperat
// Other side isn't a percentage, so the easiest way to handle it without duplicating all the logic, is just to swap `this` and `other`. // Other side isn't a percentage, so the easiest way to handle it without duplicating all the logic, is just to swap `this` and `other`.
CalculationResult new_value = other; CalculationResult new_value = other;
if (op == SumOperation::Add) { if (op == SumOperation::Add) {
new_value.add(*this, layout_node, percentage_basis); new_value.add(*this, context, percentage_basis);
} else { } else {
// Turn 'this - other' into '-other + this', as 'A + B == B + A', but 'A - B != B - A' // Turn 'this - other' into '-other + this', as 'A + B == B + A', but 'A - B != B - A'
new_value.multiply_by({ Number { Number::Type::Integer, -1.0f } }, layout_node); new_value.multiply_by({ Number { Number::Type::Integer, -1.0f } }, context);
new_value.add(*this, layout_node, percentage_basis); new_value.add(*this, context, percentage_basis);
} }
*this = new_value; *this = new_value;
}); });
} }
void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult const& other, Layout::Node const* layout_node) void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult const& other, Optional<Length::ResolutionContext const&> context)
{ {
// We know from validation when resolving the type, that at least one side must be a <number> or <integer>. // We know from validation when resolving the type, that at least one side must be a <number> or <integer>.
// Both of these are represented as a double. // Both of these are represented as a double.
@ -773,7 +773,7 @@ void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult cons
} else { } else {
// Avoid duplicating all the logic by swapping `this` and `other`. // Avoid duplicating all the logic by swapping `this` and `other`.
CalculationResult new_value = other; CalculationResult new_value = other;
new_value.multiply_by(*this, layout_node); new_value.multiply_by(*this, context);
*this = new_value; *this = new_value;
} }
}, },
@ -784,8 +784,7 @@ void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult cons
m_value = Frequency::make_hertz(frequency.to_hertz() * other.m_value.get<Number>().value()); m_value = Frequency::make_hertz(frequency.to_hertz() * other.m_value.get<Number>().value());
}, },
[&](Length const& length) { [&](Length const& length) {
VERIFY(layout_node); m_value = Length::make_px(length.to_px(*context) * static_cast<double>(other.m_value.get<Number>().value()));
m_value = Length::make_px(length.to_px(*layout_node) * static_cast<double>(other.m_value.get<Number>().value()));
}, },
[&](Time const& time) { [&](Time const& time) {
m_value = Time::make_seconds(time.to_seconds() * other.m_value.get<Number>().value()); m_value = Time::make_seconds(time.to_seconds() * other.m_value.get<Number>().value());
@ -795,7 +794,7 @@ void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult cons
}); });
} }
void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const& other, Layout::Node const* layout_node) void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const& other, Optional<Length::ResolutionContext const&> context)
{ {
// We know from validation when resolving the type, that `other` must be a <number> or <integer>. // We know from validation when resolving the type, that `other` must be a <number> or <integer>.
// Both of these are represented as a Number. // Both of these are represented as a Number.
@ -817,8 +816,7 @@ void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const&
m_value = Frequency::make_hertz(frequency.to_hertz() / denominator); m_value = Frequency::make_hertz(frequency.to_hertz() / denominator);
}, },
[&](Length const& length) { [&](Length const& length) {
VERIFY(layout_node); m_value = Length::make_px(length.to_px(*context) / static_cast<double>(denominator));
m_value = Length::make_px(length.to_px(*layout_node) / static_cast<double>(denominator));
}, },
[&](Time const& time) { [&](Time const& time) {
m_value = Time::make_seconds(time.to_seconds() / denominator); m_value = Time::make_seconds(time.to_seconds() / denominator);
@ -891,7 +889,7 @@ bool CalculatedStyleValue::equals(StyleValue const& other) const
Optional<Angle> CalculatedStyleValue::resolve_angle() const Optional<Angle> CalculatedStyleValue::resolve_angle() const
{ {
auto result = m_calculation->resolve(nullptr, {}); auto result = m_calculation->resolve({}, {});
if (result.value().has<Angle>()) if (result.value().has<Angle>())
return result.value().get<Angle>(); return result.value().get<Angle>();
@ -900,7 +898,7 @@ Optional<Angle> CalculatedStyleValue::resolve_angle() const
Optional<Angle> CalculatedStyleValue::resolve_angle_percentage(Angle const& percentage_basis) const Optional<Angle> CalculatedStyleValue::resolve_angle_percentage(Angle const& percentage_basis) const
{ {
auto result = m_calculation->resolve(nullptr, percentage_basis); auto result = m_calculation->resolve({}, percentage_basis);
return result.value().visit( return result.value().visit(
[&](Angle const& angle) -> Optional<Angle> { [&](Angle const& angle) -> Optional<Angle> {
@ -916,7 +914,7 @@ Optional<Angle> CalculatedStyleValue::resolve_angle_percentage(Angle const& perc
Optional<Frequency> CalculatedStyleValue::resolve_frequency() const Optional<Frequency> CalculatedStyleValue::resolve_frequency() const
{ {
auto result = m_calculation->resolve(nullptr, {}); auto result = m_calculation->resolve({}, {});
if (result.value().has<Frequency>()) if (result.value().has<Frequency>())
return result.value().get<Frequency>(); return result.value().get<Frequency>();
@ -925,7 +923,7 @@ Optional<Frequency> CalculatedStyleValue::resolve_frequency() const
Optional<Frequency> CalculatedStyleValue::resolve_frequency_percentage(Frequency const& percentage_basis) const Optional<Frequency> CalculatedStyleValue::resolve_frequency_percentage(Frequency const& percentage_basis) const
{ {
auto result = m_calculation->resolve(nullptr, percentage_basis); auto result = m_calculation->resolve({}, percentage_basis);
return result.value().visit( return result.value().visit(
[&](Frequency const& frequency) -> Optional<Frequency> { [&](Frequency const& frequency) -> Optional<Frequency> {
@ -939,18 +937,23 @@ Optional<Frequency> CalculatedStyleValue::resolve_frequency_percentage(Frequency
}); });
} }
Optional<Length> CalculatedStyleValue::resolve_length(Layout::Node const& layout_node) const Optional<Length> CalculatedStyleValue::resolve_length(Length::ResolutionContext const& context) const
{ {
auto result = m_calculation->resolve(&layout_node, {}); auto result = m_calculation->resolve(context, {});
if (result.value().has<Length>()) if (result.value().has<Length>())
return result.value().get<Length>(); return result.value().get<Length>();
return {}; return {};
} }
Optional<Length> CalculatedStyleValue::resolve_length(Layout::Node const& layout_node) 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 Optional<Length> CalculatedStyleValue::resolve_length_percentage(Layout::Node const& layout_node, Length const& percentage_basis) const
{ {
auto result = m_calculation->resolve(&layout_node, percentage_basis); auto result = m_calculation->resolve(Length::ResolutionContext::for_layout_node(layout_node), percentage_basis);
return result.value().visit( return result.value().visit(
[&](Length const& length) -> Optional<Length> { [&](Length const& length) -> Optional<Length> {
@ -966,7 +969,7 @@ Optional<Length> CalculatedStyleValue::resolve_length_percentage(Layout::Node co
Optional<Percentage> CalculatedStyleValue::resolve_percentage() const Optional<Percentage> CalculatedStyleValue::resolve_percentage() const
{ {
auto result = m_calculation->resolve(nullptr, {}); auto result = m_calculation->resolve({}, {});
if (result.value().has<Percentage>()) if (result.value().has<Percentage>())
return result.value().get<Percentage>(); return result.value().get<Percentage>();
return {}; return {};
@ -974,7 +977,7 @@ Optional<Percentage> CalculatedStyleValue::resolve_percentage() const
Optional<Time> CalculatedStyleValue::resolve_time() const Optional<Time> CalculatedStyleValue::resolve_time() const
{ {
auto result = m_calculation->resolve(nullptr, {}); auto result = m_calculation->resolve({}, {});
if (result.value().has<Time>()) if (result.value().has<Time>())
return result.value().get<Time>(); return result.value().get<Time>();
@ -983,7 +986,7 @@ Optional<Time> CalculatedStyleValue::resolve_time() const
Optional<Time> CalculatedStyleValue::resolve_time_percentage(Time const& percentage_basis) const Optional<Time> CalculatedStyleValue::resolve_time_percentage(Time const& percentage_basis) const
{ {
auto result = m_calculation->resolve(nullptr, percentage_basis); auto result = m_calculation->resolve({}, percentage_basis);
return result.value().visit( return result.value().visit(
[&](Time const& time) -> Optional<Time> { [&](Time const& time) -> Optional<Time> {
@ -996,7 +999,7 @@ Optional<Time> CalculatedStyleValue::resolve_time_percentage(Time const& percent
Optional<double> CalculatedStyleValue::resolve_number() const Optional<double> CalculatedStyleValue::resolve_number() const
{ {
auto result = m_calculation->resolve(nullptr, {}); auto result = m_calculation->resolve({}, {});
if (result.value().has<Number>()) if (result.value().has<Number>())
return result.value().get<Number>().value(); return result.value().get<Number>().value();
return {}; return {};
@ -1004,7 +1007,7 @@ Optional<double> CalculatedStyleValue::resolve_number() const
Optional<i64> CalculatedStyleValue::resolve_integer() Optional<i64> CalculatedStyleValue::resolve_integer()
{ {
auto result = m_calculation->resolve(nullptr, {}); auto result = m_calculation->resolve({}, {});
if (result.value().has<Number>()) if (result.value().has<Number>())
return result.value().get<Number>().integer_value(); return result.value().get<Number>().integer_value();
return {}; return {};

View file

@ -50,17 +50,17 @@ public:
: m_value(move(value)) : m_value(move(value))
{ {
} }
void add(CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis); void add(CalculationResult const& other, Optional<Length::ResolutionContext const&>, PercentageBasis const& percentage_basis);
void subtract(CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis); void subtract(CalculationResult const& other, Optional<Length::ResolutionContext const&>, PercentageBasis const& percentage_basis);
void multiply_by(CalculationResult const& other, Layout::Node const*); void multiply_by(CalculationResult const& other, Optional<Length::ResolutionContext const&>);
void divide_by(CalculationResult const& other, Layout::Node const*); void divide_by(CalculationResult const& other, Optional<Length::ResolutionContext const&>);
void negate(); void negate();
void invert(); void invert();
Value const& value() const { return m_value; } Value const& value() const { return m_value; }
private: private:
void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const*, PercentageBasis const& percentage_basis); void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Optional<Length::ResolutionContext const&>, PercentageBasis const& percentage_basis);
Value m_value; Value m_value;
}; };
@ -82,6 +82,7 @@ public:
Optional<Frequency> resolve_frequency_percentage(Frequency const& percentage_basis) const; Optional<Frequency> resolve_frequency_percentage(Frequency const& percentage_basis) const;
bool resolves_to_length() const { return m_resolved_type == ResolvedType::Length; } bool resolves_to_length() const { return m_resolved_type == ResolvedType::Length; }
[[nodiscard]] Optional<Length> resolve_length(Length::ResolutionContext const&) const;
Optional<Length> resolve_length(Layout::Node const& layout_node) 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&, Length const& percentage_basis) const;
@ -155,7 +156,7 @@ public:
virtual ErrorOr<String> to_string() const = 0; virtual ErrorOr<String> to_string() const = 0;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const = 0; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const = 0;
virtual bool contains_percentage() const = 0; virtual bool contains_percentage() const = 0;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const = 0; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const = 0;
virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) { return {}; } virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) { return {}; }
virtual ErrorOr<void> dump(StringBuilder&, int indent) const = 0; virtual ErrorOr<void> dump(StringBuilder&, int indent) const = 0;
@ -175,7 +176,7 @@ public:
virtual ErrorOr<String> to_string() const override; virtual ErrorOr<String> to_string() const override;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
virtual bool contains_percentage() const override; virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual ErrorOr<void> dump(StringBuilder&, int indent) const override; virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;
@ -192,7 +193,7 @@ public:
virtual ErrorOr<String> to_string() const override; virtual ErrorOr<String> to_string() const override;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
virtual bool contains_percentage() const override; virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override; virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override;
virtual ErrorOr<void> dump(StringBuilder&, int indent) const override; virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;
@ -210,7 +211,7 @@ public:
virtual ErrorOr<String> to_string() const override; virtual ErrorOr<String> to_string() const override;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
virtual bool contains_percentage() const override; virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override; virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override;
virtual ErrorOr<void> dump(StringBuilder&, int indent) const override; virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;
@ -228,7 +229,7 @@ public:
virtual ErrorOr<String> to_string() const override; virtual ErrorOr<String> to_string() const override;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
virtual bool contains_percentage() const override; virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override; virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override;
virtual ErrorOr<void> dump(StringBuilder&, int indent) const override; virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;
@ -246,7 +247,7 @@ public:
virtual ErrorOr<String> to_string() const override; virtual ErrorOr<String> to_string() const override;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
virtual bool contains_percentage() const override; virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override; virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override;
virtual ErrorOr<void> dump(StringBuilder&, int indent) const override; virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;
@ -264,7 +265,7 @@ public:
virtual ErrorOr<String> to_string() const override; virtual ErrorOr<String> to_string() const override;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
virtual bool contains_percentage() const override; virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override; virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override;
virtual ErrorOr<void> dump(StringBuilder&, int indent) const override; virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;
@ -282,7 +283,7 @@ public:
virtual ErrorOr<String> to_string() const override; virtual ErrorOr<String> to_string() const override;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
virtual bool contains_percentage() const override; virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override; virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override;
virtual ErrorOr<void> dump(StringBuilder&, int indent) const override; virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;
@ -300,7 +301,7 @@ public:
virtual ErrorOr<String> to_string() const override; virtual ErrorOr<String> to_string() const override;
virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override; virtual Optional<CalculatedStyleValue::ResolvedType> resolved_type() const override;
virtual bool contains_percentage() const override; virtual bool contains_percentage() const override;
virtual CalculatedStyleValue::CalculationResult resolve(Layout::Node const*, CalculatedStyleValue::PercentageBasis const&) const override; virtual CalculatedStyleValue::CalculationResult resolve(Optional<Length::ResolutionContext const&>, CalculatedStyleValue::PercentageBasis const&) const override;
virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override; virtual ErrorOr<void> for_each_child_node(Function<ErrorOr<void>(NonnullOwnPtr<CalculationNode>&)> const&) override;
virtual ErrorOr<void> dump(StringBuilder&, int indent) const override; virtual ErrorOr<void> dump(StringBuilder&, int indent) const override;