diff --git a/components/style/cbindgen.toml b/components/style/cbindgen.toml index 46162e43db5..8bcba69c057 100644 --- a/components/style/cbindgen.toml +++ b/components/style/cbindgen.toml @@ -6,7 +6,17 @@ autogen_warning = """/* DO NOT MODIFY THIS MANUALLY! This file was generated usi * 1. Get the latest cbindgen using `cargo install --force cbindgen` * a. Alternatively, you can clone `https://github.com/eqrion/cbindgen` and use a tagged release * 2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate style -o layout/style/ServoStyleConsts.h` - */""" + */ +class nsAtom; +namespace mozilla { + namespace css { + struct URLValue; + } + // Work-around weird cbindgen renaming. + typedef css::URLValue StyleURLValue; + typedef nsAtom StylensAtom; +} +""" include_guard = "mozilla_ServoStyleConsts_h" include_version = true braces = "SameLine" @@ -15,6 +25,10 @@ tab_width = 2 language = "C++" namespaces = ["mozilla"] +[parse] +parse_deps = true +include = ["cssparser"] + [struct] derive_eq = true @@ -25,9 +39,16 @@ derive_helper_methods = true prefix = "Style" include = [ "StyleAppearance", + "StyleComputedFontStretchRange", + "StyleComputedFontStyleDescriptor", + "StyleComputedFontWeightRange", "StyleDisplay", "StyleDisplayMode", "StyleFillRule", - "StylePathCommand" + "StyleFontDisplay", + "StyleFontFaceSourceListComponent", + "StyleFontLanguageOverride", + "StylePathCommand", + "StyleUnicodeRange", ] item_types = ["enums", "structs", "typedefs"] diff --git a/components/style/font_face.rs b/components/style/font_face.rs index fde25f08f6f..b78947dd400 100644 --- a/components/style/font_face.rs +++ b/components/style/font_face.rs @@ -24,7 +24,7 @@ use style_traits::values::SequenceWriter; use values::computed::font::FamilyName; use values::generics::font::FontStyle as GenericFontStyle; use values::specified::Angle; -use values::specified::font::{AbsoluteFontWeight, FontStretch as SpecifiedFontStretch}; +use values::specified::font::{AbsoluteFontWeight, FontStretch}; #[cfg(feature = "gecko")] use values::specified::font::{SpecifiedFontFeatureSettings, SpecifiedFontVariationSettings}; use values::specified::font::SpecifiedFontStyle; @@ -45,6 +45,19 @@ impl OneOrMoreSeparated for Source { type S = Comma; } +/// A POD representation for Gecko. All pointers here are non-owned and as such +/// can't outlive the rule they came from, but we can't enforce that via C++. +/// +/// All the strings are of course utf8. +#[cfg(feature = "gecko")] +#[repr(u8)] +#[allow(missing_docs)] +pub enum FontFaceSourceListComponent { + Url(*const ::gecko_bindings::structs::mozilla::css::URLValue), + Local(*mut ::gecko_bindings::structs::nsAtom), + FormatHint { length: usize, utf8_bytes: *const u8 }, +} + /// A `UrlSource` represents a font-face source that has been specified with a /// `url()` function. /// @@ -84,6 +97,7 @@ impl ToCss for UrlSource { #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss)] +#[repr(u8)] pub enum FontDisplay { Auto, Block, @@ -92,41 +106,83 @@ pub enum FontDisplay { Optional, } +macro_rules! impl_range { + ($range:ident, $component:ident) => { + impl Parse for $range { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let first = $component::parse(context, input)?; + let second = input + .try(|input| $component::parse(context, input)) + .unwrap_or_else(|_| first.clone()); + Ok($range(first, second)) + } + } + impl ToCss for $range { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: fmt::Write, + { + self.0.to_css(dest)?; + if self.0 != self.1 { + dest.write_str(" ")?; + self.1.to_css(dest)?; + } + Ok(()) + } + } + } +} + /// The font-weight descriptor: /// /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-weight -#[derive(Clone, Debug, PartialEq, ToCss)] -pub struct FontWeight(pub AbsoluteFontWeight, pub Option); +#[derive(Clone, Debug, PartialEq)] +pub struct FontWeightRange(pub AbsoluteFontWeight, pub AbsoluteFontWeight); +impl_range!(FontWeightRange, AbsoluteFontWeight); -impl Parse for FontWeight { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - let first = AbsoluteFontWeight::parse(context, input)?; - let second = input - .try(|input| AbsoluteFontWeight::parse(context, input)) - .ok(); - Ok(FontWeight(first, second)) +/// The computed representation of the above so Gecko can read them easily. +/// +/// This one is needed because cbindgen doesn't know how to generate +/// specified::Number. +#[repr(C)] +#[allow(missing_docs)] +pub struct ComputedFontWeightRange(f32, f32); + +impl FontWeightRange { + /// Returns a computed font-stretch range. + pub fn compute(&self) -> ComputedFontWeightRange { + ComputedFontWeightRange(self.0.compute().0, self.1.compute().0) } } /// The font-stretch descriptor: /// /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-stretch -#[derive(Clone, Debug, PartialEq, ToCss)] -pub struct FontStretch(pub SpecifiedFontStretch, pub Option); +#[derive(Clone, Debug, PartialEq)] +pub struct FontStretchRange(pub FontStretch, pub FontStretch); +impl_range!(FontStretchRange, FontStretch); -impl Parse for FontStretch { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - let first = SpecifiedFontStretch::parse(context, input)?; - let second = input - .try(|input| SpecifiedFontStretch::parse(context, input)) - .ok(); - Ok(FontStretch(first, second)) +/// The computed representation of the above, so that +/// Gecko can read them easily. +#[repr(C)] +#[allow(missing_docs)] +pub struct ComputedFontStretchRange(f32, f32); + +impl FontStretchRange { + /// Returns a computed font-stretch range. + pub fn compute(&self) -> ComputedFontStretchRange { + fn compute_stretch(s: &FontStretch) -> f32 { + match *s { + FontStretch::Keyword(ref kw) => kw.compute().0, + FontStretch::Stretch(ref p) => p.get(), + FontStretch::System(..) => unreachable!(), + } + } + + ComputedFontStretchRange(compute_stretch(&self.0), compute_stretch(&self.1)) } } @@ -141,6 +197,16 @@ pub enum FontStyle { Oblique(Angle, Angle), } +/// The computed representation of the above, with angles in degrees, so that +/// Gecko can read them easily. +#[repr(u8)] +#[allow(missing_docs)] +pub enum ComputedFontStyleDescriptor { + Normal, + Italic, + Oblique(f32, f32), +} + impl Parse for FontStyle { fn parse<'i, 't>( context: &ParserContext, @@ -185,6 +251,22 @@ impl ToCss for FontStyle { } } +impl FontStyle { + /// Returns a computed font-style descriptor. + pub fn compute(&self) -> ComputedFontStyleDescriptor { + match *self { + FontStyle::Normal => ComputedFontStyleDescriptor::Normal, + FontStyle::Italic => ComputedFontStyleDescriptor::Italic, + FontStyle::Oblique(ref first, ref second) => { + ComputedFontStyleDescriptor::Oblique( + SpecifiedFontStyle::compute_angle_degrees(first), + SpecifiedFontStyle::compute_angle_degrees(second), + ) + } + } + } +} + /// Parse the block inside a `@font-face` rule. /// /// Note that the prelude parsing code lives in the `stylesheets` module. @@ -459,10 +541,10 @@ font_face_descriptors! { "font-style" style / mStyle: FontStyle, /// The weight of this font face. - "font-weight" weight / mWeight: FontWeight, + "font-weight" weight / mWeight: FontWeightRange, /// The stretch of this font face. - "font-stretch" stretch / mStretch: FontStretch, + "font-stretch" stretch / mStretch: FontStretchRange, /// The display of this font face. "font-display" display / mDisplay: FontDisplay, diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index c6009c96dee..846f2113f77 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -17,7 +17,7 @@ use gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataVa use std::f32::consts::PI; use stylesheets::{Origin, RulesMutateError}; use values::computed::{Angle, CalcLengthOrPercentage, Gradient, Image}; -use values::computed::{Integer, LengthOrPercentage, LengthOrPercentageOrAuto}; +use values::computed::{Integer, LengthOrPercentage, LengthOrPercentageOrAuto, NonNegativeLengthOrPercentageOrAuto}; use values::computed::{Percentage, TextAlign}; use values::computed::image::LineDirection; use values::computed::url::ComputedImageUrl; @@ -106,6 +106,26 @@ impl From for LengthOrPercentageOrAuto { } } +// FIXME(emilio): A lot of these impl From should probably become explicit or +// disappear as we move more stuff to cbindgen. +impl From for NonNegativeLengthOrPercentageOrAuto { + fn from(other: nsStyleCoord_CalcValue) -> Self { + use style_traits::values::specified::AllowedNumericType; + use values::generics::NonNegative; + NonNegative(if other.mLength < 0 || other.mPercent < 0. { + LengthOrPercentageOrAuto::Calc( + CalcLengthOrPercentage::with_clamping_mode( + Au(other.mLength).into(), + if other.mHasPercent { Some(Percentage(other.mPercent)) } else { None }, + AllowedNumericType::NonNegative, + ) + ) + } else { + other.into() + }) + } +} + impl From for CoordDataValue { fn from(reference: Angle) -> Self { match reference { diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs index 5c744f24220..9e84a7722b1 100644 --- a/components/style/gecko/media_features.rs +++ b/components/style/gecko/media_features.rs @@ -479,7 +479,7 @@ lazy_static! { /// to support new types in these entries and (2) ensuring that either /// nsPresContext::MediaFeatureValuesChanged is called when the value that /// would be returned by the evaluator function could change. - pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 47] = [ + pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 48] = [ feature!( atom!("width"), AllowsRanges::Yes, @@ -660,6 +660,7 @@ lazy_static! { system_metric_feature!(atom!("-moz-menubar-drag")), system_metric_feature!(atom!("-moz-swipe-animation-enabled")), system_metric_feature!(atom!("-moz-gtk-csd-available")), + system_metric_feature!(atom!("-moz-gtk-csd-transparent-background")), system_metric_feature!(atom!("-moz-gtk-csd-minimize-button")), system_metric_feature!(atom!("-moz-gtk-csd-maximize-button")), system_metric_feature!(atom!("-moz-gtk-csd-close-button")), diff --git a/components/style/gecko/regen_atoms.py b/components/style/gecko/regen_atoms.py index 13f0a8c0005..097e2d6be37 100755 --- a/components/style/gecko/regen_atoms.py +++ b/components/style/gecko/regen_atoms.py @@ -15,34 +15,11 @@ sys.path.insert(0, os.path.join(os.path.dirname(GECKO_DIR), "properties")) import build -PRELUDE = """ -/* 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 http://mozilla.org/MPL/2.0/. */ - -/* Autogenerated file created by components/style/gecko/regen_atoms.py, DO NOT EDIT DIRECTLY */ -"""[1:] # NOQA: E501 - # Matches lines like `GK_ATOM(foo, "foo", 0x12345678, nsStaticAtom, PseudoElementAtom)`. PATTERN = re.compile('^GK_ATOM\(([^,]*),[^"]*"([^"]*)",\s*(0x[0-9a-f]+),\s*([^,]*),\s*([^)]*)\)', re.MULTILINE) FILE = "include/nsGkAtomList.h" -CLASS = "nsGkAtoms" - - -def gnu_symbolify(ident): - return "_ZN{}{}{}{}E".format(len(CLASS), CLASS, len(ident), ident) - - -def msvc64_symbolify(ident, ty): - return "?{}@{}@@2PEAV{}@@EA".format(ident, CLASS, ty) - - -def msvc32_symbolify(ident, ty): - # Prepend "\x01" to avoid LLVM prefixing the mangled name with "_". - # See https://github.com/rust-lang/rust/issues/36097 - return "\\x01?{}@{}@@2PAV{}@@A".format(ident, CLASS, ty) def map_atom(ident): @@ -54,7 +31,7 @@ def map_atom(ident): class Atom: def __init__(self, ident, value, hash, ty, atom_type): - self.ident = "{}_{}".format(CLASS, ident) + self.ident = "nsGkAtoms_{}".format(ident) self.original_ident = ident self.value = value self.hash = hash @@ -68,15 +45,6 @@ class Atom: if self.is_anon_box(): assert self.is_inheriting_anon_box() or self.is_non_inheriting_anon_box() - def gnu_symbol(self): - return gnu_symbolify(self.original_ident) - - def msvc32_symbol(self): - return msvc32_symbolify(self.original_ident, self.ty) - - def msvc64_symbol(self): - return msvc64_symbolify(self.original_ident, self.ty) - def type(self): return self.ty @@ -144,73 +112,94 @@ class FileAvoidWrite(BytesIO): self.close() -IMPORTS = ("\nuse gecko_bindings::structs::nsStaticAtom;" - "\nuse string_cache::Atom;\n\n") +PRELUDE = ''' +/* 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 http://mozilla.org/MPL/2.0/. */ -ATOM_TEMPLATE = (" #[link_name = \"{link_name}\"]\n" - " pub static {name}: *mut {type};") +// Autogenerated file created by components/style/gecko/regen_atoms.py. +// DO NOT EDIT DIRECTLY +'''[1:] -UNSAFE_STATIC = ("#[inline(always)]\n" - "pub unsafe fn atom_from_static(ptr: *mut nsStaticAtom) -> Atom {\n" - " Atom::from_static(ptr)\n" - "}\n\n") +IMPORTS = ''' +use gecko_bindings::structs::nsStaticAtom; +use string_cache::Atom; +''' -CFG_IF = ''' +UNSAFE_STATIC = ''' +#[inline(always)] +pub unsafe fn atom_from_static(ptr: *const nsStaticAtom) -> Atom { + Atom::from_static(ptr) +} +''' + +SATOMS_TEMPLATE = ''' + #[link_name = \"{link_name}\"] + pub static nsGkAtoms_sAtoms: *const nsStaticAtom; +'''[1:] + +CFG_IF_TEMPLATE = ''' cfg_if! {{ if #[cfg(not(target_env = "msvc"))] {{ extern {{ -{gnu} +{gnu}\ }} }} else if #[cfg(target_pointer_width = "64")] {{ extern {{ -{msvc64} +{msvc64}\ }} }} else {{ extern {{ -{msvc32} +{msvc32}\ }} }} -}} +}}\n ''' -RULE_TEMPLATE = ('("{atom}") =>\n ' - '{{{{ ' - '#[allow(unsafe_code)] #[allow(unused_unsafe)]' - 'unsafe {{ $crate::string_cache::atom_macro::atom_from_static' - '($crate::string_cache::atom_macro::{name} as *mut _) }}' - ' }}}};') +CONST_TEMPLATE = ''' +pub const k_{name}: isize = {index}; +'''[1:] -MACRO = ''' +RULE_TEMPLATE = ''' +("{atom}") => + {{{{ + use $crate::string_cache::atom_macro; + #[allow(unsafe_code)] #[allow(unused_unsafe)] + unsafe {{ atom_macro::atom_from_static(atom_macro::nsGkAtoms_sAtoms.offset(atom_macro::k_{name})) }} + }}}}; +'''[1:] + +MACRO_TEMPLATE = ''' #[macro_export] macro_rules! atom {{ -{} +{body}\ }} ''' - def write_atom_macro(atoms, file_name): - def get_symbols(func): - return '\n'.join([ATOM_TEMPLATE.format(name=atom.ident, - link_name=func(atom), - type=atom.type()) for atom in atoms]) - with FileAvoidWrite(file_name) as f: f.write(PRELUDE) f.write(IMPORTS) - - for ty in sorted(set([atom.type() for atom in atoms])): - if ty != "nsStaticAtom": - f.write("pub enum {} {{}}\n\n".format(ty)) - f.write(UNSAFE_STATIC) - gnu_symbols = get_symbols(Atom.gnu_symbol) - msvc32_symbols = get_symbols(Atom.msvc32_symbol) - msvc64_symbols = get_symbols(Atom.msvc64_symbol) - f.write(CFG_IF.format(gnu=gnu_symbols, msvc32=msvc32_symbols, msvc64=msvc64_symbols)) + gnu_name='_ZN9nsGkAtoms6sAtomsE' + gnu_symbols = SATOMS_TEMPLATE.format(link_name=gnu_name) + + # Prepend "\x01" to avoid LLVM prefixing the mangled name with "_". + # See https://github.com/rust-lang/rust/issues/36097 + msvc32_name = '\\x01?sAtoms@nsGkAtoms@@0QBVnsStaticAtom@@B' + msvc32_symbols = SATOMS_TEMPLATE.format(link_name=msvc32_name) + + msvc64_name = '?sAtoms@nsGkAtoms@@0QEBVnsStaticAtom@@EB' + msvc64_symbols = SATOMS_TEMPLATE.format(link_name=msvc64_name) + + f.write(CFG_IF_TEMPLATE.format(gnu=gnu_symbols, msvc32=msvc32_symbols, msvc64=msvc64_symbols)) + + consts = [CONST_TEMPLATE.format(name=atom.ident, index=i) for (i, atom) in enumerate(atoms)] + f.write('{}'.format(''.join(consts))) macro_rules = [RULE_TEMPLATE.format(atom=atom.value, name=atom.ident) for atom in atoms] - f.write(MACRO.format('\n'.join(macro_rules))) + f.write(MACRO_TEMPLATE.format(body=''.join(macro_rules))) def write_pseudo_elements(atoms, target_filename): diff --git a/components/style/gecko/rules.rs b/components/style/gecko/rules.rs index 233b1757ef5..3bb605bfadc 100644 --- a/components/style/gecko/rules.rs +++ b/components/style/gecko/rules.rs @@ -4,201 +4,9 @@ //! Bindings for CSS Rule objects -use byteorder::{BigEndian, WriteBytesExt}; use counter_style::{self, CounterBound}; -use cssparser::UnicodeRange; -use font_face::{FontDisplay, FontWeight, FontStretch, FontStyle, Source}; use gecko_bindings::structs::{self, nsCSSValue}; use gecko_bindings::sugar::ns_css_value::ToNsCssValue; -use properties::longhands::font_language_override; -use std::str; -use values::computed::font::FamilyName; -use values::generics::font::FontTag; -use values::specified::font::{AbsoluteFontWeight, FontStretch as SpecifiedFontStretch}; -use values::specified::font::{SpecifiedFontFeatureSettings, SpecifiedFontVariationSettings}; -use values::specified::font::SpecifiedFontStyle; - -impl<'a> ToNsCssValue for &'a FamilyName { - fn convert(self, nscssvalue: &mut nsCSSValue) { - nscssvalue.set_string_from_atom(&self.name) - } -} - -impl<'a> ToNsCssValue for &'a SpecifiedFontStretch { - fn convert(self, nscssvalue: &mut nsCSSValue) { - let number = match *self { - SpecifiedFontStretch::Stretch(ref p) => p.get(), - SpecifiedFontStretch::Keyword(ref kw) => kw.compute().0, - SpecifiedFontStretch::System(..) => unreachable!(), - }; - nscssvalue.set_font_stretch(number); - } -} - -impl<'a> ToNsCssValue for &'a AbsoluteFontWeight { - fn convert(self, nscssvalue: &mut nsCSSValue) { - nscssvalue.set_font_weight(self.compute().0) - } -} - -impl ToNsCssValue for FontTag { - fn convert(self, nscssvalue: &mut nsCSSValue) { - let mut raw = [0u8; 4]; - (&mut raw[..]).write_u32::(self.0).unwrap(); - nscssvalue.set_string(str::from_utf8(&raw).unwrap()); - } -} - -impl<'a> ToNsCssValue for &'a SpecifiedFontFeatureSettings { - fn convert(self, nscssvalue: &mut nsCSSValue) { - if self.0.is_empty() { - nscssvalue.set_normal(); - return; - } - - nscssvalue.set_pair_list(self.0.iter().map(|entry| { - let mut index = nsCSSValue::null(); - index.set_integer(entry.value.value()); - (entry.tag.into(), index) - })) - } -} - -impl<'a> ToNsCssValue for &'a SpecifiedFontVariationSettings { - fn convert(self, nscssvalue: &mut nsCSSValue) { - if self.0.is_empty() { - nscssvalue.set_normal(); - return; - } - - nscssvalue.set_pair_list(self.0.iter().map(|entry| { - let mut value = nsCSSValue::null(); - value.set_number(entry.value.into()); - (entry.tag.into(), value) - })) - } -} - -macro_rules! descriptor_range_conversion { - ($name:ident) => { - impl<'a> ToNsCssValue for &'a $name { - fn convert(self, nscssvalue: &mut nsCSSValue) { - let $name(ref first, ref second) = *self; - let second = match *second { - None => { - nscssvalue.set_from(first); - return; - }, - Some(ref second) => second, - }; - - let mut a = nsCSSValue::null(); - let mut b = nsCSSValue::null(); - - a.set_from(first); - b.set_from(second); - - nscssvalue.set_pair(&a, &b); - } - } - }; -} - -descriptor_range_conversion!(FontWeight); -descriptor_range_conversion!(FontStretch); - -impl<'a> ToNsCssValue for &'a FontStyle { - fn convert(self, nscssvalue: &mut nsCSSValue) { - match *self { - FontStyle::Normal => nscssvalue.set_normal(), - FontStyle::Italic => nscssvalue.set_enum(structs::NS_FONT_STYLE_ITALIC as i32), - FontStyle::Oblique(ref first, ref second) => { - let mut a = nsCSSValue::null(); - let mut b = nsCSSValue::null(); - - a.set_font_style(SpecifiedFontStyle::compute_angle(first).degrees()); - b.set_font_style(SpecifiedFontStyle::compute_angle(second).degrees()); - - nscssvalue.set_pair(&a, &b); - }, - } - } -} - -impl<'a> ToNsCssValue for &'a font_language_override::SpecifiedValue { - fn convert(self, nscssvalue: &mut nsCSSValue) { - match *self { - font_language_override::SpecifiedValue::Normal => nscssvalue.set_normal(), - font_language_override::SpecifiedValue::Override(ref lang) => { - nscssvalue.set_string(&*lang) - }, - // This path is unreachable because the descriptor is only specified by the user. - font_language_override::SpecifiedValue::System(_) => unreachable!(), - } - } -} - -impl<'a> ToNsCssValue for &'a Vec { - fn convert(self, nscssvalue: &mut nsCSSValue) { - let src_len = self.iter().fold(0, |acc, src| { - acc + match *src { - // Each format hint takes one position in the array of mSrc. - Source::Url(ref url) => url.format_hints.len() + 1, - Source::Local(_) => 1, - } - }); - let mut target_srcs = nscssvalue - .set_array(src_len as i32) - .as_mut_slice() - .iter_mut(); - macro_rules! next { - () => { - target_srcs - .next() - .expect("Length of target_srcs should be enough") - }; - } - for src in self.iter() { - match *src { - Source::Url(ref url) => { - next!().set_url(&url.url); - for hint in url.format_hints.iter() { - next!().set_font_format(&hint); - } - }, - Source::Local(ref family) => { - next!().set_local_font(&family.name); - }, - } - } - debug_assert!(target_srcs.next().is_none(), "Should have filled all slots"); - } -} - -impl<'a> ToNsCssValue for &'a Vec { - fn convert(self, nscssvalue: &mut nsCSSValue) { - let target_ranges = nscssvalue - .set_array((self.len() * 2) as i32) - .as_mut_slice() - .chunks_mut(2); - for (range, target) in self.iter().zip(target_ranges) { - target[0].set_integer(range.start as i32); - target[1].set_integer(range.end as i32); - } - } -} - -impl<'a> ToNsCssValue for &'a FontDisplay { - fn convert(self, nscssvalue: &mut nsCSSValue) { - nscssvalue.set_enum(match *self { - FontDisplay::Auto => structs::NS_FONT_DISPLAY_AUTO, - FontDisplay::Block => structs::NS_FONT_DISPLAY_BLOCK, - FontDisplay::Swap => structs::NS_FONT_DISPLAY_SWAP, - FontDisplay::Fallback => structs::NS_FONT_DISPLAY_FALLBACK, - FontDisplay::Optional => structs::NS_FONT_DISPLAY_OPTIONAL, - } as i32) - } -} impl<'a> ToNsCssValue for &'a counter_style::System { fn convert(self, nscssvalue: &mut nsCSSValue) { diff --git a/components/style/gecko/url.rs b/components/style/gecko/url.rs index c00fc8c27e3..8390196c523 100644 --- a/components/style/gecko/url.rs +++ b/components/style/gecko/url.rs @@ -273,14 +273,18 @@ impl ToComputedValue for SpecifiedImageUrl { } } -fn serialize_computed_url(url_value_data: &URLValueData, dest: &mut CssWriter) -> fmt::Result +fn serialize_computed_url( + url_value_data: &URLValueData, + dest: &mut CssWriter, + get_url: unsafe extern "C" fn(*const URLValueData, *mut nsCString), +) -> fmt::Result where W: Write, { dest.write_str("url(")?; unsafe { let mut string = nsCString::new(); - bindings::Gecko_GetComputedURLSpec(url_value_data, &mut string); + get_url(url_value_data, &mut string); string.as_str_unchecked().to_css(dest)?; } dest.write_char(')') @@ -298,7 +302,11 @@ impl ToCss for ComputedUrl { where W: Write, { - serialize_computed_url(&self.0.url_value._base, dest) + serialize_computed_url( + &self.0.url_value._base, + dest, + bindings::Gecko_GetComputedURLSpec, + ) } } @@ -319,7 +327,11 @@ impl ToCss for ComputedImageUrl { where W: Write, { - serialize_computed_url(&self.0.image_value._base, dest) + serialize_computed_url( + &self.0.image_value._base, + dest, + bindings::Gecko_GetComputedImageURLSpec, + ) } } diff --git a/components/style/gecko_bindings/sugar/ns_css_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs index 644166e3797..ed8892028fe 100644 --- a/components/style/gecko_bindings/sugar/ns_css_value.rs +++ b/components/style/gecko_bindings/sugar/ns_css_value.rs @@ -14,7 +14,6 @@ use std::mem; use std::ops::{Index, IndexMut}; use std::slice; use values::computed::{Angle, Length, LengthOrPercentage, Percentage}; -use values::specified::url::SpecifiedUrl; impl nsCSSValue { /// Create a CSSValue with null unit, useful to be used as a return value. @@ -167,31 +166,6 @@ impl nsCSSValue { unsafe { bindings::Gecko_CSSValue_SetAtomIdent(self, s.into_addrefed()) } } - /// Set to a font format. - pub fn set_font_format(&mut self, s: &str) { - self.set_string_internal(s, nsCSSUnit::eCSSUnit_Font_Format); - } - - /// Set to a local font value. - pub fn set_local_font(&mut self, s: &Atom) { - self.set_string_from_atom_internal(s, nsCSSUnit::eCSSUnit_Local_Font); - } - - /// Set to a font stretch. - pub fn set_font_stretch(&mut self, s: f32) { - unsafe { bindings::Gecko_CSSValue_SetFontStretch(self, s) } - } - - /// Set to a font style - pub fn set_font_style(&mut self, s: f32) { - unsafe { bindings::Gecko_CSSValue_SetFontSlantStyle(self, s) } - } - - /// Set to a font weight - pub fn set_font_weight(&mut self, w: f32) { - unsafe { bindings::Gecko_CSSValue_SetFontWeight(self, w) } - } - fn set_int_internal(&mut self, value: i32, unit: nsCSSUnit) { unsafe { bindings::Gecko_CSSValue_SetInt(self, value, unit) } } @@ -211,11 +185,6 @@ impl nsCSSValue { unsafe { bindings::Gecko_CSSValue_SetFloat(self, number, nsCSSUnit::eCSSUnit_Number) } } - /// Set to a url value - pub fn set_url(&mut self, url: &SpecifiedUrl) { - unsafe { bindings::Gecko_CSSValue_SetURL(self, url.url_value.get()) } - } - /// Set to an array of given length pub fn set_array(&mut self, len: i32) -> &mut nsCSSValue_Array { unsafe { bindings::Gecko_CSSValue_SetArray(self, len) } diff --git a/components/style/gecko_string_cache/mod.rs b/components/style/gecko_string_cache/mod.rs index 70217f233de..f4941184beb 100644 --- a/components/style/gecko_string_cache/mod.rs +++ b/components/style/gecko_string_cache/mod.rs @@ -4,6 +4,10 @@ #![allow(unsafe_code)] +// This is needed for the constants in atom_macro.rs, because we have some +// atoms whose names differ only by case, e.g. datetime and dateTime. +#![allow(non_upper_case_globals)] + //! A drop-in replacement for string_cache, but backed by Gecko `nsAtom`s. use gecko_bindings::bindings::Gecko_AddRefAtom; @@ -280,7 +284,7 @@ impl Atom { /// that way, now we have sugar for is_static, creating atoms using /// Atom::from_raw should involve almost no overhead. #[inline] - pub unsafe fn from_static(ptr: *mut nsStaticAtom) -> Self { + pub unsafe fn from_static(ptr: *const nsStaticAtom) -> Self { let atom = Atom(ptr as *mut WeakAtom); debug_assert!( atom.is_static(), diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index af5273e0a73..82c8e1501d7 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -20,6 +20,7 @@ use selector_parser::PseudoElement; use servo_arc::Arc; use shared_lock::StylesheetGuards; use smallbitvec::SmallBitVec; +use smallvec::SmallVec; use std::borrow::Cow; use std::cell::RefCell; use style_adjuster::StyleAdjuster; @@ -240,10 +241,12 @@ where let inherited_style = parent_style.unwrap_or(device.default_computed_values()); + let mut declarations = SmallVec::<[(&_, CascadeLevel); 32]>::new(); let custom_properties = { let mut builder = CustomPropertiesBuilder::new(inherited_style.custom_properties()); - for (declaration, _cascade_level) in iter_declarations() { + for (declaration, cascade_level) in iter_declarations() { + declarations.push((declaration, cascade_level)); if let PropertyDeclaration::Custom(ref declaration) = *declaration { builder.cascade(&declaration.name, &declaration.value); } @@ -278,7 +281,7 @@ where let mut cascade = Cascade::new(&mut context, cascade_mode); cascade - .apply_properties::(ApplyResetProperties::Yes, iter_declarations()); + .apply_properties::(ApplyResetProperties::Yes, declarations.iter().cloned()); cascade.compute_visited_style_if_needed( element, @@ -297,7 +300,7 @@ where ApplyResetProperties::Yes }; - cascade.apply_properties::(apply_reset, iter_declarations()); + cascade.apply_properties::(apply_reset, declarations.iter().cloned()); using_cached_reset_properties }; diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 2275316bf72..8b6298b01d2 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -4005,7 +4005,6 @@ fn static_assert() { pub fn clone_${shorthand}_size(&self) -> longhands::${shorthand}_size::computed_value::T { use gecko_bindings::structs::nsStyleCoord_CalcValue as CalcValue; use gecko_bindings::structs::nsStyleImageLayers_Size_DimensionType as DimensionType; - use values::generics::NonNegative; use values::computed::NonNegativeLengthOrPercentageOrAuto; use values::generics::background::BackgroundSize; @@ -4014,7 +4013,7 @@ fn static_assert() { NonNegativeLengthOrPercentageOrAuto::auto() } else { debug_assert_eq!(ty, DimensionType::eLengthPercentage as u8); - NonNegative(value.into()) + value.into() } } @@ -4447,7 +4446,7 @@ fn static_assert() { Some(Au(self.gecko.mClip.x + self.gecko.mClip.width).into()) }; - Either::First(ClipRect { top: top, right: right, bottom: bottom, left: left, }) + Either::First(ClipRect { top, right, bottom, left }) } } diff --git a/components/style/properties/longhands/inherited_ui.mako.rs b/components/style/properties/longhands/inherited_ui.mako.rs index 6bdd0ff51b5..e1c7b18ec11 100644 --- a/components/style/properties/longhands/inherited_ui.mako.rs +++ b/components/style/properties/longhands/inherited_ui.mako.rs @@ -72,7 +72,7 @@ ${helpers.predefined_type( "ui::ScrollbarColor", "Default::default()", spec="https://drafts.csswg.org/css-scrollbars-1/#scrollbar-color", - gecko_pref="layout.css.scrollbar-colors.enabled", + gecko_pref="layout.css.scrollbar-color.enabled", animation_value_type="ScrollbarColor", boxed=True, ignored_when_colors_disabled=True, diff --git a/components/style/stylist.rs b/components/style/stylist.rs index c933897f858..df7a55c6f18 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -1134,7 +1134,7 @@ impl Stylist { let rule_hash_target = element.rule_hash_target(); - let matches_user_rules = rule_hash_target.matches_user_and_author_rules(); + let matches_user_and_author_rules = rule_hash_target.matches_user_and_author_rules(); // Normal user-agent rules. if let Some(map) = self @@ -1162,7 +1162,7 @@ impl Stylist { // rule_hash_target.matches_user_and_author_rules()) // // Which may be more what you would probably expect. - if matches_user_rules { + if matches_user_and_author_rules { // User normal rules. if let Some(map) = self.cascade_data.user.normal_rules(pseudo_element) { map.get_all_matching_rules( @@ -1204,16 +1204,15 @@ impl Stylist { return; } - let mut match_document_author_rules = matches_user_rules; + let mut match_document_author_rules = matches_user_and_author_rules; let mut shadow_cascade_order = 0; // XBL / Shadow DOM rules, which are author rules too. - // - // TODO(emilio): Cascade order here is wrong for Shadow DOM. In - // particular, normally document rules override ::slotted() rules, but - // for !important it should be the other way around. So probably we need - // to add some sort of AuthorScoped cascade level or something. if let Some(shadow) = rule_hash_target.shadow_root() { + debug_assert!( + matches_user_and_author_rules, + "NAC should not be a shadow host" + ); if let Some(map) = shadow .style_data() .and_then(|data| data.host_rules(pseudo_element)) @@ -1238,6 +1237,10 @@ impl Stylist { let mut slots = SmallVec::<[_; 3]>::new(); let mut current = rule_hash_target.assigned_slot(); while let Some(slot) = current { + debug_assert!( + matches_user_and_author_rules, + "We should not slot NAC anywhere" + ); slots.push(slot); current = slot.assigned_slot(); } @@ -1263,55 +1266,57 @@ impl Stylist { } } - let mut current_containing_shadow = rule_hash_target.containing_shadow(); - while let Some(containing_shadow) = current_containing_shadow { - let cascade_data = containing_shadow.style_data(); - let host = containing_shadow.host(); - if let Some(map) = cascade_data.and_then(|data| data.normal_rules(pseudo_element)) { - context.with_shadow_host(Some(host), |context| { - map.get_all_matching_rules( - element, - rule_hash_target, - applicable_declarations, - context, - flags_setter, - CascadeLevel::SameTreeAuthorNormal, - shadow_cascade_order, - ); - }); - shadow_cascade_order += 1; + if matches_user_and_author_rules { + let mut current_containing_shadow = rule_hash_target.containing_shadow(); + while let Some(containing_shadow) = current_containing_shadow { + let cascade_data = containing_shadow.style_data(); + let host = containing_shadow.host(); + if let Some(map) = cascade_data.and_then(|data| data.normal_rules(pseudo_element)) { + context.with_shadow_host(Some(host), |context| { + map.get_all_matching_rules( + element, + rule_hash_target, + applicable_declarations, + context, + flags_setter, + CascadeLevel::SameTreeAuthorNormal, + shadow_cascade_order, + ); + }); + shadow_cascade_order += 1; + } + + let host_is_svg_use_element = + host.is_svg_element() && host.local_name() == &*local_name!("use"); + + if !host_is_svg_use_element { + match_document_author_rules = false; + break; + } + + debug_assert!( + cascade_data.is_none(), + "We allow no stylesheets in subtrees" + ); + + // NOTE(emilio): Hack so matches the rules of the + // enclosing tree. + // + // This is not a problem for invalidation and that kind of stuff + // because they still don't match rules based on elements + // outside of the shadow tree, and because the + // subtrees are immutable and recreated each time the source + // tree changes. + // + // We historically allow cross-document to have these + // rules applied, but I think that's not great. Gecko is the + // only engine supporting that. + // + // See https://github.com/w3c/svgwg/issues/504 for the relevant + // spec discussion. + current_containing_shadow = host.containing_shadow(); + match_document_author_rules = current_containing_shadow.is_none(); } - - let host_is_svg_use_element = - host.is_svg_element() && host.local_name() == &*local_name!("use"); - - if !host_is_svg_use_element { - match_document_author_rules = false; - break; - } - - debug_assert!( - cascade_data.is_none(), - "We allow no stylesheets in subtrees" - ); - - // NOTE(emilio): Hack so matches the rules of the - // enclosing tree. - // - // This is not a problem for invalidation and that kind of stuff - // because they still don't match rules based on elements - // outside of the shadow tree, and because the - // subtrees are immutable and recreated each time the source - // tree changes. - // - // We historically allow cross-document to have these - // rules applied, but I think that's not great. Gecko is the - // only engine supporting that. - // - // See https://github.com/w3c/svgwg/issues/504 for the relevant - // spec discussion. - current_containing_shadow = host.containing_shadow(); - match_document_author_rules = current_containing_shadow.is_none(); } let cut_xbl_binding_inheritance = diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 4cb8f7a7bdf..911193b0c0b 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -747,6 +747,7 @@ pub type FontVariationSettings = FontSettings>; /// it and store it as a 32-bit integer /// (see http://www.microsoft.com/typography/otspec/languagetags.htm). #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq)] +#[repr(C)] pub struct FontLanguageOverride(pub u32); impl FontLanguageOverride { diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 5acc2688224..d3bc0b5ebd0 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -202,21 +202,34 @@ impl ToCss for CalcLengthOrPercentage { { use num_traits::Zero; - let (length, percentage) = match (self.length, self.percentage) { - (l, None) => return l.to_css(dest), - (l, Some(p)) if l.px() == 0. => return p.to_css(dest), - (l, Some(p)) => (l, p), - }; + let length = self.unclamped_length(); + match self.percentage { + Some(p) => { + if length.px() == 0. && self.clamping_mode.clamp(p.0) == p.0 { + return p.to_css(dest); + } + } + None => { + if self.clamping_mode.clamp(length.px()) == length.px() { + return length.to_css(dest); + } + } + } dest.write_str("calc(")?; - percentage.to_css(dest)?; - - dest.write_str(if length.px() < Zero::zero() { - " - " + if let Some(percentage) = self.percentage { + percentage.to_css(dest)?; + if length.px() != 0. { + dest.write_str(if length.px() < Zero::zero() { + " - " + } else { + " + " + })?; + length.abs().to_css(dest)?; + } } else { - " + " - })?; - length.abs().to_css(dest)?; + length.to_css(dest)?; + } dest.write_str(")") } diff --git a/components/style/values/computed/percentage.rs b/components/style/values/computed/percentage.rs index 4e9ae6172a9..e7f038f4bef 100644 --- a/components/style/values/computed/percentage.rs +++ b/components/style/values/computed/percentage.rs @@ -27,6 +27,7 @@ use values::generics::NonNegative; ToAnimatedZero, ToComputedValue, )] +#[repr(C)] pub struct Percentage(pub CSSFloat); impl Percentage { diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 5613ae603d2..cdfe3228c8b 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -292,14 +292,16 @@ pub const FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES: f32 = 90.; pub const FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES: f32 = -90.; impl SpecifiedFontStyle { - /// Gets a clamped angle from a specified Angle. - pub fn compute_angle(angle: &Angle) -> ComputedAngle { - ComputedAngle::Deg( - angle - .degrees() - .max(FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES) - .min(FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES), - ) + /// Gets a clamped angle in degrees from a specified Angle. + pub fn compute_angle_degrees(angle: &Angle) -> f32 { + angle + .degrees() + .max(FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES) + .min(FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES) + } + + fn compute_angle(angle: &Angle) -> ComputedAngle { + ComputedAngle::Deg(Self::compute_angle_degrees(angle)) } /// Parse a suitable angle for font-style: oblique. @@ -380,6 +382,7 @@ impl Parse for FontStyle { /// https://drafts.csswg.org/css-fonts-4/#font-stretch-prop #[allow(missing_docs)] #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss)] +#[repr(u8)] pub enum FontStretch { Stretch(Percentage), Keyword(FontStretchKeyword), @@ -2057,6 +2060,29 @@ impl FontLanguageOverride { FontLanguageOverride::Normal } + /// The ToComputedValue implementation for non-system-font + /// FontLanguageOverride, used for @font-face descriptors. + #[inline] + pub fn compute_non_system(&self) -> computed::FontLanguageOverride { + match *self { + FontLanguageOverride::Normal => computed::FontLanguageOverride(0), + FontLanguageOverride::Override(ref lang) => { + if lang.is_empty() || lang.len() > 4 { + return computed::FontLanguageOverride(0); + } + let mut bytes = [b' '; 4]; + for (byte, lang_byte) in bytes.iter_mut().zip(lang.as_bytes()) { + if !lang_byte.is_ascii() { + return computed::FontLanguageOverride(0); + } + *byte = *lang_byte; + } + computed::FontLanguageOverride(BigEndian::read_u32(&bytes)) + }, + FontLanguageOverride::System(..) => unreachable!(), + } + } + system_font_methods!(FontLanguageOverride, font_language_override); } @@ -2066,19 +2092,8 @@ impl ToComputedValue for FontLanguageOverride { #[inline] fn to_computed_value(&self, context: &Context) -> computed::FontLanguageOverride { match *self { - FontLanguageOverride::Normal => computed::FontLanguageOverride(0), - FontLanguageOverride::Override(ref lang) => { - if lang.is_empty() || lang.len() > 4 || !lang.is_ascii() { - return computed::FontLanguageOverride(0); - } - let mut computed_lang = lang.to_string(); - while computed_lang.len() < 4 { - computed_lang.push(' '); - } - let bytes = computed_lang.into_bytes(); - computed::FontLanguageOverride(BigEndian::read_u32(&bytes)) - }, FontLanguageOverride::System(_) => self.compute_system(context), + _ => self.compute_non_system(), } } #[inline] diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index b1a611846a8..0a3a402e9ec 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -8,7 +8,7 @@ //! [image]: https://drafts.csswg.org/css-images/#image-values use Atom; -use cssparser::{Parser, Token}; +use cssparser::{Parser, Token, Delimiter}; use custom_properties::SpecifiedValue; use parser::{Parse, ParserContext}; use selectors::parser::SelectorParseErrorKind; @@ -956,17 +956,43 @@ impl GradientItem { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result, ParseError<'i>> { + let mut items = Vec::new(); let mut seen_stop = false; - let items = input.parse_comma_separated(|input| { - if seen_stop { - if let Ok(hint) = input.try(|i| LengthOrPercentage::parse(context, i)) { - seen_stop = false; - return Ok(generic::GradientItem::InterpolationHint(hint)); + + loop { + input.parse_until_before(Delimiter::Comma, |input| { + if seen_stop { + if let Ok(hint) = input.try(|i| LengthOrPercentage::parse(context, i)) { + seen_stop = false; + items.push(generic::GradientItem::InterpolationHint(hint)); + return Ok(()); + } } + + let stop = ColorStop::parse(context, input)?; + + if let Ok(multi_position) = input.try(|i| LengthOrPercentage::parse(context, i)) { + let stop_color = stop.color.clone(); + items.push(generic::GradientItem::ColorStop(stop)); + items.push(generic::GradientItem::ColorStop(ColorStop { + color: stop_color, + position: Some(multi_position), + })); + } else { + items.push(generic::GradientItem::ColorStop(stop)); + } + + seen_stop = true; + Ok(()) + })?; + + match input.next() { + Err(_) => break, + Ok(&Token::Comma) => continue, + Ok(_) => unreachable!(), } - seen_stop = true; - ColorStop::parse(context, input).map(generic::GradientItem::ColorStop) - })?; + } + if !seen_stop || items.len() < 2 { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } diff --git a/tests/wpt/metadata/css/css-images/gradient/color-stops-parsing.html.ini b/tests/wpt/metadata/css/css-images/gradient/color-stops-parsing.html.ini index 621329fc00d..5349947628e 100644 --- a/tests/wpt/metadata/css/css-images/gradient/color-stops-parsing.html.ini +++ b/tests/wpt/metadata/css/css-images/gradient/color-stops-parsing.html.ini @@ -1,51 +1,4 @@ [color-stops-parsing.html] - [linear-gradient(black 0% 50%, white) [ parsable \]] - expected: FAIL - - [linear-gradient(black 0% 50%, white 50% 100%) [ parsable \]] - expected: FAIL - - [linear-gradient(black 0% 50%, green 25% 75%, white 50% 100%) [ parsable \]] - expected: FAIL - - [linear-gradient(black 0% calc(100% / 5), 25%, green 30% 60%, calc(100% * 3 / 4), white calc(100% - 20%) 100%) [ parsable \]] - expected: FAIL - - [repeating-linear-gradient(black 0% 50%, white) [ parsable \]] - expected: FAIL - - [repeating-linear-gradient(black 0% 50%, white 50% 100%) [ parsable \]] - expected: FAIL - - [repeating-linear-gradient(black 0% 50%, green 25% 75%, white 50% 100%) [ parsable \]] - expected: FAIL - - [repeating-linear-gradient(black 0% calc(100% / 5), 25%, green 30% 60%, calc(100% * 3 / 4), white calc(100% - 20%) 100%) [ parsable \]] - expected: FAIL - - [radial-gradient(black 0% 50%, white) [ parsable \]] - expected: FAIL - - [radial-gradient(black 0% 50%, white 50% 100%) [ parsable \]] - expected: FAIL - - [radial-gradient(black 0% 50%, green 25% 75%, white 50% 100%) [ parsable \]] - expected: FAIL - - [radial-gradient(black 0% calc(100% / 5), 25%, green 30% 60%, calc(100% * 3 / 4), white calc(100% - 20%) 100%) [ parsable \]] - expected: FAIL - - [repeating-radial-gradient(black 0% 50%, white) [ parsable \]] - expected: FAIL - - [repeating-radial-gradient(black 0% 50%, white 50% 100%) [ parsable \]] - expected: FAIL - - [repeating-radial-gradient(black 0% 50%, green 25% 75%, white 50% 100%) [ parsable \]] - expected: FAIL - - [repeating-radial-gradient(black 0% calc(100% / 5), 25%, green 30% 60%, calc(100% * 3 / 4), white calc(100% - 20%) 100%) [ parsable \]] - expected: FAIL [conic-gradient(black, white) [ parsable \]] expected: FAIL diff --git a/tests/wpt/metadata/css/css-images/multiple-position-color-stop-linear-2.html.ini b/tests/wpt/metadata/css/css-images/multiple-position-color-stop-linear-2.html.ini deleted file mode 100644 index 5c6ef248505..00000000000 --- a/tests/wpt/metadata/css/css-images/multiple-position-color-stop-linear-2.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[multiple-position-color-stop-linear-2.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-images/multiple-position-color-stop-linear.html.ini b/tests/wpt/metadata/css/css-images/multiple-position-color-stop-linear.html.ini deleted file mode 100644 index b3e0af9f675..00000000000 --- a/tests/wpt/metadata/css/css-images/multiple-position-color-stop-linear.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[multiple-position-color-stop-linear.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-images/multiple-position-color-stop-radial.html.ini b/tests/wpt/metadata/css/css-images/multiple-position-color-stop-radial.html.ini deleted file mode 100644 index 1d178cb5280..00000000000 --- a/tests/wpt/metadata/css/css-images/multiple-position-color-stop-radial.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[multiple-position-color-stop-radial.html] - expected: FAIL