зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1616691 - Fix C++ side of <length-percentage> values. r=heycam
Differential Revision: https://phabricator.services.mozilla.com/D63398 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
9776b78db8
Коммит
1c8cc0fccb
|
@ -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 <typename T>
|
||||
|
@ -700,12 +699,11 @@ CSSCoord LengthPercentage::ResolveToCSSPixelsWith(T aPercentageGetter) const {
|
|||
}
|
||||
|
||||
template <typename T, typename U>
|
||||
nscoord LengthPercentage::Resolve(T aPercentageGetter,
|
||||
U aPercentageRounder) const {
|
||||
nscoord LengthPercentage::Resolve(T aPercentageGetter, U aRounder) const {
|
||||
static_assert(std::is_same<decltype(aPercentageGetter()), nscoord>::value,
|
||||
"Should return app units");
|
||||
static_assert(
|
||||
std::is_same<decltype(aPercentageRounder(1.0f)), nscoord>::value,
|
||||
std::is_same<decltype(aRounder(1.0f)), nscoord>::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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<StyleCalcNode&>(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<Length&>(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 <typename ResultT, typename PercentageConverter>
|
||||
ResultT StyleCalcNode::ResolveInternal(ResultT aPercentageBasis,
|
||||
PercentageConverter aConverter) const {
|
||||
static_assert(std::is_same_v<decltype(aConverter(1.0f)), ResultT>);
|
||||
static_assert(std::is_same_v<ResultT, nscoord> ||
|
||||
std::is_same_v<ResultT, CSSCoord>);
|
||||
|
||||
switch (tag) {
|
||||
case Tag::Leaf: {
|
||||
auto& leaf = AsLeaf();
|
||||
if (leaf.IsPercentage()) {
|
||||
return aConverter(leaf.AsPercentage()._0 * aPercentageBasis);
|
||||
}
|
||||
if constexpr (std::is_same_v<ResultT, nscoord>) {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -552,6 +552,7 @@ impl<'de> Deserialize<'de> for LengthPercentage {
|
|||
/// The leaves of a `<length-percentage>` calc expression.
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, PartialEq, Serialize, ToAnimatedZero, ToCss, ToResolvedValue)]
|
||||
#[allow(missing_docs)]
|
||||
#[repr(u8)]
|
||||
pub enum CalcLengthPercentageLeaf {
|
||||
Length(Length),
|
||||
Percentage(Percentage),
|
||||
|
|
|
@ -54,9 +54,9 @@ pub enum GenericCalcNode<L> {
|
|||
Leaf(L),
|
||||
/// A sum node, representing `a + b + c` where a, b, and c are the
|
||||
/// arguments.
|
||||
Sum(Box<[GenericCalcNode<L>]>),
|
||||
Sum(crate::OwnedSlice<GenericCalcNode<L>>),
|
||||
/// A `min` or `max` function.
|
||||
MinMax(Box<[GenericCalcNode<L>]>, MinMaxOp),
|
||||
MinMax(crate::OwnedSlice<GenericCalcNode<L>>, MinMaxOp),
|
||||
/// A `clamp()` function.
|
||||
Clamp {
|
||||
/// The minimum value.
|
||||
|
@ -131,7 +131,7 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
|
|||
fn map_children<L, O, F>(
|
||||
children: &[CalcNode<L>],
|
||||
map: &mut F,
|
||||
) -> Box<[CalcNode<O>]>
|
||||
) -> crate::OwnedSlice<CalcNode<O>>
|
||||
where
|
||||
L: CalcNodeLeaf,
|
||||
O: CalcNodeLeaf,
|
||||
|
@ -209,7 +209,7 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
|
|||
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<L: CalcNodeLeaf> CalcNode<L> {
|
|||
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<L: CalcNodeLeaf> CalcNode<L> {
|
|||
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) => {
|
||||
|
|
|
@ -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())
|
||||
})
|
||||
}
|
||||
|
||||
|
|
|
@ -271,6 +271,22 @@ renaming_overrides_prefixing = true
|
|||
inline void ScaleBy(float);
|
||||
"""
|
||||
|
||||
"GenericCalcNode" = """
|
||||
private:
|
||||
|
||||
template <typename ResultT, typename PercentageConverter>
|
||||
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;
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче