diff --git a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp index 9932b07ce1e..9b691d84cd0 100644 --- a/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp +++ b/Userland/Libraries/LibWeb/CSS/Parser/Parser.cpp @@ -6552,6 +6552,7 @@ public: { builder.appendff("{: >{}}UNPARSED({})\n", "", indent, m_component_value.to_debug_string()); } + virtual bool equals(CalculationNode const&) const override { return false; } private: UnparsedCalculationNode(ComponentValue component_value) diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp b/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp index f77baaf9312..5dacf8e27ab 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.cpp @@ -237,6 +237,15 @@ void NumericCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}NUMERIC({})\n", "", indent, m_value.visit([](auto& it) { return it.to_string(); })); } +bool NumericCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value == static_cast(other).m_value; +} + NonnullOwnPtr SumCalculationNode::create(Vector> values) { return adopt_own(*new (nothrow) SumCalculationNode(move(values))); @@ -355,6 +364,19 @@ void SumCalculationNode::dump(StringBuilder& builder, int indent) const item->dump(builder, indent + 2); } +bool SumCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + for (size_t i = 0; i < m_values.size(); ++i) { + if (!m_values[i]->equals(*static_cast(other).m_values[i])) + return false; + } + return true; +} + NonnullOwnPtr ProductCalculationNode::create(Vector> values) { return adopt_own(*new (nothrow) ProductCalculationNode(move(values))); @@ -478,6 +500,19 @@ void ProductCalculationNode::dump(StringBuilder& builder, int indent) const item->dump(builder, indent + 2); } +bool ProductCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + for (size_t i = 0; i < m_values.size(); ++i) { + if (!m_values[i]->equals(*static_cast(other).m_values[i])) + return false; + } + return true; +} + NonnullOwnPtr NegateCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) NegateCalculationNode(move(value))); @@ -532,6 +567,15 @@ void NegateCalculationNode::dump(StringBuilder& builder, int indent) const m_value->dump(builder, indent + 2); } +bool NegateCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr InvertCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) InvertCalculationNode(move(value))); @@ -593,6 +637,15 @@ void InvertCalculationNode::dump(StringBuilder& builder, int indent) const m_value->dump(builder, indent + 2); } +bool InvertCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr MinCalculationNode::create(Vector> values) { return adopt_own(*new (nothrow) MinCalculationNode(move(values))); @@ -675,6 +728,19 @@ void MinCalculationNode::dump(StringBuilder& builder, int indent) const value->dump(builder, indent + 2); } +bool MinCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + for (size_t i = 0; i < m_values.size(); ++i) { + if (!m_values[i]->equals(*static_cast(other).m_values[i])) + return false; + } + return true; +} + NonnullOwnPtr MaxCalculationNode::create(Vector> values) { return adopt_own(*new (nothrow) MaxCalculationNode(move(values))); @@ -757,6 +823,19 @@ void MaxCalculationNode::dump(StringBuilder& builder, int indent) const value->dump(builder, indent + 2); } +bool MaxCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + for (size_t i = 0; i < m_values.size(); ++i) { + if (!m_values[i]->equals(*static_cast(other).m_values[i])) + return false; + } + return true; +} + NonnullOwnPtr ClampCalculationNode::create(NonnullOwnPtr min, NonnullOwnPtr center, NonnullOwnPtr max) { return adopt_own(*new (nothrow) ClampCalculationNode(move(min), move(center), move(max))); @@ -853,6 +932,17 @@ void ClampCalculationNode::dump(StringBuilder& builder, int indent) const m_max_value->dump(builder, indent + 2); } +bool ClampCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_min_value->equals(*static_cast(other).m_min_value) + && m_center_value->equals(*static_cast(other).m_center_value) + && m_max_value->equals(*static_cast(other).m_max_value); +} + NonnullOwnPtr AbsCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) AbsCalculationNode(move(value))); @@ -915,6 +1005,15 @@ void AbsCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}ABS: {}\n", "", indent, to_string()); } +bool AbsCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr SignCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) SignCalculationNode(move(value))); @@ -979,6 +1078,15 @@ void SignCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}SIGN: {}\n", "", indent, to_string()); } +bool SignCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr ConstantCalculationNode::create(ConstantType constant) { return adopt_own(*new (nothrow) ConstantCalculationNode(constant)); @@ -1047,6 +1155,15 @@ void ConstantCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}CONSTANT: {}\n", "", indent, to_string()); } +bool ConstantCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_constant == static_cast(other).m_constant; +} + NonnullOwnPtr SinCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) SinCalculationNode(move(value))); @@ -1106,6 +1223,15 @@ void SinCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}SIN: {}\n", "", indent, to_string()); } +bool SinCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr CosCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) CosCalculationNode(move(value))); @@ -1165,6 +1291,15 @@ void CosCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}COS: {}\n", "", indent, to_string()); } +bool CosCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr TanCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) TanCalculationNode(move(value))); @@ -1224,6 +1359,15 @@ void TanCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}TAN: {}\n", "", indent, to_string()); } +bool TanCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr AsinCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) AsinCalculationNode(move(value))); @@ -1283,6 +1427,15 @@ void AsinCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}ASIN: {}\n", "", indent, to_string()); } +bool AsinCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr AcosCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) AcosCalculationNode(move(value))); @@ -1342,6 +1495,15 @@ void AcosCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}ACOS: {}\n", "", indent, to_string()); } +bool AcosCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr AtanCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) AtanCalculationNode(move(value))); @@ -1401,6 +1563,15 @@ void AtanCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}ATAN: {}\n", "", indent, to_string()); } +bool AtanCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr Atan2CalculationNode::create(NonnullOwnPtr y, NonnullOwnPtr x) { return adopt_own(*new (nothrow) Atan2CalculationNode(move(y), move(x))); @@ -1469,6 +1640,16 @@ void Atan2CalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}ATAN2: {}\n", "", indent, to_string()); } +bool Atan2CalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_x->equals(*static_cast(other).m_x) + && m_y->equals(*static_cast(other).m_y); +} + NonnullOwnPtr PowCalculationNode::create(NonnullOwnPtr x, NonnullOwnPtr y) { return adopt_own(*new (nothrow) PowCalculationNode(move(x), move(y))); @@ -1532,6 +1713,16 @@ void PowCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}POW: {}\n", "", indent, to_string()); } +bool PowCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_x->equals(*static_cast(other).m_x) + && m_y->equals(*static_cast(other).m_y); +} + NonnullOwnPtr SqrtCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) SqrtCalculationNode(move(value))); @@ -1586,6 +1777,15 @@ void SqrtCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}SQRT: {}\n", "", indent, to_string()); } +bool SqrtCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr HypotCalculationNode::create(Vector> values) { return adopt_own(*new (nothrow) HypotCalculationNode(move(values))); @@ -1666,6 +1866,19 @@ void HypotCalculationNode::dump(StringBuilder& builder, int indent) const value->dump(builder, indent + 2); } +bool HypotCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + for (size_t i = 0; i < m_values.size(); ++i) { + if (!m_values[i]->equals(*static_cast(other).m_values[i])) + return false; + } + return true; +} + NonnullOwnPtr LogCalculationNode::create(NonnullOwnPtr x, NonnullOwnPtr y) { return adopt_own(*new (nothrow) LogCalculationNode(move(x), move(y))); @@ -1729,6 +1942,16 @@ void LogCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}LOG: {}\n", "", indent, to_string()); } +bool LogCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_x->equals(*static_cast(other).m_x) + && m_y->equals(*static_cast(other).m_y); +} + NonnullOwnPtr ExpCalculationNode::create(NonnullOwnPtr value) { return adopt_own(*new (nothrow) ExpCalculationNode(move(value))); @@ -1783,6 +2006,15 @@ void ExpCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}EXP: {}\n", "", indent, to_string()); } +bool ExpCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_value->equals(*static_cast(other).m_value); +} + NonnullOwnPtr RoundCalculationNode::create(RoundingStrategy strategy, NonnullOwnPtr x, NonnullOwnPtr y) { return adopt_own(*new (nothrow) RoundCalculationNode(strategy, move(x), move(y))); @@ -1885,6 +2117,17 @@ void RoundCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}ROUND: {}\n", "", indent, to_string()); } +bool RoundCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_strategy == static_cast(other).m_strategy + && m_x->equals(*static_cast(other).m_x) + && m_y->equals(*static_cast(other).m_y); +} + NonnullOwnPtr ModCalculationNode::create(NonnullOwnPtr x, NonnullOwnPtr y) { return adopt_own(*new (nothrow) ModCalculationNode(move(x), move(y))); @@ -1961,6 +2204,16 @@ void ModCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}MOD: {}\n", "", indent, to_string()); } +bool ModCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_x->equals(*static_cast(other).m_x) + && m_y->equals(*static_cast(other).m_y); +} + NonnullOwnPtr RemCalculationNode::create(NonnullOwnPtr x, NonnullOwnPtr y) { return adopt_own(*new (nothrow) RemCalculationNode(move(x), move(y))); @@ -2036,6 +2289,16 @@ void RemCalculationNode::dump(StringBuilder& builder, int indent) const builder.appendff("{: >{}}REM: {}\n", "", indent, to_string()); } +bool RemCalculationNode::equals(CalculationNode const& other) const +{ + if (this == &other) + return true; + if (type() != other.type()) + return false; + return m_x->equals(*static_cast(other).m_x) + && m_y->equals(*static_cast(other).m_y); +} + void CalculatedStyleValue::CalculationResult::add(CalculationResult const& other, Optional context, PercentageBasis const& percentage_basis) { add_or_subtract_internal(SumOperation::Add, other, context, percentage_basis); @@ -2331,8 +2594,8 @@ bool CalculatedStyleValue::equals(StyleValue const& other) const { if (type() != other.type()) return false; - // This is a case where comparing the strings actually makes sense. - return to_string() == other.to_string(); + + return m_calculation->equals(*static_cast(other).m_calculation); } Optional CalculatedStyleValue::resolve_angle() const diff --git a/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h b/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h index a9f1339d0d5..f3a64a0826b 100644 --- a/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h +++ b/Userland/Libraries/LibWeb/CSS/StyleValues/CalculatedStyleValue.h @@ -65,6 +65,8 @@ public: Value const& value() const { return m_value; } + [[nodiscard]] bool operator==(CalculationResult const&) const = default; + private: void add_or_subtract_internal(SumOperation op, CalculationResult const& other, Optional, PercentageBasis const& percentage_basis); Value m_value; @@ -253,6 +255,7 @@ public: virtual void for_each_child_node(Function&)> const&) = 0; virtual void dump(StringBuilder&, int indent) const = 0; + virtual bool equals(CalculationNode const&) const = 0; protected: explicit CalculationNode(Type); @@ -274,6 +277,7 @@ public: virtual void for_each_child_node(Function&)> const&) override { } virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit NumericCalculationNode(NumericValue); @@ -293,6 +297,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit SumCalculationNode(Vector>); @@ -312,6 +317,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit ProductCalculationNode(Vector>); @@ -331,6 +337,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit NegateCalculationNode(NonnullOwnPtr); @@ -350,6 +357,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit InvertCalculationNode(NonnullOwnPtr); @@ -369,6 +377,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit MinCalculationNode(Vector>); @@ -388,6 +397,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit MaxCalculationNode(Vector>); @@ -407,6 +417,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit ClampCalculationNode(NonnullOwnPtr, NonnullOwnPtr, NonnullOwnPtr); @@ -428,6 +439,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: AbsCalculationNode(NonnullOwnPtr); @@ -447,6 +459,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: SignCalculationNode(NonnullOwnPtr); @@ -466,6 +479,7 @@ public: virtual void for_each_child_node(Function&)> const&) override { } virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: ConstantCalculationNode(ConstantType); @@ -485,6 +499,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: SinCalculationNode(NonnullOwnPtr); @@ -504,6 +519,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: CosCalculationNode(NonnullOwnPtr); @@ -523,6 +539,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: TanCalculationNode(NonnullOwnPtr); @@ -542,6 +559,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: AsinCalculationNode(NonnullOwnPtr); @@ -561,6 +579,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: AcosCalculationNode(NonnullOwnPtr); @@ -580,6 +599,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: AtanCalculationNode(NonnullOwnPtr); @@ -599,6 +619,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: Atan2CalculationNode(NonnullOwnPtr, NonnullOwnPtr); @@ -619,6 +640,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit PowCalculationNode(NonnullOwnPtr, NonnullOwnPtr); @@ -639,6 +661,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: SqrtCalculationNode(NonnullOwnPtr); @@ -658,6 +681,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: explicit HypotCalculationNode(Vector>); @@ -677,6 +701,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: LogCalculationNode(NonnullOwnPtr, NonnullOwnPtr); @@ -697,6 +722,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: ExpCalculationNode(NonnullOwnPtr); @@ -716,6 +742,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: RoundCalculationNode(RoundingStrategy, NonnullOwnPtr, NonnullOwnPtr); @@ -737,6 +764,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: ModCalculationNode(NonnullOwnPtr, NonnullOwnPtr); @@ -757,6 +785,7 @@ public: virtual void for_each_child_node(Function&)> const&) override; virtual void dump(StringBuilder&, int indent) const override; + virtual bool equals(CalculationNode const&) const override; private: RemCalculationNode(NonnullOwnPtr, NonnullOwnPtr);