diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index f00e5aafced2..9f8aa772d319 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -976,8 +976,7 @@ fn static_assert() { skip_longhands="${skip_position_longhands} order align-content justify-content align-self justify-self align-items justify-items - grid-auto-flow grid-template-rows - grid-template-columns"> + grid-auto-flow"> % for side in SIDES: <% impl_split_style_coord(side.ident, "mOffset", side.index) %> % endfor @@ -1025,216 +1024,6 @@ fn static_assert() { ${impl_simple_copy('order', 'mOrder')} - % for kind in ["rows", "columns"]: - pub fn set_grid_template_${kind}(&mut self, v: longhands::grid_template_${kind}::computed_value::T) { - <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %> - use crate::gecko_bindings::structs::nsTArray; - use std::usize; - use crate::values::CustomIdent; - use crate::values::generics::grid::TrackListType::Auto; - use crate::values::generics::grid::{GridTemplateComponent, RepeatCount, TrackListValue, MAX_GRID_LINE}; - - #[inline] - fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray>) { - unsafe { - bindings::Gecko_ResizeAtomArray(gecko_names, servo_names.len() as u32); - } - - for (servo_name, gecko_name) in servo_names.iter().zip(gecko_names.iter_mut()) { - gecko_name.set_move(unsafe { - RefPtr::from_addrefed(servo_name.0.clone().into_addrefed()) - }); - } - } - - let max_lines = MAX_GRID_LINE as usize - 1; // for accounting the final - - let result = match v { - GridTemplateComponent::None => ptr::null_mut(), - GridTemplateComponent::TrackList(track) => { - let mut num_values = track.values.len(); - if let Auto(_) = track.list_type { - num_values += 1; - } - - num_values = cmp::min(num_values, max_lines); - let value = unsafe { - bindings::Gecko_CreateStyleGridTemplate(num_values as u32, - (num_values + 1) as u32).as_mut().unwrap() - }; - - let mut auto_idx = usize::MAX; - let mut auto_track_size = None; - if let Auto(idx) = track.list_type { - auto_idx = idx as usize; - let auto_repeat = track.auto_repeat.as_ref().expect("expected value"); - - if auto_repeat.count == RepeatCount::AutoFill { - value.set_mIsAutoFill(true); - } - - value.mRepeatAutoIndex = idx as i16; - // NOTE: Gecko supports only one set of values in - // i.e., it can only take repeat(auto-fill, [a] 10px [b]), and no more. - set_line_names(&auto_repeat.line_names[0], &mut value.mRepeatAutoLineNameListBefore); - set_line_names(&auto_repeat.line_names[1], &mut value.mRepeatAutoLineNameListAfter); - auto_track_size = Some(auto_repeat.track_sizes.get(0).unwrap().clone()); - } else { - unsafe { - bindings::Gecko_ResizeAtomArray( - &mut value.mRepeatAutoLineNameListBefore, 0); - bindings::Gecko_ResizeAtomArray( - &mut value.mRepeatAutoLineNameListAfter, 0); - } - } - - let mut line_names = track.line_names.into_iter(); - let mut values_iter = track.values.into_iter(); - { - for (i, track_size) in value.mTrackSizingFunctions.iter_mut().enumerate().take(max_lines) { - let name_list = line_names.next().expect("expected line-names"); - set_line_names(&name_list, &mut value.mLineNameLists[i]); - *track_size = if i == auto_idx { - auto_track_size.take().expect("expected for ") - } else { - match values_iter.next().expect("expected value") { - TrackListValue::TrackSize(size) => size, - // FIXME(emilio): This shouldn't be - // representable in the first place. - TrackListValue::TrackRepeat(..) => { - unreachable!("Shouldn't have track-repeats in computed track lists") - } - } - }; - } - } - - let final_names = line_names.next().unwrap(); - set_line_names(&final_names, value.mLineNameLists.last_mut().unwrap()); - - value - }, - GridTemplateComponent::Subgrid(list) => { - let names_length = match list.fill_idx { - Some(_) => list.names.len() - 1, - None => list.names.len(), - }; - let num_values = cmp::min(names_length, max_lines + 1); - let value = unsafe { - bindings::Gecko_CreateStyleGridTemplate(0, num_values as u32).as_mut().unwrap() - }; - value.set_mIsSubgrid(true); - - let mut names = list.names.into_vec(); - if let Some(idx) = list.fill_idx { - value.set_mIsAutoFill(true); - value.mRepeatAutoIndex = idx as i16; - set_line_names(&names.swap_remove(idx as usize), - &mut value.mRepeatAutoLineNameListBefore); - } - - for (servo_names, gecko_names) in names.iter().zip(value.mLineNameLists.iter_mut()) { - set_line_names(servo_names, gecko_names); - } - - value - }, - }; - - unsafe { bindings::Gecko_SetStyleGridTemplate(&mut ${self_grid}, result); } - } - - pub fn copy_grid_template_${kind}_from(&mut self, other: &Self) { - unsafe { - bindings::Gecko_CopyStyleGridTemplateValues(&mut ${self_grid}, - other.gecko.mGridTemplate${kind.title()}.mPtr); - } - } - - pub fn reset_grid_template_${kind}(&mut self, other: &Self) { - self.copy_grid_template_${kind}_from(other) - } - - pub fn clone_grid_template_${kind}(&self) -> longhands::grid_template_${kind}::computed_value::T { - <% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %> - use crate::gecko_bindings::structs::nsTArray; - use crate::values::CustomIdent; - use crate::values::generics::grid::{GridTemplateComponent, LineNameList, RepeatCount}; - use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue, TrackRepeat}; - - let value = match unsafe { ${self_grid}.mPtr.as_ref() } { - None => return GridTemplateComponent::None, - Some(value) => value, - }; - - #[inline] - fn to_boxed_customident_slice(gecko_names: &nsTArray>) -> Box<[CustomIdent]> { - let idents: Vec = gecko_names.iter().map(|gecko_name| { - CustomIdent(unsafe { Atom::from_raw(gecko_name.mRawPtr) }) - }).collect(); - idents.into_boxed_slice() - } - - #[inline] - fn to_line_names_vec( - gecko_line_names: &nsTArray>>, - ) -> Vec> { - gecko_line_names.iter().map(|gecko_names| { - to_boxed_customident_slice(gecko_names) - }).collect() - } - - let repeat_auto_index = value.mRepeatAutoIndex as usize; - if value.mIsSubgrid() { - let mut names_vec = to_line_names_vec(&value.mLineNameLists); - let fill_idx = if value.mIsAutoFill() { - names_vec.insert( - repeat_auto_index, - to_boxed_customident_slice(&value.mRepeatAutoLineNameListBefore)); - Some(repeat_auto_index as u32) - } else { - None - }; - let names = names_vec.into_boxed_slice(); - - GridTemplateComponent::Subgrid(LineNameList{names, fill_idx}) - } else { - let mut auto_repeat = None; - let mut list_type = TrackListType::Normal; - let line_names = to_line_names_vec(&value.mLineNameLists).into_boxed_slice(); - let mut values = Vec::with_capacity(value.mTrackSizingFunctions.len()); - for (i, track_size) in value.mTrackSizingFunctions.iter().enumerate() { - if i == repeat_auto_index { - list_type = TrackListType::Auto(repeat_auto_index as u16); - - let count = if value.mIsAutoFill() { - RepeatCount::AutoFill - } else { - RepeatCount::AutoFit - }; - - let line_names = { - let mut vec: Vec> = Vec::with_capacity(2); - vec.push(to_boxed_customident_slice( - &value.mRepeatAutoLineNameListBefore)); - vec.push(to_boxed_customident_slice( - &value.mRepeatAutoLineNameListAfter)); - vec.into_boxed_slice() - }; - - let track_sizes = vec!(track_size.clone()); - - auto_repeat = Some(TrackRepeat{count, line_names, track_sizes}); - } else { - values.push(TrackListValue::TrackSize(track_size.clone())); - } - } - - GridTemplateComponent::TrackList(TrackList{list_type, values, line_names, auto_repeat}) - } - } - % endfor - ${impl_simple_type_with_conversion("grid_auto_flow")} diff --git a/components/style/properties/shorthands/position.mako.rs b/components/style/properties/shorthands/position.mako.rs index 8e61f0f6ecdd..ef59f6d03460 100644 --- a/components/style/properties/shorthands/position.mako.rs +++ b/components/style/properties/shorthands/position.mako.rs @@ -268,7 +268,7 @@ > use crate::parser::Parse; use servo_arc::Arc; - use crate::values::generics::grid::{TrackSize, TrackList, TrackListType}; + use crate::values::generics::grid::{TrackSize, TrackList}; use crate::values::generics::grid::{TrackListValue, concat_serialize_idents}; use crate::values::specified::{GridTemplateComponent, GenericGridTemplateComponent}; use crate::values::specified::grid::parse_line_names; @@ -300,26 +300,28 @@ } % endfor - let first_line_names = input.try(parse_line_names).unwrap_or(vec![].into_boxed_slice()); + let first_line_names = input.try(parse_line_names).unwrap_or_default(); if let Ok(mut string) = input.try(|i| i.expect_string().map(|s| s.as_ref().to_owned().into())) { let mut strings = vec![]; let mut values = vec![]; let mut line_names = vec![]; - let mut names = first_line_names.into_vec(); + let mut names = first_line_names; loop { - line_names.push(names.into_boxed_slice()); + line_names.push(names); strings.push(string); let size = input.try(|i| TrackSize::parse(context, i)).unwrap_or_default(); values.push(TrackListValue::TrackSize(size)); - names = input.try(parse_line_names).unwrap_or(vec![].into_boxed_slice()).into_vec(); + names = input.try(parse_line_names).unwrap_or_default(); if let Ok(v) = input.try(parse_line_names) { - names.extend(v.into_vec()); + let mut names_vec = names.into_vec(); + names_vec.extend(v.into_iter()); + names = names_vec.into(); } string = match input.try(|i| i.expect_string().map(|s| s.as_ref().to_owned().into())) { Ok(s) => s, _ => { // only the named area determines whether we should bail out - line_names.push(names.into_boxed_slice()); + line_names.push(names.into()); break }, }; @@ -327,22 +329,21 @@ if line_names.len() == values.len() { // should be one longer than track sizes - line_names.push(vec![].into_boxed_slice()); + line_names.push(Default::default()); } let template_areas = TemplateAreas::from_vec(strings) .map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))?; let template_rows = TrackList { - list_type: TrackListType::Normal, - values, - line_names: line_names.into_boxed_slice(), - auto_repeat: None, + values: values.into(), + line_names: line_names.into(), + auto_repeat_index: std::usize::MAX, }; let template_cols = if input.try(|i| i.expect_delim('/')).is_ok() { let value = GridTemplateComponent::parse_without_none(context, input)?; if let GenericGridTemplateComponent::TrackList(ref list) = value { - if list.list_type != TrackListType::Explicit { + if !list.is_explicit() { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } } @@ -407,13 +408,10 @@ let track_list = match *template_rows { GenericGridTemplateComponent::TrackList(ref list) => { - // We should fail if there is a `repeat` function. `grid` and - // `grid-template` shorthands doesn't accept that. Only longhand accepts. - if list.auto_repeat.is_some() || - list.values.iter().any(|v| match *v { - TrackListValue::TrackRepeat(_) => true, - _ => false, - }) { + // We should fail if there is a `repeat` function. + // `grid` and `grid-template` shorthands doesn't accept + // that. Only longhand accepts. + if !list.is_explicit() { return Ok(()); } list @@ -429,11 +427,7 @@ // We should fail if there is a `repeat` function. `grid` and // `grid-template` shorthands doesn't accept that. Only longhand accepts that. GenericGridTemplateComponent::TrackList(ref list) => { - if list.auto_repeat.is_some() || - list.values.iter().any(|v| match *v { - TrackListValue::TrackRepeat(_) => true, - _ => false, - }) { + if !list.is_explicit() { return Ok(()); } }, @@ -498,7 +492,7 @@ > use crate::parser::Parse; use crate::properties::longhands::{grid_auto_columns, grid_auto_rows, grid_auto_flow}; - use crate::values::generics::grid::{GridTemplateComponent, TrackListType}; + use crate::values::generics::grid::GridTemplateComponent; use crate::values::specified::{GenericGridTemplateComponent, TrackSize}; use crate::values::specified::position::{AutoFlow, GridAutoFlow, GridTemplateAreas}; @@ -597,7 +591,7 @@ // It should fail to serialize if template-rows value is not Explicit. if let GenericGridTemplateComponent::TrackList(ref list) = *self.grid_template_rows { - if list.list_type != TrackListType::Explicit { + if !list.is_explicit() { return Ok(()); } } @@ -621,7 +615,7 @@ // It should fail to serialize if template-column value is not Explicit. if let GenericGridTemplateComponent::TrackList(ref list) = *self.grid_template_columns { - if list.list_type != TrackListType::Explicit { + if !list.is_explicit() { return Ok(()); } } diff --git a/components/style/values/animated/grid.rs b/components/style/values/animated/grid.rs index d1f6be1a32b2..7b9417a08c6f 100644 --- a/components/style/values/animated/grid.rs +++ b/components/style/values/animated/grid.rs @@ -101,7 +101,7 @@ impl Animate for generics::TrackRepeat { Ok(generics::TrackRepeat { count, line_names, - track_sizes, + track_sizes: track_sizes.into(), }) } } @@ -117,20 +117,19 @@ impl Animate for TrackList { return Err(()); } - if self.list_type != other.list_type { + if self.is_explicit() != other.is_explicit() { return Err(()); } - // For now, repeat(auto-fill/auto-fit, ...) is not animatable. TrackRepeat will - // return Err(()) if we use keywords. Therefore, we can early return here to avoid - // traversing |values| in . This may be updated in the future. + // For now, repeat(auto-fill/auto-fit, ...) is not animatable. + // TrackRepeat will return Err(()) if we use keywords. Therefore, we can + // early return here to avoid traversing |values| in . + // This may be updated in the future. // https://github.com/w3c/csswg-drafts/issues/3503 - if let generics::TrackListType::Auto(_) = self.list_type { + if self.has_auto_repeat() || other.has_auto_repeat() { return Err(()); } - let list_type = self.list_type; - let auto_repeat = self.auto_repeat.animate(&other.auto_repeat, procedure)?; let values = self .values .iter() @@ -142,10 +141,9 @@ impl Animate for TrackList { let line_names = discrete(&self.line_names, &other.line_names, procedure)?; Ok(TrackList { - list_type, - values, + values: values.into(), line_names, - auto_repeat, + auto_repeat_index: self.auto_repeat_index, }) } } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 1947b83164eb..b017f195bd96 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -467,6 +467,7 @@ trivial_to_computed_value!(i32); trivial_to_computed_value!(u8); trivial_to_computed_value!(u16); trivial_to_computed_value!(u32); +trivial_to_computed_value!(usize); trivial_to_computed_value!(Atom); #[cfg(feature = "servo")] trivial_to_computed_value!(Prefix); diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index 7de109141fe8..a5b1c733b727 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -12,7 +12,7 @@ use crate::values::{CSSFloat, CustomIdent}; use crate::{Atom, Zero}; use cssparser::Parser; use std::fmt::{self, Write}; -use std::{cmp, mem, usize}; +use std::{cmp, usize}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; /// These are the limits that we choose to clamp grid line numbers to. @@ -366,6 +366,7 @@ where #[derive( Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] +#[repr(C, u8)] pub enum RepeatCount { /// A positive integer. This is allowed only for `` and `` Number(Integer), @@ -380,18 +381,15 @@ impl Parse for RepeatCount { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - // Maximum number of repeat is 10000. The greater numbers should be clamped. - const MAX_LINE: i32 = 10000; if let Ok(mut i) = input.try(|i| specified::Integer::parse_positive(context, i)) { - if i.value() > MAX_LINE { - i = specified::Integer::new(MAX_LINE); - } - Ok(RepeatCount::Number(i)) - } else { - try_match_ident_ignore_ascii_case! { input, - "auto-fill" => Ok(RepeatCount::AutoFill), - "auto-fit" => Ok(RepeatCount::AutoFit), + if i.value() > MAX_GRID_LINE { + i = specified::Integer::new(MAX_GRID_LINE); } + return Ok(RepeatCount::Number(i)) + } + try_match_ident_ignore_ascii_case! { input, + "auto-fill" => Ok(RepeatCount::AutoFill), + "auto-fit" => Ok(RepeatCount::AutoFit), } } } @@ -411,7 +409,8 @@ impl Parse for RepeatCount { ToShmem, )] #[css(function = "repeat")] -pub struct TrackRepeat { +#[repr(C)] +pub struct GenericTrackRepeat { /// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`) pub count: RepeatCount, /// `` accompanying `` values. @@ -419,11 +418,13 @@ pub struct TrackRepeat { /// If there's no ``, then it's represented by an empty vector. /// For N `` values, there will be N+1 ``, and so this vector's /// length is always one value more than that of the ``. - pub line_names: Box<[Box<[CustomIdent]>]>, + pub line_names: crate::OwnedSlice>, /// `` values. - pub track_sizes: Vec>, + pub track_sizes: crate::OwnedSlice>, } +pub use self::GenericTrackRepeat as TrackRepeat; + impl ToCss for TrackRepeat { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where @@ -457,46 +458,10 @@ impl ToCss for TrackRepeat { Ok(()) } } -impl TrackRepeat { - /// If the repeat count is numeric, then expand the values and merge accordingly. - pub fn expand(&self) -> Self { - if let RepeatCount::Number(num) = self.count { - let mut line_names = vec![]; - let mut track_sizes = vec![]; - let mut prev_names = vec![]; - - for _ in 0..num.value() { - let mut names_iter = self.line_names.iter(); - for (size, names) in self.track_sizes.iter().zip(&mut names_iter) { - prev_names.extend_from_slice(&names); - let vec = mem::replace(&mut prev_names, vec![]); - line_names.push(vec.into_boxed_slice()); - track_sizes.push(size.clone()); - } - - if let Some(names) = names_iter.next() { - prev_names.extend_from_slice(&names); - } - } - - line_names.push(prev_names.into_boxed_slice()); - TrackRepeat { - count: self.count, - track_sizes: track_sizes, - line_names: line_names.into_boxed_slice(), - } - } else { - // if it's auto-fit/auto-fill, then it's left to the layout. - TrackRepeat { - count: self.count, - track_sizes: self.track_sizes.clone(), - line_names: self.line_names.clone(), - } - } - } -} /// Track list values. Can be or +/// +/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, @@ -509,56 +474,54 @@ impl TrackRepeat { ToResolvedValue, ToShmem, )] -pub enum TrackListValue { +#[repr(C, u8)] +pub enum GenericTrackListValue { /// A value. - TrackSize(#[animation(field_bound)] TrackSize), + TrackSize(#[animation(field_bound)] GenericTrackSize), /// A value. - TrackRepeat(#[animation(field_bound)] TrackRepeat), + TrackRepeat(#[animation(field_bound)] GenericTrackRepeat), } -/// The type of a `` as determined during parsing. -/// -/// -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem)] -pub enum TrackListType { - /// [``](https://drafts.csswg.org/css-grid/#typedef-auto-track-list) - /// - /// If this type exists, then the value at the index in `line_names` field in `TrackList` - /// has the `?` list that comes before ``. If it's a specified value, - /// then the `repeat()` function (that follows the line names list) is also at the given index - /// in `values` field. On the contrary, if it's a computed value, then the `repeat()` function - /// is in the `auto_repeat` field. - Auto(u16), - /// [``](https://drafts.csswg.org/css-grid/#typedef-track-list) - Normal, - /// [``](https://drafts.csswg.org/css-grid/#typedef-explicit-track-list) - /// - /// Note that this is a subset of the normal ``, and so it could be used in place - /// of the latter. - Explicit, +pub use self::GenericTrackListValue as TrackListValue; + +impl TrackListValue { + fn is_repeat(&self) -> bool { + matches!(*self, TrackListValue::TrackRepeat(..)) + } } /// A grid `` type. /// /// -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToResolvedValue, ToShmem)] -pub struct TrackList { - /// The type of this `` (auto, explicit or general). - /// - /// In order to avoid parsing the same value multiple times, this does a single traversal - /// and arrives at the type of value it has parsed (or bails out gracefully with an error). +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)] +#[repr(C)] +pub struct GenericTrackList { + /// The index in `values` where our `` value is, if in bounds. #[css(skip)] - pub list_type: TrackListType, + pub auto_repeat_index: usize, /// A vector of ` | ` values. - pub values: Vec>, + pub values: crate::OwnedSlice>, /// `` accompanying ` | ` values. /// /// If there's no ``, then it's represented by an empty vector. /// For N values, there will be N+1 ``, and so this vector's /// length is always one value more than that of the ``. - pub line_names: Box<[Box<[CustomIdent]>]>, - /// `` value. There can only be one `` in a TrackList. - pub auto_repeat: Option>, + pub line_names: crate::OwnedSlice>, +} + +pub use self::GenericTrackList as TrackList; + +impl TrackList { + /// Whether this track list is an explicit track list (that is, doesn't have + /// any repeat values). + pub fn is_explicit(&self) -> bool { + !self.values.iter().any(|v| v.is_repeat()) + } + + /// Whether this track list has an `` value. + pub fn has_auto_repeat(&self) -> bool { + self.auto_repeat_index < self.values.len() + } } impl ToCss for TrackList { @@ -566,11 +529,6 @@ impl ToCss for TrackList { where W: Write, { - let auto_idx = match self.list_type { - TrackListType::Auto(i) => i as usize, - _ => usize::MAX, - }; - let mut values_iter = self.values.iter().peekable(); let mut line_names_iter = self.line_names.iter().peekable(); @@ -578,29 +536,20 @@ impl ToCss for TrackList { let names = line_names_iter.next().unwrap(); // This should exist! concat_serialize_idents("[", "]", names, " ", dest)?; - match self.auto_repeat { - Some(ref repeat) if idx == auto_idx => { + match values_iter.next() { + Some(value) => { if !names.is_empty() { dest.write_str(" ")?; } - repeat.to_css(dest)?; - }, - _ => match values_iter.next() { - Some(value) => { - if !names.is_empty() { - dest.write_str(" ")?; - } - - value.to_css(dest)?; - }, - None => break, + value.to_css(dest)?; }, + None => break, } if values_iter.peek().is_some() || line_names_iter.peek().map_or(false, |v| !v.is_empty()) || - (idx + 1 == auto_idx) + (idx + 1 == self.auto_repeat_index) { dest.write_str(" ")?; } @@ -613,7 +562,8 @@ impl ToCss for TrackList { /// The `` for subgrids. /// /// `subgrid [ | repeat( | auto-fill, +) ]+` -/// Old spec: https://www.w3.org/TR/2015/WD-css-grid-1-20150917/#typedef-line-name-list +/// +/// https://drafts.csswg.org/css-grid-2/#typedef-line-name-list #[derive( Clone, Debug, @@ -625,11 +575,12 @@ impl ToCss for TrackList { ToResolvedValue, ToShmem, )] +#[repr(C)] pub struct LineNameList { /// The optional `` - pub names: Box<[Box<[CustomIdent]>]>, - /// Indicates the line name that requires `auto-fill` - pub fill_idx: Option, + pub names: crate::OwnedSlice>, + /// Indicates the line name that requires `auto-fill`, if in bounds. + pub fill_idx: usize, } impl Parse for LineNameList { @@ -652,13 +603,17 @@ impl Parse for LineNameList { while let Ok(names) = input.try(parse_line_names) { names_list.push(names); } - Ok((names_list, count)) }) }); if let Ok((mut names_list, count)) = repeat_parse_result { match count { + // FIXME(emilio): we probably shouldn't expand repeat() at + // parse time for subgrid. + // + // Also this doesn't have the merging semantics that + // non-subgrid has... But maybe that's ok? RepeatCount::Number(num) => line_names.extend( names_list .iter() @@ -676,7 +631,7 @@ impl Parse for LineNameList { let names = names_list.pop().unwrap(); line_names.push(names); - fill_idx = Some(line_names.len() as u32 - 1); + fill_idx = Some(line_names.len() - 1); }, _ => return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)), } @@ -687,9 +642,13 @@ impl Parse for LineNameList { } } + if line_names.len() > MAX_GRID_LINE as usize { + line_names.truncate(MAX_GRID_LINE as usize); + } + Ok(LineNameList { - names: line_names.into_boxed_slice(), - fill_idx: fill_idx, + names: line_names.into(), + fill_idx: fill_idx.unwrap_or(usize::MAX), }) } } @@ -700,7 +659,7 @@ impl ToCss for LineNameList { W: Write, { dest.write_str("subgrid")?; - let fill_idx = self.fill_idx.map(|v| v as usize).unwrap_or(usize::MAX); + let fill_idx = self.fill_idx; for (i, names) in self.names.iter().enumerate() { if i == fill_idx { dest.write_str(" repeat(auto-fill,")?; @@ -727,8 +686,8 @@ impl ToCss for LineNameList { } /// Variants for ` | ` -/// Subgrid deferred to Level 2 spec due to lack of implementation. -/// But it's implemented in gecko, so we have to as well. +/// +/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, @@ -741,7 +700,8 @@ impl ToCss for LineNameList { ToResolvedValue, ToShmem, )] -pub enum GridTemplateComponent { +#[repr(C, u8)] +pub enum GenericGridTemplateComponent { /// `none` value. None, /// The grid `` @@ -750,7 +710,7 @@ pub enum GridTemplateComponent { #[compute(field_bound)] #[resolve(field_bound)] #[shmem(field_bound)] - TrackList, + GenericTrackList, ), /// A `subgrid ?` /// TODO: Support animations for this after subgrid is addressed in [grid-2] spec. @@ -758,6 +718,8 @@ pub enum GridTemplateComponent { Subgrid(LineNameList), } +pub use self::GenericGridTemplateComponent as GridTemplateComponent; + impl GridTemplateComponent { /// Returns length of the s pub fn track_list_len(&self) -> usize { diff --git a/components/style/values/resolved/mod.rs b/components/style/values/resolved/mod.rs index 379ea83ec6b1..e64178a1c957 100644 --- a/components/style/values/resolved/mod.rs +++ b/components/style/values/resolved/mod.rs @@ -65,6 +65,7 @@ trivial_to_resolved_value!(u8); trivial_to_resolved_value!(i8); trivial_to_resolved_value!(u16); trivial_to_resolved_value!(u32); +trivial_to_resolved_value!(usize); trivial_to_resolved_value!(String); trivial_to_resolved_value!(Box); trivial_to_resolved_value!(cssparser::RGBA); diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index 3e7f8f72a003..0d00f4cdb5db 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -6,10 +6,9 @@ //! [grids](https://drafts.csswg.org/css-grid/) use crate::parser::{Parse, ParserContext}; -use crate::values::computed::{self, Context, ToComputedValue}; use crate::values::generics::grid::{GridTemplateComponent, RepeatCount, TrackBreadth}; use crate::values::generics::grid::{LineNameList, TrackRepeat, TrackSize}; -use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue}; +use crate::values::generics::grid::{TrackList, TrackListValue}; use crate::values::specified::{Integer, LengthPercentage}; use crate::values::{CSSFloat, CustomIdent}; use cssparser::{ParseError as CssParseError, Parser, Token}; @@ -101,7 +100,7 @@ impl Parse for TrackSize { /// pub fn parse_line_names<'i, 't>( input: &mut Parser<'i, 't>, -) -> Result, ParseError<'i>> { +) -> Result, ParseError<'i>> { input.expect_square_bracket_block()?; input.parse_nested_block(|input| { let mut values = vec![]; @@ -112,7 +111,7 @@ pub fn parse_line_names<'i, 't>( values.push(ident); } - Ok(values.into_boxed_slice()) + Ok(values.into()) }) } @@ -155,9 +154,8 @@ impl TrackRepeat { let mut current_names; loop { - current_names = input - .try(parse_line_names) - .unwrap_or(vec![].into_boxed_slice()); + current_names = + input.try(parse_line_names).unwrap_or_default(); if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) { if !track_size.is_fixed() { if is_auto { @@ -183,7 +181,7 @@ impl TrackRepeat { names.push( input .try(parse_line_names) - .unwrap_or(vec![].into_boxed_slice()), + .unwrap_or_default() ); break; } @@ -201,9 +199,9 @@ impl TrackRepeat { } let repeat = TrackRepeat { - count: count, - track_sizes: values, - line_names: names.into_boxed_slice(), + count, + track_sizes: values.into(), + line_names: names.into(), }; Ok((repeat, repeat_type)) @@ -221,47 +219,35 @@ impl Parse for TrackList { let mut names = vec![]; let mut values = vec![]; - // assume it's the simplest case. - let mut list_type = TrackListType::Explicit; - // holds value. It can only be only one in a TrackList. - let mut auto_repeat = None; - // if there is any the list will be of type TrackListType::Auto(idx) - // where idx points to the position of the in the track list. If there - // is any repeat before , we need to take the number of repetitions into - // account to set the position of so it remains the same while computing - // values. - let mut auto_offset = 0; + // Whether we've parsed an `` value. + let mut auto_repeat_index = None; // assume that everything is . This flag is useful when we encounter - let mut atleast_one_not_fixed = false; + let mut at_least_one_not_fixed = false; loop { current_names.extend_from_slice( &mut input .try(parse_line_names) - .unwrap_or(vec![].into_boxed_slice()), + .unwrap_or_default() ); if let Ok(track_size) = input.try(|i| TrackSize::parse(context, i)) { if !track_size.is_fixed() { - atleast_one_not_fixed = true; - if auto_repeat.is_some() { + at_least_one_not_fixed = true; + if auto_repeat_index.is_some() { // only accepts and return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } } let vec = mem::replace(&mut current_names, vec![]); - names.push(vec.into_boxed_slice()); + names.push(vec.into()); values.push(TrackListValue::TrackSize(track_size)); } else if let Ok((repeat, type_)) = input.try(|i| TrackRepeat::parse_with_repeat_type(context, i)) { - if list_type == TrackListType::Explicit { - list_type = TrackListType::Normal; // doesn't contain repeat() - } - match type_ { RepeatType::Normal => { - atleast_one_not_fixed = true; - if auto_repeat.is_some() { + at_least_one_not_fixed = true; + if auto_repeat_index.is_some() { // only return Err( input.new_custom_error(StyleParseErrorKind::UnspecifiedError) @@ -269,132 +255,38 @@ impl Parse for TrackList { } }, RepeatType::Auto => { - if auto_repeat.is_some() || atleast_one_not_fixed { + if auto_repeat_index.is_some() || at_least_one_not_fixed { // We've either seen earlier, or there's at least one non-fixed value return Err( input.new_custom_error(StyleParseErrorKind::UnspecifiedError) ); } - - list_type = TrackListType::Auto(values.len() as u16 + auto_offset); - auto_repeat = Some(repeat); - let vec = mem::replace(&mut current_names, vec![]); - names.push(vec.into_boxed_slice()); - continue; + auto_repeat_index = Some(values.len()); }, - RepeatType::Fixed => (), + RepeatType::Fixed => {}, } let vec = mem::replace(&mut current_names, vec![]); - names.push(vec.into_boxed_slice()); - if let RepeatCount::Number(num) = repeat.count { - auto_offset += (num.value() - 1) as u16; - } + names.push(vec.into()); values.push(TrackListValue::TrackRepeat(repeat)); } else { - if values.is_empty() && auto_repeat.is_none() { + if values.is_empty() && auto_repeat_index.is_none() { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } - names.push(current_names.into_boxed_slice()); + names.push(current_names.into()); break; } } Ok(TrackList { - list_type: list_type, - values: values, - line_names: names.into_boxed_slice(), - auto_repeat: auto_repeat, + auto_repeat_index: auto_repeat_index.unwrap_or(std::usize::MAX), + values: values.into(), + line_names: names.into(), }) } } -impl ToComputedValue for TrackList { - type ComputedValue = TrackList; - - #[inline] - fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - // Merge the line names while computing values. The resulting values will - // all be bunch of `` and one . - // - // For example, - // `[a b] 100px [c d] repeat(1, 30px [g]) [h]` will be merged as `[a b] 100px [c d] 30px [g h]` - // whereas, `[a b] repeat(2, [c] 50px [d]) [e f] repeat(auto-fill, [g] 12px) 10px [h]` will be merged as - // `[a b c] 50px [d c] 50px [d e f] repeat(auto-fill, [g] 12px) 10px [h]`, with the `` value - // set in the `auto_repeat` field, and the `idx` in TrackListType::Auto pointing to the values after - // `` (in this case, `10px [h]`). - let mut prev_names = vec![]; - let mut line_names = Vec::with_capacity(self.line_names.len() + 1); - let mut values = Vec::with_capacity(self.values.len() + 1); - for (pos, names) in self.line_names.iter().enumerate() { - prev_names.extend_from_slice(&names); - if pos >= self.values.len() { - let vec = mem::replace(&mut prev_names, vec![]); - line_names.push(vec.into_boxed_slice()); - continue; - } - - match self.values[pos] { - TrackListValue::TrackSize(ref size) => { - let vec = mem::replace(&mut prev_names, vec![]); - line_names.push(vec.into_boxed_slice()); - values.push(TrackListValue::TrackSize(size.to_computed_value(context))); - }, - TrackListValue::TrackRepeat(ref repeat) => { - // If the repeat count is numeric, we expand and merge the values. - let mut repeat = repeat.expand(); - let mut repeat_names_iter = repeat.line_names.iter(); - for (size, repeat_names) in - repeat.track_sizes.drain(..).zip(&mut repeat_names_iter) - { - prev_names.extend_from_slice(&repeat_names); - let vec = mem::replace(&mut prev_names, vec![]); - line_names.push(vec.into_boxed_slice()); - values.push(TrackListValue::TrackSize(size.to_computed_value(context))); - } - - if let Some(names) = repeat_names_iter.next() { - prev_names.extend_from_slice(&names); - } - }, - } - } - - TrackList { - list_type: self.list_type.to_computed_value(context), - values: values, - line_names: line_names.into_boxed_slice(), - auto_repeat: self - .auto_repeat - .clone() - .map(|repeat| repeat.to_computed_value(context)), - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - let mut values = Vec::with_capacity(computed.values.len() + 1); - for value in computed - .values - .iter() - .map(ToComputedValue::from_computed_value) - { - values.push(value); - } - - TrackList { - list_type: computed.list_type, - values: values, - line_names: computed.line_names.clone(), - auto_repeat: computed - .auto_repeat - .clone() - .map(|ref repeat| TrackRepeat::from_computed_value(repeat)), - } - } -} - #[cfg(feature = "gecko")] #[inline] fn allow_grid_template_subgrids() -> bool { @@ -409,7 +301,6 @@ fn allow_grid_template_subgrids() -> bool { } impl Parse for GridTemplateComponent { - // FIXME: Derive Parse (probably with None_) fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, diff --git a/components/style_traits/specified_value_info.rs b/components/style_traits/specified_value_info.rs index 39740bc72621..1dd368d36e9c 100644 --- a/components/style_traits/specified_value_info.rs +++ b/components/style_traits/specified_value_info.rs @@ -82,6 +82,7 @@ impl SpecifiedValueInfo for i32 {} impl SpecifiedValueInfo for u8 {} impl SpecifiedValueInfo for u16 {} impl SpecifiedValueInfo for u32 {} +impl SpecifiedValueInfo for usize {} impl SpecifiedValueInfo for str {} impl SpecifiedValueInfo for String {} impl SpecifiedValueInfo for crate::owned_str::OwnedStr {}