mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
style: Make scroll-timeline-{name|axis} be a coordinating list property group
Named scroll progress timelines are declared in the coordinated value list constructed from the longhands of the scroll-timeline shorthand property, which form a coordinating list property group with scroll-timeline-name as the coordinating list base property. In the meantime, we also update its shorthand to match the current spec. Differential Revision: https://phabricator.services.mozilla.com/D166596
This commit is contained in:
parent
47a54ced2b
commit
b024f5b2e7
4 changed files with 52 additions and 50 deletions
|
@ -5,10 +5,12 @@
|
||||||
//! Rust helpers for Gecko's `nsStyleAutoArray`.
|
//! Rust helpers for Gecko's `nsStyleAutoArray`.
|
||||||
|
|
||||||
use crate::gecko_bindings::bindings::Gecko_EnsureStyleAnimationArrayLength;
|
use crate::gecko_bindings::bindings::Gecko_EnsureStyleAnimationArrayLength;
|
||||||
|
use crate::gecko_bindings::bindings::Gecko_EnsureStyleScrollTimelineArrayLength;
|
||||||
use crate::gecko_bindings::bindings::Gecko_EnsureStyleTransitionArrayLength;
|
use crate::gecko_bindings::bindings::Gecko_EnsureStyleTransitionArrayLength;
|
||||||
use crate::gecko_bindings::bindings::Gecko_EnsureStyleViewTimelineArrayLength;
|
use crate::gecko_bindings::bindings::Gecko_EnsureStyleViewTimelineArrayLength;
|
||||||
use crate::gecko_bindings::structs::nsStyleAutoArray;
|
use crate::gecko_bindings::structs::nsStyleAutoArray;
|
||||||
use crate::gecko_bindings::structs::{StyleAnimation, StyleTransition, StyleViewTimeline};
|
use crate::gecko_bindings::structs::{StyleAnimation, StyleTransition};
|
||||||
|
use crate::gecko_bindings::structs::{StyleScrollTimeline, StyleViewTimeline};
|
||||||
use std::iter::{once, Chain, IntoIterator, Once};
|
use std::iter::{once, Chain, IntoIterator, Once};
|
||||||
use std::ops::{Index, IndexMut};
|
use std::ops::{Index, IndexMut};
|
||||||
use std::slice::{Iter, IterMut};
|
use std::slice::{Iter, IterMut};
|
||||||
|
@ -88,6 +90,18 @@ impl nsStyleAutoArray<StyleViewTimeline> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl nsStyleAutoArray<StyleScrollTimeline> {
|
||||||
|
/// Ensures that the array has length at least the given length.
|
||||||
|
pub fn ensure_len(&mut self, len: usize) {
|
||||||
|
unsafe {
|
||||||
|
Gecko_EnsureStyleScrollTimelineArrayLength(
|
||||||
|
self as *mut nsStyleAutoArray<StyleScrollTimeline> as *mut _,
|
||||||
|
len,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T> IntoIterator for &'a mut nsStyleAutoArray<T> {
|
impl<'a, T> IntoIterator for &'a mut nsStyleAutoArray<T> {
|
||||||
type Item = &'a mut T;
|
type Item = &'a mut T;
|
||||||
type IntoIter = Chain<Once<&'a mut T>, IterMut<'a, T>>;
|
type IntoIter = Chain<Once<&'a mut T>, IterMut<'a, T>>;
|
||||||
|
|
|
@ -1721,6 +1721,7 @@ mask-mode mask-repeat mask-clip mask-origin mask-composite mask-position-x mask-
|
||||||
animation-timing-function animation-composition animation-timeline
|
animation-timing-function animation-composition animation-timeline
|
||||||
transition-duration transition-delay
|
transition-duration transition-delay
|
||||||
transition-timing-function transition-property
|
transition-timing-function transition-property
|
||||||
|
scroll-timeline-name scroll-timeline-axis
|
||||||
view-timeline-name view-timeline-axis view-timeline-inset""" %>
|
view-timeline-name view-timeline-axis view-timeline-inset""" %>
|
||||||
|
|
||||||
<%self:impl_trait style_struct_name="UI" skip_longhands="${skip_ui_longhands}">
|
<%self:impl_trait style_struct_name="UI" skip_longhands="${skip_ui_longhands}">
|
||||||
|
@ -1905,6 +1906,9 @@ mask-mode mask-repeat mask-clip mask-origin mask-composite mask-position-x mask-
|
||||||
${impl_coordinated_property('animation', 'timeline', 'Timeline')}
|
${impl_coordinated_property('animation', 'timeline', 'Timeline')}
|
||||||
${impl_coordinated_property('animation', 'timing_function', 'TimingFunction')}
|
${impl_coordinated_property('animation', 'timing_function', 'TimingFunction')}
|
||||||
|
|
||||||
|
${impl_coordinated_property('scroll_timeline', 'name', 'Name')}
|
||||||
|
${impl_coordinated_property('scroll_timeline', 'axis', 'Axis')}
|
||||||
|
|
||||||
${impl_coordinated_property('view_timeline', 'name', 'Name')}
|
${impl_coordinated_property('view_timeline', 'name', 'Name')}
|
||||||
${impl_coordinated_property('view_timeline', 'axis', 'Axis')}
|
${impl_coordinated_property('view_timeline', 'axis', 'Axis')}
|
||||||
${impl_coordinated_property('view_timeline', 'inset', 'Inset')}
|
${impl_coordinated_property('view_timeline', 'inset', 'Inset')}
|
||||||
|
|
|
@ -335,6 +335,8 @@ ${helpers.predefined_type(
|
||||||
"scroll-timeline-name",
|
"scroll-timeline-name",
|
||||||
"ScrollTimelineName",
|
"ScrollTimelineName",
|
||||||
"computed::ScrollTimelineName::none()",
|
"computed::ScrollTimelineName::none()",
|
||||||
|
vector=True,
|
||||||
|
need_index=True,
|
||||||
engines="gecko",
|
engines="gecko",
|
||||||
animation_value_type="none",
|
animation_value_type="none",
|
||||||
gecko_pref="layout.css.scroll-driven-animations.enabled",
|
gecko_pref="layout.css.scroll-driven-animations.enabled",
|
||||||
|
@ -346,6 +348,8 @@ ${helpers.predefined_type(
|
||||||
"scroll-timeline-axis",
|
"scroll-timeline-axis",
|
||||||
"ScrollAxis",
|
"ScrollAxis",
|
||||||
"computed::ScrollAxis::default()",
|
"computed::ScrollAxis::default()",
|
||||||
|
vector=True,
|
||||||
|
need_index=True,
|
||||||
engines="gecko",
|
engines="gecko",
|
||||||
animation_value_type="none",
|
animation_value_type="none",
|
||||||
gecko_pref="layout.css.scroll-driven-animations.enabled",
|
gecko_pref="layout.css.scroll-driven-animations.enabled",
|
||||||
|
|
|
@ -327,63 +327,48 @@ macro_rules! try_parse_one {
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, '_>,
|
input: &mut Parser<'i, '_>,
|
||||||
) -> Result<Longhands, ParseError<'i>> {
|
) -> Result<Longhands, ParseError<'i>> {
|
||||||
use crate::parser::Parse;
|
use crate::properties::longhands::{scroll_timeline_axis, scroll_timeline_name};
|
||||||
use crate::values::specified::box_::{ScrollAxis, ScrollTimelineName};
|
|
||||||
|
|
||||||
let mut name = None;
|
let mut names = Vec::with_capacity(1);
|
||||||
let mut axis = None;
|
let mut axes = Vec::with_capacity(1);
|
||||||
// FIXME: Bug 1809005: The order of |name| and |axis| should be fixed.
|
input.parse_comma_separated(|input| {
|
||||||
loop {
|
let name = scroll_timeline_name::single_value::parse(context, input)?;
|
||||||
// Note: When parsing positionally-ambiguous keywords in a property value, a
|
let axis = input.try_parse(|i| scroll_timeline_axis::single_value::parse(context, i));
|
||||||
// <custom-ident> production can only claim the keyword if no other unfulfilled
|
|
||||||
// production can claim it. So we try to parse `scroll-timeline-axis` first.
|
|
||||||
//
|
|
||||||
// https://drafts.csswg.org/css-values-4/#custom-idents
|
|
||||||
|
|
||||||
if axis.is_none() {
|
names.push(name);
|
||||||
axis = input.try_parse(ScrollAxis::parse).ok();
|
axes.push(axis.unwrap_or_default());
|
||||||
}
|
|
||||||
|
|
||||||
if name.is_none() {
|
Ok(())
|
||||||
if let Ok(value) = input.try_parse(|i| ScrollTimelineName::parse(context, i)) {
|
})?;
|
||||||
name = Some(value);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Must occur one or more.
|
|
||||||
if name.is_none() && axis.is_none() {
|
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(expanded! {
|
Ok(expanded! {
|
||||||
scroll_timeline_name: name.unwrap_or(ScrollTimelineName::none()),
|
scroll_timeline_name: scroll_timeline_name::SpecifiedValue(names.into()),
|
||||||
scroll_timeline_axis: axis.unwrap_or_default(),
|
scroll_timeline_axis: scroll_timeline_axis::SpecifiedValue(axes.into()),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||||
use crate::values::specified::box_::ScrollAxis;
|
// If any value list length is differs then we don't do a shorthand serialization
|
||||||
|
// either.
|
||||||
let is_default_axis = self.scroll_timeline_axis == &ScrollAxis::default();
|
let len = self.scroll_timeline_name.0.len();
|
||||||
let is_default_name = self.scroll_timeline_name.0.is_none();
|
if len != self.scroll_timeline_axis.0.len() {
|
||||||
|
return Ok(());
|
||||||
// Note: if both are default values, we serialize the default axis (because it is the
|
|
||||||
// first value per spec).
|
|
||||||
if !is_default_axis || (is_default_axis && is_default_name) {
|
|
||||||
self.scroll_timeline_axis.to_css(dest)?;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !is_default_name {
|
for i in 0..len {
|
||||||
if !is_default_axis {
|
if i != 0 {
|
||||||
dest.write_char(' ')?;
|
dest.write_str(", ")?;
|
||||||
}
|
}
|
||||||
self.scroll_timeline_name.to_css(dest)?;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
self.scroll_timeline_name.0[i].to_css(dest)?;
|
||||||
|
|
||||||
|
if self.scroll_timeline_axis.0[i] != Default::default() {
|
||||||
|
dest.write_char(' ')?;
|
||||||
|
self.scroll_timeline_axis.0[i].to_css(dest)?;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -423,14 +408,9 @@ macro_rules! try_parse_one {
|
||||||
|
|
||||||
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
impl<'a> ToCss for LonghandsToSerialize<'a> {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write {
|
||||||
let len = self.view_timeline_name.0.len();
|
|
||||||
// There should be at least one declared value
|
|
||||||
if len == 0 {
|
|
||||||
return Ok(());
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any value list length is differs then we don't do a shorthand serialization
|
// If any value list length is differs then we don't do a shorthand serialization
|
||||||
// either.
|
// either.
|
||||||
|
let len = self.view_timeline_name.0.len();
|
||||||
if len != self.view_timeline_axis.0.len() {
|
if len != self.view_timeline_axis.0.len() {
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue