diff options
28 files changed, 242 insertions, 205 deletions
diff --git a/components/layout/generated_content.rs b/components/layout/generated_content.rs index af710142446..8d1befdde33 100644 --- a/components/layout/generated_content.rs +++ b/components/layout/generated_content.rs @@ -366,16 +366,15 @@ impl<'a, 'b> ResolveGeneratedContentFragmentMutator<'a, 'b> { if quotes.0.is_empty() { return String::new(); } - let &(ref open_quote, ref close_quote) = if self.traversal.quote as usize >= quotes.0.len() - { + let pair = if self.traversal.quote as usize >= quotes.0.len() { quotes.0.last().unwrap() } else { "es.0[self.traversal.quote as usize] }; if close { - close_quote.to_string() + pair.closing.to_string() } else { - open_quote.to_string() + pair.opening.to_string() } } } diff --git a/components/style/gecko/arc_types.rs b/components/style/gecko/arc_types.rs index ed409804274..ac1175743bc 100644 --- a/components/style/gecko/arc_types.rs +++ b/components/style/gecko/arc_types.rs @@ -27,6 +27,7 @@ use gecko_bindings::structs::RawServoCssUrlData; use gecko_bindings::structs::RawServoDeclarationBlock; use gecko_bindings::structs::RawServoFontFaceRule; use gecko_bindings::structs::RawServoMediaList; +use gecko_bindings::structs::RawServoQuotes; use gecko_bindings::structs::RawServoStyleRule; use gecko_bindings::structs::RawServoStyleSheetContents; use gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI, Strong}; @@ -41,6 +42,7 @@ use stylesheets::keyframes_rule::Keyframe; use stylesheets::{CounterStyleRule, CssRules, FontFaceRule, FontFeatureValuesRule}; use stylesheets::{DocumentRule, ImportRule, KeyframesRule, MediaRule, NamespaceRule, PageRule}; use stylesheets::{StyleRule, StylesheetContents, SupportsRule}; +use values::computed::QuotePair; macro_rules! impl_arc_ffi { ($servo_type:ty => $gecko_type:ty[$addref:ident, $release:ident]) => { @@ -115,6 +117,9 @@ impl_arc_ffi!(Locked<CounterStyleRule> => RawServoCounterStyleRule impl_arc_ffi!(CssUrlData => RawServoCssUrlData [Servo_CssUrlData_AddRef, Servo_CssUrlData_Release]); +impl_arc_ffi!(Box<[QuotePair]> => RawServoQuotes + [Servo_Quotes_AddRef, Servo_Quotes_Release]); + // RuleNode is a Arc-like type but it does not use Arc. impl StrongRuleNode { diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs index 7761d9c2655..aae0104c442 100644 --- a/components/style/gecko/data.rs +++ b/components/style/gecko/data.rs @@ -8,10 +8,9 @@ use atomic_refcell::{AtomicRef, AtomicRefCell, AtomicRefMut}; use context::QuirksMode; use dom::TElement; use gecko_bindings::bindings::{self, RawServoStyleSet}; +use gecko_bindings::structs::StyleSheet as DomStyleSheet; use gecko_bindings::structs::{nsIDocument, StyleSheetInfo}; -use gecko_bindings::structs::{ - RawGeckoPresContextBorrowed, ServoStyleSetSizes, StyleSheet as DomStyleSheet, -}; +use gecko_bindings::structs::{RawGeckoPresContextBorrowed, ServoStyleSetSizes}; use gecko_bindings::sugar::ownership::{HasArcFFI, HasBoxFFI, HasFFI, HasSimpleFFI}; use invalidation::media_queries::{MediaListKey, ToMediaListKey}; use malloc_size_of::MallocSizeOfOps; diff --git a/components/style/gecko/non_ts_pseudo_class_list.rs b/components/style/gecko/non_ts_pseudo_class_list.rs index b37af9d71b6..f7d8be418de 100644 --- a/components/style/gecko/non_ts_pseudo_class_list.rs +++ b/components/style/gecko/non_ts_pseudo_class_list.rs @@ -3,29 +3,28 @@ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ /* -* This file contains a helper macro includes all supported non-tree-structural -* pseudo-classes. -* - -* FIXME: Find a way to autogenerate this file. -* -* Expected usage is as follows: -* ``` -* macro_rules! pseudo_class_macro{ -* ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { -* // do stuff -* } -* } -* apply_non_ts_list!(pseudo_class_macro) -* ``` -* -* $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType. -* $state can be either "_" or an expression of type ElementState. If present, -* the semantics are that the pseudo-class matches if any of the bits in -* $state are set on the element. -* $flags can be either "_" or an expression of type NonTSPseudoClassFlag, -* see selector_parser.rs for more details. -*/ + * This file contains a helper macro includes all supported non-tree-structural + * pseudo-classes. + * + * FIXME: Find a way to autogenerate this file. + * + * Expected usage is as follows: + * ``` + * macro_rules! pseudo_class_macro{ + * ([$(($css:expr, $name:ident, $gecko_type:tt, $state:tt, $flags:tt),)*]) => { + * // do stuff + * } + * } + * apply_non_ts_list!(pseudo_class_macro) + * ``` + * + * $gecko_type can be either "_" or an ident in Gecko's CSSPseudoClassType. + * $state can be either "_" or an expression of type ElementState. If present, + * the semantics are that the pseudo-class matches if any of the bits in + * $state are set on the element. + * $flags can be either "_" or an expression of type NonTSPseudoClassFlag, + * see selector_parser.rs for more details. + */ macro_rules! apply_non_ts_list { ($apply_macro:ident) => { diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 9020888d9a8..7f323e9d019 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -17,13 +17,10 @@ use nsstring::{nsACString, nsCStr}; use std::cmp::max; use values::computed::basic_shape::ShapeRadius as ComputedShapeRadius; use values::computed::FlexBasis as ComputedFlexBasis; -use values::computed::{ - Angle, ExtremumLength, Length, LengthOrPercentage, LengthOrPercentageOrAuto, -}; +use values::computed::{Angle, ExtremumLength, Length, LengthOrPercentage}; +use values::computed::{LengthOrPercentageOrAuto, Percentage}; use values::computed::{LengthOrPercentageOrNone, Number, NumberOrPercentage}; -use values::computed::{ - MaxLength as ComputedMaxLength, MozLength as ComputedMozLength, Percentage, -}; +use values::computed::{MaxLength as ComputedMaxLength, MozLength as ComputedMozLength}; use values::computed::{NonNegativeLength, NonNegativeLengthOrPercentage, NonNegativeNumber}; use values::generics::basic_shape::ShapeRadius; use values::generics::box_::Perspective; diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index b67e69849d1..46206aee7b3 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -44,9 +44,6 @@ use gecko_bindings::bindings::Gecko_MatchLang; use gecko_bindings::bindings::Gecko_UnsetDirtyStyleAttr; use gecko_bindings::bindings::Gecko_UpdateAnimations; use gecko_bindings::bindings::{Gecko_ElementState, Gecko_GetDocumentLWTheme}; -use gecko_bindings::bindings::{ - Gecko_GetLastChild, Gecko_GetNextStyleChild, Gecko_GetPreviousSibling, -}; use gecko_bindings::bindings::{Gecko_SetNodeFlags, Gecko_UnsetNodeFlags}; use gecko_bindings::structs; use gecko_bindings::structs::nsChangeHint; @@ -384,12 +381,12 @@ impl<'ln> TNode for GeckoNode<'ln> { #[inline] fn last_child(&self) -> Option<Self> { - unsafe { Gecko_GetLastChild(self.0).map(GeckoNode) } + unsafe { bindings::Gecko_GetLastChild(self.0).map(GeckoNode) } } #[inline] fn prev_sibling(&self) -> Option<Self> { - unsafe { Gecko_GetPreviousSibling(self.0).map(GeckoNode) } + unsafe { bindings::Gecko_GetPreviousSibling(self.0).map(GeckoNode) } } #[inline] @@ -506,7 +503,7 @@ impl<'a> Iterator for GeckoChildrenIterator<'a> { // however we can't express this easily with bindgen, and it would // introduce functions with two input lifetimes into bindgen, // which would be out of scope for elision. - Gecko_GetNextStyleChild(&mut *(it as *mut _)).map(GeckoNode) + bindings::Gecko_GetNextStyleChild(&mut *(it as *mut _)).map(GeckoNode) }, } } diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs index ca37c4e576f..d387c6da025 100644 --- a/components/style/gecko_bindings/sugar/refptr.rs +++ b/components/style/gecko_bindings/sugar/refptr.rs @@ -211,6 +211,18 @@ impl<T: RefCounted> structs::RefPtr<T> { } impl<T> structs::RefPtr<T> { + /// Sets the contents to an `Arc<T>`, releasing the old value in `self` if + /// necessary. + pub fn set_arc<U>(&mut self, other: Arc<U>) + where + U: HasArcFFI<FFIType = T>, + { + unsafe { + U::release_opt(self.mRawPtr.as_ref()); + } + self.set_arc_leaky(other); + } + /// Sets the contents to an Arc<T> /// will leak existing contents pub fn set_arc_leaky<U>(&mut self, other: Arc<U>) @@ -278,11 +290,6 @@ impl_threadsafe_refcount!( bindings::Gecko_ReleaseURLExtraDataArbitraryThread ); impl_threadsafe_refcount!( - structs::nsStyleQuoteValues, - bindings::Gecko_AddRefQuoteValuesArbitraryThread, - bindings::Gecko_ReleaseQuoteValuesArbitraryThread -); -impl_threadsafe_refcount!( structs::nsCSSValueSharedList, bindings::Gecko_AddRefCSSValueSharedListArbitraryThread, bindings::Gecko_ReleaseCSSValueSharedListArbitraryThread diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index d51a43166b9..7fe1cd4d5c7 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -4180,23 +4180,11 @@ fn static_assert() { } pub fn set_quotes(&mut self, other: longhands::quotes::computed_value::T) { - use gecko_bindings::bindings::Gecko_NewStyleQuoteValues; - use gecko_bindings::sugar::refptr::UniqueRefPtr; - - let mut refptr = unsafe { - UniqueRefPtr::from_addrefed(Gecko_NewStyleQuoteValues(other.0.len() as u32)) - }; - - for (servo, gecko) in other.0.into_iter().zip(refptr.mQuotePairs.iter_mut()) { - gecko.first.assign_str(&servo.0); - gecko.second.assign_str(&servo.1); - } - - self.gecko.mQuotes.set_move(refptr.get()) + self.gecko.mQuotes.set_arc(other.0.clone()); } pub fn copy_quotes_from(&mut self, other: &Self) { - unsafe { self.gecko.mQuotes.set(&other.gecko.mQuotes); } + self.set_quotes(other.clone_quotes()); } pub fn reset_quotes(&mut self, other: &Self) { @@ -4204,17 +4192,13 @@ fn static_assert() { } pub fn clone_quotes(&self) -> longhands::quotes::computed_value::T { - unsafe { - let ref gecko_quote_values = *self.gecko.mQuotes.mRawPtr; - longhands::quotes::computed_value::T( - gecko_quote_values.mQuotePairs.iter().map(|gecko_pair| { - ( - gecko_pair.first.to_string().into_boxed_str(), - gecko_pair.second.to_string().into_boxed_str(), - ) - }).collect::<Vec<_>>().into_boxed_slice() - ) - } + use gecko_bindings::sugar::ownership::HasArcFFI; + use values::computed::QuotePair; + + let quote_pairs = unsafe { &*self.gecko.mQuotes.mRawPtr }; + longhands::quotes::computed_value::T( + Box::<[QuotePair]>::as_arc("e_pairs).clone_arc() + ) } #[allow(non_snake_case)] diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index ba1a6444d42..2ab27687241 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -2212,7 +2212,6 @@ impl ComputedScale { Scale::None => (1.0, 1.0, 1.0), Scale::Scale3D(sx, sy, sz) => (sx, sy, sz), Scale::Scale(sx, sy) => (sx, sy, 1.), - Scale::ScaleX(sx) => (sx, 1., 1.), } } } @@ -2224,21 +2223,38 @@ impl Animate for ComputedScale { other: &Self, procedure: Procedure, ) -> Result<Self, ()> { - let from = ComputedScale::resolve(self); - let to = ComputedScale::resolve(other); - - // FIXME(emilio, bug 1464791): why does this do something different than - // Scale3D / TransformOperation::Scale3D? - if procedure == Procedure::Add { - // scale(x1,y1,z1)*scale(x2,y2,z2) = scale(x1*x2, y1*y2, z1*z2) - return Ok(Scale::Scale3D(from.0 * to.0, from.1 * to.1, from.2 * to.2)); + match (self, other) { + (&Scale::None, &Scale::None) => Ok(Scale::None), + (&Scale::Scale3D(_, ..), _) | (_, &Scale::Scale3D(_, ..)) => { + let from = ComputedScale::resolve(self); + let to = ComputedScale::resolve(other); + // FIXME(emilio, bug 1464791): why does this do something different than + // Scale3D / TransformOperation::Scale3D? + if procedure == Procedure::Add { + // scale(x1,y1,z1)*scale(x2,y2,z2) = scale(x1*x2, y1*y2, z1*z2) + return Ok(Scale::Scale3D(from.0 * to.0, from.1 * to.1, from.2 * to.2)); + } + Ok(Scale::Scale3D( + animate_multiplicative_factor(from.0, to.0, procedure)?, + animate_multiplicative_factor(from.1, to.1, procedure)?, + animate_multiplicative_factor(from.2, to.2, procedure)?, + )) + }, + (&Scale::Scale(_, ..), _) | (_, &Scale::Scale(_, ..)) => { + let from = ComputedScale::resolve(self); + let to = ComputedScale::resolve(other); + // FIXME(emilio, bug 1464791): why does this do something different than + // Scale / TransformOperation::Scale? + if procedure == Procedure::Add { + // scale(x1,y1)*scale(x2,y2) = scale(x1*x2, y1*y2) + return Ok(Scale::Scale(from.0 * to.0, from.1 * to.1)); + } + Ok(Scale::Scale( + animate_multiplicative_factor(from.0, to.0, procedure)?, + animate_multiplicative_factor(from.1, to.1, procedure)?, + )) + }, } - - Ok(Scale::Scale3D( - animate_multiplicative_factor(from.0, to.0, procedure)?, - animate_multiplicative_factor(from.1, to.1, procedure)?, - animate_multiplicative_factor(from.2, to.2, procedure)?, - )) } } diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index d5e6a9b1106..c06ed16a22e 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -604,7 +604,6 @@ ${helpers.predefined_type( ${helpers.predefined_type( "shape-image-threshold", "Opacity", "0.0", products="gecko", - gecko_pref="layout.css.shape-outside.enabled", animation_value_type="ComputedValue", flags="APPLIES_TO_FIRST_LETTER", spec="https://drafts.csswg.org/css-shapes/#shape-image-threshold-property", @@ -615,7 +614,6 @@ ${helpers.predefined_type( "NonNegativeLengthOrPercentage", "computed::NonNegativeLengthOrPercentage::zero()", products="gecko", - gecko_pref="layout.css.shape-outside.enabled", animation_value_type="NonNegativeLengthOrPercentage", flags="APPLIES_TO_FIRST_LETTER", spec="https://drafts.csswg.org/css-shapes/#shape-margin-property", @@ -627,7 +625,6 @@ ${helpers.predefined_type( "generics::basic_shape::ShapeSource::None", products="gecko", boxed=True, - gecko_pref="layout.css.shape-outside.enabled", animation_value_type="ComputedValue", flags="APPLIES_TO_FIRST_LETTER", spec="https://drafts.csswg.org/css-shapes/#shape-outside-property", diff --git a/components/style/values/animated/length.rs b/components/style/values/animated/length.rs index 5b47103f0ea..823b9ed84e9 100644 --- a/components/style/values/animated/length.rs +++ b/components/style/values/animated/length.rs @@ -5,9 +5,8 @@ //! Animation implementation for various length-related types. use super::{Animate, Procedure, ToAnimatedValue, ToAnimatedZero}; -use values::computed::length::{ - CalcLengthOrPercentage, Length, LengthOrPercentageOrAuto, LengthOrPercentageOrNone, -}; +use values::computed::length::{CalcLengthOrPercentage, Length}; +use values::computed::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone}; use values::computed::MaxLength as ComputedMaxLength; use values::computed::MozLength as ComputedMozLength; use values::computed::Percentage; diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 10e1f211db3..3a3242a386b 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -17,7 +17,7 @@ use values::generics::length::{MaxLength as GenericMaxLength, MozLength as Gener use values::generics::NonNegative; use values::specified::length::ViewportPercentageLength; use values::specified::length::{AbsoluteLength, FontBaseSize, FontRelativeLength}; -use values::{specified, Auto, CSSFloat, Either, Normal}; +use values::{specified, Auto, CSSFloat, Either, IsAuto, Normal}; pub use super::image::Image; pub use values::specified::url::UrlOrNone; @@ -528,6 +528,13 @@ impl LengthOrPercentageOrAuto { /// A wrapper of LengthOrPercentageOrAuto, whose value must be >= 0. pub type NonNegativeLengthOrPercentageOrAuto = NonNegative<LengthOrPercentageOrAuto>; +impl IsAuto for NonNegativeLengthOrPercentageOrAuto { + #[inline] + fn is_auto(&self) -> bool { + *self == Self::auto() + } +} + impl NonNegativeLengthOrPercentageOrAuto { /// `auto` #[inline] diff --git a/components/style/values/computed/list.rs b/components/style/values/computed/list.rs index bd3930fa8de..ec71a823828 100644 --- a/components/style/values/computed/list.rs +++ b/components/style/values/computed/list.rs @@ -6,26 +6,30 @@ #[cfg(feature = "gecko")] pub use values::specified::list::ListStyleType; -pub use values::specified::list::Quotes; +pub use values::specified::list::{QuotePair, Quotes}; + +use servo_arc::Arc; + +lazy_static! { + static ref INITIAL_QUOTES: Arc<Box<[QuotePair]>> = Arc::new( + vec![ + QuotePair { + opening: "\u{201c}".to_owned().into_boxed_str(), + closing: "\u{201d}".to_owned().into_boxed_str(), + }, + QuotePair { + opening: "\u{2018}".to_owned().into_boxed_str(), + closing: "\u{2019}".to_owned().into_boxed_str(), + }, + ] + .into_boxed_slice() + ); +} impl Quotes { /// Initial value for `quotes`. - /// - /// FIXME(emilio): This should ideally not allocate. #[inline] pub fn get_initial_value() -> Quotes { - Quotes( - vec![ - ( - "\u{201c}".to_owned().into_boxed_str(), - "\u{201d}".to_owned().into_boxed_str(), - ), - ( - "\u{2018}".to_owned().into_boxed_str(), - "\u{2019}".to_owned().into_boxed_str(), - ), - ] - .into_boxed_slice(), - ) + Quotes(INITIAL_QUOTES.clone()) } } diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index a5c83eb43e0..0cf1dac5686 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -37,13 +37,11 @@ pub use self::angle::Angle; pub use self::background::{BackgroundRepeat, BackgroundSize}; pub use self::basic_shape::FillRule; pub use self::border::{BorderCornerRadius, BorderRadius, BorderSpacing}; -pub use self::border::{ - BorderImageRepeat, BorderImageSideWidth, BorderImageSlice, BorderImageWidth, -}; -pub use self::box_::{ - AnimationIterationCount, AnimationName, Contain, Display, TransitionProperty, -}; +pub use self::border::{BorderImageRepeat, BorderImageSideWidth}; +pub use self::border::{BorderImageSlice, BorderImageWidth}; +pub use self::box_::{AnimationIterationCount, AnimationName, Contain}; pub use self::box_::{Appearance, Clear, Float}; +pub use self::box_::{Display, TransitionProperty}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize}; pub use self::box_::{ScrollSnapType, TouchAction, VerticalAlign, WillChange}; pub use self::color::{Color, ColorPropertyValue, RGBAColor}; @@ -52,13 +50,11 @@ pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset}; pub use self::easing::TimingFunction; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::flex::FlexBasis; -pub use self::font::{ - FontFamily, FontLanguageOverride, FontStyle, FontVariantEastAsian, FontVariationSettings, -}; +pub use self::font::{FontFamily, FontLanguageOverride, FontStyle}; pub use self::font::{FontFeatureSettings, FontVariantLigatures, FontVariantNumeric}; -pub use self::font::{ - FontSize, FontSizeAdjust, FontStretch, FontSynthesis, FontVariantAlternates, FontWeight, -}; +pub use self::font::{FontSize, FontSizeAdjust, FontStretch, FontSynthesis}; +pub use self::font::{FontVariantAlternates, FontWeight}; +pub use self::font::{FontVariantEastAsian, FontVariationSettings}; pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XLang, XTextZoom}; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; @@ -69,7 +65,7 @@ pub use self::length::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone, MaxLe pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercentageOrAuto}; #[cfg(feature = "gecko")] pub use self::list::ListStyleType; -pub use self::list::Quotes; +pub use self::list::{QuotePair, Quotes}; pub use self::motion::OffsetPath; pub use self::outline::OutlineStyle; pub use self::percentage::{NonNegativePercentage, Percentage}; @@ -81,9 +77,8 @@ pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::table::XSpan; pub use self::text::{InitialLetter, LetterSpacing, LineHeight, MozTabSize}; -pub use self::text::{ - TextAlign, TextEmphasisPosition, TextEmphasisStyle, TextOverflow, WordSpacing, -}; +pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle}; +pub use self::text::{TextOverflow, WordSpacing}; pub use self::time::Time; pub use self::transform::{Rotate, Scale, Transform, TransformOperation}; pub use self::transform::{TransformOrigin, TransformStyle, Translate}; diff --git a/components/style/values/computed/svg.rs b/components/style/values/computed/svg.rs index dd9cfb03b4b..9428ce60bae 100644 --- a/components/style/values/computed/svg.rs +++ b/components/style/values/computed/svg.rs @@ -6,9 +6,8 @@ use values::computed::color::Color; use values::computed::url::ComputedUrl; -use values::computed::{ - LengthOrPercentage, NonNegativeLengthOrPercentage, NonNegativeNumber, Number, Opacity, -}; +use values::computed::{LengthOrPercentage, NonNegativeLengthOrPercentage}; +use values::computed::{NonNegativeNumber, Number, Opacity}; use values::generics::svg as generic; use values::RGBA; diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index 9590ad4025f..e937b95c77f 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -367,7 +367,6 @@ impl Scale { pub fn to_transform_operation(&self) -> Option<TransformOperation> { match *self { generic::Scale::None => None, - generic::Scale::ScaleX(sx) => Some(generic::TransformOperation::ScaleX(sx)), generic::Scale::Scale(sx, sy) => Some(generic::TransformOperation::Scale(sx, Some(sy))), generic::Scale::Scale3D(sx, sy, sz) => { Some(generic::TransformOperation::Scale3D(sx, sy, sz)) @@ -378,8 +377,8 @@ impl Scale { /// Convert Scale to TransformOperation. pub fn from_transform_operation(operation: &TransformOperation) -> Scale { match *operation { - generic::TransformOperation::ScaleX(sx) => generic::Scale::ScaleX(sx), generic::TransformOperation::Scale(sx, Some(sy)) => generic::Scale::Scale(sx, sy), + generic::TransformOperation::Scale(sx, None) => generic::Scale::Scale(sx, sx), generic::TransformOperation::Scale3D(sx, sy, sz) => generic::Scale::Scale3D(sx, sy, sz), _ => unreachable!("Found unexpected value for scale"), } diff --git a/components/style/values/generics/background.rs b/components/style/values/generics/background.rs index a4f4c58d8cd..e1514959837 100644 --- a/components/style/values/generics/background.rs +++ b/components/style/values/generics/background.rs @@ -4,6 +4,10 @@ //! Generic types for CSS values related to backgrounds. +use std::fmt::{self, Write}; +use style_traits::{CssWriter, ToCss}; +use values::IsAuto; + /// A generic value for the `background-size` property. #[derive( Animate, @@ -17,7 +21,6 @@ ToAnimatedValue, ToAnimatedZero, ToComputedValue, - ToCss, )] pub enum BackgroundSize<LengthOrPercentageOrAuto> { /// `<width> <height>` @@ -34,3 +37,29 @@ pub enum BackgroundSize<LengthOrPercentageOrAuto> { #[animation(error)] Contain, } + +impl<LengthOrPercentageOrAuto> ToCss for BackgroundSize<LengthOrPercentageOrAuto> +where + LengthOrPercentageOrAuto: ToCss + IsAuto, +{ + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: Write, + { + match self { + BackgroundSize::Explicit { width, height } => { + width.to_css(dest)?; + // NOTE(emilio): We should probably simplify all these in case + // `width == `height`, but all other browsers agree on only + // special-casing `auto`. + if !width.is_auto() || !height.is_auto() { + dest.write_str(" ")?; + height.to_css(dest)?; + } + Ok(()) + }, + BackgroundSize::Cover => dest.write_str("cover"), + BackgroundSize::Contain => dest.write_str("contain"), + } + } +} diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index b4d011fd682..1eb46b0bd1d 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -7,6 +7,8 @@ use app_units::Au; use euclid::{self, Rect, Transform3D}; use num_traits::Zero; +use std::fmt::{self, Write}; +use style_traits::{CssWriter, ToCss}; use values::computed::length::Length as ComputedLength; use values::computed::length::LengthOrPercentage as ComputedLengthOrPercentage; use values::specified::angle::Angle as SpecifiedAngle; @@ -560,7 +562,6 @@ pub enum Rotate<Number, Angle> { SpecifiedValueInfo, ToAnimatedZero, ToComputedValue, - ToCss, )] /// A value of the `Scale` property /// @@ -568,14 +569,38 @@ pub enum Rotate<Number, Angle> { pub enum Scale<Number> { /// 'none' None, - /// '<number>' - ScaleX(Number), - /// '<number>{2}' + /// '<number>{1,2}' Scale(Number, Number), /// '<number>{3}' Scale3D(Number, Number, Number), } +impl<Number: ToCss + PartialEq> ToCss for Scale<Number> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: fmt::Write, + { + match *self { + Scale::None => dest.write_str("none"), + Scale::Scale(ref x, ref y) => { + x.to_css(dest)?; + if x != y { + dest.write_char(' ')?; + y.to_css(dest)?; + } + Ok(()) + }, + Scale::Scale3D(ref x, ref y, ref z) => { + x.to_css(dest)?; + dest.write_char(' ')?; + y.to_css(dest)?; + dest.write_char(' ')?; + z.to_css(dest) + }, + } + } +} + #[derive( Clone, ComputeSquaredDistance, diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index f182477e374..6d2dd1c2b3a 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -8,9 +8,8 @@ #![deny(missing_docs)] -pub use cssparser::{ - serialize_identifier, serialize_name, CowRcStr, Parser, SourceLocation, Token, RGBA, -}; +pub use cssparser::{serialize_identifier, serialize_name, CowRcStr, Parser}; +pub use cssparser::{SourceLocation, Token, RGBA}; use parser::{Parse, ParserContext}; use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Debug, Write}; @@ -243,6 +242,13 @@ impl KeyframesName { impl Eq for KeyframesName {} +/// A trait that returns whether a given type is the `auto` value or not. So far +/// only needed for background-size serialization, which special-cases `auto`. +pub trait IsAuto { + /// Returns whether the value is the `auto` value. + fn is_auto(&self) -> bool; +} + impl PartialEq for KeyframesName { fn eq(&self, other: &Self) -> bool { self.as_atom() == other.as_atom() diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index 589d0b13d0c..060cb093d8e 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -10,9 +10,8 @@ use parser::{Parse, ParserContext}; use properties::{LonghandId, PropertyDeclarationId, PropertyFlags, PropertyId, ShorthandId}; use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Write}; -use style_traits::{ - CssWriter, KeywordsCollectFn, ParseError, SpecifiedValueInfo, StyleParseErrorKind, ToCss, -}; +use style_traits::{CssWriter, KeywordsCollectFn, ParseError}; +use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; use values::generics::box_::AnimationIterationCount as GenericAnimationIterationCount; use values::generics::box_::Perspective as GenericPerspective; use values::generics::box_::VerticalAlign as GenericVerticalAlign; diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index a2323c75c4b..45c9aa0e4e6 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -24,9 +24,8 @@ use values::generics::font::{self as generics, FeatureTagValue, FontSettings, Fo use values::generics::font::{KeywordSize, VariationValue}; use values::generics::NonNegative; use values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX}; -use values::specified::{ - AllowQuirks, Angle, Integer, LengthOrPercentage, NoCalcLength, Number, Percentage, -}; +use values::specified::{AllowQuirks, Angle, Integer, LengthOrPercentage}; +use values::specified::{NoCalcLength, Number, Percentage}; use values::CustomIdent; use Atom; diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 05f5ccd55cd..535cf6f65ee 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -20,7 +20,7 @@ use values::computed::{self, CSSPixelLength, Context, ExtremumLength}; use values::generics::length::{MaxLength as GenericMaxLength, MozLength as GenericMozLength}; use values::generics::NonNegative; use values::specified::calc::CalcNode; -use values::{Auto, CSSFloat, Either, Normal}; +use values::{Auto, CSSFloat, Either, IsAuto, Normal}; pub use super::image::{ColorStop, EndingShape as GradientEndingShape, Gradient}; pub use super::image::{GradientKind, Image}; @@ -980,6 +980,13 @@ impl Parse for LengthOrPercentageOrAuto { /// A wrapper of LengthOrPercentageOrAuto, whose value must be >= 0. pub type NonNegativeLengthOrPercentageOrAuto = NonNegative<LengthOrPercentageOrAuto>; +impl IsAuto for NonNegativeLengthOrPercentageOrAuto { + #[inline] + fn is_auto(&self) -> bool { + *self == Self::auto() + } +} + impl NonNegativeLengthOrPercentageOrAuto { /// 0 #[inline] diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs index 4e30364eff5..3c0fb89258b 100644 --- a/components/style/values/specified/list.rs +++ b/components/style/values/specified/list.rs @@ -6,8 +6,8 @@ use cssparser::{Parser, Token}; use parser::{Parse, ParserContext}; -use std::fmt::{self, Write}; -use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; +use servo_arc::Arc; +use style_traits::{ParseError, StyleParseErrorKind}; #[cfg(feature = "gecko")] use values::generics::CounterStyleOrNone; #[cfg(feature = "gecko")] @@ -73,41 +73,24 @@ impl Parse for ListStyleType { } } -/// Specified and computed `quote` property. -/// -/// FIXME(emilio): It's a shame that this allocates all the time it's computed, -/// probably should just be refcounted. -/// FIXME This can probably derive ToCss. -#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)] -pub struct Quotes(#[css(if_empty = "none")] pub Box<[(Box<str>, Box<str>)]>); - -impl ToCss for Quotes { - fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result - where - W: Write, - { - let mut iter = self.0.iter(); - - match iter.next() { - Some(&(ref l, ref r)) => { - l.to_css(dest)?; - dest.write_char(' ')?; - r.to_css(dest)?; - }, - None => return dest.write_str("none"), - } - - for &(ref l, ref r) in iter { - dest.write_char(' ')?; - l.to_css(dest)?; - dest.write_char(' ')?; - r.to_css(dest)?; - } +/// A quote pair. +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] +pub struct QuotePair { + /// The opening quote. + pub opening: Box<str>, - Ok(()) - } + /// The closing quote. + pub closing: Box<str>, } +/// Specified and computed `quotes` property. +#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)] +pub struct Quotes( + #[css(iterable, if_empty = "none")] + #[ignore_malloc_size_of = "Arc"] + pub Arc<Box<[QuotePair]>>, +); + impl Parse for Quotes { fn parse<'i, 't>( _: &ParserContext, @@ -117,24 +100,24 @@ impl Parse for Quotes { .try(|input| input.expect_ident_matching("none")) .is_ok() { - return Ok(Quotes(Vec::new().into_boxed_slice())); + return Ok(Quotes(Arc::new(Box::new([])))); } let mut quotes = Vec::new(); loop { let location = input.current_source_location(); - let first = match input.next() { + let opening = match input.next() { Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into_boxed_str(), Ok(t) => return Err(location.new_unexpected_token_error(t.clone())), Err(_) => break, }; - let second = input.expect_string()?.as_ref().to_owned().into_boxed_str(); - quotes.push((first, second)) + let closing = input.expect_string()?.as_ref().to_owned().into_boxed_str(); + quotes.push(QuotePair { opening, closing }); } if !quotes.is_empty() { - Ok(Quotes(quotes.into_boxed_slice())) + Ok(Quotes(Arc::new(quotes.into_boxed_slice()))) } else { Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index afac1f50a39..21fd4b86e94 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -43,13 +43,11 @@ pub use self::counters::{Content, ContentItem, CounterIncrement, CounterReset}; pub use self::easing::TimingFunction; pub use self::effects::{BoxShadow, Filter, SimpleShadow}; pub use self::flex::FlexBasis; -pub use self::font::{ - FontFamily, FontLanguageOverride, FontStyle, FontVariantEastAsian, FontVariationSettings, -}; +pub use self::font::{FontFamily, FontLanguageOverride, FontStyle}; pub use self::font::{FontFeatureSettings, FontVariantLigatures, FontVariantNumeric}; -pub use self::font::{ - FontSize, FontSizeAdjust, FontStretch, FontSynthesis, FontVariantAlternates, FontWeight, -}; +pub use self::font::{FontSize, FontSizeAdjust, FontStretch, FontSynthesis}; +pub use self::font::{FontVariantAlternates, FontWeight}; +pub use self::font::{FontVariantEastAsian, FontVariationSettings}; pub use self::font::{MozScriptLevel, MozScriptMinSize, MozScriptSizeMultiplier, XLang, XTextZoom}; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; @@ -63,7 +61,7 @@ pub use self::length::{NoCalcLength, ViewportPercentageLength}; pub use self::length::{NonNegativeLengthOrPercentage, NonNegativeLengthOrPercentageOrAuto}; #[cfg(feature = "gecko")] pub use self::list::ListStyleType; -pub use self::list::Quotes; +pub use self::list::{QuotePair, Quotes}; pub use self::motion::OffsetPath; pub use self::outline::OutlineStyle; pub use self::percentage::Percentage; diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index d306211329e..d397d3d3607 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -423,6 +423,6 @@ impl Parse for Scale { } // 'scale: <number>' - Ok(generic::Scale::ScaleX(sx)) + Ok(generic::Scale::Scale(sx, sx)) } } diff --git a/tests/wpt/metadata/css/css-backgrounds/background-331.html.ini b/tests/wpt/metadata/css/css-backgrounds/background-331.html.ini index 45ff8ab5b26..761126c8873 100644 --- a/tests/wpt/metadata/css/css-backgrounds/background-331.html.ini +++ b/tests/wpt/metadata/css/css-backgrounds/background-331.html.ini @@ -1,7 +1,5 @@ [background-331.html] type: testharness - [background_initial_size] - expected: FAIL [background_initial_position] expected: FAIL diff --git a/tests/wpt/metadata/css/css-backgrounds/background-333.html.ini b/tests/wpt/metadata/css/css-backgrounds/background-333.html.ini index b8af0d97a00..6b126041716 100644 --- a/tests/wpt/metadata/css/css-backgrounds/background-333.html.ini +++ b/tests/wpt/metadata/css/css-backgrounds/background-333.html.ini @@ -1,7 +1,5 @@ [background-333.html] type: testharness - [background_specified_color_size] - expected: FAIL [background_specified_color_position] expected: FAIL diff --git a/tests/wpt/metadata/css/css-backgrounds/background-size-001.html.ini b/tests/wpt/metadata/css/css-backgrounds/background-size-001.html.ini index c5e74478dc1..071ab97fece 100644 --- a/tests/wpt/metadata/css/css-backgrounds/background-size-001.html.ini +++ b/tests/wpt/metadata/css/css-backgrounds/background-size-001.html.ini @@ -1,10 +1,5 @@ [background-size-001.html] type: testharness - [background-size_initial] - expected: FAIL - - [background-size_auto] - expected: FAIL [background-size_length_zero] expected: FAIL @@ -27,6 +22,3 @@ [background-size_percentage_max] expected: FAIL - [background-size_auto_auto] - expected: FAIL - |