From 1c8cc0fccb1ce273ae81f143eb78f4cda3ce2911 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 21 Feb 2020 00:46:50 +0000 Subject: [PATCH] Bug 1616691 - Fix C++ side of values. r=heycam Differential Revision: https://phabricator.services.mozilla.com/D63398 --HG-- extra : moz-landing-system : lando --- layout/style/ServoStyleConstsInlines.h | 32 +++--- layout/style/nsStyleStruct.cpp | 106 ++++++++++++++++++ .../values/computed/length_percentage.rs | 1 + .../components/style/values/generics/calc.rs | 12 +- .../components/style/values/specified/calc.rs | 7 +- servo/ports/geckolib/cbindgen.toml | 16 +++ 6 files changed, 146 insertions(+), 28 deletions(-) diff --git a/layout/style/ServoStyleConstsInlines.h b/layout/style/ServoStyleConstsInlines.h index c2a78899b546..17aaa4243b6b 100644 --- a/layout/style/ServoStyleConstsInlines.h +++ b/layout/style/ServoStyleConstsInlines.h @@ -644,12 +644,7 @@ CSSCoord LengthPercentage::ToLengthInCSSPixels() const { } bool LengthPercentage::ConvertsToPercentage() const { - if (IsPercentage()) { - return true; - } - MOZ_ASSERT(IsLength() || !AsCalc().length.IsZero(), - "Should've been simplified to a percentage"); - return false; + return IsPercentage(); } float LengthPercentage::ToPercentage() const { @@ -673,11 +668,16 @@ bool LengthPercentage::IsDefinitelyZero() const { if (IsPercentage()) { return AsPercentage()._0 == 0.0f; } - MOZ_ASSERT(!AsCalc().length.IsZero(), - "Should've been simplified to a percentage"); + // calc() should've been simplified to a percentage. return false; } +template <> +CSSCoord StyleCalcNode::ResolveToCSSPixels(CSSCoord aPercentageBasis) const; + +template <> +void StyleCalcNode::ScaleLengthsBy(float); + CSSCoord LengthPercentage::ResolveToCSSPixels(CSSCoord aPercentageBasis) const { if (IsLength()) { return AsLength().ToCSSPixels(); @@ -685,8 +685,7 @@ CSSCoord LengthPercentage::ResolveToCSSPixels(CSSCoord aPercentageBasis) const { if (IsPercentage()) { return AsPercentage()._0 * aPercentageBasis; } - auto& calc = AsCalc(); - return calc.length.ToCSSPixels() + calc.percentage._0 * aPercentageBasis; + return AsCalc().node.ResolveToCSSPixels(aPercentageBasis); } template @@ -700,12 +699,11 @@ CSSCoord LengthPercentage::ResolveToCSSPixelsWith(T aPercentageGetter) const { } template -nscoord LengthPercentage::Resolve(T aPercentageGetter, - U aPercentageRounder) const { +nscoord LengthPercentage::Resolve(T aPercentageGetter, U aRounder) const { static_assert(std::is_same::value, "Should return app units"); static_assert( - std::is_same::value, + std::is_same::value, "Should return app units"); if (ConvertsToLength()) { return ToLength(); @@ -715,11 +713,9 @@ nscoord LengthPercentage::Resolve(T aPercentageGetter, } nscoord basis = aPercentageGetter(); if (IsPercentage()) { - return aPercentageRounder(basis * AsPercentage()._0); + return aRounder(basis * AsPercentage()._0); } - auto& calc = AsCalc(); - return calc.length.ToAppUnits() + - aPercentageRounder(basis * calc.percentage._0); + return AsCalc().node.Resolve(basis, aRounder); } nscoord LengthPercentage::Resolve(nscoord aPercentageBasis) const { @@ -743,7 +739,7 @@ void LengthPercentage::ScaleLengthsBy(float aScale) { AsLength().ScaleBy(aScale); } if (IsCalc()) { - AsCalc().length.ScaleBy(aScale); + AsCalc().node.ScaleLengthsBy(aScale); } } diff --git a/layout/style/nsStyleStruct.cpp b/layout/style/nsStyleStruct.cpp index ebf44d67116e..c69995188cea 100644 --- a/layout/style/nsStyleStruct.cpp +++ b/layout/style/nsStyleStruct.cpp @@ -3446,3 +3446,109 @@ bool StyleTransform::HasPercent() const { } return false; } + +template <> +void StyleCalcNode::ScaleLengthsBy(float aScale) { + auto ScaleNode = [aScale](const StyleCalcNode& aNode) { + // This const_cast could be removed by generating more mut-casts, if + // needed. + const_cast(aNode).ScaleLengthsBy(aScale); + }; + + switch (tag) { + case Tag::Leaf: { + auto& leaf = AsLeaf(); + if (leaf.IsLength()) { + // This const_cast could be removed by generating more mut-casts, if + // needed. + const_cast(leaf.AsLength()).ScaleBy(aScale); + } + break; + } + case Tag::Clamp: { + auto& clamp = AsClamp(); + ScaleNode(*clamp.min); + ScaleNode(*clamp.center); + ScaleNode(*clamp.max); + break; + } + case Tag::MinMax: { + for (auto& child : AsMinMax()._0.AsSpan()) { + ScaleNode(child); + } + break; + } + case Tag::Sum: { + for (auto& child : AsSum().AsSpan()) { + ScaleNode(child); + } + break; + } + } +} + +template <> +template +ResultT StyleCalcNode::ResolveInternal(ResultT aPercentageBasis, + PercentageConverter aConverter) const { + static_assert(std::is_same_v); + static_assert(std::is_same_v || + std::is_same_v); + + switch (tag) { + case Tag::Leaf: { + auto& leaf = AsLeaf(); + if (leaf.IsPercentage()) { + return aConverter(leaf.AsPercentage()._0 * aPercentageBasis); + } + if constexpr (std::is_same_v) { + return leaf.AsLength().ToAppUnits(); + } else { + return leaf.AsLength().ToCSSPixels(); + } + } + case Tag::Clamp: { + auto& clamp = AsClamp(); + auto min = clamp.min->ResolveInternal(aPercentageBasis, aConverter); + auto center = clamp.center->ResolveInternal(aPercentageBasis, aConverter); + auto max = clamp.max->ResolveInternal(aPercentageBasis, aConverter); + return std::max(min, std::min(center, max)); + } + case Tag::MinMax: { + auto children = AsMinMax()._0.AsSpan(); + StyleMinMaxOp op = AsMinMax()._1; + + ResultT result = children[0].ResolveInternal(aPercentageBasis, aConverter); + for (auto& child : children.From(1)) { + ResultT candidate = child.ResolveInternal(aPercentageBasis, aConverter); + if (op == StyleMinMaxOp::Max) { + result = std::max(result, candidate); + } else { + result = std::min(result, candidate); + } + } + return result; + } + case Tag::Sum: { + ResultT result = 0; + for (auto& child : AsSum().AsSpan()) { + result += child.ResolveInternal(aPercentageBasis, aConverter); + } + return result; + } + } + + MOZ_ASSERT_UNREACHABLE("Unknown calc node"); + return 0; +} + +template<> +CSSCoord StyleCalcNode::ResolveToCSSPixels(CSSCoord aBasis) const { + return ResolveInternal(aBasis, [](CSSCoord aPercent) { return aPercent; }); +} + +template<> +nscoord StyleCalcNode::Resolve(nscoord aBasis, + CoordPercentageRounder aRounder) const { + return ResolveInternal(aBasis, aRounder); +} diff --git a/servo/components/style/values/computed/length_percentage.rs b/servo/components/style/values/computed/length_percentage.rs index b70117f3b18e..4e2e6e5695fd 100644 --- a/servo/components/style/values/computed/length_percentage.rs +++ b/servo/components/style/values/computed/length_percentage.rs @@ -552,6 +552,7 @@ impl<'de> Deserialize<'de> for LengthPercentage { /// The leaves of a `` calc expression. #[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, ToAnimatedZero, ToCss, ToResolvedValue)] #[allow(missing_docs)] +#[repr(u8)] pub enum CalcLengthPercentageLeaf { Length(Length), Percentage(Percentage), diff --git a/servo/components/style/values/generics/calc.rs b/servo/components/style/values/generics/calc.rs index 6a920ddcd78b..833864aebf20 100644 --- a/servo/components/style/values/generics/calc.rs +++ b/servo/components/style/values/generics/calc.rs @@ -54,9 +54,9 @@ pub enum GenericCalcNode { Leaf(L), /// A sum node, representing `a + b + c` where a, b, and c are the /// arguments. - Sum(Box<[GenericCalcNode]>), + Sum(crate::OwnedSlice>), /// A `min` or `max` function. - MinMax(Box<[GenericCalcNode]>, MinMaxOp), + MinMax(crate::OwnedSlice>, MinMaxOp), /// A `clamp()` function. Clamp { /// The minimum value. @@ -131,7 +131,7 @@ impl CalcNode { fn map_children( children: &[CalcNode], map: &mut F, - ) -> Box<[CalcNode]> + ) -> crate::OwnedSlice> where L: CalcNodeLeaf, O: CalcNodeLeaf, @@ -209,7 +209,7 @@ impl CalcNode { pub fn simplify_and_sort_children(&mut self) { macro_rules! replace_self_with { ($slot:expr) => {{ - let dummy = Self::MinMax(Box::new([]), MinMaxOp::Max); + let dummy = Self::MinMax(Default::default(), MinMaxOp::Max); let result = mem::replace($slot, dummy); mem::replace(self, result); }}; @@ -315,7 +315,7 @@ impl CalcNode { return replace_self_with!(&mut children_slot[0]); } - let mut children = mem::replace(children_slot, Box::new([])).into_vec(); + let mut children = mem::replace(children_slot, Default::default()).into_vec(); if !sums_to_merge.is_empty() { children.reserve(extra_kids - sums_to_merge.len()); @@ -347,7 +347,7 @@ impl CalcNode { replace_self_with!(&mut children[0]); } else { // Else put our simplified children back. - mem::replace(children_slot, children.into_boxed_slice()); + mem::replace(children_slot, children.into_boxed_slice().into()); } }, Self::Leaf(ref mut l) => { diff --git a/servo/components/style/values/specified/calc.rs b/servo/components/style/values/specified/calc.rs index 9d0d407fbf43..9f5817a77036 100644 --- a/servo/components/style/values/specified/calc.rs +++ b/servo/components/style/values/specified/calc.rs @@ -397,8 +397,7 @@ impl CalcNode { let arguments = input .parse_comma_separated(|input| { Self::parse_argument(context, input, expected_unit) - })? - .into_boxed_slice(); + })?; let op = match function { MathFunction::Min => MinMaxOp::Min, @@ -406,7 +405,7 @@ impl CalcNode { _ => unreachable!(), }; - Ok(Self::MinMax(arguments, op)) + Ok(Self::MinMax(arguments.into(), op)) }, } }) @@ -452,7 +451,7 @@ impl CalcNode { Ok(if sum.len() == 1 { sum.drain(..).next().unwrap() } else { - Self::Sum(sum.into_boxed_slice()) + Self::Sum(sum.into_boxed_slice().into()) }) } diff --git a/servo/ports/geckolib/cbindgen.toml b/servo/ports/geckolib/cbindgen.toml index ee86b2ef051e..623e63711607 100644 --- a/servo/ports/geckolib/cbindgen.toml +++ b/servo/ports/geckolib/cbindgen.toml @@ -271,6 +271,22 @@ renaming_overrides_prefixing = true inline void ScaleBy(float); """ +"GenericCalcNode" = """ + private: + + template + ResultT ResolveInternal(ResultT aPercentageBasis, + PercentageConverter aPercentageConverter) const; + + public: + CSSCoord ResolveToCSSPixels(CSSCoord aPercentageBasis) const; + + using CoordPercentageRounder = nscoord(*)(float); + nscoord Resolve(nscoord aBasis, CoordPercentageRounder) const; + + void ScaleLengthsBy(float); +""" + "LengthPercentageUnion" = """ using Self = StyleLengthPercentageUnion;