mirror of
https://github.com/LadybirdBrowser/ladybird.git
synced 2025-07-31 05:09:12 +00:00
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:
parent
ad9d9bb684
commit
1d71662f31
Notes:
github-actions[bot]
2025-01-30 18:33:58 +00:00
Author: https://github.com/AtkinsSJ
Commit: 1d71662f31
Pull-request: https://github.com/LadybirdBrowser/ladybird/pull/3383
18 changed files with 256 additions and 309 deletions
|
@ -84,9 +84,14 @@ Optional<Angle::Type> Angle::unit_from_name(StringView name)
|
|||
return {};
|
||||
}
|
||||
|
||||
Angle Angle::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&, Angle const& reference_value)
|
||||
Angle Angle::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node, Angle const& reference_value)
|
||||
{
|
||||
return calculated->resolve_angle_percentage(reference_value).value();
|
||||
return calculated->resolve_angle(
|
||||
{
|
||||
.percentage_basis = reference_value,
|
||||
.length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node),
|
||||
})
|
||||
.value();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -386,7 +386,7 @@ int CSSStyleValue::to_font_weight() const
|
|||
return round_to<int>(as_number().number());
|
||||
}
|
||||
if (is_calculated()) {
|
||||
auto maybe_weight = as_calculated().resolve_integer();
|
||||
auto maybe_weight = as_calculated().resolve_integer({});
|
||||
if (maybe_weight.has_value())
|
||||
return maybe_weight.value();
|
||||
}
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
namespace Web::CSS {
|
||||
|
||||
Angle AngleOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
|
||||
Angle AngleOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_angle().value();
|
||||
return calculated->resolve_angle({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
NonnullRefPtr<CSSStyleValue> AngleOrCalculated::create_style_value() const
|
||||
|
@ -27,9 +27,9 @@ NonnullRefPtr<CSSStyleValue> AngleOrCalculated::create_style_value() const
|
|||
return AngleStyleValue::create(value());
|
||||
}
|
||||
|
||||
Flex FlexOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
|
||||
Flex FlexOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_flex().value();
|
||||
return calculated->resolve_flex({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
NonnullRefPtr<CSSStyleValue> FlexOrCalculated::create_style_value() const
|
||||
|
@ -37,9 +37,9 @@ NonnullRefPtr<CSSStyleValue> FlexOrCalculated::create_style_value() const
|
|||
return FlexStyleValue::create(value());
|
||||
}
|
||||
|
||||
Frequency FrequencyOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
|
||||
Frequency FrequencyOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_frequency().value();
|
||||
return calculated->resolve_frequency({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
NonnullRefPtr<CSSStyleValue> FrequencyOrCalculated::create_style_value() const
|
||||
|
@ -49,13 +49,13 @@ NonnullRefPtr<CSSStyleValue> FrequencyOrCalculated::create_style_value() const
|
|||
|
||||
i64 IntegerOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_integer(layout_node).value();
|
||||
return calculated->resolve_integer({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
i64 IntegerOrCalculated::resolved(Length::ResolutionContext const& context) const
|
||||
{
|
||||
if (is_calculated())
|
||||
return calculated()->resolve_integer(context).value();
|
||||
return calculated()->resolve_integer({ .length_resolution_context = context }).value();
|
||||
return value();
|
||||
}
|
||||
|
||||
|
@ -66,13 +66,13 @@ NonnullRefPtr<CSSStyleValue> IntegerOrCalculated::create_style_value() const
|
|||
|
||||
Length LengthOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_length(layout_node).value();
|
||||
return calculated->resolve_length({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
Length LengthOrCalculated::resolved(Length::ResolutionContext const& context) const
|
||||
{
|
||||
if (is_calculated())
|
||||
return calculated()->resolve_length(context).value();
|
||||
return calculated()->resolve_length({ .length_resolution_context = context }).value();
|
||||
return value();
|
||||
}
|
||||
|
||||
|
@ -83,7 +83,7 @@ NonnullRefPtr<CSSStyleValue> LengthOrCalculated::create_style_value() const
|
|||
|
||||
double NumberOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_number(layout_node).value();
|
||||
return calculated->resolve_number({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
NonnullRefPtr<CSSStyleValue> NumberOrCalculated::create_style_value() const
|
||||
|
@ -91,9 +91,9 @@ NonnullRefPtr<CSSStyleValue> NumberOrCalculated::create_style_value() const
|
|||
return NumberStyleValue::create(value());
|
||||
}
|
||||
|
||||
Percentage PercentageOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
|
||||
Percentage PercentageOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_percentage().value();
|
||||
return calculated->resolve_percentage({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
NonnullRefPtr<CSSStyleValue> PercentageOrCalculated::create_style_value() const
|
||||
|
@ -101,15 +101,15 @@ NonnullRefPtr<CSSStyleValue> PercentageOrCalculated::create_style_value() const
|
|||
return PercentageStyleValue::create(value());
|
||||
}
|
||||
|
||||
Resolution ResolutionOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
|
||||
Resolution ResolutionOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_resolution().value();
|
||||
return calculated->resolve_resolution({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
Resolution ResolutionOrCalculated::resolved() const
|
||||
{
|
||||
if (is_calculated())
|
||||
return calculated()->resolve_resolution().value();
|
||||
return calculated()->resolve_resolution({}).value();
|
||||
return value();
|
||||
}
|
||||
|
||||
|
@ -118,9 +118,9 @@ NonnullRefPtr<CSSStyleValue> ResolutionOrCalculated::create_style_value() const
|
|||
return ResolutionStyleValue::create(value());
|
||||
}
|
||||
|
||||
Time TimeOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&) const
|
||||
Time TimeOrCalculated::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node) const
|
||||
{
|
||||
return calculated->resolve_time().value();
|
||||
return calculated->resolve_time({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value();
|
||||
}
|
||||
|
||||
NonnullRefPtr<CSSStyleValue> TimeOrCalculated::create_style_value() const
|
||||
|
|
|
@ -301,8 +301,12 @@ CSSPixels ComputedProperties::compute_line_height(CSSPixelRect const& viewport_r
|
|||
}
|
||||
|
||||
if (line_height.is_calculated()) {
|
||||
CalculationResolutionContext context {
|
||||
.percentage_basis = Length(1, Length::Type::Em),
|
||||
.length_resolution_context = Length::ResolutionContext { viewport_rect, font_metrics, root_font_metrics },
|
||||
};
|
||||
if (line_height.as_calculated().resolves_to_number()) {
|
||||
auto resolved = line_height.as_calculated().resolve_number();
|
||||
auto resolved = line_height.as_calculated().resolve_number(context);
|
||||
if (!resolved.has_value()) {
|
||||
dbgln("FIXME: Failed to resolve calc() line-height (number): {}", line_height.as_calculated().to_string(CSSStyleValue::SerializationMode::Normal));
|
||||
return CSSPixels::nearest_value_for(m_font_list->first().pixel_metrics().line_spacing());
|
||||
|
@ -310,7 +314,7 @@ CSSPixels ComputedProperties::compute_line_height(CSSPixelRect const& viewport_r
|
|||
return Length(resolved.value(), Length::Type::Em).to_px(viewport_rect, font_metrics, root_font_metrics);
|
||||
}
|
||||
|
||||
auto resolved = line_height.as_calculated().resolve_length(Length::ResolutionContext { viewport_rect, font_metrics, root_font_metrics });
|
||||
auto resolved = line_height.as_calculated().resolve_length(context);
|
||||
if (!resolved.has_value()) {
|
||||
dbgln("FIXME: Failed to resolve calc() line-height: {}", line_height.as_calculated().to_string(CSSStyleValue::SerializationMode::Normal));
|
||||
return CSSPixels::nearest_value_for(m_font_list->first().pixel_metrics().line_spacing());
|
||||
|
@ -346,14 +350,15 @@ float ComputedProperties::resolve_opacity_value(CSSStyleValue const& value)
|
|||
unclamped_opacity = value.as_number().number();
|
||||
} else if (value.is_calculated()) {
|
||||
auto const& calculated = value.as_calculated();
|
||||
CalculationResolutionContext context {};
|
||||
if (calculated.resolves_to_percentage()) {
|
||||
auto maybe_percentage = value.as_calculated().resolve_percentage();
|
||||
auto maybe_percentage = value.as_calculated().resolve_percentage(context);
|
||||
if (maybe_percentage.has_value())
|
||||
unclamped_opacity = maybe_percentage->as_fraction();
|
||||
else
|
||||
dbgln("Unable to resolve calc() as opacity (percentage): {}", value.to_string(CSSStyleValue::SerializationMode::Normal));
|
||||
} else if (calculated.resolves_to_number()) {
|
||||
auto maybe_number = value.as_calculated().resolve_number();
|
||||
auto maybe_number = value.as_calculated().resolve_number(context);
|
||||
if (maybe_number.has_value())
|
||||
unclamped_opacity = maybe_number.value();
|
||||
else
|
||||
|
@ -485,7 +490,7 @@ CSS::Length ComputedProperties::border_spacing_horizontal(Layout::Node const& la
|
|||
if (value.is_length())
|
||||
return value.as_length().length();
|
||||
if (value.is_calculated())
|
||||
return value.as_calculated().resolve_length(layout_node).value_or(CSS::Length(0, CSS::Length::Type::Px));
|
||||
return value.as_calculated().resolve_length({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value_or(CSS::Length(0, CSS::Length::Type::Px));
|
||||
auto const& list = value.as_value_list();
|
||||
return list.value_at(0, false)->as_length().length();
|
||||
}
|
||||
|
@ -496,7 +501,7 @@ CSS::Length ComputedProperties::border_spacing_vertical(Layout::Node const& layo
|
|||
if (value.is_length())
|
||||
return value.as_length().length();
|
||||
if (value.is_calculated())
|
||||
return value.as_calculated().resolve_length(layout_node).value_or(CSS::Length(0, CSS::Length::Type::Px));
|
||||
return value.as_calculated().resolve_length({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) }).value_or(CSS::Length(0, CSS::Length::Type::Px));
|
||||
auto const& list = value.as_value_list();
|
||||
return list.value_at(1, false)->as_length().length();
|
||||
}
|
||||
|
@ -1038,7 +1043,7 @@ Vector<ShadowData> ComputedProperties::shadow(PropertyID property_id, Layout::No
|
|||
if (value->is_length())
|
||||
return value->as_length().length();
|
||||
if (value->is_calculated())
|
||||
return value->as_calculated().resolve_length(layout_node);
|
||||
return value->as_calculated().resolve_length({ .length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node) });
|
||||
return {};
|
||||
};
|
||||
|
||||
|
@ -1503,7 +1508,7 @@ Vector<CounterData> ComputedProperties::counter_data(PropertyID property_id) con
|
|||
if (counter.value->is_integer()) {
|
||||
data.value = AK::clamp_to<i32>(counter.value->as_integer().integer());
|
||||
} else if (counter.value->is_calculated()) {
|
||||
auto maybe_int = counter.value->as_calculated().resolve_integer();
|
||||
auto maybe_int = counter.value->as_calculated().resolve_integer({});
|
||||
if (maybe_int.has_value())
|
||||
data.value = AK::clamp_to<i32>(*maybe_int);
|
||||
} else {
|
||||
|
|
|
@ -63,9 +63,14 @@ Optional<Frequency::Type> Frequency::unit_from_name(StringView name)
|
|||
return {};
|
||||
}
|
||||
|
||||
Frequency Frequency::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&, Frequency const& reference_value)
|
||||
Frequency Frequency::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node, Frequency const& reference_value)
|
||||
{
|
||||
return calculated->resolve_frequency_percentage(reference_value).value();
|
||||
return calculated->resolve_frequency(
|
||||
{
|
||||
.percentage_basis = reference_value,
|
||||
.length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node),
|
||||
})
|
||||
.value();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -411,12 +411,22 @@ Length Length::absolutized(CSSPixelRect const& viewport_rect, FontMetrics const&
|
|||
|
||||
Length Length::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node, Length const& reference_value)
|
||||
{
|
||||
return calculated->resolve_length_percentage(layout_node, reference_value).value();
|
||||
return calculated->resolve_length(
|
||||
{
|
||||
.percentage_basis = reference_value,
|
||||
.length_resolution_context = ResolutionContext::for_layout_node(layout_node),
|
||||
})
|
||||
.value();
|
||||
}
|
||||
|
||||
Length Length::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node, CSSPixels reference_value)
|
||||
{
|
||||
return calculated->resolve_length_percentage(layout_node, reference_value).value();
|
||||
return calculated->resolve_length(
|
||||
{
|
||||
.percentage_basis = make_px(reference_value),
|
||||
.length_resolution_context = ResolutionContext::for_layout_node(layout_node),
|
||||
})
|
||||
.value();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -2174,6 +2174,10 @@ Optional<Ratio> Parser::parse_ratio(TokenStream<ComponentValue>& tokens)
|
|||
auto transaction = tokens.begin_transaction();
|
||||
tokens.discard_whitespace();
|
||||
|
||||
// FIXME: It seems like `calc(...) / calc(...)` is a valid <ratio>, but this case is neither mentioned in a spec,
|
||||
// nor tested in WPT, as far as I can tell.
|
||||
// Still, we should probably support it. That means not assuming we can resolve the calculation immediately.
|
||||
|
||||
auto read_number_value = [this](ComponentValue const& component_value) -> Optional<double> {
|
||||
if (component_value.is(Token::Type::Number)) {
|
||||
return component_value.token().number_value();
|
||||
|
@ -2181,7 +2185,7 @@ Optional<Ratio> Parser::parse_ratio(TokenStream<ComponentValue>& tokens)
|
|||
auto maybe_calc = parse_calculated_value(component_value);
|
||||
if (!maybe_calc || !maybe_calc->resolves_to_number())
|
||||
return {};
|
||||
if (auto resolved_number = maybe_calc->resolve_number(); resolved_number.has_value() && resolved_number.value() >= 0) {
|
||||
if (auto resolved_number = maybe_calc->resolve_number({}); resolved_number.has_value() && resolved_number.value() >= 0) {
|
||||
return resolved_number.value();
|
||||
}
|
||||
}
|
||||
|
@ -8129,7 +8133,7 @@ RefPtr<GridTrackPlacementStyleValue> Parser::parse_grid_track_placement(TokenStr
|
|||
auto const& token = tokens.consume_a_token();
|
||||
if (auto maybe_calculated = parse_calculated_value(token); maybe_calculated && maybe_calculated->resolves_to_number()) {
|
||||
transaction.commit();
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast<int>(maybe_calculated->resolve_integer().value()), {}));
|
||||
return GridTrackPlacementStyleValue::create(GridTrackPlacement::make_line(static_cast<int>(maybe_calculated->resolve_integer({}).value()), {}));
|
||||
}
|
||||
if (token.is_ident("auto"sv)) {
|
||||
transaction.commit();
|
||||
|
@ -9710,17 +9714,19 @@ bool Parser::expand_unresolved_values(DOM::Element& element, FlyString const& pr
|
|||
}
|
||||
|
||||
if (property.has_value()) {
|
||||
// FIXME: I think we don't need any of this once simplification is implemented. It runs inside parse_calculation_node() already.
|
||||
// So, this is just a temporary hack to not change behaviour until that's done.
|
||||
if (auto maybe_calc_value = parse_calculated_value(value); maybe_calc_value && maybe_calc_value->is_calculated()) {
|
||||
// FIXME: Run the actual simplification algorithm
|
||||
auto& calc_value = maybe_calc_value->as_calculated();
|
||||
CalculationResolutionContext context {};
|
||||
if (property_accepts_type(*property, ValueType::Angle) && calc_value.resolves_to_angle()) {
|
||||
auto resolved_value = calc_value.resolve_angle();
|
||||
dest.empend(Token::create_dimension(resolved_value->to_degrees(), "deg"_fly_string));
|
||||
if (auto resolved_value = calc_value.resolve_angle(context); resolved_value.has_value())
|
||||
dest.empend(Token::create_dimension(resolved_value->to_degrees(), "deg"_fly_string));
|
||||
continue;
|
||||
}
|
||||
if (property_accepts_type(*property, ValueType::Frequency) && calc_value.resolves_to_frequency()) {
|
||||
auto resolved_value = calc_value.resolve_frequency();
|
||||
dest.empend(Token::create_dimension(resolved_value->to_hertz(), "hz"_fly_string));
|
||||
if (auto resolved_value = calc_value.resolve_frequency(context); resolved_value.has_value())
|
||||
dest.empend(Token::create_dimension(resolved_value->to_hertz(), "hz"_fly_string));
|
||||
continue;
|
||||
}
|
||||
if (property_accepts_type(*property, ValueType::Length) && calc_value.resolves_to_length()) {
|
||||
|
@ -9729,23 +9735,23 @@ bool Parser::expand_unresolved_values(DOM::Element& element, FlyString const& pr
|
|||
// This might be easier once we have calc-simplification implemented.
|
||||
}
|
||||
if (property_accepts_type(*property, ValueType::Percentage) && calc_value.resolves_to_percentage()) {
|
||||
auto resolved_value = calc_value.resolve_percentage();
|
||||
dest.empend(Token::create_percentage(resolved_value.value().value()));
|
||||
if (auto resolved_value = calc_value.resolve_percentage(context); resolved_value.has_value())
|
||||
dest.empend(Token::create_percentage(resolved_value.value().value()));
|
||||
continue;
|
||||
}
|
||||
if (property_accepts_type(*property, ValueType::Time) && calc_value.resolves_to_time()) {
|
||||
auto resolved_value = calc_value.resolve_time();
|
||||
dest.empend(Token::create_dimension(resolved_value->to_seconds(), "s"_fly_string));
|
||||
if (auto resolved_value = calc_value.resolve_time(context); resolved_value.has_value())
|
||||
dest.empend(Token::create_dimension(resolved_value->to_seconds(), "s"_fly_string));
|
||||
continue;
|
||||
}
|
||||
if (property_accepts_type(*property, ValueType::Number) && calc_value.resolves_to_number()) {
|
||||
auto resolved_value = calc_value.resolve_number();
|
||||
dest.empend(Token::create_number(resolved_value.value(), Number::Type::Number));
|
||||
if (auto resolved_value = calc_value.resolve_number(context); resolved_value.has_value())
|
||||
dest.empend(Token::create_number(resolved_value.value(), Number::Type::Number));
|
||||
continue;
|
||||
}
|
||||
if (property_accepts_type(*property, ValueType::Integer) && calc_value.resolves_to_number()) {
|
||||
auto resolved_value = calc_value.resolve_integer();
|
||||
dest.empend(Token::create_number(resolved_value.value(), Number::Type::Integer));
|
||||
if (auto resolved_value = calc_value.resolve_integer(context); resolved_value.has_value())
|
||||
dest.empend(Token::create_number(resolved_value.value(), Number::Type::Integer));
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -621,7 +621,7 @@ GC::Ptr<CSSFontFaceRule> Parser::convert_to_font_face_rule(AtRule const& rule)
|
|||
// TODO: Once we implement calc-simplification in the parser, we should no longer see math values here,
|
||||
// unless they're impossible to resolve and thus invalid.
|
||||
if (percentage_value->is_calculated()) {
|
||||
if (auto result = percentage_value->as_calculated().resolve_percentage(); result.has_value())
|
||||
if (auto result = percentage_value->as_calculated().resolve_percentage({}); result.has_value())
|
||||
return result.value();
|
||||
}
|
||||
|
||||
|
@ -736,7 +736,7 @@ GC::Ptr<CSSFontFaceRule> Parser::convert_to_font_face_rule(AtRule const& rule)
|
|||
if (setting_value->is_integer()) {
|
||||
settings.set(feature_tag->as_open_type_tagged().tag(), setting_value->as_integer().integer());
|
||||
} else if (setting_value->is_calculated() && setting_value->as_calculated().resolves_to_number()) {
|
||||
if (auto integer = setting_value->as_calculated().resolve_integer(); integer.has_value()) {
|
||||
if (auto integer = setting_value->as_calculated().resolve_integer({}); integer.has_value()) {
|
||||
settings.set(feature_tag->as_open_type_tagged().tag(), *integer);
|
||||
} else {
|
||||
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Calculated value in font-feature-settings descriptor cannot be resolved at parse time; skipping");
|
||||
|
@ -810,7 +810,7 @@ GC::Ptr<CSSFontFaceRule> Parser::convert_to_font_face_rule(AtRule const& rule)
|
|||
if (setting_value->is_number()) {
|
||||
settings.set(variation_tag->as_open_type_tagged().tag(), setting_value->as_number().number());
|
||||
} else if (setting_value->is_calculated() && setting_value->as_calculated().resolves_to_number()) {
|
||||
if (auto number = setting_value->as_calculated().resolve_number(); number.has_value()) {
|
||||
if (auto number = setting_value->as_calculated().resolve_number({}); number.has_value()) {
|
||||
settings.set(variation_tag->as_open_type_tagged().tag(), *number);
|
||||
} else {
|
||||
dbgln_if(CSS_PARSER_DEBUG, "CSSParser: Calculated value in font-variation-settings descriptor cannot be resolved at parse time; skipping");
|
||||
|
|
|
@ -1963,11 +1963,10 @@ RefPtr<Gfx::FontCascadeList const> StyleComputer::compute_font_for_style_values(
|
|||
} else if (font_size.is_length()) {
|
||||
maybe_length = font_size.as_length().length();
|
||||
} else if (font_size.is_calculated()) {
|
||||
if (font_size.as_calculated().contains_percentage()) {
|
||||
maybe_length = font_size.as_calculated().resolve_length_percentage(length_resolution_context, Length::make_px(parent_font_size()));
|
||||
} else {
|
||||
maybe_length = font_size.as_calculated().resolve_length(length_resolution_context);
|
||||
}
|
||||
maybe_length = font_size.as_calculated().resolve_length({
|
||||
.percentage_basis = Length::make_px(parent_font_size()),
|
||||
.length_resolution_context = length_resolution_context,
|
||||
});
|
||||
}
|
||||
if (maybe_length.has_value()) {
|
||||
font_size_in_px = maybe_length.value().to_px(length_resolution_context);
|
||||
|
@ -3034,7 +3033,7 @@ void StyleComputer::compute_math_depth(ComputedProperties& style, DOM::Element c
|
|||
if (integer_value.is_integer())
|
||||
return integer_value.as_integer().integer();
|
||||
if (integer_value.is_calculated())
|
||||
return integer_value.as_calculated().resolve_integer().value();
|
||||
return integer_value.as_calculated().resolve_integer({}).value();
|
||||
VERIFY_NOT_REACHED();
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
};
|
||||
|
|
|
@ -74,9 +74,14 @@ Optional<Time::Type> Time::unit_from_name(StringView name)
|
|||
return {};
|
||||
}
|
||||
|
||||
Time Time::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const&, Time const& reference_value)
|
||||
Time Time::resolve_calculated(NonnullRefPtr<CalculatedStyleValue> const& calculated, Layout::Node const& layout_node, Time const& reference_value)
|
||||
{
|
||||
return calculated->resolve_time_percentage(reference_value).value();
|
||||
return calculated->resolve_time(
|
||||
{
|
||||
.percentage_basis = reference_value,
|
||||
.length_resolution_context = Length::ResolutionContext::for_layout_node(layout_node),
|
||||
})
|
||||
.value();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -550,14 +550,16 @@ void LayoutState::UsedValues::set_node(NodeWithStyle& node, UsedValues const* co
|
|||
}
|
||||
|
||||
if (size.is_calculated()) {
|
||||
CSS::CalculationResolutionContext context {
|
||||
.length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(node),
|
||||
};
|
||||
if (size.calculated().contains_percentage()) {
|
||||
if (!containing_block_has_definite_size)
|
||||
return false;
|
||||
auto containing_block_size_as_length = width ? containing_block_used_values->content_width() : containing_block_used_values->content_height();
|
||||
resolved_definite_size = adjust_for_box_sizing(size.calculated().resolve_length_percentage(node, containing_block_size_as_length).value_or(CSS::Length::make_auto()).to_px(node), size, width);
|
||||
return true;
|
||||
context.percentage_basis = CSS::Length::make_px(containing_block_size_as_length);
|
||||
}
|
||||
resolved_definite_size = adjust_for_box_sizing(size.calculated().resolve_length(node)->to_px(node), size, width);
|
||||
resolved_definite_size = adjust_for_box_sizing(size.calculated().resolve_length(context)->to_px(node), size, width);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -787,7 +787,7 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
|
|||
computed_values.set_transition_delay(transition_delay.time());
|
||||
} else if (transition_delay_property.is_calculated()) {
|
||||
auto const& transition_delay = transition_delay_property.as_calculated();
|
||||
computed_values.set_transition_delay(transition_delay.resolve_time().value());
|
||||
computed_values.set_transition_delay(transition_delay.resolve_time({ .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*this) }).value());
|
||||
}
|
||||
|
||||
auto do_border_style = [&](CSS::BorderData& border, CSS::PropertyID width_property, CSS::PropertyID color_property, CSS::PropertyID style_property) {
|
||||
|
@ -808,7 +808,8 @@ void NodeWithStyle::apply_style(CSS::ComputedProperties const& computed_style)
|
|||
auto resolve_border_width = [&]() -> CSSPixels {
|
||||
auto const& value = computed_style.property(width_property);
|
||||
if (value.is_calculated())
|
||||
return max(CSSPixels { 0 }, value.as_calculated().resolve_length(*this)->to_px(*this));
|
||||
return max(CSSPixels { 0 },
|
||||
value.as_calculated().resolve_length({ .length_resolution_context = CSS::Length::ResolutionContext::for_layout_node(*this) })->to_px(*this));
|
||||
if (value.is_length())
|
||||
return value.as_length().length().to_px(*this);
|
||||
if (value.is_keyword()) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue