diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp index 67d057ca83..3c17869a30 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.cpp @@ -249,6 +249,7 @@ String BackgroundStyleValue::to_string() const return builder.to_string(); } +<<<<<<< HEAD String BackgroundRepeatStyleValue::to_string() const { return String::formatted("{} {}", CSS::to_string(m_repeat_x), CSS::to_string(m_repeat_y)); @@ -272,6 +273,113 @@ String BorderRadiusStyleValue::to_string() const String BoxShadowStyleValue::to_string() const { return String::formatted("{} {} {} {}", m_offset_x.to_string(), m_offset_y.to_string(), m_blur_radius.to_string(), m_color.to_string()); +======= +void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other, Layout::Node const* layout_node, Length const& percentage_basis) +{ + add_or_subtract_internal(SumOperation::Add, other, layout_node, percentage_basis); +} + +void CalculatedStyleValue::CalculationResult::subtract(CalculationResult const& other, Layout::Node const* layout_node, Length const& percentage_basis) +{ + add_or_subtract_internal(SumOperation::Subtract, other, layout_node, percentage_basis); +} + +void CalculatedStyleValue::CalculationResult::add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const* layout_node, Length const& percentage_basis) +{ + // We know from validation when resolving the type, that "both sides have the same type, or that one side is a and the other is an ". + // Though, having the same type may mean that one side is a and the other a . + // Note: This is almost identical to ::add() + + m_value.visit( + [&](float f) { + if (op == SumOperation::Add) + m_value = f + other.m_value.get(); + else + m_value = f - other.m_value.get(); + }, + [&](Length const& length) { + auto this_px = length.to_px(*layout_node); + if (other.m_value.has()) { + auto other_px = other.m_value.get().to_px(*layout_node); + if (op == SumOperation::Add) + m_value = Length::make_px(this_px + other_px); + else + m_value = Length::make_px(this_px - other_px); + } else { + VERIFY(!percentage_basis.is_undefined()); + + auto other_px = percentage_basis.percentage_of(other.m_value.get()).to_px(*layout_node); + if (op == SumOperation::Add) + m_value = Length::make_px(this_px + other_px); + else + m_value = Length::make_px(this_px - other_px); + } + }, + [&](Percentage const& percentage) { + if (other.m_value.has()) { + if (op == SumOperation::Add) + m_value = Percentage { percentage.value() + other.m_value.get().value() }; + else + m_value = Percentage { percentage.value() - other.m_value.get().value() }; + return; + } + + // Other side isn't a percentage, so the easiest way to handle it without duplicating all the logic, is just to swap `this` and `other`. + CalculationResult new_value = other; + if (op == SumOperation::Add) + new_value.add(*this, layout_node, percentage_basis); + else + new_value.subtract(*this, layout_node, percentage_basis); + + *this = new_value; + }); +} + +void CalculatedStyleValue::CalculationResult::multiply_by(CalculationResult const& other, Layout::Node const* layout_node) +{ + // We know from validation when resolving the type, that at least one side must be a or . + // Both of these are represented as a float. + VERIFY(m_value.has() || other.m_value.has()); + bool other_is_number = other.m_value.has(); + + m_value.visit( + [&](float f) { + if (other_is_number) { + m_value = f * other.m_value.get(); + } else { + // Avoid duplicating all the logic by swapping `this` and `other`. + CalculationResult new_value = other; + new_value.multiply_by(*this, layout_node); + *this = new_value; + } + }, + [&](Length const& length) { + m_value = Length::make_px(length.to_px(*layout_node) * other.m_value.get()); + }, + [&](Percentage const& percentage) { + m_value = Percentage { percentage.value() * other.m_value.get() }; + }); +} + +void CalculatedStyleValue::CalculationResult::divide_by(CalculationResult const& other, Layout::Node const* layout_node) +{ + // We know from validation when resolving the type, that `other` must be a or . + // Both of these are represented as a float. + float denominator = other.m_value.get(); + // FIXME: Dividing by 0 is invalid, and should be caught during parsing. + VERIFY(denominator != 0.0f); + + m_value.visit( + [&](float f) { + m_value = f / denominator; + }, + [&](Length const& length) { + m_value = Length::make_px(length.to_px(*layout_node) / denominator); + }, + [&](Percentage const& percentage) { + m_value = Percentage { percentage.value() / denominator }; + }); +>>>>>>> d91d120251 (LibWeb: Implement CalculationResult type for calc() results) } static float resolve_calc_value(CalculatedStyleValue::CalcValue const& calc_value, Layout::Node const& layout_node); diff --git a/Userland/Libraries/LibWeb/CSS/StyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValue.h index 04afe626a9..3bfd434bf9 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValue.h @@ -664,6 +664,33 @@ public: Time, }; + enum class SumOperation { + Add, + Subtract, + }; + enum class ProductOperation { + Multiply, + Divide, + }; + + class CalculationResult { + public: + CalculationResult(Variant value) + : m_value(move(value)) + { + } + void add(CalculationResult const& other, Layout::Node const*, Length const& percentage_basis); + void subtract(CalculationResult const& other, Layout::Node const*, Length const& percentage_basis); + void multiply_by(CalculationResult const& other, Layout::Node const*); + void divide_by(CalculationResult const& other, Layout::Node const*); + + Variant const& value() const { return m_value; } + + private: + void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Layout::Node const*, Length const& percentage_basis); + Variant m_value; + }; + struct CalcSum; struct CalcSumPartWithOperator; struct CalcProduct; @@ -683,15 +710,6 @@ public: Optional resolved_type() const; }; - enum class SumOperation { - Add, - Subtract, - }; - enum class ProductOperation { - Multiply, - Divide, - }; - // This represents that: https://www.w3.org/TR/css-values-3/#calc-syntax struct CalcSum { CalcSum(NonnullOwnPtr first_calc_product, NonnullOwnPtrVector additional)