diff --git a/Libraries/LibWeb/CSS/Interpolation.cpp b/Libraries/LibWeb/CSS/Interpolation.cpp index 74188858db8..42ee4c02f34 100644 --- a/Libraries/LibWeb/CSS/Interpolation.cpp +++ b/Libraries/LibWeb/CSS/Interpolation.cpp @@ -577,6 +577,14 @@ NonnullRefPtr interpolate_value(DOM::Element& element, Calc return delta >= 0.5f ? to : from; } + static auto interpolate_length_percentage = [](LengthPercentage const& from, LengthPercentage const& to, float delta) -> Optional { + if (from.is_length() && to.is_length()) + return Length::make_px(interpolate_raw(from.length().raw_value(), to.length().raw_value(), delta)); + if (from.is_percentage() && to.is_percentage()) + return Percentage(interpolate_raw(from.percentage().value(), to.percentage().value(), delta)); + return {}; + }; + switch (from.type()) { case CSSStyleValue::Type::Angle: return AngleStyleValue::create(Angle::make_degrees(interpolate_raw(from.as_angle().angle().to_degrees(), to.as_angle().angle().to_degrees(), delta))); @@ -586,6 +594,17 @@ NonnullRefPtr interpolate_value(DOM::Element& element, Calc layout_node = *node; return CSSColorValue::create_from_color(interpolate_color(from.to_color(layout_node), to.to_color(layout_node), delta), ColorSyntax::Modern); } + case CSSStyleValue::Type::Edge: { + auto resolved_from = from.as_edge().resolved_value(calculation_context); + auto resolved_to = to.as_edge().resolved_value(calculation_context); + auto const& edge = delta >= 0.5f ? resolved_to->edge() : resolved_from->edge(); + auto const& from_offset = resolved_from->offset(); + auto const& to_offset = resolved_to->offset(); + if (auto interpolated_value = interpolate_length_percentage(from_offset, to_offset, delta); interpolated_value.has_value()) + return EdgeStyleValue::create(edge, *interpolated_value); + + return delta >= 0.5f ? to : from; + } case CSSStyleValue::Type::Integer: { // https://drafts.csswg.org/css-values/#combine-integers // Interpolation of is defined as Vresult = round((1 - p) × VA + p × VB); diff --git a/Libraries/LibWeb/CSS/StyleValues/EdgeStyleValue.cpp b/Libraries/LibWeb/CSS/StyleValues/EdgeStyleValue.cpp index 265d8530b2d..fef30da7615 100644 --- a/Libraries/LibWeb/CSS/StyleValues/EdgeStyleValue.cpp +++ b/Libraries/LibWeb/CSS/StyleValues/EdgeStyleValue.cpp @@ -11,27 +11,9 @@ namespace Web::CSS { String EdgeStyleValue::to_string(SerializationMode mode) const { if (mode == CSSStyleValue::SerializationMode::ResolvedValue) { - if (edge() == PositionEdge::Right || edge() == PositionEdge::Bottom) { - if (offset().is_percentage()) { - auto flipped_percentage = 100 - offset().percentage().value(); - return Percentage(flipped_percentage).to_string(); - } - - // FIXME: Figure out how to get the proper calculation context here - CalculationContext context = {}; - - Vector> sum_parts; - sum_parts.append(NumericCalculationNode::create(Percentage(100), context)); - if (offset().is_length()) { - sum_parts.append(NegateCalculationNode::create(NumericCalculationNode::create(offset().length(), context))); - } else { - // FIXME: Flip calculated offsets (convert CalculatedStyleValue to CalculationNode, then negate and append) - return to_string(CSSStyleValue::SerializationMode::Normal); - } - auto flipped_absolute = CalculatedStyleValue::create(SumCalculationNode::create(move(sum_parts)), CSSNumericType(CSSNumericType::BaseType::Length, 1), context); - return flipped_absolute->to_string(mode); - } - return offset().to_string(); + // FIXME: Figure out how to get the proper calculation context here + CalculationContext context {}; + return resolved_value(context)->offset().to_string(); } StringBuilder builder; @@ -48,4 +30,27 @@ String EdgeStyleValue::to_string(SerializationMode mode) const return builder.to_string_without_validation(); } +ValueComparingNonnullRefPtr EdgeStyleValue::resolved_value(CalculationContext context) const +{ + if (edge() == PositionEdge::Right || edge() == PositionEdge::Bottom) { + if (offset().is_percentage()) { + auto flipped_percentage = 100 - offset().percentage().value(); + return create({}, Percentage(flipped_percentage)); + } + + Vector> sum_parts; + sum_parts.append(NumericCalculationNode::create(Percentage(100), context)); + if (offset().is_length()) { + sum_parts.append(NegateCalculationNode::create(NumericCalculationNode::create(offset().length(), context))); + } else { + // FIXME: Flip calculated offsets (convert CalculatedStyleValue to CalculationNode, then negate and append) + return *this; + } + auto flipped_absolute = CalculatedStyleValue::create(SumCalculationNode::create(move(sum_parts)), CSSNumericType(CSSNumericType::BaseType::Length, 1), context); + return create({}, flipped_absolute); + } + + return *this; +} + } diff --git a/Libraries/LibWeb/CSS/StyleValues/EdgeStyleValue.h b/Libraries/LibWeb/CSS/StyleValues/EdgeStyleValue.h index bd354108abb..3c0f8c92cff 100644 --- a/Libraries/LibWeb/CSS/StyleValues/EdgeStyleValue.h +++ b/Libraries/LibWeb/CSS/StyleValues/EdgeStyleValue.h @@ -41,6 +41,8 @@ public: virtual String to_string(SerializationMode) const override; + ValueComparingNonnullRefPtr resolved_value(CalculationContext context) const; + bool properties_equal(EdgeStyleValue const& other) const { return m_properties == other.m_properties; } private: