diff --git a/components/style/macros.rs b/components/style/macros.rs index 3084d33dd3d..5f3a1ea463b 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -65,46 +65,6 @@ macro_rules! try_match_ident_ignore_ascii_case { }} } -macro_rules! define_keyword_type { - ($name:ident, $css:expr) => { - #[allow(missing_docs)] - #[derive( - Animate, - Clone, - ComputeSquaredDistance, - Copy, - MallocSizeOf, - PartialEq, - SpecifiedValueInfo, - ToAnimatedValue, - ToAnimatedZero, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, - )] - pub struct $name; - - impl fmt::Debug for $name { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - f.write_str($css) - } - } - - impl $crate::parser::Parse for $name { - fn parse<'i, 't>( - _context: &$crate::parser::ParserContext, - input: &mut ::cssparser::Parser<'i, 't>, - ) -> Result<$name, ::style_traits::ParseError<'i>> { - input - .expect_ident_matching($css) - .map(|_| $name) - .map_err(|e| e.into()) - } - } - }; -} - #[cfg(feature = "servo")] macro_rules! local_name { ($s:tt) => { diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 9c085d20509..2b0605d4e9e 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -466,6 +466,7 @@ class Longhand(Property): "JustifyItems", "JustifySelf", "LineBreak", + "LineClamp", "MasonryAutoFlow", "MozForceBrokenImageIcon", "text::MozControlCharacterVisibility", @@ -483,7 +484,6 @@ class Longhand(Property): "OverflowWrap", "OverscrollBehavior", "Percentage", - "PositiveIntegerOrNone", "PrintColorAdjust", "Resize", "RubyPosition", diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index e74f1ef9990..7bb4571cb20 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -38,7 +38,7 @@ use crate::selector_parser::PseudoElement; use servo_arc::{Arc, RawOffsetArc, UniqueArc}; use std::mem::{forget, MaybeUninit}; use std::{cmp, ops, ptr}; -use crate::values::{self, CustomIdent, Either, KeyframesName, None_}; +use crate::values::{self, CustomIdent, KeyframesName}; use crate::values::computed::{Percentage, TransitionProperty}; use crate::values::computed::BorderStyle; use crate::values::computed::font::FontSize; @@ -1127,9 +1127,7 @@ fn static_assert() { ${impl_copy_animation_value(ident, gecko_ffi_name)} -<% skip_box_longhands= """display - clear - -webkit-line-clamp""" %> +<% skip_box_longhands= """display clear""" %> <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}"> #[inline] pub fn set_display(&mut self, v: longhands::display::computed_value::T) { @@ -1169,28 +1167,6 @@ fn static_assert() { gecko_inexhaustive=True, ) %> ${impl_keyword('clear', 'mBreakType', clear_keyword)} - - #[allow(non_snake_case)] - pub fn set__webkit_line_clamp(&mut self, v: longhands::_webkit_line_clamp::computed_value::T) { - self.gecko.mLineClamp = match v { - Either::First(n) => n.0 as u32, - Either::Second(None_) => 0, - }; - } - - ${impl_simple_copy('_webkit_line_clamp', 'mLineClamp')} - - #[allow(non_snake_case)] - pub fn clone__webkit_line_clamp(&self) -> longhands::_webkit_line_clamp::computed_value::T { - match self.gecko.mLineClamp { - 0 => Either::Second(None_), - n => { - debug_assert!(n <= std::i32::MAX as u32); - Either::First((n as i32).into()) - } - } - } - <%def name="simple_image_array_property(name, shorthand, field_name)"> diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index edfe0797993..0073582df03 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -119,8 +119,6 @@ use crate::values::computed::{Context, ToComputedValue}; #[allow(unused_imports)] use crate::values::{computed, specified}; - #[allow(unused_imports)] - use crate::values::{Auto, Either, None_}; ${caller.body()} } @@ -414,8 +412,6 @@ #[allow(unused_imports)] use crate::properties::{UnparsedValue, ShorthandId}; #[allow(unused_imports)] - use crate::values::{Auto, Either, None_}; - #[allow(unused_imports)] use crate::error_reporting::ParseErrorReporter; #[allow(unused_imports)] use crate::properties::longhands; diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index 6598885c3a1..5c2142d002b 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -547,16 +547,13 @@ ${helpers.predefined_type( spec="https://compat.spec.whatwg.org/#touch-action", )} -// Note that we only implement -webkit-line-clamp as a single, longhand -// property for now, but the spec defines line-clamp as a shorthand for separate -// max-lines, block-ellipsis, and continue properties. ${helpers.predefined_type( "-webkit-line-clamp", - "PositiveIntegerOrNone", - "Either::Second(None_)", + "LineClamp", + "computed::LineClamp::none()", engines="gecko", gecko_pref="layout.css.webkit-line-clamp.enabled", - animation_value_type="Integer", + animation_value_type="ComputedValue", spec="https://drafts.csswg.org/css-overflow-3/#line-clamp", )} diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 226c01a9a49..b36946c4926 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -378,6 +378,7 @@ trivial_to_animated_value!(ComputedAngle); trivial_to_animated_value!(ComputedUrl); trivial_to_animated_value!(bool); trivial_to_animated_value!(f32); +trivial_to_animated_value!(i32); // Note: This implementation is for ToAnimatedValue of ShapeSource. // // SVGPathData uses Box<[T]>. If we want to derive ToAnimatedValue for all the diff --git a/components/style/values/computed/box.rs b/components/style/values/computed/box.rs index 28d704b015c..2758289295b 100644 --- a/components/style/values/computed/box.rs +++ b/components/style/values/computed/box.rs @@ -4,12 +4,11 @@ //! Computed types for box properties. +use crate::values::animated::{Animate, Procedure}; use crate::values::computed::length::{LengthPercentage, NonNegativeLength}; -use crate::values::computed::{Context, Number, ToComputedValue}; +use crate::values::computed::{Context, Integer, Number, ToComputedValue}; use crate::values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; -use crate::values::generics::box_::Perspective as GenericPerspective; -use crate::values::generics::box_::VerticalAlign as GenericVerticalAlign; -use crate::values::generics::box_::ContainIntrinsicSize as GenericContainIntrinsicSize; +use crate::values::generics::box_::{GenericLineClamp, GenericPerspective, GenericVerticalAlign, GenericContainIntrinsicSize}; use crate::values::specified::box_ as specified; pub use crate::values::specified::box_::{ @@ -30,6 +29,22 @@ pub type AnimationIterationCount = GenericAnimationIterationCount; /// A computed value for the `contain-intrinsic-size` property. pub type ContainIntrinsicSize = GenericContainIntrinsicSize; +/// A computed value for the `line-clamp` property. +pub type LineClamp = GenericLineClamp; + +impl Animate for LineClamp { + #[inline] + fn animate(&self, other: &Self, procedure: Procedure) -> Result { + if self.is_none() != other.is_none() { + return Err(()); + } + if self.is_none() { + return Ok(Self::none()) + } + Ok(Self(self.0.animate(&other.0, procedure)?.max(1))) + } +} + impl AnimationIterationCount { /// Returns the value `1.0`. #[inline] diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 6449495cb0c..e185d297f84 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -47,7 +47,7 @@ pub use self::border::{BorderImageRepeat, BorderImageSideWidth}; pub use self::border::{BorderImageSlice, BorderImageWidth}; pub use self::box_::{AnimationIterationCount, AnimationName, AnimationTimeline, Contain, ContainerName, ContainerType}; pub use self::box_::{Appearance, BreakBetween, BreakWithin, Clear, ContentVisibility, ContainIntrinsicSize, Float}; -pub use self::box_::{Display, Overflow, OverflowAnchor, TransitionProperty}; +pub use self::box_::{Display, LineClamp, Overflow, OverflowAnchor, TransitionProperty}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize, ScrollbarGutter}; pub use self::box_::{ScrollAxis, ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop}; pub use self::box_::{ScrollSnapStrictness, ScrollSnapType, ScrollTimelineName}; @@ -101,7 +101,6 @@ pub use self::ui::{Cursor, MozForceBrokenImageIcon, UserSelect}; pub use super::specified::TextTransform; pub use super::specified::ViewportVariant; pub use super::specified::{BorderStyle, TextDecorationLine}; -pub use super::{Auto, Either, None_}; pub use app_units::Au; #[cfg(feature = "gecko")] @@ -876,9 +875,6 @@ impl From for PositiveInteger { } } -/// A computed positive `` value or `none`. -pub type PositiveIntegerOrNone = Either; - /// rect(...) | auto pub type ClipRect = generics::GenericClipRect; diff --git a/components/style/values/generics/box.rs b/components/style/values/generics/box.rs index b64852e645a..073d2edbe65 100644 --- a/components/style/values/generics/box.rs +++ b/components/style/values/generics/box.rs @@ -107,7 +107,6 @@ pub enum GenericContainIntrinsicSize { pub use self::GenericContainIntrinsicSize as ContainIntrinsicSize; impl ToCss for ContainIntrinsicSize { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, @@ -123,6 +122,55 @@ impl ToCss for ContainIntrinsicSize { } } +/// Note that we only implement -webkit-line-clamp as a single, longhand +/// property for now, but the spec defines line-clamp as a shorthand for +/// separate max-lines, block-ellipsis, and continue properties. +/// +/// https://drafts.csswg.org/css-overflow-3/#line-clamp +#[derive( + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToAnimatedValue, + ToAnimatedZero, + ToResolvedValue, + ToShmem, +)] +#[repr(transparent)] +#[value_info(other_values = "auto")] +pub struct GenericLineClamp(pub I); + +pub use self::GenericLineClamp as LineClamp; + +impl LineClamp { + /// Returns the `none` value. + pub fn none() -> Self { + Self(crate::Zero::zero()) + } + + /// Returns whether we're the `none` value. + pub fn is_none(&self) -> bool { + self.0.is_zero() + } +} + +impl ToCss for LineClamp { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + if self.is_none() { + return dest.write_str("none"); + } + self.0.to_css(dest) + } +} + /// https://drafts.csswg.org/css-animations/#animation-iteration-count #[derive( Clone, @@ -135,13 +183,15 @@ impl ToCss for ContainIntrinsicSize { ToResolvedValue, ToShmem, )] -pub enum AnimationIterationCount { +pub enum GenericAnimationIterationCount { /// A `` value. Number(Number), /// The `infinite` keyword. Infinite, } +pub use self::GenericAnimationIterationCount as AnimationIterationCount; + /// A generic value for the `perspective` property. #[derive( Animate, diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 5db6d2555e8..dbb52013093 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -48,9 +48,6 @@ pub fn normalize(v: CSSFloat) -> CSSFloat { /// A CSS integer value. pub type CSSInteger = i32; -define_keyword_type!(None_, "none"); -define_keyword_type!(Auto, "auto"); - /// Serialize an identifier which is represented as an atom. #[cfg(feature = "gecko")] pub fn serialize_atom_identifier(ident: &Atom, dest: &mut W) -> fmt::Result diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index 8ed3ee3c594..47561c9a51a 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -8,11 +8,10 @@ use crate::custom_properties::Name as CustomPropertyName; use crate::parser::{Parse, ParserContext}; use crate::properties::{LonghandId, PropertyDeclarationId}; use crate::properties::{PropertyId, ShorthandId}; -use crate::values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; -use crate::values::generics::box_::Perspective as GenericPerspective; +use crate::values::generics::box_::{GenericAnimationIterationCount, GenericPerspective, GenericLineClamp}; use crate::values::generics::box_::{GenericContainIntrinsicSize, GenericVerticalAlign, VerticalAlignKeyword}; use crate::values::specified::length::{LengthPercentage, NonNegativeLength}; -use crate::values::specified::{AllowQuirks, Number}; +use crate::values::specified::{AllowQuirks, Number, Integer}; use crate::values::{CustomIdent, KeyframesName, TimelineName}; use crate::Atom; use cssparser::Parser; @@ -615,6 +614,9 @@ impl Debug for Display { /// A specified value for the `contain-intrinsic-size` property. pub type ContainIntrinsicSize = GenericContainIntrinsicSize; +/// A specified value for the `line-clamp` property. +pub type LineClamp = GenericLineClamp; + /// A specified value for the `vertical-align` property. pub type VerticalAlign = GenericVerticalAlign; @@ -1443,6 +1445,21 @@ impl Parse for ContainIntrinsicSize { } } +impl Parse for LineClamp { + /// none | + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + if let Ok(i) = input.try_parse(|i| crate::values::specified::PositiveInteger::parse(context, i)) + { + return Ok(Self(i.0)) + } + input.expect_ident_matching("none")?; + Ok(Self::none()) + } +} + /// https://drafts.csswg.org/css-contain-2/#content-visibility #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive( diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index fbb0a42d94f..fbd9c52934b 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -13,7 +13,7 @@ use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as Generic use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize}; use super::generics::transform::IsParallelTo; use super::generics::{self, GreaterThanOrEqualToOne, NonNegative}; -use super::{CSSFloat, CSSInteger, Either, None_}; +use super::{CSSFloat, CSSInteger}; use crate::context::QuirksMode; use crate::parser::{Parse, ParserContext}; use crate::values::serialize_atom_identifier; @@ -38,7 +38,7 @@ pub use self::border::{BorderImageRepeat, BorderImageSideWidth}; pub use self::border::{BorderRadius, BorderSideWidth, BorderSpacing, BorderStyle}; pub use self::box_::{AnimationIterationCount, AnimationName, AnimationTimeline, Contain, Display}; pub use self::box_::{Appearance, BreakBetween, BreakWithin, ContainerName, ContainerType}; -pub use self::box_::{Clear, ContentVisibility, ContainIntrinsicSize, Float, Overflow, OverflowAnchor}; +pub use self::box_::{Clear, ContentVisibility, ContainIntrinsicSize, LineClamp, Float, Overflow, OverflowAnchor}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize, ScrollbarGutter}; pub use self::box_::{ScrollAxis, ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStop}; pub use self::box_::{ScrollSnapStrictness, ScrollSnapType, ScrollTimelineName}; @@ -708,9 +708,6 @@ impl Parse for PositiveInteger { } } -/// A specified positive `` value or `none`. -pub type PositiveIntegerOrNone = Either; - /// The specified value of a grid `` pub type TrackBreadth = GenericTrackBreadth;