diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index c00420e7b1d..7b89cb0cefb 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -18,7 +18,7 @@ use gecko_bindings::sugar::ns_style_coord::{CoordDataValue, CoordData, CoordData use std::f32::consts::PI; use stylesheets::{Origin, RulesMutateError}; use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image}; -use values::computed::{LengthOrPercentage, LengthOrPercentageOrAuto, Percentage}; +use values::computed::{Integer, LengthOrPercentage, LengthOrPercentageOrAuto, Percentage}; use values::generics::box_::VerticalAlign; use values::generics::grid::{TrackListValue, TrackSize}; use values::generics::image::{CompatMode, Image as GenericImage, GradientItem}; @@ -896,7 +896,7 @@ impl TrackSize { } } -impl TrackListValue { +impl TrackListValue { /// Return TrackSize from given two nsStyleCoord pub fn from_gecko_style_coords(gecko_min: &T, gecko_max: &T) -> Self { TrackListValue::TrackSize(TrackSize::from_gecko_style_coords(gecko_min, gecko_max)) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index fb59b00c704..a2d01bbf4ca 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1700,7 +1700,7 @@ fn static_assert() { if let Some(integer) = v.line_num { // clamping the integer between a range self.gecko.${value.gecko}.mInteger = cmp::max(nsStyleGridLine_kMinLine, - cmp::min(integer.value(), nsStyleGridLine_kMaxLine)); + cmp::min(integer, nsStyleGridLine_kMaxLine)); } } @@ -1717,7 +1717,6 @@ fn static_assert() { pub fn clone_${value.name}(&self) -> longhands::${value.name}::computed_value::T { use gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine}; use string_cache::Atom; - use values::specified::Integer; longhands::${value.name}::computed_value::T { is_span: self.gecko.${value.gecko}.mHasSpan, @@ -1735,7 +1734,7 @@ fn static_assert() { } else { debug_assert!(nsStyleGridLine_kMinLine <= self.gecko.${value.gecko}.mInteger); debug_assert!(self.gecko.${value.gecko}.mInteger <= nsStyleGridLine_kMaxLine); - Some(Integer::new(self.gecko.${value.gecko}.mInteger)) + Some(self.gecko.${value.gecko}.mInteger) }, } } diff --git a/components/style/properties/shorthand/position.mako.rs b/components/style/properties/shorthand/position.mako.rs index 667462f6b05..6a4661c4f56 100644 --- a/components/style/properties/shorthand/position.mako.rs +++ b/components/style/properties/shorthand/position.mako.rs @@ -147,7 +147,7 @@ let end = if input.try(|i| i.expect_delim('/')).is_ok() { GridLine::parse(context, input)? } else { - let mut line = GridLine::default(); + let mut line = GridLine::auto(); if start.line_num.is_none() && !start.is_span { line.ident = start.ident.clone(); // ident from start value should be taken } @@ -182,7 +182,7 @@ pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { fn line_with_ident_from(other: &GridLine) -> GridLine { - let mut this = GridLine::default(); + let mut this = GridLine::auto(); if other.line_num.is_none() && !other.is_span { this.ident = other.ident.clone(); } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index a1ca7b8422b..304fee4bba9 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -21,9 +21,9 @@ use std::sync::Arc; use style_traits::ToCss; use super::{CSSFloat, CSSInteger}; use super::generics::{GreaterThanOrEqualToOne, NonNegative}; -use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; +use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth}; +use super::generics::grid::{TrackSize as GenericTrackSize, TrackList as GenericTrackList}; use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; -use super::generics::grid::TrackList as GenericTrackList; use super::specified; pub use app_units::Au; @@ -44,7 +44,6 @@ pub use self::gecko::ScrollSnapPoint; pub use self::rect::LengthOrNumberRect; pub use super::{Auto, Either, None_}; pub use super::specified::BorderStyle; -pub use super::generics::grid::GridLine; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNone, LengthOrNumber, LengthOrPercentage}; pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLength, MozLength}; pub use self::length::NonNegativeLengthOrPercentage; @@ -502,10 +501,13 @@ pub type TrackSize = GenericTrackSize; /// The computed value of a grid `` /// (could also be `` or ``) -pub type TrackList = GenericTrackList; +pub type TrackList = GenericTrackList; + +/// The computed value of a ``. +pub type GridLine = GenericGridLine; /// ` | ` -pub type GridTemplateComponent = GenericGridTemplateComponent; +pub type GridTemplateComponent = GenericGridTemplateComponent; impl ClipRectOrAuto { /// Return an auto (default for clip-rect and image-region) value diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index a70c0e7c4c3..5a05b318733 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -11,15 +11,15 @@ use std::{fmt, mem, usize}; use style_traits::{ToCss, ParseError, StyleParseError}; use values::{CSSFloat, CustomIdent, serialize_dimension}; use values::computed::{ComputedValueAsSpecified, Context, ToComputedValue}; -use values::specified::Integer; +use values::specified; use values::specified::grid::parse_line_names; -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, Default, PartialEq, ToComputedValue)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] /// A `` type. /// /// https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line -pub struct GridLine { +pub struct GridLine { /// Flag to check whether it's a `span` keyword. pub is_span: bool, /// A custom identifier for named lines. @@ -30,24 +30,26 @@ pub struct GridLine { pub line_num: Option, } -impl GridLine { +impl GridLine { + /// The `auto` value. + pub fn auto() -> Self { + Self { + is_span: false, + line_num: None, + ident: None, + } + } + /// Check whether this `` represents an `auto` value. pub fn is_auto(&self) -> bool { self.ident.is_none() && self.line_num.is_none() && !self.is_span } } -impl Default for GridLine { - fn default() -> Self { - GridLine { - is_span: false, - ident: None, - line_num: None, - } - } -} - -impl ToCss for GridLine { +impl ToCss for GridLine +where + Integer: ToCss, +{ fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { if self.is_auto() { return dest.write_str("auto") @@ -57,9 +59,9 @@ impl ToCss for GridLine { dest.write_str("span")?; } - if let Some(i) = self.line_num { + if let Some(ref i) = self.line_num { dest.write_str(" ")?; - i.value().to_css(dest)?; + i.to_css(dest)?; } if let Some(ref s) = self.ident { @@ -71,9 +73,9 @@ impl ToCss for GridLine { } } -impl Parse for GridLine { +impl Parse for GridLine { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - let mut grid_line = Default::default(); + let mut grid_line = Self::auto(); if input.try(|i| i.expect_ident_matching("auto")).is_ok() { return Ok(grid_line) } @@ -95,7 +97,8 @@ impl Parse for GridLine { } grid_line.is_span = true; - } else if let Ok(i) = input.try(|i| Integer::parse(context, i)) { + } else if let Ok(i) = input.try(|i| specified::Integer::parse(context, i)) { + // FIXME(emilio): Probably shouldn't reject if it's calc()... if i.value() == 0 || val_before_span || grid_line.line_num.is_some() { return Err(StyleParseError::UnspecifiedError.into()) } @@ -129,8 +132,6 @@ impl Parse for GridLine { } } -impl ComputedValueAsSpecified for GridLine {} - define_css_keyword_enum!{ TrackKeyword: "auto" => Auto, "max-content" => MaxContent, @@ -316,9 +317,15 @@ impl ToComputedValue for TrackSize { /// Helper function for serializing identifiers with a prefix and suffix, used /// for serializing (in grid). -pub fn concat_serialize_idents(prefix: &str, suffix: &str, - slice: &[CustomIdent], sep: &str, dest: &mut W) -> fmt::Result - where W: fmt::Write +pub fn concat_serialize_idents( + prefix: &str, + suffix: &str, + slice: &[CustomIdent], + sep: &str, + dest: &mut W, +) -> fmt::Result +where + W: fmt::Write { if let Some((ref first, rest)) = slice.split_first() { dest.write_str(prefix)?; @@ -338,8 +345,8 @@ pub fn concat_serialize_idents(prefix: &str, suffix: &str, /// /// https://drafts.csswg.org/css-grid/#typedef-track-repeat #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq, ToCss)] -pub enum RepeatCount { +#[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)] +pub enum RepeatCount { /// A positive integer. This is allowed only for `` and `` Number(Integer), /// An `` keyword allowed only for `` @@ -348,19 +355,15 @@ pub enum RepeatCount { AutoFit, } -impl Parse for RepeatCount { +impl Parse for RepeatCount { fn parse<'i, 't>(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| Integer::parse(context, i)) { - if i.value() > 0 { - if i.value() > MAX_LINE { - i = Integer::new(MAX_LINE); - } - Ok(RepeatCount::Number(i)) - } else { - Err(StyleParseError::UnspecifiedError.into()) + 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.expect_ident()?, "auto-fill" => Ok(RepeatCount::AutoFill), @@ -370,17 +373,15 @@ impl Parse for RepeatCount { } } -impl ComputedValueAsSpecified for RepeatCount {} - /// The structure containing `` and `` values. /// /// It can also hold `repeat()` function parameters, which expands into the respective /// values in its computed form. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, PartialEq, ToComputedValue)] -pub struct TrackRepeat { +pub struct TrackRepeat { /// The number of times for the value to be repeated (could also be `auto-fit` or `auto-fill`) - pub count: RepeatCount, + pub count: RepeatCount, /// `` accompanying `` values. /// /// If there's no ``, then it's represented by an empty vector. @@ -392,7 +393,7 @@ pub struct TrackRepeat { pub track_sizes: Vec>, } -impl ToCss for TrackRepeat { +impl ToCss for TrackRepeat { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { dest.write_str("repeat(")?; self.count.to_css(dest)?; @@ -418,7 +419,7 @@ impl ToCss for TrackRepeat { Ok(()) } } -impl TrackRepeat { +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 { @@ -460,11 +461,11 @@ impl TrackRepeat { /// Track list values. Can be or #[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -pub enum TrackListValue { +pub enum TrackListValue { /// A value. - TrackSize(TrackSize), + TrackSize(TrackSize), /// A value. - TrackRepeat(TrackRepeat), + TrackRepeat(TrackRepeat), } /// The type of a `` as determined during parsing. @@ -497,14 +498,14 @@ impl ComputedValueAsSpecified for TrackListType {} /// https://drafts.csswg.org/css-grid/#typedef-track-list #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, PartialEq)] -pub struct TrackList { +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). pub list_type: TrackListType, /// A vector of ` | ` values. - pub values: Vec>, + pub values: Vec>, /// `` accompanying ` | ` values. /// /// If there's no ``, then it's represented by an empty vector. @@ -512,10 +513,10 @@ pub struct TrackList { /// 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 auto_repeat: Option>, } -impl ToCss for TrackList { +impl ToCss for TrackList { fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { let auto_idx = match self.list_type { TrackListType::Auto(i) => i as usize, @@ -661,16 +662,16 @@ impl ComputedValueAsSpecified for LineNameList {} /// But it's implemented in gecko, so we have to as well. #[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[derive(Clone, Debug, PartialEq, ToComputedValue, ToCss)] -pub enum GridTemplateComponent { +pub enum GridTemplateComponent { /// `none` value. None, /// The grid `` - TrackList(TrackList), + TrackList(TrackList), /// A `subgrid ?` Subgrid(LineNameList), } -impl GridTemplateComponent { +impl GridTemplateComponent { /// Returns length of the s pub fn track_list_len(&self) -> usize { match *self { diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index f68325f9c27..72e6ebec5d8 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -14,7 +14,7 @@ use values::{CSSFloat, CustomIdent}; use values::computed::{self, Context, ToComputedValue}; use values::generics::grid::{GridTemplateComponent, RepeatCount, TrackBreadth, TrackKeyword, TrackRepeat}; use values::generics::grid::{LineNameList, TrackSize, TrackList, TrackListType, TrackListValue}; -use values::specified::LengthOrPercentage; +use values::specified::{LengthOrPercentage, Integer}; /// Parse a single flexible length. pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { @@ -97,9 +97,11 @@ enum RepeatType { Fixed, } -impl TrackRepeat { - fn parse_with_repeat_type<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result<(TrackRepeat, RepeatType), ParseError<'i>> { +impl TrackRepeat { + fn parse_with_repeat_type<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<(Self, RepeatType), ParseError<'i>> { input.try(|i| i.expect_function_matching("repeat").map_err(|e| e.into())).and_then(|_| { input.parse_nested_block(|input| { let count = RepeatCount::parse(context, input)?; @@ -165,7 +167,7 @@ impl TrackRepeat { } } -impl Parse for TrackList { +impl Parse for TrackList { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { let mut current_names = vec![]; let mut names = vec![]; @@ -248,8 +250,8 @@ impl Parse for TrackList { } } -impl ToComputedValue for TrackList { - type ComputedValue = TrackList; +impl ToComputedValue for TrackList { + type ComputedValue = TrackList; #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { @@ -321,7 +323,7 @@ impl ToComputedValue for TrackList { } } -impl Parse for GridTemplateComponent { +impl Parse for GridTemplateComponent { // FIXME: Derive Parse (probably with None_) fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { if input.try(|i| i.expect_ident_matching("none")).is_ok() { @@ -332,10 +334,12 @@ impl Parse for GridTemplateComponent { } } -impl GridTemplateComponent { +impl GridTemplateComponent { /// Parses a `GridTemplateComponent` except `none` keyword. - pub fn parse_without_none<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { + pub fn parse_without_none<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { if let Ok(t) = input.try(|i| TrackList::parse(context, i)) { return Ok(GridTemplateComponent::TrackList(t)) } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index ecceede0156..7c91096bb8b 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -19,8 +19,8 @@ use style_traits::values::specified::AllowedNumericType; use super::{Auto, CSSFloat, CSSInteger, Either, None_}; use super::computed::{Context, ToComputedValue}; use super::generics::{GreaterThanOrEqualToOne, NonNegative}; -use super::generics::grid::{TrackBreadth as GenericTrackBreadth, TrackSize as GenericTrackSize}; -use super::generics::grid::TrackList as GenericTrackList; +use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth}; +use super::generics::grid::{TrackSize as GenericTrackSize, TrackList as GenericTrackList}; use values::computed::ComputedValueAsSpecified; use values::specified::calc::CalcNode; @@ -52,7 +52,6 @@ pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind, SVGStrokeDash pub use self::text::{InitialLetter, LetterSpacing, LineHeight, WordSpacing}; pub use self::time::Time; pub use self::transform::{TimingFunction, TransformOrigin}; -pub use super::generics::grid::GridLine; pub use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; #[cfg(feature = "gecko")] @@ -356,9 +355,11 @@ impl ToComputedValue for Opacity { } } +/// An specified ``, optionally coming from a `calc()` expression. +/// +/// https://drafts.csswg.org/css-values/#integers #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] #[cfg_attr(feature = "servo", derive(HeapSizeOf))] -#[allow(missing_docs)] pub struct Integer { value: CSSInteger, was_calc: bool, @@ -387,7 +388,6 @@ impl Integer { } } - impl Parse for Integer { fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { parse_integer(context, input) @@ -395,25 +395,37 @@ impl Parse for Integer { } impl Integer { - #[allow(missing_docs)] - pub fn parse_with_minimum<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>, min: i32) - -> Result> { + /// Parse an integer value which is at least `min`. + pub fn parse_with_minimum<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + min: i32 + ) -> Result> { match parse_integer(context, input) { + // FIXME(emilio): The spec asks us to avoid rejecting it at parse + // time except until computed value time. + // + // It's not totally clear it's worth it though, and no other browser + // does this. Ok(value) if value.value() >= min => Ok(value), Ok(_value) => Err(StyleParseError::UnspecifiedError.into()), Err(e) => Err(e), } } - #[allow(missing_docs)] - pub fn parse_non_negative<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { + /// Parse a non-negative integer. + pub fn parse_non_negative<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { Integer::parse_with_minimum(context, input, 0) } - #[allow(missing_docs)] - pub fn parse_positive<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) - -> Result> { + /// Parse a positive integer (>= 1). + pub fn parse_positive<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't> + ) -> Result> { Integer::parse_with_minimum(context, input, 1) } } @@ -484,10 +496,13 @@ pub type TrackSize = GenericTrackSize; /// The specified value of a grid `` /// (could also be `` or ``) -pub type TrackList = GenericTrackList; +pub type TrackList = GenericTrackList; + +/// The specified value of a ``. +pub type GridLine = GenericGridLine; /// ` | ` -pub type GridTemplateComponent = GenericGridTemplateComponent; +pub type GridTemplateComponent = GenericGridTemplateComponent; /// | | pub type LengthOrPercentageOrNumber = Either;