mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
style: Use an ArcSlice as the computed value representation of inherited list properties.
This adds a bit of complexity, which I think will pay off in the end. Removals incoming. Differential Revision: https://phabricator.services.mozilla.com/D30544
This commit is contained in:
parent
5e4fdf647d
commit
2bc4c42d45
4 changed files with 135 additions and 28 deletions
|
@ -3811,9 +3811,10 @@ fn static_assert() {
|
||||||
self.copy_text_shadow_from(other)
|
self.copy_text_shadow_from(other)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(emilio): Remove by sharing representation.
|
||||||
pub fn clone_text_shadow(&self) -> longhands::text_shadow::computed_value::T {
|
pub fn clone_text_shadow(&self) -> longhands::text_shadow::computed_value::T {
|
||||||
let buf = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow()).collect::<Vec<_>>();
|
let iter = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow());
|
||||||
longhands::text_shadow::computed_value::List(buf.into())
|
longhands::text_shadow::computed_value::List(crate::ArcSlice::from_iter(iter))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn clear_text_emphasis_style_if_string(&mut self) {
|
fn clear_text_emphasis_style_if_string(&mut self) {
|
||||||
|
@ -4185,16 +4186,14 @@ clip-path
|
||||||
self.gecko.mContextProps.len()
|
self.gecko.mContextProps.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME(emilio): Remove by sharing representation.
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
pub fn _moz_context_properties_at(
|
pub fn clone__moz_context_properties(&self) -> longhands::_moz_context_properties::computed_value::T {
|
||||||
&self,
|
use crate::values::specified::svg::MozContextProperties;
|
||||||
index: usize,
|
let buf = self.gecko.mContextProps.iter().map(|v| {
|
||||||
) -> longhands::_moz_context_properties::computed_value::single_value::T {
|
MozContextProperties(CustomIdent(unsafe { Atom::from_raw(v.mRawPtr) }))
|
||||||
longhands::_moz_context_properties::computed_value::single_value::T(
|
}).collect::<Vec<_>>();
|
||||||
CustomIdent(unsafe {
|
longhands::_moz_context_properties::computed_value::List(crate::ArcSlice::from_iter(buf.into_iter()))
|
||||||
Atom::from_raw(self.gecko.mContextProps[index].mRawPtr)
|
|
||||||
})
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
|
|
|
@ -80,6 +80,16 @@
|
||||||
We assume that the default/initial value is an empty vector for these.
|
We assume that the default/initial value is an empty vector for these.
|
||||||
`initial_value` need not be defined for these.
|
`initial_value` need not be defined for these.
|
||||||
</%doc>
|
</%doc>
|
||||||
|
|
||||||
|
// The setup here is roughly:
|
||||||
|
//
|
||||||
|
// * UnderlyingList is the list that is stored in the computed value. This may
|
||||||
|
// be a shared ArcSlice if the property is inherited.
|
||||||
|
// * UnderlyingOwnedList is the list that is used for animation.
|
||||||
|
// * Specified values always use OwnedSlice, since it's more compact.
|
||||||
|
// * computed_value::List is just a convenient alias that you can use for the
|
||||||
|
// computed value list, since this is in the computed_value module.
|
||||||
|
//
|
||||||
<%def name="vector_longhand(name, animation_value_type=None,
|
<%def name="vector_longhand(name, animation_value_type=None,
|
||||||
vector_animation_type=None, allow_empty=False,
|
vector_animation_type=None, allow_empty=False,
|
||||||
separator='Comma',
|
separator='Comma',
|
||||||
|
@ -111,6 +121,10 @@
|
||||||
|
|
||||||
/// The definition of the computed value for ${name}.
|
/// The definition of the computed value for ${name}.
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use crate::values::animated::ToAnimatedValue;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use crate::values::resolved::ToResolvedValue;
|
||||||
pub use super::single_value::computed_value as single_value;
|
pub use super::single_value::computed_value as single_value;
|
||||||
pub use self::single_value::T as SingleComputedValue;
|
pub use self::single_value::T as SingleComputedValue;
|
||||||
% if not allow_empty or allow_empty == "NotInitial":
|
% if not allow_empty or allow_empty == "NotInitial":
|
||||||
|
@ -118,7 +132,32 @@
|
||||||
% endif
|
% endif
|
||||||
use crate::values::computed::ComputedVecIter;
|
use crate::values::computed::ComputedVecIter;
|
||||||
|
|
||||||
/// The generic type defining the value for this property.
|
<% is_shared_list = allow_empty and allow_empty != "NotInitial" and data.longhands_by_name[name].style_struct.inherited %>
|
||||||
|
|
||||||
|
// FIXME(emilio): Add an OwnedNonEmptySlice type, and figure out
|
||||||
|
// something for transition-name, which is the only remaining user
|
||||||
|
// of NotInitial.
|
||||||
|
pub type UnderlyingList<T> =
|
||||||
|
% if allow_empty and allow_empty != "NotInitial":
|
||||||
|
% if data.longhands_by_name[name].style_struct.inherited:
|
||||||
|
crate::ArcSlice<T>;
|
||||||
|
% else:
|
||||||
|
crate::OwnedSlice<T>;
|
||||||
|
% endif
|
||||||
|
% else:
|
||||||
|
SmallVec<[T; 1]>;
|
||||||
|
% endif
|
||||||
|
|
||||||
|
pub type UnderlyingOwnedList<T> =
|
||||||
|
% if allow_empty and allow_empty != "NotInitial":
|
||||||
|
crate::OwnedSlice<T>;
|
||||||
|
% else:
|
||||||
|
SmallVec<[T; 1]>;
|
||||||
|
% endif
|
||||||
|
|
||||||
|
|
||||||
|
/// The generic type defining the animated and resolved values for
|
||||||
|
/// this property.
|
||||||
///
|
///
|
||||||
/// Making this type generic allows the compiler to figure out the
|
/// Making this type generic allows the compiler to figure out the
|
||||||
/// animated value for us, instead of having to implement it
|
/// animated value for us, instead of having to implement it
|
||||||
|
@ -135,22 +174,69 @@
|
||||||
ToResolvedValue,
|
ToResolvedValue,
|
||||||
ToCss,
|
ToCss,
|
||||||
)]
|
)]
|
||||||
pub struct List<T>(
|
pub struct OwnedList<T>(
|
||||||
% if not allow_empty:
|
% if not allow_empty:
|
||||||
#[css(iterable)]
|
#[css(iterable)]
|
||||||
% else:
|
% else:
|
||||||
#[css(if_empty = "none", iterable)]
|
#[css(if_empty = "none", iterable)]
|
||||||
% endif
|
% endif
|
||||||
% if allow_empty and allow_empty != "NotInitial":
|
pub UnderlyingOwnedList<T>,
|
||||||
pub crate::OwnedSlice<T>,
|
|
||||||
% else:
|
|
||||||
// FIXME(emilio): Add an OwnedNonEmptySlice type, and figure out
|
|
||||||
// something for transition-name, which is the only remaining
|
|
||||||
// user of NotInitial.
|
|
||||||
pub SmallVec<[T; 1]>,
|
|
||||||
% endif
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/// The computed value for this property.
|
||||||
|
% if not is_shared_list:
|
||||||
|
pub type ComputedList = OwnedList<single_value::T>;
|
||||||
|
pub use self::OwnedList as List;
|
||||||
|
% else:
|
||||||
|
pub use self::ComputedList as List;
|
||||||
|
|
||||||
|
% if separator == "Comma":
|
||||||
|
#[css(comma)]
|
||||||
|
% endif
|
||||||
|
#[derive(
|
||||||
|
Clone,
|
||||||
|
Debug,
|
||||||
|
MallocSizeOf,
|
||||||
|
PartialEq,
|
||||||
|
ToCss,
|
||||||
|
)]
|
||||||
|
pub struct ComputedList(
|
||||||
|
% if not allow_empty:
|
||||||
|
#[css(iterable)]
|
||||||
|
% else:
|
||||||
|
#[css(if_empty = "none", iterable)]
|
||||||
|
% endif
|
||||||
|
% if is_shared_list:
|
||||||
|
#[ignore_malloc_size_of = "Arc"]
|
||||||
|
% endif
|
||||||
|
pub UnderlyingList<single_value::T>,
|
||||||
|
);
|
||||||
|
|
||||||
|
type ResolvedList = OwnedList<<single_value::T as ToResolvedValue>::ResolvedValue>;
|
||||||
|
impl ToResolvedValue for ComputedList {
|
||||||
|
type ResolvedValue = ResolvedList;
|
||||||
|
|
||||||
|
fn to_resolved_value(self, context: &crate::values::resolved::Context) -> Self::ResolvedValue {
|
||||||
|
OwnedList(
|
||||||
|
self.0
|
||||||
|
.iter()
|
||||||
|
.cloned()
|
||||||
|
.map(|v| v.to_resolved_value(context))
|
||||||
|
.collect()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
|
||||||
|
% if not is_shared_list:
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
% endif
|
||||||
|
let iter =
|
||||||
|
resolved.0.into_iter().map(ToResolvedValue::from_resolved_value);
|
||||||
|
ComputedList(UnderlyingList::from_iter(iter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
|
||||||
|
|
||||||
% if vector_animation_type:
|
% if vector_animation_type:
|
||||||
% if not animation_value_type:
|
% if not animation_value_type:
|
||||||
|
@ -158,13 +244,31 @@
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
use crate::properties::animated_properties::ListAnimation;
|
use crate::properties::animated_properties::ListAnimation;
|
||||||
use crate::values::animated::{Animate, ToAnimatedValue, ToAnimatedZero, Procedure};
|
use crate::values::animated::{Animate, ToAnimatedZero, Procedure};
|
||||||
use crate::values::distance::{SquaredDistance, ComputeSquaredDistance};
|
use crate::values::distance::{SquaredDistance, ComputeSquaredDistance};
|
||||||
|
|
||||||
// FIXME(emilio): For some reason rust thinks that this alias is
|
// FIXME(emilio): For some reason rust thinks that this alias is
|
||||||
// unused, even though it's clearly used below?
|
// unused, even though it's clearly used below?
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
type AnimatedList = <List<single_value::T> as ToAnimatedValue>::AnimatedValue;
|
type AnimatedList = OwnedList<<single_value::T as ToAnimatedValue>::AnimatedValue>;
|
||||||
|
|
||||||
|
% if is_shared_list:
|
||||||
|
impl ToAnimatedValue for ComputedList {
|
||||||
|
type AnimatedValue = AnimatedList;
|
||||||
|
|
||||||
|
fn to_animated_value(self) -> Self::AnimatedValue {
|
||||||
|
OwnedList(
|
||||||
|
self.0.iter().map(|v| v.clone().to_animated_value()).collect()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn from_animated_value(animated: Self::AnimatedValue) -> Self {
|
||||||
|
let iter =
|
||||||
|
animated.0.into_iter().map(ToAnimatedValue::from_animated_value);
|
||||||
|
ComputedList(UnderlyingList::from_iter(iter))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
% endif
|
||||||
|
|
||||||
impl ToAnimatedZero for AnimatedList {
|
impl ToAnimatedZero for AnimatedList {
|
||||||
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
|
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
|
||||||
|
@ -176,7 +280,7 @@
|
||||||
other: &Self,
|
other: &Self,
|
||||||
procedure: Procedure,
|
procedure: Procedure,
|
||||||
) -> Result<Self, ()> {
|
) -> Result<Self, ()> {
|
||||||
Ok(List(
|
Ok(OwnedList(
|
||||||
self.0.animate_${vector_animation_type}(&other.0, procedure)?
|
self.0.animate_${vector_animation_type}(&other.0, procedure)?
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
@ -192,7 +296,7 @@
|
||||||
% endif
|
% endif
|
||||||
|
|
||||||
/// The computed value, effectively a list of single values.
|
/// The computed value, effectively a list of single values.
|
||||||
pub type T = List<single_value::T>;
|
pub use self::ComputedList as T;
|
||||||
|
|
||||||
pub type Iter<'a, 'cx, 'cx_a> = ComputedVecIter<'a, 'cx, 'cx_a, super::single_value::SpecifiedValue>;
|
pub type Iter<'a, 'cx, 'cx_a> = ComputedVecIter<'a, 'cx, 'cx_a, super::single_value::SpecifiedValue>;
|
||||||
}
|
}
|
||||||
|
@ -255,7 +359,12 @@
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||||
computed_value::List(self.0.iter().map(|i| i.to_computed_value(context)).collect())
|
% if not is_shared_list:
|
||||||
|
use std::iter::FromIterator;
|
||||||
|
% endif
|
||||||
|
computed_value::List(computed_value::UnderlyingList::from_iter(
|
||||||
|
self.0.iter().map(|i| i.to_computed_value(context))
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -196,7 +196,6 @@ ${helpers.predefined_type(
|
||||||
"MozContextProperties",
|
"MozContextProperties",
|
||||||
initial_value=None,
|
initial_value=None,
|
||||||
vector=True,
|
vector=True,
|
||||||
need_index=True,
|
|
||||||
animation_value_type="none",
|
animation_value_type="none",
|
||||||
products="gecko",
|
products="gecko",
|
||||||
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)",
|
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)",
|
||||||
|
|
|
@ -93,7 +93,7 @@ impl<T: Sized> OwnedSlice<T> {
|
||||||
|
|
||||||
/// Iterate over all the elements in the slice taking ownership of them.
|
/// Iterate over all the elements in the slice taking ownership of them.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn into_iter(self) -> impl Iterator<Item = T> {
|
pub fn into_iter(self) -> impl Iterator<Item = T> + ExactSizeIterator {
|
||||||
self.into_vec().into_iter()
|
self.into_vec().into_iter()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue