aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--components/layout/generated_content.rs7
-rw-r--r--components/style/gecko/arc_types.rs5
-rw-r--r--components/style/gecko/data.rs5
-rw-r--r--components/style/gecko/non_ts_pseudo_class_list.rs45
-rw-r--r--components/style/gecko/values.rs9
-rw-r--r--components/style/gecko/wrapper.rs9
-rw-r--r--components/style/gecko_bindings/sugar/refptr.rs17
-rw-r--r--components/style/properties/gecko.mako.rs34
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs46
-rw-r--r--components/style/properties/longhands/box.mako.rs3
-rw-r--r--components/style/values/animated/length.rs5
-rw-r--r--components/style/values/computed/length.rs9
-rw-r--r--components/style/values/computed/list.rs36
-rw-r--r--components/style/values/computed/mod.rs27
-rw-r--r--components/style/values/computed/svg.rs5
-rw-r--r--components/style/values/computed/transform.rs3
-rw-r--r--components/style/values/generics/background.rs31
-rw-r--r--components/style/values/generics/transform.rs33
-rw-r--r--components/style/values/mod.rs12
-rw-r--r--components/style/values/specified/box.rs5
-rw-r--r--components/style/values/specified/font.rs5
-rw-r--r--components/style/values/specified/length.rs9
-rw-r--r--components/style/values/specified/list.rs61
-rw-r--r--components/style/values/specified/mod.rs12
-rw-r--r--components/style/values/specified/transform.rs2
-rw-r--r--tests/wpt/metadata/css/css-backgrounds/background-331.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-backgrounds/background-333.html.ini2
-rw-r--r--tests/wpt/metadata/css/css-backgrounds/background-size-001.html.ini8
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 {
&quotes.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(&quote_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
-