mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 21:01:08 +00:00
Bug 1706346 part 1 - [css-lists] Style system changes to support 'reversed(<counter-name>)'. r=emilio
Differential Revision: https://phabricator.services.mozilla.com/D129955
This commit is contained in:
parent
e432845f02
commit
2e0a36d04d
@ -101,7 +101,7 @@ void HTMLSharedListElement::MapOLAttributesIntoRule(
|
||||
}
|
||||
}
|
||||
if (haveStart || haveReversed) {
|
||||
aDecls.SetCounterResetListItem(start);
|
||||
aDecls.SetCounterResetListItem(start, haveReversed);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -101,9 +101,10 @@ class MappedDeclarations final {
|
||||
Servo_DeclarationBlock_SetMathDepthValue(mDecl, aValue, aIsRelative);
|
||||
}
|
||||
|
||||
// Set "counter-reset: list-item <integer>".
|
||||
void SetCounterResetListItem(int32_t aValue) {
|
||||
Servo_DeclarationBlock_SetCounterResetListItem(mDecl, aValue);
|
||||
// Set "counter-reset: list-item <integer>". If aIsReversed is true then
|
||||
// "list-item" instead becomes "reversed(list-item)".
|
||||
void SetCounterResetListItem(int32_t aValue, bool aIsReversed) {
|
||||
Servo_DeclarationBlock_SetCounterResetListItem(mDecl, aValue, aIsReversed);
|
||||
}
|
||||
|
||||
// Set "counter-set: list-item <integer>".
|
||||
|
@ -557,7 +557,8 @@ cbindgen-types = [
|
||||
{ gecko = "StyleVariantAlternatesList", servo = "crate::values::specified::font::VariantAlternatesList" },
|
||||
{ gecko = "StyleSVGPaintOrder", servo = "crate::values::specified::svg::SVGPaintOrder" },
|
||||
{ gecko = "StyleClipRectOrAuto", servo = "crate::values::computed::ClipRectOrAuto" },
|
||||
{ gecko = "StyleCounterSetOrReset", servo = "crate::values::computed::CounterSetOrReset" },
|
||||
{ gecko = "StyleCounterReset", servo = "crate::values::computed::CounterReset" },
|
||||
{ gecko = "StyleCounterSet", servo = "crate::values::computed::CounterSet" },
|
||||
{ gecko = "StyleCounterIncrement", servo = "crate::values::computed::CounterIncrement" },
|
||||
{ gecko = "StyleContent", servo = "crate::values::computed::counters::Content" },
|
||||
{ gecko = "StyleSymbolsType", servo = "crate::values::generics::SymbolsType" },
|
||||
|
@ -1704,8 +1704,8 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleContent {
|
||||
|
||||
mozilla::StyleContent mContent;
|
||||
mozilla::StyleCounterIncrement mCounterIncrement;
|
||||
mozilla::StyleCounterSetOrReset mCounterReset;
|
||||
mozilla::StyleCounterSetOrReset mCounterSet;
|
||||
mozilla::StyleCounterReset mCounterReset;
|
||||
mozilla::StyleCounterSet mCounterSet;
|
||||
};
|
||||
|
||||
struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsStyleUIReset {
|
||||
|
@ -29,7 +29,7 @@ ${helpers.predefined_type(
|
||||
|
||||
${helpers.predefined_type(
|
||||
"counter-reset",
|
||||
"CounterSetOrReset",
|
||||
"CounterReset",
|
||||
engines="gecko servo-2013",
|
||||
initial_value="Default::default()",
|
||||
animation_value_type="discrete",
|
||||
@ -39,7 +39,7 @@ ${helpers.predefined_type(
|
||||
|
||||
${helpers.predefined_type(
|
||||
"counter-set",
|
||||
"CounterSetOrReset",
|
||||
"CounterSet",
|
||||
engines="gecko",
|
||||
initial_value="Default::default()",
|
||||
animation_value_type="discrete",
|
||||
|
@ -7,13 +7,17 @@
|
||||
use crate::values::computed::image::Image;
|
||||
use crate::values::generics::counters as generics;
|
||||
use crate::values::generics::counters::CounterIncrement as GenericCounterIncrement;
|
||||
use crate::values::generics::counters::CounterSetOrReset as GenericCounterSetOrReset;
|
||||
use crate::values::generics::counters::CounterReset as GenericCounterReset;
|
||||
use crate::values::generics::counters::CounterSet as GenericCounterSet;
|
||||
|
||||
/// A computed value for the `counter-increment` property.
|
||||
pub type CounterIncrement = GenericCounterIncrement<i32>;
|
||||
|
||||
/// A computed value for the `counter-set` and `counter-reset` properties.
|
||||
pub type CounterSetOrReset = GenericCounterSetOrReset<i32>;
|
||||
/// A computed value for the `counter-reset` property.
|
||||
pub type CounterReset = GenericCounterReset<i32>;
|
||||
|
||||
/// A computed value for the `counter-set` property.
|
||||
pub type CounterSet = GenericCounterSet<i32>;
|
||||
|
||||
/// A computed value for the `content` property.
|
||||
pub type Content = generics::GenericContent<Image>;
|
||||
|
@ -50,7 +50,7 @@ pub use self::box_::{ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStrictness, Scro
|
||||
pub use self::box_::{TouchAction, VerticalAlign, WillChange};
|
||||
pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, ColorScheme};
|
||||
pub use self::column::ColumnCount;
|
||||
pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset};
|
||||
pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset, CounterSet};
|
||||
pub use self::easing::TimingFunction;
|
||||
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
||||
pub use self::flex::FlexBasis;
|
||||
|
@ -12,6 +12,8 @@ use crate::values::generics::CounterStyle;
|
||||
use crate::values::specified::Attr;
|
||||
use crate::values::CustomIdent;
|
||||
use std::ops::Deref;
|
||||
use std::fmt::{self, Write};
|
||||
use style_traits::{CssWriter, ToCss};
|
||||
|
||||
/// A name / value pair for counters.
|
||||
#[derive(
|
||||
@ -21,7 +23,6 @@ use std::ops::Deref;
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
@ -31,9 +32,35 @@ pub struct GenericCounterPair<Integer> {
|
||||
pub name: CustomIdent,
|
||||
/// The value of the counter / increment / etc.
|
||||
pub value: Integer,
|
||||
/// If true, then this represents `reversed(name)`.
|
||||
/// NOTE: It can only be true on `counter-reset` values.
|
||||
pub is_reversed: bool,
|
||||
}
|
||||
pub use self::GenericCounterPair as CounterPair;
|
||||
|
||||
impl<Integer> ToCss for CounterPair<Integer>
|
||||
where
|
||||
Integer: ToCss + PartialEq<i32>,
|
||||
{
|
||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||
where
|
||||
W: Write,
|
||||
{
|
||||
if self.is_reversed {
|
||||
dest.write_str("reversed(")?;
|
||||
}
|
||||
self.name.to_css(dest)?;
|
||||
if self.is_reversed {
|
||||
dest.write_str(")")?;
|
||||
if self.value == i32::min_value() {
|
||||
return Ok(());
|
||||
}
|
||||
}
|
||||
dest.write_str(" ")?;
|
||||
self.value.to_css(dest)
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic value for the `counter-increment` property.
|
||||
#[derive(
|
||||
Clone,
|
||||
@ -48,7 +75,7 @@ pub use self::GenericCounterPair as CounterPair;
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct GenericCounterIncrement<I>(pub GenericCounters<I>);
|
||||
pub struct GenericCounterIncrement<I>(#[css(field_bound)] pub GenericCounters<I>);
|
||||
pub use self::GenericCounterIncrement as CounterIncrement;
|
||||
|
||||
impl<I> CounterIncrement<I> {
|
||||
@ -68,7 +95,7 @@ impl<I> Deref for CounterIncrement<I> {
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic value for the `counter-set` and `counter-reset` properties.
|
||||
/// A generic value for the `counter-set` property.
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
@ -82,18 +109,52 @@ impl<I> Deref for CounterIncrement<I> {
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct GenericCounterSetOrReset<I>(pub GenericCounters<I>);
|
||||
pub use self::GenericCounterSetOrReset as CounterSetOrReset;
|
||||
pub struct GenericCounterSet<I>(#[css(field_bound)] pub GenericCounters<I>);
|
||||
pub use self::GenericCounterSet as CounterSet;
|
||||
|
||||
impl<I> CounterSetOrReset<I> {
|
||||
/// Returns a new value for `counter-set` / `counter-reset`.
|
||||
impl<I> CounterSet<I> {
|
||||
/// Returns a new value for `counter-set`.
|
||||
#[inline]
|
||||
pub fn new(counters: Vec<CounterPair<I>>) -> Self {
|
||||
CounterSetOrReset(Counters(counters.into()))
|
||||
CounterSet(Counters(counters.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Deref for CounterSetOrReset<I> {
|
||||
impl<I> Deref for CounterSet<I> {
|
||||
type Target = [CounterPair<I>];
|
||||
|
||||
#[inline]
|
||||
fn deref(&self) -> &Self::Target {
|
||||
&(self.0).0
|
||||
}
|
||||
}
|
||||
|
||||
/// A generic value for the `counter-reset` property.
|
||||
#[derive(
|
||||
Clone,
|
||||
Debug,
|
||||
Default,
|
||||
MallocSizeOf,
|
||||
PartialEq,
|
||||
SpecifiedValueInfo,
|
||||
ToComputedValue,
|
||||
ToCss,
|
||||
ToResolvedValue,
|
||||
ToShmem,
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct GenericCounterReset<I>(#[css(field_bound)] pub GenericCounters<I>);
|
||||
pub use self::GenericCounterReset as CounterReset;
|
||||
|
||||
impl<I> CounterReset<I> {
|
||||
/// Returns a new value for `counter-reset`.
|
||||
#[inline]
|
||||
pub fn new(counters: Vec<CounterPair<I>>) -> Self {
|
||||
CounterReset(Counters(counters.into()))
|
||||
}
|
||||
}
|
||||
|
||||
impl<I> Deref for CounterReset<I> {
|
||||
type Target = [CounterPair<I>];
|
||||
|
||||
#[inline]
|
||||
@ -119,7 +180,9 @@ impl<I> Deref for CounterSetOrReset<I> {
|
||||
)]
|
||||
#[repr(transparent)]
|
||||
pub struct GenericCounters<I>(
|
||||
#[css(iterable, if_empty = "none")] crate::OwnedSlice<GenericCounterPair<I>>,
|
||||
#[css(field_bound)]
|
||||
#[css(iterable, if_empty = "none")]
|
||||
crate::OwnedSlice<GenericCounterPair<I>>,
|
||||
);
|
||||
pub use self::GenericCounters as Counters;
|
||||
|
||||
|
@ -21,6 +21,18 @@ use cssparser::{Parser, Token};
|
||||
use selectors::parser::SelectorParseErrorKind;
|
||||
use style_traits::{KeywordsCollectFn, ParseError, SpecifiedValueInfo, StyleParseErrorKind};
|
||||
|
||||
#[derive(PartialEq)]
|
||||
enum CounterType { Increment, Set, Reset, }
|
||||
|
||||
impl CounterType {
|
||||
fn default_value(&self) -> i32 {
|
||||
match *self {
|
||||
Self::Increment => 1,
|
||||
Self::Reset | Self::Set => 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// A specified value for the `counter-increment` property.
|
||||
pub type CounterIncrement = generics::GenericCounterIncrement<Integer>;
|
||||
|
||||
@ -29,26 +41,38 @@ impl Parse for CounterIncrement {
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
Ok(Self::new(parse_counters(context, input, 1)?))
|
||||
Ok(Self::new(parse_counters(context, input, CounterType::Increment)?))
|
||||
}
|
||||
}
|
||||
|
||||
/// A specified value for the `counter-set` and `counter-reset` properties.
|
||||
pub type CounterSetOrReset = generics::GenericCounterSetOrReset<Integer>;
|
||||
/// A specified value for the `counter-set` property.
|
||||
pub type CounterSet = generics::GenericCounterSet<Integer>;
|
||||
|
||||
impl Parse for CounterSetOrReset {
|
||||
impl Parse for CounterSet {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
Ok(Self::new(parse_counters(context, input, 0)?))
|
||||
Ok(Self::new(parse_counters(context, input, CounterType::Set)?))
|
||||
}
|
||||
}
|
||||
|
||||
/// A specified value for the `counter-reset` property.
|
||||
pub type CounterReset = generics::GenericCounterReset<Integer>;
|
||||
|
||||
impl Parse for CounterReset {
|
||||
fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Result<Self, ParseError<'i>> {
|
||||
Ok(Self::new(parse_counters(context, input, CounterType::Reset)?))
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_counters<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
default_value: i32,
|
||||
counter_type: CounterType,
|
||||
) -> Result<Vec<CounterPair<Integer>>, ParseError<'i>> {
|
||||
if input
|
||||
.try_parse(|input| input.expect_ident_matching("none"))
|
||||
@ -60,8 +84,14 @@ fn parse_counters<'i, 't>(
|
||||
let mut counters = Vec::new();
|
||||
loop {
|
||||
let location = input.current_source_location();
|
||||
let name = match input.next() {
|
||||
Ok(&Token::Ident(ref ident)) => CustomIdent::from_ident(location, ident, &["none"])?,
|
||||
let (name, is_reversed) = match input.next() {
|
||||
Ok(&Token::Ident(ref ident)) => (CustomIdent::from_ident(location, ident, &["none"])?, false),
|
||||
Ok(&Token::Function(ref name)) if counter_type == CounterType::Reset && name.eq_ignore_ascii_case("reversed") => {
|
||||
input.parse_nested_block(|input| {
|
||||
let location = input.current_source_location();
|
||||
Ok((CustomIdent::from_ident(location, input.expect_ident()?, &["none"])?, true))
|
||||
})?
|
||||
}
|
||||
Ok(t) => {
|
||||
let t = t.clone();
|
||||
return Err(location.new_unexpected_token_error(t));
|
||||
@ -69,10 +99,19 @@ fn parse_counters<'i, 't>(
|
||||
Err(_) => break,
|
||||
};
|
||||
|
||||
let value = input
|
||||
.try_parse(|input| Integer::parse(context, input))
|
||||
.unwrap_or(Integer::new(default_value));
|
||||
counters.push(CounterPair { name, value });
|
||||
let value = match input.try_parse(|input| Integer::parse(context, input)) {
|
||||
Ok(start) =>
|
||||
if start.value == i32::min_value() {
|
||||
// The spec says that values must be clamped to the valid range,
|
||||
// and we reserve i32::min_value() as an internal magic value.
|
||||
// https://drafts.csswg.org/css-lists/#auto-numbering
|
||||
Integer::new(i32::min_value() + 1)
|
||||
} else {
|
||||
start
|
||||
},
|
||||
_ => Integer::new(if is_reversed { i32::min_value() } else { counter_type.default_value() }),
|
||||
};
|
||||
counters.push(CounterPair { name, value, is_reversed });
|
||||
}
|
||||
|
||||
if !counters.is_empty() {
|
||||
|
@ -44,7 +44,7 @@ pub use self::box_::{ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStrictness, Scro
|
||||
pub use self::box_::{TouchAction, TransitionProperty, VerticalAlign, WillChange};
|
||||
pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, ColorScheme};
|
||||
pub use self::column::ColumnCount;
|
||||
pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset};
|
||||
pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset, CounterSet};
|
||||
pub use self::easing::TimingFunction;
|
||||
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
||||
pub use self::flex::FlexBasis;
|
||||
@ -577,6 +577,12 @@ impl One for Integer {
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<i32> for Integer {
|
||||
fn eq(&self, value: &i32) -> bool {
|
||||
self.value() == *value
|
||||
}
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
/// Trivially constructs a new `Integer` value.
|
||||
pub fn new(val: CSSInteger) -> Self {
|
||||
|
@ -202,7 +202,8 @@ include = [
|
||||
"PaintOrder",
|
||||
"SVGPaintOrder",
|
||||
"ClipRectOrAuto",
|
||||
"CounterSetOrReset",
|
||||
"CounterReset",
|
||||
"CounterSet",
|
||||
"CounterIncrement",
|
||||
"WritingMode",
|
||||
"Content",
|
||||
|
@ -5089,13 +5089,15 @@ pub extern "C" fn Servo_DeclarationBlock_SetMathDepthValue(
|
||||
pub extern "C" fn Servo_DeclarationBlock_SetCounterResetListItem(
|
||||
declarations: &RawServoDeclarationBlock,
|
||||
counter_value: i32,
|
||||
is_reversed: bool,
|
||||
) {
|
||||
use style::properties::PropertyDeclaration;
|
||||
use style::values::generics::counters::{CounterPair, CounterSetOrReset};
|
||||
use style::values::generics::counters::{CounterPair, CounterReset};
|
||||
|
||||
let prop = PropertyDeclaration::CounterReset(CounterSetOrReset::new(vec![CounterPair {
|
||||
let prop = PropertyDeclaration::CounterReset(CounterReset::new(vec![CounterPair {
|
||||
name: CustomIdent(atom!("list-item")),
|
||||
value: style::values::specified::Integer::new(counter_value),
|
||||
is_reversed,
|
||||
}]));
|
||||
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
||||
decls.push(prop, Importance::Normal);
|
||||
@ -5108,11 +5110,12 @@ pub extern "C" fn Servo_DeclarationBlock_SetCounterSetListItem(
|
||||
counter_value: i32,
|
||||
) {
|
||||
use style::properties::PropertyDeclaration;
|
||||
use style::values::generics::counters::{CounterPair, CounterSetOrReset};
|
||||
use style::values::generics::counters::{CounterPair, CounterSet};
|
||||
|
||||
let prop = PropertyDeclaration::CounterSet(CounterSetOrReset::new(vec![CounterPair {
|
||||
let prop = PropertyDeclaration::CounterSet(CounterSet::new(vec![CounterPair {
|
||||
name: CustomIdent(atom!("list-item")),
|
||||
value: style::values::specified::Integer::new(counter_value),
|
||||
is_reversed: false,
|
||||
}]));
|
||||
write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| {
|
||||
decls.push(prop, Importance::Normal);
|
||||
|
Loading…
Reference in New Issue
Block a user