summaryrefslogtreecommitdiffstats
path: root/servo/components/style/values/generics
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:35:37 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-06-12 05:35:37 +0000
commita90a5cba08fdf6c0ceb95101c275108a152a3aed (patch)
tree532507288f3defd7f4dcf1af49698bcb76034855 /servo/components/style/values/generics
parentAdding debian version 126.0.1-1. (diff)
downloadfirefox-a90a5cba08fdf6c0ceb95101c275108a152a3aed.tar.xz
firefox-a90a5cba08fdf6c0ceb95101c275108a152a3aed.zip
Merging upstream version 127.0.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'servo/components/style/values/generics')
-rw-r--r--servo/components/style/values/generics/calc.rs243
-rw-r--r--servo/components/style/values/generics/counters.rs37
2 files changed, 179 insertions, 101 deletions
diff --git a/servo/components/style/values/generics/calc.rs b/servo/components/style/values/generics/calc.rs
index abcb5fe6eb..215db1932b 100644
--- a/servo/components/style/values/generics/calc.rs
+++ b/servo/components/style/values/generics/calc.rs
@@ -255,12 +255,15 @@ bitflags! {
const TIME = 1 << 3;
/// <resolution>
const RESOLUTION = 1 << 4;
+ /// A component of a color (r, g, b, h, s, l, alpha, etc.)
+ const COLOR_COMPONENT = 1 << 5;
/// <length-percentage>
const LENGTH_PERCENTAGE = Self::LENGTH.bits() | Self::PERCENTAGE.bits();
// NOTE: When you add to this, make sure to make Atan2 deal with these.
/// Allow all units.
- const ALL = Self::LENGTH.bits() | Self::PERCENTAGE.bits() | Self::ANGLE.bits() | Self::TIME.bits() | Self::RESOLUTION.bits();
+ const ALL = Self::LENGTH.bits() | Self::PERCENTAGE.bits() | Self::ANGLE.bits() |
+ Self::TIME.bits() | Self::RESOLUTION.bits() | Self::COLOR_COMPONENT.bits();
}
}
@@ -323,8 +326,8 @@ pub trait CalcNodeLeaf: Clone + Sized + PartialEq + ToCss {
/// Returns the unit of the leaf.
fn unit(&self) -> CalcUnits;
- /// Returns the unitless value of this leaf.
- fn unitless_value(&self) -> f32;
+ /// Returns the unitless value of this leaf if one is available.
+ fn unitless_value(&self) -> Option<f32>;
/// Return true if the units of both leaves are equal. (NOTE: Does not take
/// the values into account)
@@ -347,23 +350,31 @@ pub trait CalcNodeLeaf: Clone + Sized + PartialEq + ToCss {
fn as_number(&self) -> Option<f32>;
/// Whether this value is known-negative.
- fn is_negative(&self) -> bool {
- self.unitless_value().is_sign_negative()
+ fn is_negative(&self) -> Result<bool, ()> {
+ self.unitless_value()
+ .map(|v| Ok(v.is_sign_negative()))
+ .unwrap_or_else(|| Err(()))
}
/// Whether this value is infinite.
- fn is_infinite(&self) -> bool {
- self.unitless_value().is_infinite()
+ fn is_infinite(&self) -> Result<bool, ()> {
+ self.unitless_value()
+ .map(|v| Ok(v.is_infinite()))
+ .unwrap_or_else(|| Err(()))
}
/// Whether this value is zero.
- fn is_zero(&self) -> bool {
- self.unitless_value().is_zero()
+ fn is_zero(&self) -> Result<bool, ()> {
+ self.unitless_value()
+ .map(|v| Ok(v.is_zero()))
+ .unwrap_or_else(|| Err(()))
}
/// Whether this value is NaN.
- fn is_nan(&self) -> bool {
- self.unitless_value().is_nan()
+ fn is_nan(&self) -> Result<bool, ()> {
+ self.unitless_value()
+ .map(|v| Ok(v.is_nan()))
+ .unwrap_or_else(|| Err(()))
}
/// Tries to merge one leaf into another using the sum, that is, perform `x` + `y`.
@@ -379,12 +390,7 @@ pub trait CalcNodeLeaf: Clone + Sized + PartialEq + ToCss {
O: Fn(f32, f32) -> f32;
/// Map the value of this node with the given operation.
- fn map(&mut self, op: impl FnMut(f32) -> f32);
-
- /// Negates the leaf.
- fn negate(&mut self) {
- self.map(std::ops::Neg::neg);
- }
+ fn map(&mut self, op: impl FnMut(f32) -> f32) -> Result<(), ()>;
/// Canonicalizes the expression if necessary.
fn simplify(&mut self);
@@ -393,16 +399,20 @@ pub trait CalcNodeLeaf: Clone + Sized + PartialEq + ToCss {
fn sort_key(&self) -> SortKey;
/// Create a new leaf containing the sign() result of the given leaf.
- fn sign_from(leaf: &impl CalcNodeLeaf) -> Self {
- Self::new_number(if leaf.is_nan() {
+ fn sign_from(leaf: &impl CalcNodeLeaf) -> Result<Self, ()> {
+ let Some(value) = leaf.unitless_value() else {
+ return Err(());
+ };
+
+ Ok(Self::new_number(if value.is_nan() {
f32::NAN
- } else if leaf.is_zero() {
- leaf.unitless_value()
- } else if leaf.is_negative() {
+ } else if value.is_zero() {
+ value
+ } else if value.is_sign_negative() {
-1.0
} else {
1.0
- })
+ }))
}
}
@@ -426,8 +436,8 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
/// Change all the leaf nodes to have the given value. This is useful when
/// you have `calc(1px * nan)` and you want to replace the product node with
/// `calc(nan)`, in which case the unit will be retained.
- fn coerce_to_value(&mut self, value: f32) {
- self.map(|_| value);
+ fn coerce_to_value(&mut self, value: f32) -> Result<(), ()> {
+ self.map(|_| value)
}
/// Return true if a product is distributive over this node.
@@ -436,7 +446,7 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
#[inline]
pub fn is_product_distributive(&self) -> bool {
match self {
- Self::Leaf(_) => true,
+ Self::Leaf(l) => l.unit() != CalcUnits::COLOR_COMPONENT,
Self::Sum(children) => children.iter().all(|c| c.is_product_distributive()),
_ => false,
}
@@ -546,7 +556,11 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
}
match *self {
- CalcNode::Leaf(ref mut leaf) => leaf.negate(),
+ CalcNode::Leaf(ref mut leaf) => {
+ if leaf.map(std::ops::Neg::neg).is_err() {
+ wrap_self_in_negate(self)
+ }
+ },
CalcNode::Negate(ref mut value) => {
// Don't negate the value here. Replace `self` with it's child.
let result = mem::replace(value.as_mut(), Self::dummy());
@@ -668,7 +682,9 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
}
if self.is_product_distributive() {
- self.map(|v| v * number);
+ if self.map(|v| v * number).is_err() {
+ return false;
+ }
return true;
}
}
@@ -682,7 +698,9 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
}
if other.is_product_distributive() {
- other.map(|v| v * number);
+ if other.map(|v| v * number).is_err() {
+ return false;
+ }
std::mem::swap(self, other);
return true;
}
@@ -706,48 +724,52 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
}
/// Map the value of this node with the given operation.
- pub fn map(&mut self, mut op: impl FnMut(f32) -> f32) {
- fn map_internal<L: CalcNodeLeaf>(node: &mut CalcNode<L>, op: &mut impl FnMut(f32) -> f32) {
+ pub fn map(&mut self, mut op: impl FnMut(f32) -> f32) -> Result<(), ()> {
+ fn map_internal<L: CalcNodeLeaf>(
+ node: &mut CalcNode<L>,
+ op: &mut impl FnMut(f32) -> f32,
+ ) -> Result<(), ()> {
match node {
CalcNode::Leaf(l) => l.map(op),
CalcNode::Negate(v) | CalcNode::Invert(v) => map_internal(v, op),
CalcNode::Sum(children) | CalcNode::Product(children) => {
for node in &mut **children {
- map_internal(node, op);
+ map_internal(node, op)?;
}
+ Ok(())
},
CalcNode::MinMax(children, _) => {
for node in &mut **children {
- map_internal(node, op);
+ map_internal(node, op)?;
}
+ Ok(())
},
CalcNode::Clamp { min, center, max } => {
- map_internal(min, op);
- map_internal(center, op);
- map_internal(max, op);
+ map_internal(min, op)?;
+ map_internal(center, op)?;
+ map_internal(max, op)
},
CalcNode::Round { value, step, .. } => {
- map_internal(value, op);
- map_internal(step, op);
+ map_internal(value, op)?;
+ map_internal(step, op)
},
CalcNode::ModRem {
dividend, divisor, ..
} => {
- map_internal(dividend, op);
- map_internal(divisor, op);
+ map_internal(dividend, op)?;
+ map_internal(divisor, op)
},
CalcNode::Hypot(children) => {
for node in &mut **children {
- map_internal(node, op);
+ map_internal(node, op)?;
}
+ Ok(())
},
- CalcNode::Abs(child) | CalcNode::Sign(child) => {
- map_internal(child, op);
- },
+ CalcNode::Abs(child) | CalcNode::Sign(child) => map_internal(child, op),
}
}
- map_internal(self, &mut op);
+ map_internal(self, &mut op)
}
/// Convert this `CalcNode` into a `CalcNode` with a different leaf kind.
@@ -849,12 +871,12 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
Self::Leaf(l) => leaf_to_output_fn(l),
Self::Negate(child) => {
let mut result = child.resolve_internal(leaf_to_output_fn)?;
- result.map(|v| v.neg());
+ result.map(|v| v.neg())?;
Ok(result)
},
Self::Invert(child) => {
let mut result = child.resolve_internal(leaf_to_output_fn)?;
- result.map(|v| 1.0 / v);
+ result.map(|v| 1.0 / v)?;
Ok(result)
},
Self::Sum(children) => {
@@ -878,13 +900,13 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
Some(left) => {
// Left side is a number, so we use the right node as the result.
result = right;
- result.map(|v| v * left);
+ result.map(|v| v * left)?;
},
None => {
// Left side is not a number, so check if the right side is.
match right.as_number() {
Some(right) => {
- result.map(|v| v * right);
+ result.map(|v| v * right)?;
},
None => {
// Multiplying with both sides having units.
@@ -900,7 +922,7 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
Self::MinMax(children, op) => {
let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
- if result.is_nan() {
+ if result.is_nan()? {
return Ok(result);
}
@@ -912,7 +934,7 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
return Err(());
}
- if candidate.is_nan() {
+ if candidate.is_nan()? {
result = candidate;
break;
}
@@ -938,15 +960,15 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
return Err(());
}
- if min.is_nan() {
+ if min.is_nan()? {
return Ok(min);
}
- if center.is_nan() {
+ if center.is_nan()? {
return Ok(center);
}
- if max.is_nan() {
+ if max.is_nan()? {
return Ok(max);
}
@@ -972,7 +994,10 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
return Err(());
}
- let step = step.unitless_value().abs();
+ let Some(step) = step.unitless_value() else {
+ return Err(());
+ };
+ let step = step.abs();
value.map(|value| {
// TODO(emilio): Seems like at least a few of these
@@ -1039,7 +1064,7 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
}
},
}
- });
+ })?;
Ok(value)
},
@@ -1055,13 +1080,15 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
return Err(());
}
- let divisor = divisor.unitless_value();
- dividend.map(|dividend| op.apply(dividend, divisor));
+ let Some(divisor) = divisor.unitless_value() else {
+ return Err(());
+ };
+ dividend.map(|dividend| op.apply(dividend, divisor))?;
Ok(dividend)
},
Self::Hypot(children) => {
let mut result = children[0].resolve_internal(leaf_to_output_fn)?;
- result.map(|v| v.powi(2));
+ result.map(|v| v.powi(2))?;
for child in children.iter().skip(1) {
let child_value = child.resolve_internal(leaf_to_output_fn)?;
@@ -1070,45 +1097,48 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
return Err(());
}
- result.map(|v| v + child_value.unitless_value().powi(2));
+ let Some(child_value) = child_value.unitless_value() else {
+ return Err(());
+ };
+ result.map(|v| v + child_value.powi(2))?;
}
- result.map(|v| v.sqrt());
+ result.map(|v| v.sqrt())?;
Ok(result)
},
Self::Abs(ref c) => {
let mut result = c.resolve_internal(leaf_to_output_fn)?;
- result.map(|v| v.abs());
+ result.map(|v| v.abs())?;
Ok(result)
},
Self::Sign(ref c) => {
let result = c.resolve_internal(leaf_to_output_fn)?;
- Ok(L::sign_from(&result))
+ Ok(L::sign_from(&result)?)
},
}
}
- fn is_negative_leaf(&self) -> bool {
- match *self {
- Self::Leaf(ref l) => l.is_negative(),
+ fn is_negative_leaf(&self) -> Result<bool, ()> {
+ Ok(match *self {
+ Self::Leaf(ref l) => l.is_negative()?,
_ => false,
- }
+ })
}
- fn is_zero_leaf(&self) -> bool {
- match *self {
- Self::Leaf(ref l) => l.is_zero(),
+ fn is_zero_leaf(&self) -> Result<bool, ()> {
+ Ok(match *self {
+ Self::Leaf(ref l) => l.is_zero()?,
_ => false,
- }
+ })
}
- fn is_infinite_leaf(&self) -> bool {
- match *self {
- Self::Leaf(ref l) => l.is_infinite(),
+ fn is_infinite_leaf(&self) -> Result<bool, ()> {
+ Ok(match *self {
+ Self::Leaf(ref l) => l.is_infinite()?,
_ => false,
- }
+ })
}
/// Visits all the nodes in this calculation tree recursively, starting by
@@ -1250,54 +1280,64 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
ref mut value,
ref mut step,
} => {
- if step.is_zero_leaf() {
- value.coerce_to_value(f32::NAN);
+ if value_or_stop!(step.is_zero_leaf()) {
+ value_or_stop!(value.coerce_to_value(f32::NAN));
replace_self_with!(&mut **value);
return;
}
- if value.is_infinite_leaf() && step.is_infinite_leaf() {
- value.coerce_to_value(f32::NAN);
+ if value_or_stop!(value.is_infinite_leaf()) &&
+ value_or_stop!(step.is_infinite_leaf())
+ {
+ value_or_stop!(value.coerce_to_value(f32::NAN));
replace_self_with!(&mut **value);
return;
}
- if value.is_infinite_leaf() {
+ if value_or_stop!(value.is_infinite_leaf()) {
replace_self_with!(&mut **value);
return;
}
- if step.is_infinite_leaf() {
+ if value_or_stop!(step.is_infinite_leaf()) {
match strategy {
RoundingStrategy::Nearest | RoundingStrategy::ToZero => {
- value.coerce_to_value(0.0);
+ value_or_stop!(value.coerce_to_value(0.0));
replace_self_with!(&mut **value);
return;
},
RoundingStrategy::Up => {
- if !value.is_negative_leaf() && !value.is_zero_leaf() {
- value.coerce_to_value(f32::INFINITY);
+ if !value_or_stop!(value.is_negative_leaf()) &&
+ !value_or_stop!(value.is_zero_leaf())
+ {
+ value_or_stop!(value.coerce_to_value(f32::INFINITY));
replace_self_with!(&mut **value);
return;
- } else if !value.is_negative_leaf() && value.is_zero_leaf() {
+ } else if !value_or_stop!(value.is_negative_leaf()) &&
+ value_or_stop!(value.is_zero_leaf())
+ {
replace_self_with!(&mut **value);
return;
} else {
- value.coerce_to_value(0.0);
+ value_or_stop!(value.coerce_to_value(0.0));
replace_self_with!(&mut **value);
return;
}
},
RoundingStrategy::Down => {
- if value.is_negative_leaf() && !value.is_zero_leaf() {
- value.coerce_to_value(f32::INFINITY);
+ if value_or_stop!(value.is_negative_leaf()) &&
+ !value_or_stop!(value.is_zero_leaf())
+ {
+ value_or_stop!(value.coerce_to_value(f32::INFINITY));
replace_self_with!(&mut **value);
return;
- } else if value.is_negative_leaf() && value.is_zero_leaf() {
+ } else if value_or_stop!(value.is_negative_leaf()) &&
+ value_or_stop!(value.is_zero_leaf())
+ {
replace_self_with!(&mut **value);
return;
} else {
- value.coerce_to_value(0.0);
+ value_or_stop!(value.coerce_to_value(0.0));
replace_self_with!(&mut **value);
return;
}
@@ -1305,17 +1345,18 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
}
}
- if step.is_negative_leaf() {
+ if value_or_stop!(step.is_negative_leaf()) {
step.negate();
}
let remainder = value_or_stop!(value.try_op(step, Rem::rem));
- if remainder.is_zero_leaf() {
+ if value_or_stop!(remainder.is_zero_leaf()) {
replace_self_with!(&mut **value);
return;
}
- let (mut lower_bound, mut upper_bound) = if value.is_negative_leaf() {
+ let (mut lower_bound, mut upper_bound) = if value_or_stop!(value.is_negative_leaf())
+ {
let upper_bound = value_or_stop!(value.try_op(&remainder, Sub::sub));
let lower_bound = value_or_stop!(upper_bound.try_op(&step, Sub::sub));
@@ -1348,11 +1389,11 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
let mut lower_diff = lower_bound.clone();
let mut upper_diff = upper_bound.clone();
- if lower_diff.is_negative_leaf() {
+ if value_or_stop!(lower_diff.is_negative_leaf()) {
lower_diff.negate();
}
- if upper_diff.is_negative_leaf() {
+ if value_or_stop!(upper_diff.is_negative_leaf()) {
upper_diff.negate();
}
@@ -1518,13 +1559,13 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
},
Self::Abs(ref mut child) => {
if let CalcNode::Leaf(leaf) = child.as_mut() {
- leaf.map(|v| v.abs());
+ value_or_stop!(leaf.map(|v| v.abs()));
replace_self_with!(&mut **child);
}
},
Self::Sign(ref mut child) => {
if let CalcNode::Leaf(leaf) = child.as_mut() {
- let mut result = Self::Leaf(L::sign_from(leaf));
+ let mut result = Self::Leaf(value_or_stop!(L::sign_from(leaf)));
replace_self_with!(&mut result);
}
},
@@ -1553,7 +1594,7 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
// 1. If root’s child is a number (not a percentage or dimension) return the
// reciprocal of the child’s value.
if leaf.unit().is_empty() {
- child.map(|v| 1.0 / v);
+ value_or_stop!(child.map(|v| 1.0 / v));
replace_self_with!(&mut **child);
}
},
@@ -1678,10 +1719,12 @@ impl<L: CalcNodeLeaf> CalcNode<L> {
if !first {
match child {
Self::Leaf(l) => {
- if l.is_negative() {
+ if let Ok(true) = l.is_negative() {
dest.write_str(" - ")?;
let mut negated = l.clone();
- negated.negate();
+ // We can unwrap here, because we already
+ // checked if the value inside is negative.
+ negated.map(std::ops::Neg::neg).unwrap();
negated.to_css(dest)?;
} else {
dest.write_str(" + ")?;
diff --git a/servo/components/style/values/generics/counters.rs b/servo/components/style/values/generics/counters.rs
index 3f23c74b33..d6db48f9c4 100644
--- a/servo/components/style/values/generics/counters.rs
+++ b/servo/components/style/values/generics/counters.rs
@@ -203,6 +203,41 @@ fn is_decimal(counter_type: &CounterStyleType) -> bool {
*counter_type == CounterStyle::decimal()
}
+/// The non-normal, non-none values of the content property.
+#[derive(
+ Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToShmem,
+)]
+#[repr(C)]
+pub struct GenericContentItems<Image> {
+ /// The actual content items. Note that, past the alt marker, only some subset (strings,
+ /// attr(), counter())
+ pub items: thin_vec::ThinVec<GenericContentItem<Image>>,
+ /// The index at which alt text starts, always non-zero. If equal to items.len(), no alt text
+ /// exists.
+ pub alt_start: usize,
+}
+
+impl<Image> ToCss for GenericContentItems<Image>
+where
+ Image: ToCss,
+{
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ where
+ W: Write,
+ {
+ for (i, item) in self.items.iter().enumerate() {
+ if i == self.alt_start {
+ dest.write_str(" /")?;
+ }
+ if i != 0 {
+ dest.write_str(" ")?;
+ }
+ item.to_css(dest)?;
+ }
+ Ok(())
+ }
+}
+
/// The specified value for the `content` property.
///
/// https://drafts.csswg.org/css-content/#propdef-content
@@ -216,7 +251,7 @@ pub enum GenericContent<Image> {
/// `none` reserved keyword.
None,
/// Content items.
- Items(#[css(iterable)] crate::OwnedSlice<GenericContentItem<Image>>),
+ Items(GenericContentItems<Image>),
}
pub use self::GenericContent as Content;