diff options
52 files changed, 649 insertions, 1391 deletions
diff --git a/components/servo_arc/lib.rs b/components/servo_arc/lib.rs index aa79140e044..53c7d7aaa31 100644 --- a/components/servo_arc/lib.rs +++ b/components/servo_arc/lib.rs @@ -182,7 +182,7 @@ impl<T> Arc<T> { // FIXME(emilio): Would be so amazing to have // std::intrinsics::type_name() around, so that we could also report // a real size. - NS_LogCtor(ptr as *const _, b"ServoArc\0".as_ptr() as *const _, 8); + NS_LogCtor(ptr as *mut _, b"ServoArc\0".as_ptr() as *const _, 8); } unsafe { @@ -314,11 +314,7 @@ impl<T: ?Sized> Arc<T> { fn record_drop(&self) { #[cfg(feature = "gecko_refcount_logging")] unsafe { - NS_LogDtor( - self.ptr() as *const _, - b"ServoArc\0".as_ptr() as *const _, - 8, - ); + NS_LogDtor(self.ptr() as *mut _, b"ServoArc\0".as_ptr() as *const _, 8); } } @@ -355,12 +351,12 @@ impl<T: ?Sized> Arc<T> { #[cfg(feature = "gecko_refcount_logging")] extern "C" { fn NS_LogCtor( - aPtr: *const std::os::raw::c_void, + aPtr: *mut std::os::raw::c_void, aTypeName: *const std::os::raw::c_char, aSize: u32, ); fn NS_LogDtor( - aPtr: *const std::os::raw::c_void, + aPtr: *mut std::os::raw::c_void, aTypeName: *const std::os::raw::c_char, aSize: u32, ); @@ -762,7 +758,7 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> { if !is_static { // FIXME(emilio): Would be so amazing to have // std::intrinsics::type_name() around. - NS_LogCtor(ptr as *const _, b"ServoArc\0".as_ptr() as *const _, 8) + NS_LogCtor(ptr as *mut _, b"ServoArc\0".as_ptr() as *const _, 8) } } diff --git a/components/style/font_face.rs b/components/style/font_face.rs index c8e7e65785b..50814c5f5e8 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -416,13 +416,13 @@ macro_rules! is_descriptor_enabled { ("font-display") => { unsafe { use crate::gecko_bindings::structs::mozilla; - mozilla::StaticPrefs_sVarCache_layout_css_font_display_enabled + mozilla::StaticPrefs::sVarCache_layout_css_font_display_enabled } }; ("font-variation-settings") => { unsafe { use crate::gecko_bindings::structs::mozilla; - mozilla::StaticPrefs_sVarCache_layout_css_font_variations_enabled != 0 + mozilla::StaticPrefs::sVarCache_layout_css_font_variations_enabled != 0 } }; ($name:tt) => { diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index bf1b93422f0..5b777e89033 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -10,57 +10,15 @@ #![allow(unsafe_code)] -use crate::gecko::values::GeckoStyleCoordConvertible; use crate::gecko_bindings::bindings; -use crate::gecko_bindings::structs::{self, nsStyleCoord_CalcValue, Matrix4x4Components}; +use crate::gecko_bindings::structs::{self, Matrix4x4Components}; use crate::gecko_bindings::structs::{nsStyleImage, nsresult}; -use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue}; use crate::stylesheets::RulesMutateError; use crate::values::computed::transform::Matrix3D; use crate::values::computed::url::ComputedImageUrl; -use crate::values::computed::{Angle, Gradient, Image}; -use crate::values::computed::{Integer, LengthPercentage}; -use crate::values::computed::{Length, Percentage, TextAlign}; -use crate::values::generics::grid::{TrackListValue, TrackSize}; +use crate::values::computed::{Gradient, Image, TextAlign}; use crate::values::generics::image::GenericImage; use crate::values::generics::rect::Rect; -use crate::Zero; -use app_units::Au; -use style_traits::values::specified::AllowedNumericType; - -impl From<LengthPercentage> for nsStyleCoord_CalcValue { - fn from(other: LengthPercentage) -> nsStyleCoord_CalcValue { - debug_assert!( - other.was_calc || !other.has_percentage || other.unclamped_length() == Length::zero() - ); - nsStyleCoord_CalcValue { - mLength: other.unclamped_length().to_i32_au(), - mPercent: other.percentage(), - mHasPercent: other.has_percentage, - } - } -} - -impl From<nsStyleCoord_CalcValue> for LengthPercentage { - fn from(other: nsStyleCoord_CalcValue) -> LengthPercentage { - let percentage = if other.mHasPercent { - Some(Percentage(other.mPercent)) - } else { - None - }; - Self::with_clamping_mode( - Au(other.mLength).into(), - percentage, - AllowedNumericType::All, - /* was_calc = */ true, - ) - } -} -impl From<Angle> for CoordDataValue { - fn from(reference: Angle) -> Self { - CoordDataValue::Degree(reference.degrees()) - } -} impl nsStyleImage { /// Set a given Servo `Image` value into this `nsStyleImage`. @@ -77,18 +35,12 @@ impl nsStyleImage { // Set CropRect let ref mut rect = *self.mCropRect.mPtr; - image_rect - .top - .to_gecko_style_coord(&mut rect.data_at_mut(0)); - image_rect - .right - .to_gecko_style_coord(&mut rect.data_at_mut(1)); - image_rect - .bottom - .to_gecko_style_coord(&mut rect.data_at_mut(2)); - image_rect - .left - .to_gecko_style_coord(&mut rect.data_at_mut(3)); + *rect = Rect( + image_rect.top, + image_rect.right, + image_rect.bottom, + image_rect.left, + ); } }, GenericImage::Element(ref element) => unsafe { @@ -106,7 +58,7 @@ impl nsStyleImage { /// Converts into Image. pub unsafe fn into_image(self: &nsStyleImage) -> Option<Image> { use crate::gecko_bindings::structs::nsStyleImageType; - use crate::values::computed::{MozImageRect, NumberOrPercentage}; + use crate::values::computed::MozImageRect; match self.mType { nsStyleImageType::eStyleImageType_Null => None, @@ -115,30 +67,14 @@ impl nsStyleImage { if self.mCropRect.mPtr.is_null() { Some(GenericImage::Url(url)) } else { - let ref rect = *self.mCropRect.mPtr; - match ( - NumberOrPercentage::from_gecko_style_coord(&rect.data_at(0)), - NumberOrPercentage::from_gecko_style_coord(&rect.data_at(1)), - NumberOrPercentage::from_gecko_style_coord(&rect.data_at(2)), - NumberOrPercentage::from_gecko_style_coord(&rect.data_at(3)), - ) { - (Some(top), Some(right), Some(bottom), Some(left)) => { - Some(GenericImage::Rect(Box::new(MozImageRect { - url, - top, - right, - bottom, - left, - }))) - }, - _ => { - debug_assert!( - false, - "mCropRect could not convert to NumberOrPercentage" - ); - None - }, - } + let rect = &*self.mCropRect.mPtr; + Some(GenericImage::Rect(Box::new(MozImageRect { + url, + top: rect.0, + right: rect.1, + bottom: rect.2, + left: rect.3, + }))) } }, nsStyleImageType::eStyleImageType_Gradient => { @@ -331,98 +267,6 @@ impl From<RulesMutateError> for nsresult { } } -impl TrackSize<LengthPercentage> { - /// Return TrackSize from given two nsStyleCoord - pub fn from_gecko_style_coords<T: CoordData>(gecko_min: &T, gecko_max: &T) -> Self { - use crate::gecko_bindings::structs::root::nsStyleUnit; - use crate::values::generics::grid::TrackBreadth; - - if gecko_min.unit() == nsStyleUnit::eStyleUnit_None { - debug_assert!( - gecko_max.unit() == nsStyleUnit::eStyleUnit_Coord || - gecko_max.unit() == nsStyleUnit::eStyleUnit_Percent || - gecko_max.unit() == nsStyleUnit::eStyleUnit_Calc - ); - return TrackSize::FitContent( - LengthPercentage::from_gecko_style_coord(gecko_max) - .expect("gecko_max could not convert to LengthPercentage"), - ); - } - - let min = TrackBreadth::from_gecko_style_coord(gecko_min) - .expect("gecko_min could not convert to TrackBreadth"); - let max = TrackBreadth::from_gecko_style_coord(gecko_max) - .expect("gecko_max could not convert to TrackBreadth"); - if min == max { - TrackSize::Breadth(max) - } else { - TrackSize::Minmax(min, max) - } - } - - /// Save TrackSize to given gecko fields. - pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) { - match *self { - TrackSize::FitContent(ref lop) => { - // Gecko sets min value to None and max value to the actual value in fit-content - // https://searchfox.org/mozilla-central/rev/c05d9d61188d32b8/layout/style/nsRuleNode.cpp#7910 - gecko_min.set_value(CoordDataValue::None); - lop.to_gecko_style_coord(gecko_max); - }, - TrackSize::Breadth(ref breadth) => { - // Set the value to both fields if there's one breadth value - // https://searchfox.org/mozilla-central/rev/c05d9d61188d32b8/layout/style/nsRuleNode.cpp#7919 - breadth.to_gecko_style_coord(gecko_min); - breadth.to_gecko_style_coord(gecko_max); - }, - TrackSize::Minmax(ref min, ref max) => { - min.to_gecko_style_coord(gecko_min); - max.to_gecko_style_coord(gecko_max); - }, - } - } -} - -impl TrackListValue<LengthPercentage, Integer> { - /// Return TrackSize from given two nsStyleCoord - pub fn from_gecko_style_coords<T: CoordData>(gecko_min: &T, gecko_max: &T) -> Self { - TrackListValue::TrackSize(TrackSize::from_gecko_style_coords(gecko_min, gecko_max)) - } - - /// Save TrackSize to given gecko fields. - pub fn to_gecko_style_coords<T: CoordDataMut>(&self, gecko_min: &mut T, gecko_max: &mut T) { - match *self { - TrackListValue::TrackSize(ref size) => size.to_gecko_style_coords(gecko_min, gecko_max), - _ => unreachable!("Should only transform from track-size computed values"), - } - } -} - -impl<T> Rect<T> -where - T: GeckoStyleCoordConvertible, -{ - /// Convert this generic Rect to given Gecko fields. - pub fn to_gecko_rect(&self, sides: &mut crate::gecko_bindings::structs::nsStyleSides) { - self.0.to_gecko_style_coord(&mut sides.data_at_mut(0)); - self.1.to_gecko_style_coord(&mut sides.data_at_mut(1)); - self.2.to_gecko_style_coord(&mut sides.data_at_mut(2)); - self.3.to_gecko_style_coord(&mut sides.data_at_mut(3)); - } - - /// Convert from given Gecko data to generic Rect. - pub fn from_gecko_rect( - sides: &crate::gecko_bindings::structs::nsStyleSides, - ) -> Option<crate::values::generics::rect::Rect<T>> { - Some(Rect::new( - T::from_gecko_style_coord(&sides.data_at(0)).expect("coord[0] cound not convert"), - T::from_gecko_style_coord(&sides.data_at(1)).expect("coord[1] cound not convert"), - T::from_gecko_style_coord(&sides.data_at(2)).expect("coord[2] cound not convert"), - T::from_gecko_style_coord(&sides.data_at(3)).expect("coord[3] cound not convert"), - )) - } -} - impl TextAlign { /// Obtain a specified value from a Gecko keyword value /// diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 4c04d9573e5..459d58121ac 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -271,7 +271,7 @@ impl Device { return true; } let document_color_use = - unsafe { structs::StaticPrefs_sVarCache_browser_display_document_color_use }; + unsafe { structs::StaticPrefs::sVarCache_browser_display_document_color_use }; let prefs = self.pref_sheet_prefs(); match document_color_use { 1 => true, diff --git a/components/style/gecko/pseudo_element.rs b/components/style/gecko/pseudo_element.rs index dffd5acf086..501611830ff 100644 --- a/components/style/gecko/pseudo_element.rs +++ b/components/style/gecko/pseudo_element.rs @@ -182,12 +182,18 @@ impl PseudoElement { /// Property flag that properties must have to apply to this pseudo-element. #[inline] pub fn property_restriction(&self) -> Option<PropertyFlags> { - match *self { - PseudoElement::FirstLetter => Some(PropertyFlags::APPLIES_TO_FIRST_LETTER), - PseudoElement::FirstLine => Some(PropertyFlags::APPLIES_TO_FIRST_LINE), - PseudoElement::Placeholder => Some(PropertyFlags::APPLIES_TO_PLACEHOLDER), - _ => None, - } + Some(match *self { + PseudoElement::FirstLetter => PropertyFlags::APPLIES_TO_FIRST_LETTER, + PseudoElement::FirstLine => PropertyFlags::APPLIES_TO_FIRST_LINE, + PseudoElement::Placeholder => PropertyFlags::APPLIES_TO_PLACEHOLDER, + PseudoElement::Cue => PropertyFlags::APPLIES_TO_CUE, + PseudoElement::Marker + if unsafe { structs::StaticPrefs::sVarCache_layout_css_marker_restricted } => + { + PropertyFlags::APPLIES_TO_MARKER + }, + _ => return None, + }) } /// Whether this pseudo-element should actually exist if it has diff --git a/components/style/gecko/pseudo_element_definition.mako.rs b/components/style/gecko/pseudo_element_definition.mako.rs index a752d84c481..562b4c18444 100644 --- a/components/style/gecko/pseudo_element_definition.mako.rs +++ b/components/style/gecko/pseudo_element_definition.mako.rs @@ -112,7 +112,7 @@ impl PseudoElement { % for pseudo in PSEUDOS: ${pseudo_element_variant(pseudo)} => % if pseudo.is_tree_pseudo_element(): - if unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_tree_pseudos_content_enabled } { + if unsafe { structs::StaticPrefs::sVarCache_layout_css_xul_tree_pseudos_content_enabled } { 0 } else { structs::CSS_PSEUDO_ELEMENT_ENABLED_IN_UA_SHEETS_AND_CHROME @@ -210,7 +210,7 @@ impl PseudoElement { return PseudoElement::tree_pseudo_element(name, Box::new([])) } if unsafe { - structs::StaticPrefs_sVarCache_layout_css_unknown_webkit_pseudo_element + structs::StaticPrefs::sVarCache_layout_css_unknown_webkit_pseudo_element } { const WEBKIT_PREFIX: &str = "-webkit-"; if starts_with_ignore_ascii_case(name, WEBKIT_PREFIX) { diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index fc27e1a8610..1da352249d4 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -175,7 +175,7 @@ impl NonTSPseudoClass { // For pseudo-classes with pref, the availability in content // depends on the pref. NonTSPseudoClass::Fullscreen => unsafe { - mozilla::StaticPrefs_sVarCache_full_screen_api_unprefix_enabled + mozilla::StaticPrefs::sVarCache_full_screen_api_unprefix_enabled }, // Otherwise, a pseudo-class is enabled in content when it // doesn't have any enabled flag. @@ -355,7 +355,7 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { #[inline] fn parse_part(&self) -> bool { self.chrome_rules_enabled() || - unsafe { structs::StaticPrefs_sVarCache_layout_css_shadow_parts_enabled } + unsafe { structs::StaticPrefs::sVarCache_layout_css_shadow_parts_enabled } } fn parse_non_ts_pseudo_class( diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 8df85339265..f0c998f8f08 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -7,215 +7,15 @@ //! Different kind of helpers to interact with Gecko values. use crate::counter_style::{Symbol, Symbols}; -use crate::gecko_bindings::structs::StyleGridTrackBreadth; -use crate::gecko_bindings::structs::{nsStyleCoord, CounterStylePtr}; -use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue}; -use crate::values::computed::{Angle, Length, LengthPercentage}; -use crate::values::computed::{Number, NumberOrPercentage, Percentage}; -use crate::values::generics::grid::{TrackBreadth, TrackKeyword}; -use crate::values::generics::length::LengthPercentageOrAuto; -use crate::values::generics::{CounterStyleOrNone, NonNegative}; +use crate::gecko_bindings::structs::CounterStylePtr; +use crate::values::generics::CounterStyleOrNone; use crate::values::Either; -use crate::{Atom, Zero}; +use crate::Atom; use app_units::Au; use cssparser::RGBA; use nsstring::{nsACString, nsCStr}; use std::cmp::max; -/// A trait that defines an interface to convert from and to `nsStyleCoord`s. -/// -/// TODO(emilio): Almost everything that is in this file should be somehow -/// switched to cbindgen. -pub trait GeckoStyleCoordConvertible: Sized { - /// Convert this to a `nsStyleCoord`. - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T); - /// Given a `nsStyleCoord`, try to get a value of this type.. - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self>; -} - -impl nsStyleCoord { - #[inline] - /// Set this `nsStyleCoord` value to `val`. - pub fn set<T: GeckoStyleCoordConvertible>(&mut self, val: T) { - val.to_gecko_style_coord(self); - } -} - -impl<Inner> GeckoStyleCoordConvertible for NonNegative<Inner> -where - Inner: GeckoStyleCoordConvertible, -{ - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - self.0.to_gecko_style_coord(coord) - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - Some(NonNegative(Inner::from_gecko_style_coord(coord)?)) - } -} - -impl GeckoStyleCoordConvertible for Number { - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - coord.set_value(CoordDataValue::Factor(*self)); - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - match coord.as_value() { - CoordDataValue::Factor(f) => Some(f), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for Percentage { - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - coord.set_value(CoordDataValue::Percent(self.0)); - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - match coord.as_value() { - CoordDataValue::Percent(p) => Some(Percentage(p)), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for NumberOrPercentage { - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - match *self { - NumberOrPercentage::Number(ref n) => n.to_gecko_style_coord(coord), - NumberOrPercentage::Percentage(ref p) => p.to_gecko_style_coord(coord), - } - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - match coord.as_value() { - CoordDataValue::Factor(f) => Some(NumberOrPercentage::Number(f)), - CoordDataValue::Percent(p) => Some(NumberOrPercentage::Percentage(Percentage(p))), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for LengthPercentage { - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - if self.was_calc { - return coord.set_value(CoordDataValue::Calc((*self).into())); - } - debug_assert!(!self.has_percentage || self.unclamped_length() == Length::zero()); - if self.has_percentage { - return coord.set_value(CoordDataValue::Percent(self.percentage())); - } - coord.set_value(CoordDataValue::Coord(self.unclamped_length().to_i32_au())) - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - match coord.as_value() { - CoordDataValue::Coord(coord) => Some(LengthPercentage::new(Au(coord).into(), None)), - CoordDataValue::Percent(p) => { - Some(LengthPercentage::new(Au(0).into(), Some(Percentage(p)))) - }, - CoordDataValue::Calc(calc) => Some(calc.into()), - _ => None, - } - } -} - -impl GeckoStyleCoordConvertible for Length { - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - coord.set_value(CoordDataValue::Coord(self.to_i32_au())); - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - match coord.as_value() { - CoordDataValue::Coord(coord) => Some(Au(coord).into()), - _ => None, - } - } -} - -impl<LengthPercentage> GeckoStyleCoordConvertible for LengthPercentageOrAuto<LengthPercentage> -where - LengthPercentage: GeckoStyleCoordConvertible, -{ - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - match *self { - LengthPercentageOrAuto::Auto => coord.set_value(CoordDataValue::Auto), - LengthPercentageOrAuto::LengthPercentage(ref lp) => lp.to_gecko_style_coord(coord), - } - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - match coord.as_value() { - CoordDataValue::Auto => Some(LengthPercentageOrAuto::Auto), - _ => LengthPercentage::from_gecko_style_coord(coord) - .map(LengthPercentageOrAuto::LengthPercentage), - } - } -} - -impl<L: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for TrackBreadth<L> { - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - match *self { - TrackBreadth::Breadth(ref lp) => lp.to_gecko_style_coord(coord), - TrackBreadth::Fr(fr) => coord.set_value(CoordDataValue::FlexFraction(fr)), - TrackBreadth::Keyword(TrackKeyword::Auto) => coord.set_value(CoordDataValue::Auto), - TrackBreadth::Keyword(TrackKeyword::MinContent) => coord.set_value( - CoordDataValue::Enumerated(StyleGridTrackBreadth::MinContent as u32), - ), - TrackBreadth::Keyword(TrackKeyword::MaxContent) => coord.set_value( - CoordDataValue::Enumerated(StyleGridTrackBreadth::MaxContent as u32), - ), - } - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - L::from_gecko_style_coord(coord) - .map(TrackBreadth::Breadth) - .or_else(|| match coord.as_value() { - CoordDataValue::Enumerated(v) => { - if v == StyleGridTrackBreadth::MinContent as u32 { - Some(TrackBreadth::Keyword(TrackKeyword::MinContent)) - } else if v == StyleGridTrackBreadth::MaxContent as u32 { - Some(TrackBreadth::Keyword(TrackKeyword::MaxContent)) - } else { - None - } - }, - CoordDataValue::FlexFraction(fr) => Some(TrackBreadth::Fr(fr)), - CoordDataValue::Auto => Some(TrackBreadth::Keyword(TrackKeyword::Auto)), - _ => L::from_gecko_style_coord(coord).map(TrackBreadth::Breadth), - }) - } -} - -impl<T: GeckoStyleCoordConvertible> GeckoStyleCoordConvertible for Option<T> { - fn to_gecko_style_coord<U: CoordDataMut>(&self, coord: &mut U) { - if let Some(ref me) = *self { - me.to_gecko_style_coord(coord); - } else { - coord.set_value(CoordDataValue::None); - } - } - - fn from_gecko_style_coord<U: CoordData>(coord: &U) -> Option<Self> { - Some(T::from_gecko_style_coord(coord)) - } -} - -impl GeckoStyleCoordConvertible for Angle { - fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) { - coord.set_value(CoordDataValue::from(*self)); - } - - fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> { - match coord.as_value() { - CoordDataValue::Degree(val) => Some(Angle::from_degrees(val)), - _ => None, - } - } -} - /// Convert a given RGBA value to `nscolor`. pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 { ((rgba.alpha as u32) << 24) | diff --git a/components/style/gecko_bindings/sugar/mod.rs b/components/style/gecko_bindings/sugar/mod.rs index 338236c175a..00faf63ba66 100644 --- a/components/style/gecko_bindings/sugar/mod.rs +++ b/components/style/gecko_bindings/sugar/mod.rs @@ -7,7 +7,6 @@ mod ns_com_ptr; mod ns_compatibility; mod ns_style_auto_array; -pub mod ns_style_coord; mod ns_t_array; pub mod origin_flags; pub mod ownership; diff --git a/components/style/gecko_bindings/sugar/ns_style_coord.rs b/components/style/gecko_bindings/sugar/ns_style_coord.rs deleted file mode 100644 index 7c6612f35ef..00000000000 --- a/components/style/gecko_bindings/sugar/ns_style_coord.rs +++ /dev/null @@ -1,369 +0,0 @@ -/* This Source Code Form is subject to the terms of the Mozilla Public - * License, v. 2.0. If a copy of the MPL was not distributed with this - * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ - -//! Rust helpers for Gecko's `nsStyleCoord`. - -use crate::gecko_bindings::bindings; -use crate::gecko_bindings::structs::nsStyleSides; -use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue}; -use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord}; -use std::mem; - -impl nsStyleCoord { - #[inline] - /// Get a `null` nsStyleCoord. - pub fn null() -> Self { - // Can't construct directly because it has private fields - let mut coord: Self = unsafe { mem::zeroed() }; - coord.leaky_set_null(); - coord - } -} - -unsafe impl CoordData for nsStyleCoord { - #[inline] - fn unit(&self) -> nsStyleUnit { - unsafe { *self.get_mUnit() } - } - #[inline] - fn union(&self) -> nsStyleUnion { - unsafe { *self.get_mValue() } - } -} - -unsafe impl CoordDataMut for nsStyleCoord { - unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) { - let unit = self.get_mUnit_mut() as *mut _; - let value = self.get_mValue_mut() as *mut _; - (&mut *unit, &mut *value) - } -} - -impl nsStyleCoord_CalcValue { - /// Create an "empty" CalcValue (whose value is `0`). - pub fn new() -> Self { - nsStyleCoord_CalcValue { - mLength: 0, - mPercent: 0.0, - mHasPercent: false, - } - } -} - -impl PartialEq for nsStyleCoord_CalcValue { - fn eq(&self, other: &Self) -> bool { - self.mLength == other.mLength && - self.mPercent == other.mPercent && - self.mHasPercent == other.mHasPercent - } -} - -impl nsStyleSides { - /// Immutably get the `nsStyleCoord`-like object representing the side at - /// index `index`. - #[inline] - pub fn data_at(&self, index: usize) -> SidesData { - SidesData { - sides: self, - index: index, - } - } - - /// Mutably get the `nsStyleCoord`-like object representing the side at - /// index `index`. - #[inline] - pub fn data_at_mut(&mut self, index: usize) -> SidesDataMut { - SidesDataMut { - sides: self, - index: index, - } - } -} - -/// A `nsStyleCoord`-like object on top of an immutable reference to -/// `nsStyleSides`. -pub struct SidesData<'a> { - sides: &'a nsStyleSides, - index: usize, -} - -/// A `nsStyleCoord`-like object on top of an mutable reference to -/// `nsStyleSides`. -pub struct SidesDataMut<'a> { - sides: &'a mut nsStyleSides, - index: usize, -} - -unsafe impl<'a> CoordData for SidesData<'a> { - #[inline] - fn unit(&self) -> nsStyleUnit { - unsafe { self.sides.get_mUnits()[self.index] } - } - #[inline] - fn union(&self) -> nsStyleUnion { - unsafe { self.sides.get_mValues()[self.index] } - } -} -unsafe impl<'a> CoordData for SidesDataMut<'a> { - #[inline] - fn unit(&self) -> nsStyleUnit { - unsafe { self.sides.get_mUnits()[self.index] } - } - #[inline] - fn union(&self) -> nsStyleUnion { - unsafe { self.sides.get_mValues()[self.index] } - } -} -unsafe impl<'a> CoordDataMut for SidesDataMut<'a> { - unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) { - let unit = &mut self.sides.get_mUnits_mut()[self.index] as *mut _; - let value = &mut self.sides.get_mValues_mut()[self.index] as *mut _; - (&mut *unit, &mut *value) - } -} - -/// Enum representing the tagged union that is CoordData. -/// -/// In release mode this should never actually exist in the code, and will be -/// optimized out by threading matches and inlining. -#[derive(Clone, Copy, Debug, PartialEq)] -pub enum CoordDataValue { - /// eStyleUnit_Null - Null, - /// eStyleUnit_Normal - Normal, - /// eStyleUnit_Auto - Auto, - /// eStyleUnit_None - None, - /// eStyleUnit_Percent - Percent(f32), - /// eStyleUnit_Factor - Factor(f32), - /// eStyleUnit_Degree - Degree(f32), - /// eStyleUnit_FlexFraction - FlexFraction(f32), - /// eStyleUnit_Coord - Coord(nscoord), - /// eStyleUnit_Integer - Integer(i32), - /// eStyleUnit_Enumerated - Enumerated(u32), - /// eStyleUnit_Calc - Calc(nsStyleCoord_CalcValue), -} - -/// A trait to abstract on top of a mutable `nsStyleCoord`-like object. -pub unsafe trait CoordDataMut: CoordData { - /// Get mutably the unit and the union. - /// - /// This is unsafe since it's possible to modify the unit without changing - /// the union. - /// - /// NB: This can't be two methods since we can't mutably borrow twice - unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion); - - /// Clean up any resources used by the union. - /// - /// Currently, this only happens if the nsStyleUnit is a Calc. - #[inline] - fn reset(&mut self) { - unsafe { - if self.unit() == nsStyleUnit::eStyleUnit_Calc { - let (unit, union) = self.values_mut(); - bindings::Gecko_ResetStyleCoord(unit, union); - } - } - } - - #[inline] - /// Copies the unit and value from another `CoordData` type. - fn copy_from<T: CoordData>(&mut self, other: &T) { - unsafe { - self.reset(); - self.copy_from_unchecked(other); - self.addref_if_calc(); - } - } - - #[inline] - /// Moves the unit and value from another `CoordData` type. - fn move_from<T: CoordData>(&mut self, other: T) { - unsafe { - self.reset(); - self.copy_from_unchecked(&other); - } - } - - #[inline] - /// Copies the unit and value from another `CoordData` type without checking - /// the type of the value (so refcounted values like calc may leak). - unsafe fn copy_from_unchecked<T: CoordData>(&mut self, other: &T) { - let (unit, union) = self.values_mut(); - *unit = other.unit(); - *union = other.union(); - } - - /// Useful for initializing uninits, given that `set_value` may segfault on - /// uninits. - fn leaky_set_null(&mut self) { - use crate::gecko_bindings::structs::nsStyleUnit::*; - unsafe { - let (unit, union) = self.values_mut(); - *unit = eStyleUnit_Null; - *union.mInt.as_mut() = 0; - } - } - - #[inline(always)] - /// Sets the inner value. - fn set_value(&mut self, value: CoordDataValue) { - use self::CoordDataValue::*; - use crate::gecko_bindings::structs::nsStyleUnit::*; - self.reset(); - unsafe { - let (unit, union) = self.values_mut(); - match value { - Null => { - *unit = eStyleUnit_Null; - *union.mInt.as_mut() = 0; - }, - Normal => { - *unit = eStyleUnit_Normal; - *union.mInt.as_mut() = 0; - }, - Auto => { - *unit = eStyleUnit_Auto; - *union.mInt.as_mut() = 0; - }, - None => { - *unit = eStyleUnit_None; - *union.mInt.as_mut() = 0; - }, - Percent(f) => { - *unit = eStyleUnit_Percent; - *union.mFloat.as_mut() = f; - }, - Factor(f) => { - *unit = eStyleUnit_Factor; - *union.mFloat.as_mut() = f; - }, - Degree(f) => { - *unit = eStyleUnit_Degree; - *union.mFloat.as_mut() = f; - }, - FlexFraction(f) => { - *unit = eStyleUnit_FlexFraction; - *union.mFloat.as_mut() = f; - }, - Coord(coord) => { - *unit = eStyleUnit_Coord; - *union.mInt.as_mut() = coord; - }, - Integer(i) => { - *unit = eStyleUnit_Integer; - *union.mInt.as_mut() = i; - }, - Enumerated(i) => { - *unit = eStyleUnit_Enumerated; - *union.mInt.as_mut() = i as i32; - }, - Calc(calc) => { - // Gecko_SetStyleCoordCalcValue changes the unit internally - bindings::Gecko_SetStyleCoordCalcValue(unit, union, calc); - }, - } - } - } - - #[inline] - /// Gets the `Calc` value mutably, asserts in debug builds if the unit is - /// not `Calc`. - unsafe fn as_calc_mut(&mut self) -> &mut nsStyleCoord_Calc { - debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc); - &mut *(*self.union().mPointer.as_mut() as *mut nsStyleCoord_Calc) - } - - #[inline] - /// Does what it promises, if the unit is `calc`, it bumps the reference - /// count _of the calc expression_. - fn addref_if_calc(&mut self) { - unsafe { - if self.unit() == nsStyleUnit::eStyleUnit_Calc { - bindings::Gecko_AddRefCalcArbitraryThread(self.as_calc_mut()); - } - } - } -} -/// A trait to abstract on top of a `nsStyleCoord`-like object. -pub unsafe trait CoordData { - /// Get the unit of this object. - fn unit(&self) -> nsStyleUnit; - /// Get the `nsStyleUnion` for this object. - fn union(&self) -> nsStyleUnion; - - #[inline(always)] - /// Get the appropriate value for this object. - fn as_value(&self) -> CoordDataValue { - use self::CoordDataValue::*; - use crate::gecko_bindings::structs::nsStyleUnit::*; - unsafe { - match self.unit() { - eStyleUnit_Null => Null, - eStyleUnit_Normal => Normal, - eStyleUnit_Auto => Auto, - eStyleUnit_None => None, - eStyleUnit_Percent => Percent(self.get_float()), - eStyleUnit_Factor => Factor(self.get_float()), - eStyleUnit_Degree => Degree(self.get_float()), - eStyleUnit_FlexFraction => FlexFraction(self.get_float()), - eStyleUnit_Coord => Coord(self.get_integer()), - eStyleUnit_Integer => Integer(self.get_integer()), - eStyleUnit_Enumerated => Enumerated(self.get_integer() as u32), - eStyleUnit_Calc => Calc(self.get_calc_value()), - } - } - } - - #[inline] - /// Pretend inner value is a float; obtain it. - unsafe fn get_float(&self) -> f32 { - use crate::gecko_bindings::structs::nsStyleUnit::*; - debug_assert!( - self.unit() == eStyleUnit_Percent || - self.unit() == eStyleUnit_Factor || - self.unit() == eStyleUnit_Degree || - self.unit() == eStyleUnit_FlexFraction - ); - *self.union().mFloat.as_ref() - } - - #[inline] - /// Pretend inner value is an int; obtain it. - unsafe fn get_integer(&self) -> i32 { - use crate::gecko_bindings::structs::nsStyleUnit::*; - debug_assert!( - self.unit() == eStyleUnit_Coord || - self.unit() == eStyleUnit_Integer || - self.unit() == eStyleUnit_Enumerated - ); - *self.union().mInt.as_ref() - } - - #[inline] - /// Pretend inner value is a calc; obtain it. - /// Ensure that the unit is Calc before calling this. - unsafe fn get_calc_value(&self) -> nsStyleCoord_CalcValue { - debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc); - (*self.as_calc())._base - } - - #[inline] - /// Pretend the inner value is a calc expression, and obtain it. - unsafe fn as_calc(&self) -> &nsStyleCoord_Calc { - debug_assert_eq!(self.unit(), nsStyleUnit::eStyleUnit_Calc); - &*(*self.union().mPointer.as_ref() as *const nsStyleCoord_Calc) - } -} diff --git a/components/style/matching.rs b/components/style/matching.rs index b4b472ea1c3..dfc5685098c 100644 --- a/components/style/matching.rs +++ b/components/style/matching.rs @@ -503,30 +503,32 @@ trait PrivateMatchMethods: TElement { let old_display = old_values.get_box().clone_display(); let new_display = new_values.get_box().clone_display(); - // If we used to be a display: none element, and no longer are, - // our children need to be restyled because they're unstyled. - // - // NOTE(emilio): Gecko has the special-case of -moz-binding, but - // that gets handled on the frame constructor when processing - // the reframe, so no need to handle that here. - if old_display == Display::None && old_display != new_display { - return ChildCascadeRequirement::MustCascadeChildren; - } - - // Blockification of children may depend on our display value, - // so we need to actually do the recascade. We could potentially - // do better, but it doesn't seem worth it. - if old_display.is_item_container() != new_display.is_item_container() { - return ChildCascadeRequirement::MustCascadeChildren; - } - - // Line break suppression may also be affected if the display - // type changes from ruby to non-ruby. - #[cfg(feature = "gecko")] - { - if old_display.is_ruby_type() != new_display.is_ruby_type() { + if old_display != new_display { + // If we used to be a display: none element, and no longer are, our + // children need to be restyled because they're unstyled. + if old_display == Display::None { return ChildCascadeRequirement::MustCascadeChildren; } + // Blockification of children may depend on our display value, + // so we need to actually do the recascade. We could potentially + // do better, but it doesn't seem worth it. + if old_display.is_item_container() != new_display.is_item_container() { + return ChildCascadeRequirement::MustCascadeChildren; + } + // We may also need to blockify and un-blockify descendants if our + // display goes from / to display: contents, since the "layout + // parent style" changes. + if old_display.is_contents() || new_display.is_contents() { + return ChildCascadeRequirement::MustCascadeChildren; + } + // Line break suppression may also be affected if the display + // type changes from ruby to non-ruby. + #[cfg(feature = "gecko")] + { + if old_display.is_ruby_type() != new_display.is_ruby_type() { + return ChildCascadeRequirement::MustCascadeChildren; + } + } } // Children with justify-items: auto may depend on our diff --git a/components/style/media_queries/media_feature_expression.rs b/components/style/media_queries/media_feature_expression.rs index 5b5c4f4fad7..310cbd2b8bb 100644 --- a/components/style/media_queries/media_feature_expression.rs +++ b/components/style/media_queries/media_feature_expression.rs @@ -302,7 +302,7 @@ impl MediaFeatureExpression { feature_name = &feature_name[8..]; requirements.insert(ParsingRequirements::WEBKIT_PREFIX); if unsafe { - structs::StaticPrefs_sVarCache_layout_css_prefixes_device_pixel_ratio_webkit + structs::StaticPrefs::sVarCache_layout_css_prefixes_device_pixel_ratio_webkit } { requirements.insert( ParsingRequirements::WEBKIT_DEVICE_PIXEL_RATIO_PREF_ENABLED, diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index af6c563b319..1e362fb1bc4 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -686,7 +686,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { return; } - let use_document_fonts = unsafe { structs::StaticPrefs_sVarCache_browser_display_use_document_fonts != 0 }; + let use_document_fonts = unsafe { structs::StaticPrefs::sVarCache_browser_display_use_document_fonts != 0 }; let builder = &mut self.context.builder; let (default_font_type, prioritize_user_fonts) = { let font = builder.get_font().gecko(); diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 13496104a04..0c9321d004c 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -336,7 +336,9 @@ class Longhand(object): "MozScriptLevel", "MozScriptMinSize", "MozScriptSizeMultiplier", + "TextDecorationSkipInk", "NonNegativeNumber", + "Number", "OffsetRotate", "Opacity", "OutlineStyle", @@ -556,7 +558,7 @@ class PropertiesData(object): longhand = Longhand(self.current_style_struct, name, **kwargs) self.add_prefixed_aliases(longhand) - longhand.alias = list(map(lambda (x, p): Alias(x, longhand, p), longhand.alias)) + longhand.alias = list(map(lambda xp: Alias(xp[0], longhand, xp[1]), longhand.alias)) self.longhand_aliases += longhand.alias self.current_style_struct.longhands.append(longhand) self.longhands.append(longhand) @@ -572,7 +574,7 @@ class PropertiesData(object): sub_properties = [self.longhands_by_name[s] for s in sub_properties] shorthand = Shorthand(name, sub_properties, *args, **kwargs) self.add_prefixed_aliases(shorthand) - shorthand.alias = list(map(lambda (x, p): Alias(x, shorthand, p), shorthand.alias)) + shorthand.alias = list(map(lambda xp: Alias(xp[0], shorthand, xp[1]), shorthand.alias)) self.shorthand_aliases += shorthand.alias self.shorthands.append(shorthand) return shorthand diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index fe0a1935e97..11bd30136d7 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -36,7 +36,6 @@ use crate::gecko_bindings::bindings::Gecko_SetNullImageValue; use crate::gecko_bindings::structs; use crate::gecko_bindings::structs::nsCSSPropertyID; use crate::gecko_bindings::structs::mozilla::PseudoStyleType; -use crate::gecko_bindings::sugar::ns_style_coord::CoordDataMut; use crate::gecko_bindings::sugar::refptr::RefPtr; use crate::gecko::values::round_border_to_device_pixels; use crate::logical_geometry::WritingMode; @@ -524,107 +523,6 @@ def set_gecko_property(ffi_name, expr): } </%def> -<%def name="impl_svg_paint(ident, gecko_ffi_name)"> - #[allow(non_snake_case)] - pub fn set_${ident}(&mut self, mut v: longhands::${ident}::computed_value::T) { - use crate::values::generics::svg::SVGPaintKind; - use self::structs::nsStyleSVGPaintType; - use self::structs::nsStyleSVGFallbackType; - - let ref mut paint = ${get_gecko_property(gecko_ffi_name)}; - unsafe { - bindings::Gecko_nsStyleSVGPaint_Reset(paint); - } - let fallback = v.fallback.take(); - match v.kind { - SVGPaintKind::None => return, - SVGPaintKind::ContextFill => { - paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_ContextFill; - } - SVGPaintKind::ContextStroke => { - paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke; - } - SVGPaintKind::PaintServer(url) => { - unsafe { - bindings::Gecko_nsStyleSVGPaint_SetURLValue( - paint, - &url - ) - } - } - SVGPaintKind::Color(color) => { - paint.mType = nsStyleSVGPaintType::eStyleSVGPaintType_Color; - unsafe { - *paint.mPaint.mColor.as_mut() = color.into(); - } - } - } - - paint.mFallbackType = match fallback { - Some(Either::First(color)) => { - paint.mFallbackColor = color.into(); - nsStyleSVGFallbackType::eStyleSVGFallbackType_Color - }, - Some(Either::Second(_)) => { - nsStyleSVGFallbackType::eStyleSVGFallbackType_None - }, - None => nsStyleSVGFallbackType::eStyleSVGFallbackType_NotSet - }; - } - - #[allow(non_snake_case)] - pub fn copy_${ident}_from(&mut self, other: &Self) { - unsafe { - bindings::Gecko_nsStyleSVGPaint_CopyFrom( - &mut ${get_gecko_property(gecko_ffi_name)}, - & ${get_gecko_property(gecko_ffi_name, "other")} - ); - } - } - - #[allow(non_snake_case)] - pub fn reset_${ident}(&mut self, other: &Self) { - self.copy_${ident}_from(other) - } - - #[allow(non_snake_case)] - pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - use crate::values::generics::svg::{SVGPaint, SVGPaintKind}; - use self::structs::nsStyleSVGPaintType; - use self::structs::nsStyleSVGFallbackType; - let ref paint = ${get_gecko_property(gecko_ffi_name)}; - - let fallback = match paint.mFallbackType { - nsStyleSVGFallbackType::eStyleSVGFallbackType_Color => { - Some(Either::First(paint.mFallbackColor.into())) - }, - nsStyleSVGFallbackType::eStyleSVGFallbackType_None => { - Some(Either::Second(None_)) - }, - nsStyleSVGFallbackType::eStyleSVGFallbackType_NotSet => None, - }; - - let kind = match paint.mType { - nsStyleSVGPaintType::eStyleSVGPaintType_None => SVGPaintKind::None, - nsStyleSVGPaintType::eStyleSVGPaintType_ContextFill => SVGPaintKind::ContextFill, - nsStyleSVGPaintType::eStyleSVGPaintType_ContextStroke => SVGPaintKind::ContextStroke, - nsStyleSVGPaintType::eStyleSVGPaintType_Server => { - SVGPaintKind::PaintServer(unsafe { - paint.mPaint.mPaintServer.as_ref().clone() - }) - } - nsStyleSVGPaintType::eStyleSVGPaintType_Color => { - let col = unsafe { *paint.mPaint.mColor.as_ref() }; - SVGPaintKind::Color(col.into()) - } - }; - SVGPaint { - kind: kind, - fallback: fallback, - } - } -</%def> - <%def name="impl_non_negative_length(ident, gecko_ffi_name, inherit_from=None, round_to_pixels=False)"> #[allow(non_snake_case)] @@ -834,7 +732,6 @@ impl Clone for ${style_struct.gecko_struct_name} { "MozScriptMinSize": impl_absolute_length, "SVGLength": impl_svg_length, "SVGOpacity": impl_svg_opacity, - "SVGPaint": impl_svg_paint, "SVGWidth": impl_svg_length, } @@ -880,15 +777,8 @@ class Side(object): self.ident = name.lower() self.index = index -class GridLine(object): - def __init__(self, name): - self.ident = "grid-" + name.lower() - self.name = self.ident.replace('-', '_') - self.gecko = "m" + to_camel_case(self.ident) - SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)] CORNERS = ["top_left", "top_right", "bottom_right", "bottom_left"] -GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"]) %> #[allow(dead_code)] @@ -1077,12 +967,11 @@ fn static_assert() { % endfor </%self:impl_trait> -<% skip_position_longhands = " ".join(x.ident for x in SIDES + GRID_LINES) %> +<% skip_position_longhands = " ".join(x.ident for x in SIDES) %> <%self:impl_trait style_struct_name="Position" skip_longhands="${skip_position_longhands} order align-content justify-content align-self justify-self align-items justify-items - grid-auto-rows grid-auto-columns grid-auto-flow grid-template-rows grid-template-columns"> % for side in SIDES: @@ -1132,92 +1021,14 @@ fn static_assert() { ${impl_simple_copy('order', 'mOrder')} - % for value in GRID_LINES: - pub fn set_${value.name}(&mut self, v: longhands::${value.name}::computed_value::T) { - use crate::gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine}; - - let line = &mut self.gecko.${value.gecko}; - line.mLineName.set_move(unsafe { - RefPtr::from_addrefed(match v.ident { - Some(i) => i.0, - None => atom!(""), - }.into_addrefed()) - }); - line.mHasSpan = v.is_span; - if let Some(integer) = v.line_num { - // clamping the integer between a range - line.mInteger = cmp::max( - nsStyleGridLine_kMinLine, - cmp::min(integer, nsStyleGridLine_kMaxLine), - ); - } - } - - pub fn copy_${value.name}_from(&mut self, other: &Self) { - self.gecko.${value.gecko}.mHasSpan = other.gecko.${value.gecko}.mHasSpan; - self.gecko.${value.gecko}.mInteger = other.gecko.${value.gecko}.mInteger; - unsafe { - self.gecko.${value.gecko}.mLineName.set(&other.gecko.${value.gecko}.mLineName); - } - } - - pub fn reset_${value.name}(&mut self, other: &Self) { - self.copy_${value.name}_from(other) - } - - pub fn clone_${value.name}(&self) -> longhands::${value.name}::computed_value::T { - use crate::gecko_bindings::structs::{nsStyleGridLine_kMinLine, nsStyleGridLine_kMaxLine}; - - longhands::${value.name}::computed_value::T { - is_span: self.gecko.${value.gecko}.mHasSpan, - ident: { - let name = unsafe { Atom::from_raw(self.gecko.${value.gecko}.mLineName.mRawPtr) }; - if name == atom!("") { - None - } else { - Some(CustomIdent(name)) - } - }, - line_num: - if self.gecko.${value.gecko}.mInteger == 0 { - None - } else { - debug_assert!(nsStyleGridLine_kMinLine <= self.gecko.${value.gecko}.mInteger); - debug_assert!(self.gecko.${value.gecko}.mInteger <= nsStyleGridLine_kMaxLine); - Some(self.gecko.${value.gecko}.mInteger) - }, - } - } - % endfor - % for kind in ["rows", "columns"]: - pub fn set_grid_auto_${kind}(&mut self, v: longhands::grid_auto_${kind}::computed_value::T) { - let gecko = &mut *self.gecko; - v.to_gecko_style_coords(&mut gecko.mGridAuto${kind.title()}Min, - &mut gecko.mGridAuto${kind.title()}Max) - } - - pub fn copy_grid_auto_${kind}_from(&mut self, other: &Self) { - self.gecko.mGridAuto${kind.title()}Min.copy_from(&other.gecko.mGridAuto${kind.title()}Min); - self.gecko.mGridAuto${kind.title()}Max.copy_from(&other.gecko.mGridAuto${kind.title()}Max); - } - - pub fn reset_grid_auto_${kind}(&mut self, other: &Self) { - self.copy_grid_auto_${kind}_from(other) - } - - pub fn clone_grid_auto_${kind}(&self) -> longhands::grid_auto_${kind}::computed_value::T { - crate::values::generics::grid::TrackSize::from_gecko_style_coords(&self.gecko.mGridAuto${kind.title()}Min, - &self.gecko.mGridAuto${kind.title()}Max) - } - 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, nsStyleGridLine_kMaxLine}; + 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}; + use crate::values::generics::grid::{GridTemplateComponent, RepeatCount, TrackListValue, MAX_GRID_LINE}; #[inline] fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray<structs::RefPtr<structs::nsAtom>>) { @@ -1232,7 +1043,7 @@ fn static_assert() { } } - let max_lines = nsStyleGridLine_kMaxLine as usize - 1; // for accounting the final <line-names> + let max_lines = MAX_GRID_LINE as usize - 1; // for accounting the final <line-names> let result = match v { GridTemplateComponent::None => ptr::null_mut(), @@ -1276,20 +1087,21 @@ fn static_assert() { let mut line_names = track.line_names.into_iter(); let mut values_iter = track.values.into_iter(); { - let min_max_iter = value.mMinTrackSizingFunctions.iter_mut() - .zip(value.mMaxTrackSizingFunctions.iter_mut()); - for (i, (gecko_min, gecko_max)) in min_max_iter.enumerate().take(max_lines) { + 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]); - if i == auto_idx { - let track_size = auto_track_size.take() - .expect("expected <track-size> for <auto-track-repeat>"); - track_size.to_gecko_style_coords(gecko_min, gecko_max); - continue - } - - let track_size = values_iter.next().expect("expected <track-size> value"); - track_size.to_gecko_style_coords(gecko_min, gecko_max); + *track_size = if i == auto_idx { + auto_track_size.take().expect("expected <track-size> for <auto-track-repeat>") + } else { + match values_iter.next().expect("expected <track-size> 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") + } + } + }; } } @@ -1344,7 +1156,7 @@ fn static_assert() { 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, TrackSize}; + use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue, TrackRepeat}; let value = match unsafe { ${self_grid}.mPtr.as_ref() } { None => return GridTemplateComponent::None, @@ -1386,13 +1198,8 @@ fn static_assert() { 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.mMinTrackSizingFunctions.len()); - - let min_max_iter = value.mMinTrackSizingFunctions.iter() - .zip(value.mMaxTrackSizingFunctions.iter()); - for (i, (gecko_min, gecko_max)) in min_max_iter.enumerate() { - let track_size = TrackSize::from_gecko_style_coords(gecko_min, gecko_max); - + 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); @@ -1411,11 +1218,11 @@ fn static_assert() { vec.into_boxed_slice() }; - let track_sizes = vec!(track_size); + let track_sizes = vec!(track_size.clone()); auto_repeat = Some(TrackRepeat{count, line_names, track_sizes}); } else { - values.push(TrackListValue::TrackSize(track_size)); + values.push(TrackListValue::TrackSize(track_size.clone())); } } diff --git a/components/style/properties/longhands/background.mako.rs b/components/style/properties/longhands/background.mako.rs index e9e866983c0..cc416bc3af0 100644 --- a/components/style/properties/longhands/background.mako.rs +++ b/components/style/properties/longhands/background.mako.rs @@ -15,7 +15,7 @@ ${helpers.predefined_type( animation_value_type="AnimatedColor", ignored_when_colors_disabled=True, allow_quirks="Yes", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \ + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \ CAN_ANIMATE_ON_COMPOSITOR", )} @@ -28,7 +28,7 @@ ${helpers.predefined_type( vector="True", animation_value_type="discrete", ignored_when_colors_disabled="True", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", )} % for (axis, direction, initial) in [("x", "Horizontal", "left"), ("y", "Vertical", "top")]: @@ -41,7 +41,7 @@ ${helpers.predefined_type( animation_value_type="ComputedValue", vector=True, vector_animation_type="repeatable_list", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", )} % endfor @@ -53,7 +53,7 @@ ${helpers.predefined_type( animation_value_type="discrete", vector=True, spec="https://drafts.csswg.org/css-backgrounds/#the-background-repeat", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", )} ${helpers.single_keyword( @@ -63,7 +63,7 @@ ${helpers.single_keyword( gecko_enum_prefix="StyleImageLayerAttachment", spec="https://drafts.csswg.org/css-backgrounds/#the-background-attachment", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", )} ${helpers.single_keyword( @@ -75,7 +75,7 @@ ${helpers.single_keyword( gecko_inexhaustive=True, spec="https://drafts.csswg.org/css-backgrounds/#the-background-clip", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", )} ${helpers.single_keyword( @@ -86,7 +86,7 @@ ${helpers.single_keyword( gecko_inexhaustive=True, spec="https://drafts.csswg.org/css-backgrounds/#the-background-origin", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER" + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER" )} ${helpers.predefined_type( @@ -98,7 +98,7 @@ ${helpers.predefined_type( vector=True, vector_animation_type="repeatable_list", animation_value_type="BackgroundSizeList", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", extra_prefixes="webkit")} // https://drafts.fxtf.org/compositing/#background-blend-mode @@ -110,5 +110,5 @@ ${helpers.single_keyword( gecko_constant_prefix="NS_STYLE_BLEND", vector=True, products="gecko", animation_value_type="discrete", spec="https://drafts.fxtf.org/compositing/#background-blend-mode", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", )} diff --git a/components/style/properties/longhands/counters.mako.rs b/components/style/properties/longhands/counters.mako.rs index f8971315603..fce23f3a1ea 100644 --- a/components/style/properties/longhands/counters.mako.rs +++ b/components/style/properties/longhands/counters.mako.rs @@ -13,6 +13,7 @@ ${helpers.predefined_type( initial_specified_value="specified::Content::normal()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-content/#propdef-content", + flags="APPLIES_TO_MARKER", servo_restyle_damage="rebuild_and_reflow", )} diff --git a/components/style/properties/longhands/effects.mako.rs b/components/style/properties/longhands/effects.mako.rs index c50a0d18ca6..ac2b92cbe52 100644 --- a/components/style/properties/longhands/effects.mako.rs +++ b/components/style/properties/longhands/effects.mako.rs @@ -12,7 +12,7 @@ ${helpers.predefined_type( "Opacity", "1.0", animation_value_type="ComputedValue", - flags="CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \ + flags="APPLIES_TO_CUE CREATES_STACKING_CONTEXT APPLIES_TO_PLACEHOLDER \ CAN_ANIMATE_ON_COMPOSITOR", spec="https://drafts.csswg.org/css-color/#opacity", servo_restyle_damage = "reflow_out_of_flow", @@ -57,6 +57,22 @@ ${helpers.predefined_type( spec="https://drafts.fxtf.org/filters/#propdef-filter", )} +${helpers.predefined_type( + "backdrop-filter", + "Filter", + None, + vector=True, + simple_vector_bindings=True, + gecko_ffi_name="mBackdropFilters", + separator="Space", + animation_value_type="AnimatedFilterList", + vector_animation_type="with_zero", + flags="CREATES_STACKING_CONTEXT FIXPOS_CB", + gecko_pref="layout.css.backdrop-filter.enabled", + spec="https://drafts.fxtf.org/filter-effects-2/#propdef-backdrop-filter", + products="gecko", +)} + ${helpers.single_keyword( "mix-blend-mode", """normal multiply screen overlay darken lighten color-dodge diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs index 8d84ef34cb3..d65afad693d 100644 --- a/components/style/properties/longhands/font.mako.rs +++ b/components/style/properties/longhands/font.mako.rs @@ -12,7 +12,7 @@ ${helpers.predefined_type( "FontFamily", initial_value="computed::FontFamily::serif()", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-family", servo_restyle_damage="rebuild_and_reflow", )} @@ -23,7 +23,7 @@ ${helpers.predefined_type( initial_value="computed::FontStyle::normal()", initial_specified_value="specified::FontStyle::normal()", animation_value_type="FontStyle", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-style", servo_restyle_damage="rebuild_and_reflow", )} @@ -42,7 +42,7 @@ ${helpers.single_keyword_system( gecko_ffi_name="mFont.variantCaps", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-caps", custom_consts=font_variant_caps_custom_consts, - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", animation_value_type="discrete", servo_restyle_damage="rebuild_and_reflow", )} @@ -53,7 +53,7 @@ ${helpers.predefined_type( initial_value="computed::FontWeight::normal()", initial_specified_value="specified::FontWeight::normal()", animation_value_type="Number", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-weight", servo_restyle_damage="rebuild_and_reflow", )} @@ -65,7 +65,7 @@ ${helpers.predefined_type( initial_specified_value="specified::FontSize::medium()", animation_value_type="NonNegativeLength", allow_quirks="Yes", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-size", servo_restyle_damage="rebuild_and_reflow", )} @@ -77,7 +77,7 @@ ${helpers.predefined_type( initial_value="computed::FontSizeAdjust::none()", initial_specified_value="specified::FontSizeAdjust::none()", animation_value_type="ComputedValue", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust", )} @@ -87,7 +87,7 @@ ${helpers.predefined_type( products="gecko", initial_value="specified::FontSynthesis::get_initial_value()", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-synthesis", )} @@ -97,7 +97,7 @@ ${helpers.predefined_type( initial_value="computed::FontStretch::hundred()", initial_specified_value="specified::FontStretch::normal()", animation_value_type="Percentage", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-stretch", servo_restyle_damage="rebuild_and_reflow", )} @@ -109,7 +109,7 @@ ${helpers.single_keyword_system( gecko_ffi_name="mFont.kerning", gecko_constant_prefix="NS_FONT_KERNING", spec="https://drafts.csswg.org/css-fonts/#propdef-font-kerning", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", animation_value_type="discrete", )} @@ -120,7 +120,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariantAlternates::get_initial_value()", initial_specified_value="specified::FontVariantAlternates::get_initial_specified_value()", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates", )} @@ -131,7 +131,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariantEastAsian::empty()", initial_specified_value="specified::FontVariantEastAsian::empty()", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-east-asian", )} @@ -142,7 +142,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariantLigatures::empty()", initial_specified_value="specified::FontVariantLigatures::empty()", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-ligatures", )} @@ -153,7 +153,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariantNumeric::empty()", initial_specified_value="specified::FontVariantNumeric::empty()", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-numeric", )} @@ -164,7 +164,7 @@ ${helpers.single_keyword_system( gecko_ffi_name="mFont.variantPosition", gecko_constant_prefix="NS_FONT_VARIANT_POSITION", spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-position", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", animation_value_type="discrete", )} @@ -176,7 +176,7 @@ ${helpers.predefined_type( initial_specified_value="specified::FontFeatureSettings::normal()", extra_prefixes="moz:layout.css.prefixes.font-features", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts/#propdef-font-feature-settings", )} @@ -195,7 +195,7 @@ ${helpers.predefined_type( initial_value="computed::FontVariationSettings::normal()", initial_specified_value="specified::FontVariationSettings::normal()", animation_value_type="ComputedValue", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="${variation_spec}", )} @@ -207,7 +207,7 @@ ${helpers.predefined_type( initial_specified_value="specified::FontLanguageOverride::normal()", animation_value_type="discrete", extra_prefixes="moz:layout.css.prefixes.font-features", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://drafts.csswg.org/css-fonts-3/#propdef-font-language-override", )} @@ -219,7 +219,7 @@ ${helpers.single_keyword_system( gecko_ffi_name="mFont.opticalSizing", gecko_constant_prefix="NS_FONT_OPTICAL_SIZING", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", spec="https://www.w3.org/TR/css-fonts-4/#font-optical-sizing-def", )} @@ -412,7 +412,7 @@ ${helpers.predefined_type( is_system_font: true, }, font_size: FontSize { - size: Au(system.size).into(), + size: cx.maybe_zoom_text(Au(system.size).into()), keyword_info: None }, font_weight, @@ -514,7 +514,7 @@ ${helpers.single_keyword( gecko_pref="layout.css.osx-font-smoothing.enabled", products="gecko", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/font-smooth)", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", animation_value_type="discrete", )} diff --git a/components/style/properties/longhands/inherited_box.mako.rs b/components/style/properties/longhands/inherited_box.mako.rs index 0e3799f6c46..94ed265defa 100644 --- a/components/style/properties/longhands/inherited_box.mako.rs +++ b/components/style/properties/longhands/inherited_box.mako.rs @@ -14,6 +14,7 @@ ${helpers.single_keyword( gecko_ffi_name="mVisible", animation_value_type="ComputedValue", spec="https://drafts.csswg.org/css-box/#propdef-visibility", + flags="APPLIES_TO_CUE", )} // CSS Writing Modes Level 3 @@ -37,6 +38,7 @@ ${helpers.single_keyword( animation_value_type="none", spec="https://drafts.csswg.org/css-writing-modes/#propdef-direction", needs_conversion=True, + flags="APPLIES_TO_MARKER", servo_restyle_damage="rebuild_and_reflow", )} diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index fc934d901eb..c81e8392f94 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -11,7 +11,7 @@ ${helpers.predefined_type( "ColorPropertyValue", "::cssparser::RGBA::new(0, 0, 0, 255)", animation_value_type="AnimatedRGBA", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER APPLIES_TO_MARKER", ignored_when_colors_disabled="True", spec="https://drafts.csswg.org/css-color/#color", )} @@ -21,7 +21,7 @@ ${helpers.predefined_type( "LineHeight", "computed::LineHeight::normal()", animation_value_type="LineHeight", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE \ + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE \ APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH", spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height", servo_restyle_damage="reflow" @@ -181,7 +181,7 @@ ${helpers.predefined_type( needs_conversion="True" animation_value_type="discrete" // Only allowed for UA sheets, which set it !important. - flags="APPLIES_TO_PLACEHOLDER" + flags="APPLIES_TO_CUE APPLIES_TO_PLACEHOLDER" spec="https://drafts.csswg.org/css-text/#propdef-white-space" servo_restyle_damage="rebuild_and_reflow" > @@ -229,7 +229,7 @@ ${helpers.predefined_type( animation_value_type="AnimatedTextShadowList", ignored_when_colors_disabled=True, simple_vector_bindings=True, - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property", )} @@ -337,6 +337,7 @@ ${helpers.single_keyword( products="gecko", animation_value_type="discrete", spec="https://drafts.csswg.org/css-ruby/#ruby-position-property", + flags="APPLIES_TO_CUE", )} // CSS Writing Modes Module Level 3 @@ -348,6 +349,7 @@ ${helpers.single_keyword( products="gecko", animation_value_type="discrete", spec="https://drafts.csswg.org/css-writing-modes-3/#text-combine-upright", + flags="APPLIES_TO_CUE APPLIES_TO_MARKER", )} // SVG 1.1: Section 11 - Painting: Filling, Stroking and Marker Symbols @@ -382,3 +384,15 @@ ${helpers.predefined_type( gecko_pref="layout.css.text-underline-offset.enabled", spec="https://drafts.csswg.org/css-text-decor-4/#underline-offset", )} + +// text decoration skip ink +${helpers.predefined_type( + "text-decoration-skip-ink", + "TextDecorationSkipInk", + "computed::TextDecorationSkipInk::Auto", + products="gecko", + needs_context=False, + animation_value_type="discrete", + gecko_pref="layout.css.text-decoration-skip-ink.enabled", + spec="https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-ink-property", +)} diff --git a/components/style/properties/longhands/outline.mako.rs b/components/style/properties/longhands/outline.mako.rs index 8d0d326180b..ec765e631b8 100644 --- a/components/style/properties/longhands/outline.mako.rs +++ b/components/style/properties/longhands/outline.mako.rs @@ -18,6 +18,7 @@ ${helpers.predefined_type( animation_value_type="AnimatedColor", ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-ui/#propdef-outline-color", + flags="APPLIES_TO_CUE", )} ${helpers.predefined_type( @@ -27,6 +28,7 @@ ${helpers.predefined_type( initial_specified_value="specified::OutlineStyle::none()", animation_value_type="discrete", spec="https://drafts.csswg.org/css-ui/#propdef-outline-style", + flags="APPLIES_TO_CUE", )} ${helpers.predefined_type( @@ -37,6 +39,7 @@ ${helpers.predefined_type( computed_type="crate::values::computed::NonNegativeLength", animation_value_type="NonNegativeLength", spec="https://drafts.csswg.org/css-ui/#propdef-outline-width", + flags="APPLIES_TO_CUE", )} // The -moz-outline-radius-* properties are non-standard and not on a standards track. diff --git a/components/style/properties/longhands/position.mako.rs b/components/style/properties/longhands/position.mako.rs index 34216385fed..14fc443a352 100644 --- a/components/style/properties/longhands/position.mako.rs +++ b/components/style/properties/longhands/position.mako.rs @@ -322,7 +322,6 @@ ${helpers.predefined_type( animation_value_type="discrete", spec="https://drafts.csswg.org/css-grid/#propdef-grid-%s-%s" % (kind, range), products="gecko", - boxed=True, )} % endfor @@ -392,3 +391,17 @@ ${helpers.predefined_type( animation_value_type="NonNegativeLengthPercentageOrNormal", servo_restyle_damage="reflow", )} + +// NOTE(emilio): Before exposing this property to content, we probably need to +// change syntax and such, and make it apply to more elements. +// +// For now, it's used only for mapped attributes. +${helpers.predefined_type( + "aspect-ratio", + "Number", + "computed::Number::zero()", + animation_value_type="ComputedValue", + spec="Internal, for now", + enabled_in="", + servo_restyle_damage="reflow", +)} diff --git a/components/style/properties/longhands/text.mako.rs b/components/style/properties/longhands/text.mako.rs index 91412d2ee6e..44adc21766d 100644 --- a/components/style/properties/longhands/text.mako.rs +++ b/components/style/properties/longhands/text.mako.rs @@ -23,6 +23,7 @@ ${helpers.single_keyword( "normal embed isolate bidi-override isolate-override plaintext", animation_value_type="none", spec="https://drafts.csswg.org/css-writing-modes/#propdef-unicode-bidi", + flags="APPLIES_TO_MARKER", servo_restyle_damage="rebuild_and_reflow", )} @@ -32,7 +33,7 @@ ${helpers.predefined_type( "specified::TextDecorationLine::none()", initial_specified_value="specified::TextDecorationLine::none()", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-line", servo_restyle_damage="rebuild_and_reflow", )} @@ -42,7 +43,7 @@ ${helpers.single_keyword( "solid double dotted dashed wavy -moz-none", products="gecko", animation_value_type="discrete", - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-style", )} @@ -54,7 +55,7 @@ ${helpers.predefined_type( products="gecko", animation_value_type="AnimatedColor", ignored_when_colors_disabled=True, - flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", + flags="APPLIES_TO_CUE APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER", spec="https://drafts.csswg.org/css-text-decor/#propdef-text-decoration-color", )} diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index c2b390c89d9..4f07d6feb84 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -939,7 +939,7 @@ impl CSSWideKeyword { bitflags! { /// A set of flags for properties. - pub struct PropertyFlags: u8 { + pub struct PropertyFlags: u16 { /// This property requires a stacking context. const CREATES_STACKING_CONTEXT = 1 << 0; /// This property has values that can establish a containing block for @@ -954,13 +954,17 @@ bitflags! { const APPLIES_TO_FIRST_LINE = 1 << 4; /// This longhand property applies to ::placeholder. const APPLIES_TO_PLACEHOLDER = 1 << 5; + /// This longhand property applies to ::cue. + const APPLIES_TO_CUE = 1 << 6; + /// This longhand property applies to ::marker. + const APPLIES_TO_MARKER = 1 << 7; /// This property's getComputedStyle implementation requires layout /// to be flushed. - const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 6; + const GETCS_NEEDS_LAYOUT_FLUSH = 1 << 8; /// This property is a legacy shorthand. /// /// https://drafts.csswg.org/css-cascade/#legacy-shorthand - const IS_LEGACY_SHORTHAND = 1 << 7; + const IS_LEGACY_SHORTHAND = 1 << 9; /* The following flags are currently not used in Rust code, they * only need to be listed in corresponding properties so that @@ -1184,7 +1188,7 @@ impl LonghandId { pub fn flags(self) -> PropertyFlags { // TODO(emilio): This can be simplified further as Rust gains more // constant expression support. - const FLAGS: [u8; ${len(data.longhands)}] = [ + const FLAGS: [u16; ${len(data.longhands)}] = [ % for property in data.longhands: % for flag in property.flags: PropertyFlags::${flag}.bits | @@ -1446,7 +1450,7 @@ impl ShorthandId { /// Returns PropertyFlags for the given shorthand property. #[inline] pub fn flags(self) -> PropertyFlags { - const FLAGS: [u8; ${len(data.shorthands)}] = [ + const FLAGS: [u16; ${len(data.shorthands)}] = [ % for property in data.shorthands: % for flag in property.flags: PropertyFlags::${flag}.bits | @@ -2834,6 +2838,19 @@ impl ComputedValues { pub fn resolve_color(&self, color: computed::Color) -> RGBA { color.to_rgba(self.get_inherited_text().clone_color()) } + + /// Returns which longhand properties have different values in the two + /// ComputedValues. + #[cfg(feature = "gecko_debug")] + pub fn differing_properties(&self, other: &ComputedValues) -> LonghandIdSet { + let mut set = LonghandIdSet::new(); + % for prop in data.longhands: + if self.clone_${prop.ident}() != other.clone_${prop.ident}() { + set.insert(LonghandId::${prop.camel_case}); + } + % endfor + set + } } #[cfg(feature = "servo")] diff --git a/components/style/properties/shorthands/position.mako.rs b/components/style/properties/shorthands/position.mako.rs index ea2f34b9db8..ded5eb951b7 100644 --- a/components/style/properties/shorthands/position.mako.rs +++ b/components/style/properties/shorthands/position.mako.rs @@ -144,6 +144,7 @@ products="gecko"> use crate::values::specified::GridLine; use crate::parser::Parse; + use crate::Zero; // NOTE: Since both the shorthands have the same code, we should (re-)use code from one to implement // the other. This might not be a big deal for now, but we should consider looking into this in the future @@ -157,8 +158,8 @@ GridLine::parse(context, input)? } else { 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 + if start.line_num.is_zero() && !start.is_span { + line.ident = start.ident.clone(); // ident from start value should be taken } line @@ -186,6 +187,7 @@ products="gecko"> use crate::values::specified::GridLine; use crate::parser::Parse; + use crate::Zero; // The code is the same as `grid-{row,column}` except that this can have four values at most. pub fn parse_value<'i, 't>( @@ -194,7 +196,7 @@ ) -> Result<Longhands, ParseError<'i>> { fn line_with_ident_from(other: &GridLine) -> GridLine { let mut this = GridLine::auto(); - if other.line_num.is_none() && !other.is_span { + if other.line_num.is_zero() && !other.is_span { this.ident = other.ident.clone(); } diff --git a/components/style/rule_tree/mod.rs b/components/style/rule_tree/mod.rs index 8f255898fc8..c52b7874a70 100644 --- a/components/style/rule_tree/mod.rs +++ b/components/style/rule_tree/mod.rs @@ -950,8 +950,8 @@ mod gecko_leak_checking { use std::os::raw::{c_char, c_void}; extern "C" { - pub fn NS_LogCtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32); - pub fn NS_LogDtor(aPtr: *const c_void, aTypeName: *const c_char, aSize: u32); + fn NS_LogCtor(aPtr: *mut c_void, aTypeName: *const c_char, aSize: u32); + fn NS_LogDtor(aPtr: *mut c_void, aTypeName: *const c_char, aSize: u32); } static NAME: &'static [u8] = b"RuleNode\0"; @@ -960,7 +960,7 @@ mod gecko_leak_checking { pub fn log_ctor(ptr: *const RuleNode) { let s = NAME as *const [u8] as *const u8 as *const c_char; unsafe { - NS_LogCtor(ptr as *const c_void, s, size_of::<RuleNode>() as u32); + NS_LogCtor(ptr as *mut c_void, s, size_of::<RuleNode>() as u32); } } @@ -968,7 +968,7 @@ mod gecko_leak_checking { pub fn log_dtor(ptr: *const RuleNode) { let s = NAME as *const [u8] as *const u8 as *const c_char; unsafe { - NS_LogDtor(ptr as *const c_void, s, size_of::<RuleNode>() as u32); + NS_LogDtor(ptr as *mut c_void, s, size_of::<RuleNode>() as u32); } } diff --git a/components/style/stylesheets/document_rule.rs b/components/style/stylesheets/document_rule.rs index 8dd4306c179..62e814ac48b 100644 --- a/components/style/stylesheets/document_rule.rs +++ b/components/style/stylesheets/document_rule.rs @@ -260,12 +260,12 @@ impl DocumentCondition { return true; } - if unsafe { structs::StaticPrefs_sVarCache_layout_css_moz_document_content_enabled } { + if unsafe { structs::StaticPrefs::sVarCache_layout_css_moz_document_content_enabled } { return true; } if !unsafe { - structs::StaticPrefs_sVarCache_layout_css_moz_document_url_prefix_hack_enabled + structs::StaticPrefs::sVarCache_layout_css_moz_document_url_prefix_hack_enabled } { return false; } diff --git a/components/style/stylesheets/supports_rule.rs b/components/style/stylesheets/supports_rule.rs index a22acad1aa0..4b709974c7d 100644 --- a/components/style/stylesheets/supports_rule.rs +++ b/components/style/stylesheets/supports_rule.rs @@ -324,7 +324,7 @@ impl RawSelector { #[cfg(feature = "gecko")] { if unsafe { - !crate::gecko_bindings::structs::StaticPrefs_sVarCache_layout_css_supports_selector_enabled + !crate::gecko_bindings::structs::StaticPrefs::sVarCache_layout_css_supports_selector_enabled } { return false; } diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs index 49e751fec55..67557e54b77 100644 --- a/components/style/values/animated/effects.rs +++ b/components/style/values/animated/effects.rs @@ -19,8 +19,9 @@ pub type AnimatedSimpleShadow = GenericSimpleShadow<Color, Length, Length>; /// An animated value for a single `filter`. #[cfg(feature = "gecko")] -pub type AnimatedFilter = GenericFilter<Angle, Number, Length, AnimatedSimpleShadow, ComputedUrl>; +pub type AnimatedFilter = + GenericFilter<Angle, Number, Number, Length, AnimatedSimpleShadow, ComputedUrl>; /// An animated value for a single `filter`. #[cfg(not(feature = "gecko"))] -pub type AnimatedFilter = GenericFilter<Angle, Number, Length, Impossible, Impossible>; +pub type AnimatedFilter = GenericFilter<Angle, Number, Number, Length, Impossible, Impossible>; diff --git a/components/style/values/animated/grid.rs b/components/style/values/animated/grid.rs index 2b59f32e437..d1f6be1a32b 100644 --- a/components/style/values/animated/grid.rs +++ b/components/style/values/animated/grid.rs @@ -62,10 +62,7 @@ impl Animate for TrackSize { } } -impl Animate for generics::TrackRepeat<LengthPercentage, Integer> -where - generics::RepeatCount<Integer>: PartialEq, -{ +impl Animate for generics::TrackRepeat<LengthPercentage, Integer> { fn animate(&self, other: &Self, procedure: Procedure) -> Result<Self, ()> { // If the keyword, auto-fit/fill, is the same it can result in different // number of tracks. For both auto-fit/fill, the number of columns isn't diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 267ef0c8e6f..ea43d01112e 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -447,17 +447,13 @@ where } } -impl<T> ToAnimatedZero for Box<[T]> +impl<T> ToAnimatedZero for crate::OwnedSlice<T> where T: ToAnimatedZero, { #[inline] fn to_animated_zero(&self) -> Result<Self, ()> { - let v = self - .iter() - .map(|v| v.to_animated_zero()) - .collect::<Result<Vec<_>, _>>()?; - Ok(v.into_boxed_slice()) + self.iter().map(|v| v.to_animated_zero()).collect() } } diff --git a/components/style/values/animated/svg.rs b/components/style/values/animated/svg.rs index 436bb73d658..13ad10174b5 100644 --- a/components/style/values/animated/svg.rs +++ b/components/style/values/animated/svg.rs @@ -4,25 +4,10 @@ //! Animation implementations for various SVG-related types. -use super::{Animate, Procedure, ToAnimatedZero}; +use super::{Animate, Procedure}; use crate::properties::animated_properties::ListAnimation; -use crate::values::animated::color::Color as AnimatedColor; -use crate::values::computed::url::ComputedUrl; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; -use crate::values::generics::svg::{SVGPaint, SVGStrokeDashArray}; - -/// Animated SVGPaint. -pub type IntermediateSVGPaint = SVGPaint<AnimatedColor, ComputedUrl>; - -impl ToAnimatedZero for IntermediateSVGPaint { - #[inline] - fn to_animated_zero(&self) -> Result<Self, ()> { - Ok(IntermediateSVGPaint { - kind: self.kind.to_animated_zero()?, - fallback: self.fallback.and_then(|v| v.to_animated_zero().ok()), - }) - } -} +use crate::values::generics::svg::SVGStrokeDashArray; /// <https://www.w3.org/TR/SVG11/painting.html#StrokeDasharrayProperty> impl<L> Animate for SVGStrokeDashArray<L> diff --git a/components/style/values/computed/effects.rs b/components/style/values/computed/effects.rs index 24ec689e49c..b0a92024cad 100644 --- a/components/style/values/computed/effects.rs +++ b/components/style/values/computed/effects.rs @@ -8,7 +8,7 @@ use crate::values::computed::color::Color; use crate::values::computed::length::{Length, NonNegativeLength}; #[cfg(feature = "gecko")] use crate::values::computed::url::ComputedUrl; -use crate::values::computed::{Angle, NonNegativeNumber}; +use crate::values::computed::{Angle, NonNegativeNumber, ZeroToOneNumber}; use crate::values::generics::effects::BoxShadow as GenericBoxShadow; use crate::values::generics::effects::Filter as GenericFilter; use crate::values::generics::effects::SimpleShadow as GenericSimpleShadow; @@ -20,13 +20,25 @@ pub type BoxShadow = GenericBoxShadow<Color, Length, NonNegativeLength, Length>; /// A computed value for a single `filter`. #[cfg(feature = "gecko")] -pub type Filter = - GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, SimpleShadow, ComputedUrl>; +pub type Filter = GenericFilter< + Angle, + NonNegativeNumber, + ZeroToOneNumber, + NonNegativeLength, + SimpleShadow, + ComputedUrl, +>; /// A computed value for a single `filter`. #[cfg(feature = "servo")] -pub type Filter = - GenericFilter<Angle, NonNegativeNumber, NonNegativeLength, Impossible, Impossible>; +pub type Filter = GenericFilter< + Angle, + NonNegativeNumber, + ZeroToOneNumber, + NonNegativeLength, + Impossible, + Impossible, +>; /// A computed value for the `drop-shadow()` filter. pub type SimpleShadow = GenericSimpleShadow<Color, Length, NonNegativeLength>; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index f9711947673..cea768abeff 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -7,10 +7,10 @@ use self::transform::DirectionVector; use super::animated::ToAnimatedValue; use super::generics::grid::GridTemplateComponent as GenericGridTemplateComponent; -use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as GenericTrackBreadth}; -use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize}; +use super::generics::grid::{GenericGridLine, GenericTrackBreadth}; +use super::generics::grid::{GenericTrackSize, TrackList as GenericTrackList}; use super::generics::transform::IsParallelTo; -use super::generics::{self, GreaterThanOrEqualToOne, NonNegative}; +use super::generics::{self, GreaterThanOrEqualToOne, NonNegative, ZeroToOne}; use super::specified; use super::{CSSFloat, CSSInteger}; use crate::context::QuirksMode; @@ -75,6 +75,7 @@ pub use self::svg::MozContextProperties; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::table::XSpan; +pub use self::text::TextDecorationSkipInk; pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight}; pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing}; pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle}; @@ -519,6 +520,30 @@ impl From<NonNegativeNumber> for CSSFloat { } } +/// A wrapper of Number, but the value between 0 and 1 +pub type ZeroToOneNumber = ZeroToOne<CSSFloat>; + +impl ToAnimatedValue for ZeroToOneNumber { + type AnimatedValue = CSSFloat; + + #[inline] + fn to_animated_value(self) -> Self::AnimatedValue { + self.0 + } + + #[inline] + fn from_animated_value(animated: Self::AnimatedValue) -> Self { + Self(animated.max(0.).min(1.)) + } +} + +impl From<CSSFloat> for ZeroToOneNumber { + #[inline] + fn from(number: CSSFloat) -> Self { + Self(number) + } +} + /// A wrapper of Number, but the value >= 1. pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne<CSSFloat>; diff --git a/components/style/values/computed/svg.rs b/components/style/values/computed/svg.rs index f05e9f836da..54648572f86 100644 --- a/components/style/values/computed/svg.rs +++ b/components/style/values/computed/svg.rs @@ -11,23 +11,13 @@ use crate::values::generics::svg as generic; use crate::values::RGBA; use crate::Zero; -pub use crate::values::specified::SVGPaintOrder; - -pub use crate::values::specified::MozContextProperties; +pub use crate::values::specified::{MozContextProperties, SVGPaintOrder}; /// Computed SVG Paint value -pub type SVGPaint = generic::SVGPaint<Color, ComputedUrl>; -/// Computed SVG Paint Kind value -pub type SVGPaintKind = generic::SVGPaintKind<Color, ComputedUrl>; +pub type SVGPaint = generic::GenericSVGPaint<Color, ComputedUrl>; -impl Default for SVGPaint { - fn default() -> Self { - SVGPaint { - kind: generic::SVGPaintKind::None, - fallback: None, - } - } -} +/// Computed SVG Paint Kind value +pub type SVGPaintKind = generic::GenericSVGPaintKind<Color, ComputedUrl>; impl SVGPaint { /// Opaque black color @@ -35,7 +25,7 @@ impl SVGPaint { let rgba = RGBA::from_floats(0., 0., 0., 1.).into(); SVGPaint { kind: generic::SVGPaintKind::Color(rgba), - fallback: None, + fallback: generic::SVGPaintFallback::Unset, } } } @@ -62,16 +52,16 @@ impl SVGWidth { } /// [ <length> | <percentage> | <number> ]# | context-value -pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPercentage>; +pub type SVGStrokeDashArray = generic::GenericSVGStrokeDashArray<NonNegativeLengthPercentage>; impl Default for SVGStrokeDashArray { fn default() -> Self { - generic::SVGStrokeDashArray::Values(vec![]) + generic::SVGStrokeDashArray::Values(Default::default()) } } /// <opacity-value> | context-fill-opacity | context-stroke-opacity -pub type SVGOpacity = generic::SVGOpacity<Opacity>; +pub type SVGOpacity = generic::GenericSVGOpacity<Opacity>; impl Default for SVGOpacity { fn default() -> Self { diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index bc4086a2b9c..500595253ff 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -19,9 +19,9 @@ use std::fmt::{self, Write}; use style_traits::{CssWriter, ToCss}; pub use crate::values::specified::TextAlignKeyword as TextAlign; -pub use crate::values::specified::TextTransform; pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak}; pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition}; +pub use crate::values::specified::{TextDecorationSkipInk, TextTransform}; /// A computed value for the `initial-letter` property. pub type InitialLetter = GenericInitialLetter<CSSFloat, CSSInteger>; diff --git a/components/style/values/generics/easing.rs b/components/style/values/generics/easing.rs index 8817c3d2603..aab2ef547ba 100644 --- a/components/style/values/generics/easing.rs +++ b/components/style/values/generics/easing.rs @@ -70,7 +70,7 @@ pub enum TimingKeyword { #[cfg(feature = "gecko")] fn step_position_jump_enabled(_context: &ParserContext) -> bool { use crate::gecko_bindings::structs; - unsafe { structs::StaticPrefs_sVarCache_layout_css_step_position_jump_enabled } + unsafe { structs::StaticPrefs::sVarCache_layout_css_step_position_jump_enabled } } #[cfg(feature = "servo")] diff --git a/components/style/values/generics/effects.rs b/components/style/values/generics/effects.rs index beca716e997..724f484f283 100644 --- a/components/style/values/generics/effects.rs +++ b/components/style/values/generics/effects.rs @@ -52,34 +52,34 @@ pub use self::GenericBoxShadow as BoxShadow; ToShmem, )] #[repr(C, u8)] -pub enum GenericFilter<Angle, Factor, Length, Shadow, U> { +pub enum GenericFilter<Angle, NonNegativeFactor, ZeroToOneFactor, Length, Shadow, U> { /// `blur(<length>)` #[css(function)] Blur(Length), /// `brightness(<factor>)` #[css(function)] - Brightness(Factor), + Brightness(NonNegativeFactor), /// `contrast(<factor>)` #[css(function)] - Contrast(Factor), + Contrast(NonNegativeFactor), /// `grayscale(<factor>)` #[css(function)] - Grayscale(Factor), + Grayscale(ZeroToOneFactor), /// `hue-rotate(<angle>)` #[css(function)] HueRotate(Angle), /// `invert(<factor>)` #[css(function)] - Invert(Factor), + Invert(ZeroToOneFactor), /// `opacity(<factor>)` #[css(function)] - Opacity(Factor), + Opacity(ZeroToOneFactor), /// `saturate(<factor>)` #[css(function)] - Saturate(Factor), + Saturate(NonNegativeFactor), /// `sepia(<factor>)` #[css(function)] - Sepia(Factor), + Sepia(ZeroToOneFactor), /// `drop-shadow(...)` #[css(function)] DropShadow(Shadow), diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index d20ba265ab2..7de109141fe 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -6,15 +6,22 @@ //! [grids](https://drafts.csswg.org/css-grid/). use crate::parser::{Parse, ParserContext}; -use crate::values::computed::{Context, ToComputedValue}; use crate::values::specified; use crate::values::specified::grid::parse_line_names; use crate::values::{CSSFloat, CustomIdent}; +use crate::{Atom, Zero}; use cssparser::Parser; use std::fmt::{self, Write}; -use std::{mem, usize}; +use std::{cmp, mem, usize}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; +/// These are the limits that we choose to clamp grid line numbers to. +/// http://drafts.csswg.org/css-grid/#overlarge-grids +/// line_num is clamped to this range at parse time. +pub const MIN_GRID_LINE: i32 = -10000; +/// See above. +pub const MAX_GRID_LINE: i32 = 10000; + /// A `<grid-line>` type. /// /// <https://drafts.csswg.org/css-grid/#typedef-grid-row-start-grid-line> @@ -29,36 +36,48 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; ToResolvedValue, ToShmem, )] -pub struct GridLine<Integer> { - /// Flag to check whether it's a `span` keyword. - pub is_span: bool, - /// A custom identifier for named lines. +#[repr(C)] +pub struct GenericGridLine<Integer> { + /// A custom identifier for named lines, or the empty atom otherwise. /// /// <https://drafts.csswg.org/css-grid/#grid-placement-slot> - pub ident: Option<CustomIdent>, + pub ident: Atom, /// Denotes the nth grid line from grid item's placement. - pub line_num: Option<Integer>, + /// + /// This is clamped by MIN_GRID_LINE and MAX_GRID_LINE. + /// + /// NOTE(emilio): If we ever allow animating these we need to either do + /// something more complicated for the clamping, or do this clamping at + /// used-value time. + pub line_num: Integer, + /// Flag to check whether it's a `span` keyword. + pub is_span: bool, } -impl<Integer> GridLine<Integer> { +pub use self::GenericGridLine as GridLine; + +impl<Integer> GridLine<Integer> +where + Integer: Zero, +{ /// The `auto` value. pub fn auto() -> Self { Self { is_span: false, - line_num: None, - ident: None, + line_num: Zero::zero(), + ident: atom!(""), } } /// Check whether this `<grid-line>` represents an `auto` value. pub fn is_auto(&self) -> bool { - self.ident.is_none() && self.line_num.is_none() && !self.is_span + self.ident == atom!("") && self.line_num.is_zero() && !self.is_span } } impl<Integer> ToCss for GridLine<Integer> where - Integer: ToCss, + Integer: ToCss + Zero, { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where @@ -72,18 +91,18 @@ where dest.write_str("span")?; } - if let Some(ref i) = self.line_num { + if !self.line_num.is_zero() { if self.is_span { dest.write_str(" ")?; } - i.to_css(dest)?; + self.line_num.to_css(dest)?; } - if let Some(ref s) = self.ident { - if self.is_span || self.line_num.is_some() { + if self.ident != atom!("") { + if self.is_span || !self.line_num.is_zero() { dest.write_str(" ")?; } - s.to_css(dest)?; + CustomIdent(self.ident.clone()).to_css(dest)?; } Ok(()) @@ -114,25 +133,29 @@ impl Parse for GridLine<specified::Integer> { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } - if grid_line.line_num.is_some() || grid_line.ident.is_some() { + if !grid_line.line_num.is_zero() || grid_line.ident != atom!("") { val_before_span = true; } grid_line.is_span = true; } 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() { + let value = i.value(); + if value == 0 || val_before_span || !grid_line.line_num.is_zero() { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } - grid_line.line_num = Some(i); + grid_line.line_num = specified::Integer::new(cmp::max( + MIN_GRID_LINE, + cmp::min(value, MAX_GRID_LINE), + )); } else if let Ok(name) = input.try(|i| i.expect_ident_cloned()) { - if val_before_span || grid_line.ident.is_some() { + if val_before_span || grid_line.ident != atom!("") { return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } // NOTE(emilio): `span` is consumed above, so we only need to // reject `auto`. - grid_line.ident = Some(CustomIdent::from_ident(location, &name, &["auto"])?); + grid_line.ident = CustomIdent::from_ident(location, &name, &["auto"])?.0; } else { break; } @@ -143,12 +166,12 @@ impl Parse for GridLine<specified::Integer> { } if grid_line.is_span { - if let Some(i) = grid_line.line_num { - if i.value() <= 0 { + if !grid_line.line_num.is_zero() { + if grid_line.line_num.value() <= 0 { // disallow negative integers for grid spans return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } - } else if grid_line.ident.is_none() { + } else if grid_line.ident == atom!("") { // integer could be omitted return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } @@ -158,33 +181,12 @@ impl Parse for GridLine<specified::Integer> { } } -#[allow(missing_docs)] -#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive( - Animate, - Clone, - Copy, - Debug, - Eq, - MallocSizeOf, - Parse, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, -)] -pub enum TrackKeyword { - Auto, - MaxContent, - MinContent, -} - /// A track breadth for explicit grid track sizing. It's generic solely to /// avoid re-implementing it for the computed type. /// /// <https://drafts.csswg.org/css-grid/#typedef-track-breadth> +/// +/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, @@ -197,16 +199,23 @@ pub enum TrackKeyword { ToResolvedValue, ToShmem, )] -pub enum TrackBreadth<L> { +#[repr(C, u8)] +pub enum GenericTrackBreadth<L> { /// The generic type is almost always a non-negative `<length-percentage>` Breadth(L), /// A flex fraction specified in `fr` units. #[css(dimension)] Fr(CSSFloat), - /// One of the track-sizing keywords (`auto`, `min-content`, `max-content`) - Keyword(TrackKeyword), + /// `auto` + Auto, + /// `min-content` + MinContent, + /// `max-content` + MaxContent, } +pub use self::GenericTrackBreadth as TrackBreadth; + impl<L> TrackBreadth<L> { /// Check whether this is a `<fixed-breadth>` (i.e., it only has `<length-percentage>`) /// @@ -221,23 +230,40 @@ impl<L> TrackBreadth<L> { /// generic only to avoid code bloat. It only takes `<length-percentage>` /// /// <https://drafts.csswg.org/css-grid/#typedef-track-size> -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToResolvedValue, ToShmem)] -pub enum TrackSize<L> { +/// +/// cbindgen:derive-tagged-enum-copy-constructor=true +#[derive( + Clone, + Debug, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +#[repr(C, u8)] +pub enum GenericTrackSize<L> { /// A flexible `<track-breadth>` - Breadth(TrackBreadth<L>), + Breadth(GenericTrackBreadth<L>), /// A `minmax` function for a range over an inflexible `<track-breadth>` /// and a flexible `<track-breadth>` /// /// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-minmax> #[css(function)] - Minmax(TrackBreadth<L>, TrackBreadth<L>), + Minmax(GenericTrackBreadth<L>, GenericTrackBreadth<L>), /// A `fit-content` function. /// + /// This stores a TrackBreadth<L> for convenience, but it can only be a + /// LengthPercentage. + /// /// <https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-fit-content> #[css(function)] - FitContent(L), + FitContent(GenericTrackBreadth<L>), } +pub use self::GenericTrackSize as TrackSize; + impl<L> TrackSize<L> { /// Check whether this is a `<fixed-size>` /// @@ -266,7 +292,7 @@ impl<L> TrackSize<L> { impl<L> Default for TrackSize<L> { fn default() -> Self { - TrackSize::Breadth(TrackBreadth::Keyword(TrackKeyword::Auto)) + TrackSize::Breadth(TrackBreadth::Auto) } } @@ -287,7 +313,7 @@ impl<L: ToCss> ToCss for TrackSize<L> { TrackSize::Minmax(ref min, ref max) => { // According to gecko minmax(auto, <flex>) is equivalent to <flex>, // and both are serialized as <flex>. - if let TrackBreadth::Keyword(TrackKeyword::Auto) = *min { + if let TrackBreadth::Auto = *min { if let TrackBreadth::Fr(_) = *max { return max.to_css(dest); } @@ -308,48 +334,6 @@ impl<L: ToCss> ToCss for TrackSize<L> { } } -impl<L: ToComputedValue> ToComputedValue for TrackSize<L> { - type ComputedValue = TrackSize<L::ComputedValue>; - - #[inline] - fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - match *self { - TrackSize::Breadth(TrackBreadth::Fr(ref f)) => { - // <flex> outside `minmax()` expands to `mimmax(auto, <flex>)` - // https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-flex - // FIXME(nox): This sounds false, the spec just says that <flex> - // implies `minmax(auto, <flex>)`, not that it should be changed - // into `minmax` at computed value time. - TrackSize::Minmax( - TrackBreadth::Keyword(TrackKeyword::Auto), - TrackBreadth::Fr(f.to_computed_value(context)), - ) - }, - TrackSize::Breadth(ref b) => TrackSize::Breadth(b.to_computed_value(context)), - TrackSize::Minmax(ref b1, ref b2) => { - TrackSize::Minmax(b1.to_computed_value(context), b2.to_computed_value(context)) - }, - TrackSize::FitContent(ref lp) => TrackSize::FitContent(lp.to_computed_value(context)), - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - match *computed { - TrackSize::Breadth(ref b) => { - TrackSize::Breadth(ToComputedValue::from_computed_value(b)) - }, - TrackSize::Minmax(ref b1, ref b2) => TrackSize::Minmax( - ToComputedValue::from_computed_value(b1), - ToComputedValue::from_computed_value(b2), - ), - TrackSize::FitContent(ref lp) => { - TrackSize::FitContent(ToComputedValue::from_computed_value(lp)) - }, - } - } -} - /// Helper function for serializing identifiers with a prefix and suffix, used /// for serializing <line-names> (in grid). pub fn concat_serialize_idents<W>( diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 08ae15a4c2c..343aad87694 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -103,7 +103,12 @@ pub enum CounterStyleOrNone { Name(CustomIdent), /// `symbols()` #[css(function)] - Symbols(SymbolsType, Symbols), + Symbols(#[css(skip_if = "is_symbolic")] SymbolsType, Symbols), +} + +#[inline] +fn is_symbolic(symbols_type: &SymbolsType) -> bool { + *symbols_type == SymbolsType::Symbolic } impl CounterStyleOrNone { @@ -227,6 +232,28 @@ impl<T: Zero> Zero for NonNegative<T> { )] pub struct GreaterThanOrEqualToOne<T>(pub T); +/// A wrapper of values between zero and one. +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Hash, + MallocSizeOf, + PartialEq, + PartialOrd, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(transparent)] +pub struct ZeroToOne<T>(pub T); + /// A clip rect for clip and image-region #[allow(missing_docs)] #[derive( diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 0cd67dbf10e..4a1fc42551d 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -5,14 +5,47 @@ //! Generic types for CSS values in SVG use crate::parser::{Parse, ParserContext}; -use crate::values::{Either, None_}; use cssparser::Parser; -use style_traits::{ParseError, StyleParseErrorKind}; +use style_traits::ParseError; + +/// The fallback of an SVG paint server value. +/// cbindgen:derive-tagged-enum-copy-constructor=true +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + MallocSizeOf, + PartialEq, + Parse, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(C, u8)] +pub enum GenericSVGPaintFallback<C> { + /// The `none` keyword. + None, + /// A magic value that represents no fallback specified and serializes to + /// the empty string. + #[css(skip)] + Unset, + /// A color. + Color(C), +} + +pub use self::GenericSVGPaintFallback as SVGPaintFallback; /// An SVG paint value /// /// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint> -#[animation(no_bound(UrlPaintServer))] +/// +/// cbindgen:derive-tagged-enum-copy-constructor=true +#[animation(no_bound(Url))] #[derive( Animate, Clone, @@ -22,24 +55,38 @@ use style_traits::{ParseError, StyleParseErrorKind}; PartialEq, SpecifiedValueInfo, ToAnimatedValue, + ToAnimatedZero, ToComputedValue, ToCss, ToResolvedValue, ToShmem, )] -pub struct SVGPaint<ColorType, UrlPaintServer> { - /// The paint source - pub kind: SVGPaintKind<ColorType, UrlPaintServer>, - /// The fallback color. It would be empty, the `none` keyword or <color>. - pub fallback: Option<Either<ColorType, None_>>, +#[repr(C)] +pub struct GenericSVGPaint<Color, Url> { + /// The paint source. + pub kind: GenericSVGPaintKind<Color, Url>, + /// The fallback color. + pub fallback: GenericSVGPaintFallback<Color>, +} + +pub use self::GenericSVGPaint as SVGPaint; + +impl<C, U> Default for SVGPaint<C, U> { + fn default() -> Self { + Self { + kind: SVGPaintKind::None, + fallback: SVGPaintFallback::Unset, + } + } } -/// An SVG paint value without the fallback +/// An SVG paint value without the fallback. /// -/// Whereas the spec only allows PaintServer -/// to have a fallback, Gecko lets the context -/// properties have a fallback as well. -#[animation(no_bound(UrlPaintServer))] +/// Whereas the spec only allows PaintServer to have a fallback, Gecko lets the +/// context properties have a fallback as well. +/// +/// cbindgen:derive-tagged-enum-copy-constructor=true +#[animation(no_bound(U))] #[derive( Animate, Clone, @@ -47,6 +94,7 @@ pub struct SVGPaint<ColorType, UrlPaintServer> { Debug, MallocSizeOf, PartialEq, + Parse, SpecifiedValueInfo, ToAnimatedValue, ToAnimatedZero, @@ -55,80 +103,40 @@ pub struct SVGPaint<ColorType, UrlPaintServer> { ToResolvedValue, ToShmem, )] -pub enum SVGPaintKind<ColorType, UrlPaintServer> { +#[repr(C, u8)] +pub enum GenericSVGPaintKind<C, U> { /// `none` #[animation(error)] None, /// `<color>` - Color(ColorType), + Color(C), /// `url(...)` #[animation(error)] - PaintServer(UrlPaintServer), + PaintServer(U), /// `context-fill` ContextFill, /// `context-stroke` ContextStroke, } -impl<ColorType, UrlPaintServer> SVGPaintKind<ColorType, UrlPaintServer> { - /// Parse a keyword value only - fn parse_ident<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { - try_match_ident_ignore_ascii_case! { input, - "none" => Ok(SVGPaintKind::None), - "context-fill" => Ok(SVGPaintKind::ContextFill), - "context-stroke" => Ok(SVGPaintKind::ContextStroke), - } - } -} +pub use self::GenericSVGPaintKind as SVGPaintKind; -/// Parse SVGPaint's fallback. -/// fallback is keyword(none), Color or empty. -/// <https://svgwg.org/svg2-draft/painting.html#SpecifyingPaint> -fn parse_fallback<'i, 't, ColorType: Parse>( - context: &ParserContext, - input: &mut Parser<'i, 't>, -) -> Option<Either<ColorType, None_>> { - if input.try(|i| i.expect_ident_matching("none")).is_ok() { - Some(Either::Second(None_)) - } else { - if let Ok(color) = input.try(|i| ColorType::parse(context, i)) { - Some(Either::First(color)) - } else { - None - } - } -} - -impl<ColorType: Parse, UrlPaintServer: Parse> Parse for SVGPaint<ColorType, UrlPaintServer> { +impl<C: Parse, U: Parse> Parse for SVGPaint<C, U> { fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(url) = input.try(|i| UrlPaintServer::parse(context, i)) { - Ok(SVGPaint { - kind: SVGPaintKind::PaintServer(url), - fallback: parse_fallback(context, input), - }) - } else if let Ok(kind) = input.try(SVGPaintKind::parse_ident) { - if let SVGPaintKind::None = kind { - Ok(SVGPaint { - kind: kind, - fallback: None, - }) - } else { - Ok(SVGPaint { - kind: kind, - fallback: parse_fallback(context, input), - }) - } - } else if let Ok(color) = input.try(|i| ColorType::parse(context, i)) { - Ok(SVGPaint { - kind: SVGPaintKind::Color(color), - fallback: None, - }) - } else { - Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + let kind = SVGPaintKind::parse(context, input)?; + if matches!(kind, SVGPaintKind::None | SVGPaintKind::Color(..)) { + return Ok(SVGPaint { + kind, + fallback: SVGPaintFallback::Unset, + }); } + let fallback = input + .try(|i| SVGPaintFallback::parse(context, i)) + .unwrap_or(SVGPaintFallback::Unset); + Ok(SVGPaint { kind, fallback }) } } @@ -171,14 +179,17 @@ pub enum SVGLength<L> { ToResolvedValue, ToShmem, )] -pub enum SVGStrokeDashArray<L> { +#[repr(C, u8)] +pub enum GenericSVGStrokeDashArray<L> { /// `[ <length> | <percentage> | <number> ]#` #[css(comma)] - Values(#[css(if_empty = "none", iterable)] Vec<L>), + Values(#[css(if_empty = "none", iterable)] crate::OwnedSlice<L>), /// `context-value` ContextValue, } +pub use self::GenericSVGStrokeDashArray as SVGStrokeDashArray; + /// An SVG opacity value accepts `context-{fill,stroke}-opacity` in /// addition to opacity value. #[derive( @@ -197,7 +208,8 @@ pub enum SVGStrokeDashArray<L> { ToResolvedValue, ToShmem, )] -pub enum SVGOpacity<OpacityType> { +#[repr(C, u8)] +pub enum GenericSVGOpacity<OpacityType> { /// `<opacity-value>` Opacity(OpacityType), /// `context-fill-opacity` @@ -207,3 +219,5 @@ pub enum SVGOpacity<OpacityType> { #[animation(error)] ContextStrokeOpacity, } + +pub use self::GenericSVGOpacity as SVGOpacity; diff --git a/components/style/values/generics/text.rs b/components/style/values/generics/text.rs index a09260aa7e4..b55a9ad62dc 100644 --- a/components/style/values/generics/text.rs +++ b/components/style/values/generics/text.rs @@ -75,7 +75,7 @@ fn line_height_moz_block_height_enabled(context: &ParserContext) -> bool { use crate::gecko_bindings::structs; context.in_ua_sheet() || unsafe { - structs::StaticPrefs_sVarCache_layout_css_line_height_moz_block_height_content_enabled + structs::StaticPrefs::sVarCache_layout_css_line_height_moz_block_height_content_enabled } } diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 64fb1e254a5..f6fd800247a 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -542,11 +542,7 @@ impl<T: ToMatrix> Transform<T> { ) }; - let (m, is_3d) = match self.to_transform_3d_matrix_f64(reference_box) { - Ok(result) => result, - Err(err) => return Err(err), - }; - + let (m, is_3d) = self.to_transform_3d_matrix_f64(reference_box)?; Ok((cast_3d_transform(m), is_3d)) } diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index 7ee33d0580e..8dccf4594f0 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -60,7 +60,7 @@ pub type Polygon = generic::GenericPolygon<LengthPercentage>; fn is_clip_path_path_enabled(context: &ParserContext) -> bool { use crate::gecko_bindings::structs::mozilla; context.chrome_rules_enabled() || - unsafe { mozilla::StaticPrefs_sVarCache_layout_css_clip_path_path_enabled } + unsafe { mozilla::StaticPrefs::sVarCache_layout_css_clip_path_path_enabled } } #[cfg(feature = "servo")] fn is_clip_path_path_enabled(_: &ParserContext) -> bool { diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs index 338b0d18c27..6ac569f3390 100644 --- a/components/style/values/specified/border.rs +++ b/components/style/values/specified/border.rs @@ -242,7 +242,7 @@ impl Parse for BorderSpacing { input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { Size2D::parse_with(context, input, |context, input| { - NonNegativeLength::parse_quirky(context, input, AllowQuirks::Yes).map(From::from) + NonNegativeLength::parse_quirky(context, input, AllowQuirks::Yes) }) .map(GenericBorderSpacing) } diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index a64216087d7..3b8f1df005b 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -25,7 +25,7 @@ use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; fn moz_display_values_enabled(context: &ParserContext) -> bool { use crate::gecko_bindings::structs; context.in_ua_or_chrome_sheet() || - unsafe { structs::StaticPrefs_sVarCache_layout_css_xul_display_values_content_enabled } + unsafe { structs::StaticPrefs::sVarCache_layout_css_xul_display_values_content_enabled } } #[cfg(feature = "gecko")] @@ -33,7 +33,7 @@ fn moz_box_display_values_enabled(context: &ParserContext) -> bool { use crate::gecko_bindings::structs; context.in_ua_or_chrome_sheet() || unsafe { - structs::StaticPrefs_sVarCache_layout_css_xul_box_display_values_content_enabled + structs::StaticPrefs::sVarCache_layout_css_xul_box_display_values_content_enabled } } diff --git a/components/style/values/specified/effects.rs b/components/style/values/specified/effects.rs index 25ef99a362e..c10445fa62f 100644 --- a/components/style/values/specified/effects.rs +++ b/components/style/values/specified/effects.rs @@ -8,6 +8,7 @@ use crate::parser::{Parse, ParserContext}; use crate::values::computed::effects::BoxShadow as ComputedBoxShadow; use crate::values::computed::effects::SimpleShadow as ComputedSimpleShadow; use crate::values::computed::NonNegativeNumber as ComputedNonNegativeNumber; +use crate::values::computed::ZeroToOneNumber as ComputedZeroToOneNumber; use crate::values::computed::{Context, ToComputedValue}; use crate::values::generics::effects::BoxShadow as GenericBoxShadow; use crate::values::generics::effects::Filter as GenericFilter; @@ -30,74 +31,98 @@ pub type BoxShadow = /// A specified value for a single `filter`. #[cfg(feature = "gecko")] -pub type SpecifiedFilter = - GenericFilter<Angle, Factor, NonNegativeLength, SimpleShadow, SpecifiedUrl>; +pub type SpecifiedFilter = GenericFilter< + Angle, + NonNegativeFactor, + ZeroToOneFactor, + NonNegativeLength, + SimpleShadow, + SpecifiedUrl, +>; /// A specified value for a single `filter`. #[cfg(feature = "servo")] -pub type SpecifiedFilter = GenericFilter<Angle, Factor, NonNegativeLength, Impossible, Impossible>; +pub type SpecifiedFilter = GenericFilter< + Angle, + NonNegativeFactor, + ZeroToOneFactor, + NonNegativeLength, + Impossible, + Impossible, +>; pub use self::SpecifiedFilter as Filter; /// A value for the `<factor>` parts in `Filter`. #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] -pub struct Factor(NumberOrPercentage); +pub struct NonNegativeFactor(NumberOrPercentage); -impl Factor { - /// Parse this factor but clamp to one if the value is over 100%. - #[inline] - pub fn parse_with_clamping_to_one<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result<Self, ParseError<'i>> { - Factor::parse(context, input).map(|v| v.clamp_to_one()) +/// A value for the `<factor>` parts in `Filter` which clamps to one. +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] +pub struct ZeroToOneFactor(NumberOrPercentage); + +/// Clamp the value to 1 if the value is over 100%. +#[inline] +fn clamp_to_one(number: NumberOrPercentage) -> NumberOrPercentage { + match number { + NumberOrPercentage::Percentage(percent) => { + NumberOrPercentage::Percentage(percent.clamp_to_hundred()) + }, + NumberOrPercentage::Number(number) => NumberOrPercentage::Number(number.clamp_to_one()), } +} - /// Clamp the value to 1 if the value is over 100%. - #[inline] - fn clamp_to_one(self) -> Self { - match self.0 { - NumberOrPercentage::Percentage(percent) => { - Factor(NumberOrPercentage::Percentage(percent.clamp_to_hundred())) - }, - NumberOrPercentage::Number(number) => { - Factor(NumberOrPercentage::Number(number.clamp_to_one())) - }, +macro_rules! factor_impl_common { + ($ty:ty, $computed_ty:ty) => { + impl $ty { + fn one() -> Self { + Self(NumberOrPercentage::Number(Number::new(1.))) + } } - } - fn one() -> Self { - Factor(NumberOrPercentage::Number(Number::new(1.0))) - } + impl ToComputedValue for $ty { + type ComputedValue = $computed_ty; + + #[inline] + fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { + use crate::values::computed::NumberOrPercentage; + match self.0.to_computed_value(context) { + NumberOrPercentage::Number(n) => n.into(), + NumberOrPercentage::Percentage(p) => p.0.into(), + } + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + Self(NumberOrPercentage::Number( + ToComputedValue::from_computed_value(&computed.0), + )) + } + } + }; } +factor_impl_common!(NonNegativeFactor, ComputedNonNegativeNumber); +factor_impl_common!(ZeroToOneFactor, ComputedZeroToOneNumber); -impl Parse for Factor { +impl Parse for NonNegativeFactor { #[inline] fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - NumberOrPercentage::parse_non_negative(context, input).map(Factor) + NumberOrPercentage::parse_non_negative(context, input).map(Self) } } -impl ToComputedValue for Factor { - type ComputedValue = ComputedNonNegativeNumber; - +impl Parse for ZeroToOneFactor { #[inline] - fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { - use crate::values::computed::NumberOrPercentage; - match self.0.to_computed_value(context) { - NumberOrPercentage::Number(n) => n.into(), - NumberOrPercentage::Percentage(p) => p.0.into(), - } - } - - #[inline] - fn from_computed_value(computed: &Self::ComputedValue) -> Self { - Factor(NumberOrPercentage::Number( - ToComputedValue::from_computed_value(&computed.0), - )) + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + NumberOrPercentage::parse_non_negative(context, input) + .map(clamp_to_one) + .map(Self) } } @@ -221,19 +246,19 @@ impl Parse for Filter { .unwrap_or(Zero::zero()), )), "brightness" => Ok(GenericFilter::Brightness( - i.try(|i| Factor::parse(context, i)) - .unwrap_or(Factor::one()), + i.try(|i| NonNegativeFactor::parse(context, i)) + .unwrap_or(NonNegativeFactor::one()), )), "contrast" => Ok(GenericFilter::Contrast( - i.try(|i| Factor::parse(context, i)) - .unwrap_or(Factor::one()), + i.try(|i| NonNegativeFactor::parse(context, i)) + .unwrap_or(NonNegativeFactor::one()), )), "grayscale" => { // Values of amount over 100% are allowed but UAs must clamp the values to 1. // https://drafts.fxtf.org/filter-effects/#funcdef-filter-grayscale Ok(GenericFilter::Grayscale( - i.try(|i| Factor::parse_with_clamping_to_one(context, i)) - .unwrap_or(Factor::one()), + i.try(|i| ZeroToOneFactor::parse(context, i)) + .unwrap_or(ZeroToOneFactor::one()), )) }, "hue-rotate" => { @@ -248,28 +273,28 @@ impl Parse for Filter { // Values of amount over 100% are allowed but UAs must clamp the values to 1. // https://drafts.fxtf.org/filter-effects/#funcdef-filter-invert Ok(GenericFilter::Invert( - i.try(|i| Factor::parse_with_clamping_to_one(context, i)) - .unwrap_or(Factor::one()), + i.try(|i| ZeroToOneFactor::parse(context, i)) + .unwrap_or(ZeroToOneFactor::one()), )) }, "opacity" => { // Values of amount over 100% are allowed but UAs must clamp the values to 1. // https://drafts.fxtf.org/filter-effects/#funcdef-filter-opacity Ok(GenericFilter::Opacity( - i.try(|i| Factor::parse_with_clamping_to_one(context, i)) - .unwrap_or(Factor::one()), + i.try(|i| ZeroToOneFactor::parse(context, i)) + .unwrap_or(ZeroToOneFactor::one()), )) }, "saturate" => Ok(GenericFilter::Saturate( - i.try(|i| Factor::parse(context, i)) - .unwrap_or(Factor::one()), + i.try(|i| NonNegativeFactor::parse(context, i)) + .unwrap_or(NonNegativeFactor::one()), )), "sepia" => { // Values of amount over 100% are allowed but UAs must clamp the values to 1. // https://drafts.fxtf.org/filter-effects/#funcdef-filter-sepia Ok(GenericFilter::Sepia( - i.try(|i| Factor::parse_with_clamping_to_one(context, i)) - .unwrap_or(Factor::one()), + i.try(|i| ZeroToOneFactor::parse(context, i)) + .unwrap_or(ZeroToOneFactor::one()), )) }, "drop-shadow" => Ok(GenericFilter::DropShadow(Parse::parse(context, i)?)), diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index b3e18e66e8e..3e7f8f72a00 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -8,7 +8,7 @@ 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, TrackKeyword, TrackRepeat, TrackSize}; +use crate::values::generics::grid::{LineNameList, TrackRepeat, TrackSize}; use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue}; use crate::values::specified::{Integer, LengthPercentage}; use crate::values::{CSSFloat, CustomIdent}; @@ -27,11 +27,32 @@ pub fn parse_flex<'i, 't>(input: &mut Parser<'i, 't>) -> Result<CSSFloat, ParseE } } +impl<L> TrackBreadth<L> { + fn parse_keyword<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { + #[derive(Parse)] + enum TrackKeyword { + Auto, + MaxContent, + MinContent, + } + + Ok(match TrackKeyword::parse(input)? { + TrackKeyword::Auto => TrackBreadth::Auto, + TrackKeyword::MaxContent => TrackBreadth::MaxContent, + TrackKeyword::MinContent => TrackBreadth::MinContent, + }) + } +} + impl Parse for TrackBreadth<LengthPercentage> { fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { + // FIXME: This and other callers in this file should use + // NonNegativeLengthPercentage instead. + // + // Though it seems these cannot be animated so it's ~ok. if let Ok(lp) = input.try(|i| LengthPercentage::parse_non_negative(context, i)) { return Ok(TrackBreadth::Breadth(lp)); } @@ -40,7 +61,7 @@ impl Parse for TrackBreadth<LengthPercentage> { return Ok(TrackBreadth::Fr(f)); } - TrackKeyword::parse(input).map(TrackBreadth::Keyword) + Self::parse_keyword(input) } } @@ -58,10 +79,7 @@ impl Parse for TrackSize<LengthPercentage> { let inflexible_breadth = match input.try(|i| LengthPercentage::parse_non_negative(context, i)) { Ok(lp) => TrackBreadth::Breadth(lp), - Err(..) => { - let keyword = TrackKeyword::parse(input)?; - TrackBreadth::Keyword(keyword) - }, + Err(..) => TrackBreadth::parse_keyword(input)?, }; input.expect_comma()?; @@ -74,7 +92,7 @@ impl Parse for TrackSize<LengthPercentage> { input.expect_function_matching("fit-content")?; let lp = input.parse_nested_block(|i| LengthPercentage::parse_non_negative(context, i))?; - Ok(TrackSize::FitContent(lp)) + Ok(TrackSize::FitContent(TrackBreadth::Breadth(lp))) } } @@ -381,7 +399,7 @@ impl ToComputedValue for TrackList<LengthPercentage, Integer> { #[inline] fn allow_grid_template_subgrids() -> bool { use crate::gecko_bindings::structs::mozilla; - unsafe { mozilla::StaticPrefs_sVarCache_layout_css_grid_template_subgrid_value_enabled } + unsafe { mozilla::StaticPrefs::sVarCache_layout_css_grid_template_subgrid_value_enabled } } #[cfg(feature = "servo")] diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 409f5abe161..14439d2eea0 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -17,9 +17,9 @@ use crate::context::QuirksMode; use crate::parser::{Parse, ParserContext}; use crate::values::serialize_atom_identifier; use crate::values::specified::calc::CalcNode; -use crate::{Atom, Namespace, Prefix}; +use crate::{Atom, Namespace, Prefix, Zero}; use cssparser::{Parser, Token}; -use num_traits::{One, Zero}; +use num_traits::One; use std::f32; use std::fmt::{self, Write}; use std::ops::Add; @@ -74,14 +74,14 @@ pub use self::position::{PositionComponent, ZIndex}; pub use self::rect::NonNegativeLengthOrNumberRect; pub use self::resolution::Resolution; pub use self::svg::MozContextProperties; -pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; +pub use self::svg::{SVGLength, SVGOpacity, SVGPaint}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::svg_path::SVGPathData; pub use self::table::XSpan; -pub use self::text::TextTransform; pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign}; pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak}; pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing}; +pub use self::text::{TextDecorationSkipInk, TextTransform}; pub use self::time::Time; pub use self::transform::{Rotate, Scale, Transform}; pub use self::transform::{TransformOrigin, TransformStyle, Translate}; @@ -342,8 +342,6 @@ impl Parse for GreaterThanOrEqualToOneNumber { /// <number> | <percentage> /// /// Accepts only non-negative numbers. -/// -/// FIXME(emilio): Should probably use Either. #[allow(missing_docs)] #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] pub enum NumberOrPercentage { @@ -449,6 +447,18 @@ pub struct Integer { was_calc: bool, } +impl Zero for Integer { + #[inline] + fn zero() -> Self { + Self::new(0) + } + + #[inline] + fn is_zero(&self) -> bool { + self.value() == 0 + } +} + impl One for Integer { #[inline] fn one() -> Self { diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index 578870a4a91..9279707935f 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -18,10 +18,7 @@ use style_traits::{CommaWithSpace, CssWriter, ParseError, Separator}; use style_traits::{StyleParseErrorKind, ToCss}; /// Specified SVG Paint value -pub type SVGPaint = generic::SVGPaint<Color, SpecifiedUrl>; - -/// Specified SVG Paint Kind value -pub type SVGPaintKind = generic::SVGPaintKind<Color, SpecifiedUrl>; +pub type SVGPaint = generic::GenericSVGPaint<Color, SpecifiedUrl>; /// <length> | <percentage> | <number> | context-value pub type SVGLength = generic::SVGLength<LengthPercentage>; @@ -36,7 +33,7 @@ pub type SVGStrokeDashArray = generic::SVGStrokeDashArray<NonNegativeLengthPerce #[cfg(feature = "gecko")] pub fn is_context_value_enabled() -> bool { use crate::gecko_bindings::structs::mozilla; - unsafe { mozilla::StaticPrefs_sVarCache_gfx_font_rendering_opentype_svg_enabled } + unsafe { mozilla::StaticPrefs::sVarCache_gfx_font_rendering_opentype_svg_enabled } } /// Whether the `context-value` value is enabled. @@ -80,14 +77,14 @@ impl Parse for SVGStrokeDashArray { NonNegativeLengthPercentage::parse_quirky(context, i, AllowQuirks::Always) }) }) { - return Ok(generic::SVGStrokeDashArray::Values(values)); + return Ok(generic::SVGStrokeDashArray::Values(values.into())); } try_match_ident_ignore_ascii_case! { input, "context-value" if is_context_value_enabled() => { Ok(generic::SVGStrokeDashArray::ContextValue) }, - "none" => Ok(generic::SVGStrokeDashArray::Values(vec![])), + "none" => Ok(generic::SVGStrokeDashArray::Values(Default::default())), } } } @@ -200,7 +197,7 @@ impl Parse for SVGPaintOrder { // fill in rest for i in pos..PAINT_ORDER_COUNT { - for paint in 0..PAINT_ORDER_COUNT { + for paint in 1..(PAINT_ORDER_COUNT + 1) { // if not seen, set bit at position, mark as seen if (seen & (1 << paint)) == 0 { seen |= 1 << paint; diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index 188eb18f720..c66e93803f6 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -1054,3 +1054,28 @@ pub enum OverflowWrap { BreakWord, Anywhere, } + +/// Implements text-decoration-skip-ink which takes the keywords auto | none +/// +/// https://drafts.csswg.org/css-text-decor-4/#text-decoration-skip-ink-property +#[repr(u8)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[allow(missing_docs)] +pub enum TextDecorationSkipInk { + Auto, + None, +} |