aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2019-05-29 16:49:16 -0400
committerGitHub <noreply@github.com>2019-05-29 16:49:16 -0400
commitb4fb2cda087a4467742681cc27291c803d0dc825 (patch)
treeec530c726d1e55ca06de9bbb57d8cb0e0671c8bd
parentd8983b51275fa0b67cb56f686510ab5695c024d6 (diff)
parent324aed53f1d3852caadf33c4c611cb7ed6985996 (diff)
downloadservo-b4fb2cda087a4467742681cc27291c803d0dc825.tar.gz
servo-b4fb2cda087a4467742681cc27291c803d0dc825.zip
Auto merge of #23456 - emilio:gecko-sync, r=emilio
style: Sync changes from mozilla-central. See each individual commit for details. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/23456) <!-- Reviewable:end -->
-rw-r--r--Cargo.lock1
-rw-r--r--components/atoms/static_atoms.txt4
-rw-r--r--components/layout/display_list/border.rs2
-rw-r--r--components/layout/fragment.rs2
-rw-r--r--components/layout_thread/dom_wrapper.rs8
-rw-r--r--components/script/dom/element.rs10
-rw-r--r--components/selectors/builder.rs6
-rw-r--r--components/selectors/matching.rs13
-rw-r--r--components/selectors/parser.rs18
-rw-r--r--components/selectors/tree.rs4
-rw-r--r--components/servo_arc/lib.rs23
-rw-r--r--components/style/Cargo.toml3
-rw-r--r--components/style/counter_style/mod.rs125
-rw-r--r--components/style/dom.rs15
-rw-r--r--components/style/driver.rs1
-rw-r--r--components/style/gecko/arc_types.rs5
-rw-r--r--components/style/gecko/boxed_types.rs10
-rw-r--r--components/style/gecko/conversions.rs24
-rw-r--r--components/style/gecko/mod.rs3
-rw-r--r--components/style/gecko/profiler.rs75
-rw-r--r--components/style/gecko/rules.rs135
-rw-r--r--components/style/gecko/url.rs19
-rw-r--r--components/style/gecko/values.rs26
-rw-r--r--components/style/gecko/wrapper.rs13
-rw-r--r--components/style/gecko_bindings/sugar/mod.rs3
-rw-r--r--components/style/gecko_bindings/sugar/ns_css_shadow_array.rs78
-rw-r--r--components/style/gecko_bindings/sugar/ns_css_shadow_item.rs59
-rw-r--r--components/style/gecko_bindings/sugar/ns_css_value.rs424
-rw-r--r--components/style/gecko_bindings/sugar/refptr.rs5
-rw-r--r--components/style/gecko_string_cache/mod.rs1
-rw-r--r--components/style/invalidation/element/element_wrapper.rs4
-rw-r--r--components/style/lib.rs1
-rw-r--r--components/style/macros.rs29
-rw-r--r--components/style/parallel.rs2
-rw-r--r--components/style/properties/cascade.rs4
-rw-r--r--components/style/properties/data.py6
-rw-r--r--components/style/properties/declaration_block.rs33
-rw-r--r--components/style/properties/gecko.mako.rs844
-rw-r--r--components/style/properties/helpers.mako.rs217
-rw-r--r--components/style/properties/helpers/animated_properties.mako.rs10
-rw-r--r--components/style/properties/longhands/background.mako.rs2
-rw-r--r--components/style/properties/longhands/border.mako.rs61
-rw-r--r--components/style/properties/longhands/box.mako.rs61
-rw-r--r--components/style/properties/longhands/color.mako.rs1
-rw-r--r--components/style/properties/longhands/effects.mako.rs3
-rw-r--r--components/style/properties/longhands/font.mako.rs2
-rw-r--r--components/style/properties/longhands/inherited_svg.mako.rs7
-rw-r--r--components/style/properties/longhands/inherited_text.mako.rs13
-rw-r--r--components/style/properties/longhands/margin.mako.rs2
-rw-r--r--components/style/properties/longhands/padding.mako.rs2
-rw-r--r--components/style/properties/longhands/position.mako.rs8
-rw-r--r--components/style/properties/longhands/svg.mako.rs63
-rw-r--r--components/style/properties/longhands/ui.mako.rs6
-rw-r--r--components/style/properties/properties.mako.rs27
-rw-r--r--components/style/properties/shorthands/background.mako.rs49
-rw-r--r--components/style/properties/shorthands/border.mako.rs2
-rw-r--r--components/style/properties/shorthands/box.mako.rs4
-rw-r--r--components/style/properties/shorthands/margin.mako.rs2
-rw-r--r--components/style/properties/shorthands/padding.mako.rs2
-rw-r--r--components/style/properties/shorthands/position.mako.rs2
-rw-r--r--components/style/properties/shorthands/svg.mako.rs41
-rw-r--r--components/style/rule_collector.rs15
-rw-r--r--components/style/style_adjuster.rs5
-rw-r--r--components/style/style_resolver.rs10
-rw-r--r--components/style/stylist.rs4
-rw-r--r--components/style/values/animated/effects.rs10
-rw-r--r--components/style/values/animated/transform.rs16
-rw-r--r--components/style/values/computed/angle.rs1
-rw-r--r--components/style/values/computed/border.rs2
-rw-r--r--components/style/values/computed/gecko.rs11
-rw-r--r--components/style/values/computed/list.rs14
-rw-r--r--components/style/values/computed/mod.rs17
-rw-r--r--components/style/values/computed/motion.rs34
-rw-r--r--components/style/values/computed/text.rs3
-rw-r--r--components/style/values/computed/transform.rs84
-rw-r--r--components/style/values/generics/border.rs9
-rw-r--r--components/style/values/generics/effects.rs12
-rw-r--r--components/style/values/generics/gecko.rs44
-rw-r--r--components/style/values/generics/mod.rs2
-rw-r--r--components/style/values/generics/transform.rs62
-rw-r--r--components/style/values/mod.rs1
-rw-r--r--components/style/values/specified/border.rs2
-rw-r--r--components/style/values/specified/box.rs47
-rw-r--r--components/style/values/specified/effects.rs51
-rw-r--r--components/style/values/specified/gecko.rs21
-rw-r--r--components/style/values/specified/list.rs18
-rw-r--r--components/style/values/specified/mod.rs6
-rw-r--r--components/style/values/specified/motion.rs108
-rw-r--r--components/style/values/specified/svg.rs77
-rw-r--r--components/style/values/specified/text.rs35
-rw-r--r--components/style/values/specified/transform.rs350
-rw-r--r--components/style_traits/Cargo.toml1
-rw-r--r--components/style_traits/arc_slice.rs57
-rw-r--r--components/style_traits/lib.rs5
-rw-r--r--components/style_traits/owned_slice.rs11
-rw-r--r--components/style_traits/owned_str.rs53
-rw-r--r--components/style_traits/specified_value_info.rs3
-rw-r--r--components/style_traits/values.rs10
-rw-r--r--tests/unit/style/animated_properties.rs12
-rw-r--r--tests/unit/style/parsing/animation.rs43
-rw-r--r--tests/unit/style/parsing/mod.rs1
-rw-r--r--tests/unit/style/stylesheets.rs16
-rw-r--r--tests/wpt/metadata/css/filter-effects/filters-test-brightness-003.html.ini2
-rw-r--r--tests/wpt/metadata/css/filter-effects/parsing/filter-computed.html.ini27
-rw-r--r--tests/wpt/metadata/css/filter-effects/parsing/filter-parsing-valid.html.ini27
105 files changed, 1452 insertions, 2512 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 179e7109d5d..88bbbeca206 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4562,6 +4562,7 @@ dependencies = [
"bitflags 1.0.3 (registry+https://github.com/rust-lang/crates.io-index)",
"cssparser 0.25.5 (registry+https://github.com/rust-lang/crates.io-index)",
"euclid 0.19.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "lazy_static 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)",
"malloc_size_of 0.0.1",
"malloc_size_of_derive 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
"selectors 0.21.0",
diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt
index a42e998c958..c85d3563e75 100644
--- a/components/atoms/static_atoms.txt
+++ b/components/atoms/static_atoms.txt
@@ -30,6 +30,8 @@ error
fantasy
fetch
file
+fill
+fill-opacity
formdata
fullscreenchange
fullscreenerror
@@ -100,6 +102,8 @@ serif
signalingstatechange
srclang
statechange
+stroke
+stroke-opacity
storage
submit
suspend
diff --git a/components/layout/display_list/border.rs b/components/layout/display_list/border.rs
index dcbef4473fe..848386cb630 100644
--- a/components/layout/display_list/border.rs
+++ b/components/layout/display_list/border.rs
@@ -159,7 +159,7 @@ fn side_image_width(
total_length: Au,
) -> f32 {
match border_image_width {
- BorderImageSideWidth::Length(v) => v.to_used_value(total_length).to_f32_px(),
+ BorderImageSideWidth::LengthPercentage(v) => v.to_used_value(total_length).to_f32_px(),
BorderImageSideWidth::Number(x) => border_width * x.0,
BorderImageSideWidth::Auto => border_width,
}
diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs
index ccc3de5ec7e..d3e9dbb6779 100644
--- a/components/layout/fragment.rs
+++ b/components/layout/fragment.rs
@@ -2793,7 +2793,7 @@ impl Fragment {
let mut overflow = Overflow::from_rect(&border_box);
// Box shadows cause us to draw outside our border box.
- for box_shadow in &self.style().get_effects().box_shadow.0 {
+ for box_shadow in &*self.style().get_effects().box_shadow.0 {
let offset = Vector2D::new(
Au::from(box_shadow.base.horizontal),
Au::from(box_shadow.base.vertical),
diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs
index 301a7500713..d738ef1151f 100644
--- a/components/layout_thread/dom_wrapper.rs
+++ b/components/layout_thread/dom_wrapper.rs
@@ -888,6 +888,10 @@ impl<'le> ::selectors::Element for ServoLayoutElement<'le> {
self.element.namespace()
}
+ fn is_pseudo_element(&self) -> bool {
+ false
+ }
+
fn match_pseudo_element(
&self,
_pseudo: &PseudoElement,
@@ -1394,6 +1398,10 @@ impl<'le> ::selectors::Element for ServoThreadSafeLayoutElement<'le> {
::selectors::OpaqueElement::new(unsafe { &*(self.as_node().opaque().0 as *const ()) })
}
+ fn is_pseudo_element(&self) -> bool {
+ false
+ }
+
fn parent_element(&self) -> Option<Self> {
warn!("ServoThreadSafeLayoutElement::parent_element called");
None
diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs
index 1b918c0537b..c4174309af9 100644
--- a/components/script/dom/element.rs
+++ b/components/script/dom/element.rs
@@ -685,9 +685,9 @@ impl LayoutElementHelpers for LayoutDom<Element> {
if let Some(url) = background {
hints.push(from_declaration(
shared_lock,
- PropertyDeclaration::BackgroundImage(background_image::SpecifiedValue(vec![
- Either::Second(specified::Image::for_cascade(url.into())),
- ])),
+ PropertyDeclaration::BackgroundImage(background_image::SpecifiedValue(
+ vec![Either::Second(specified::Image::for_cascade(url.into()))].into(),
+ )),
));
}
@@ -2945,6 +2945,10 @@ impl<'a> SelectorsElement for DomRoot<Element> {
}
}
+ fn is_pseudo_element(&self) -> bool {
+ false
+ }
+
fn match_pseudo_element(
&self,
_pseudo: &PseudoElement,
diff --git a/components/selectors/builder.rs b/components/selectors/builder.rs
index b548ceb83ce..c3e733cbeb0 100644
--- a/components/selectors/builder.rs
+++ b/components/selectors/builder.rs
@@ -84,12 +84,6 @@ impl<Impl: SelectorImpl> SelectorBuilder<Impl> {
self.current_len = 0;
}
- /// Returns true if no simple selectors have ever been pushed to this builder.
- #[inline(always)]
- pub fn is_empty(&self) -> bool {
- self.simple_selectors.is_empty()
- }
-
/// Returns true if combinators have ever been pushed to this builder.
#[inline(always)]
pub fn has_combinators(&self) -> bool {
diff --git a/components/selectors/matching.rs b/components/selectors/matching.rs
index aa200cc4b26..6554f2f9cc4 100644
--- a/components/selectors/matching.rs
+++ b/components/selectors/matching.rs
@@ -331,11 +331,9 @@ where
return false;
}
- // Advance to the non-pseudo-element part of the selector, but let the
- // context note that .
- if iter.next_sequence().is_none() {
- return true;
- }
+ // Advance to the non-pseudo-element part of the selector.
+ let next_sequence = iter.next_sequence().unwrap();
+ debug_assert_eq!(next_sequence, Combinator::PseudoElement);
}
let result =
@@ -452,10 +450,6 @@ where
},
Combinator::Part => element.containing_shadow_host(),
Combinator::SlotAssignment => {
- debug_assert!(
- context.current_host.is_some(),
- "Should not be trying to match slotted rules in a non-shadow-tree context"
- );
debug_assert!(element
.assigned_slot()
.map_or(true, |s| s.is_html_slot_element()));
@@ -677,7 +671,6 @@ where
Component::Slotted(ref selector) => {
// <slots> are never flattened tree slottables.
!element.is_html_slot_element() &&
- element.assigned_slot().is_some() &&
context.shared.nest(|context| {
matches_complex_selector(selector.iter(), element, context, flags_setter)
})
diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs
index a924bbc17d0..f049555730c 100644
--- a/components/selectors/parser.rs
+++ b/components/selectors/parser.rs
@@ -2002,9 +2002,7 @@ where
},
SimpleSelectorParseResult::SlottedPseudo(selector) => {
state.insert(SelectorParsingState::AFTER_SLOTTED);
- if !builder.is_empty() {
- builder.push_combinator(Combinator::SlotAssignment);
- }
+ builder.push_combinator(Combinator::SlotAssignment);
builder.push_simple_selector(Component::Slotted(selector));
},
SimpleSelectorParseResult::PseudoElement(p) => {
@@ -2012,9 +2010,7 @@ where
if !p.accepts_state_pseudo_classes() {
state.insert(SelectorParsingState::AFTER_NON_STATEFUL_PSEUDO_ELEMENT);
}
- if !builder.is_empty() {
- builder.push_combinator(Combinator::PseudoElement);
- }
+ builder.push_combinator(Combinator::PseudoElement);
builder.push_simple_selector(Component::PseudoElement(p));
},
}
@@ -2828,7 +2824,10 @@ pub mod tests {
assert_eq!(
parse("::before"),
Ok(SelectorList::from_vec(vec![Selector::from_vec(
- vec![Component::PseudoElement(PseudoElement::Before)],
+ vec![
+ Component::Combinator(Combinator::PseudoElement),
+ Component::PseudoElement(PseudoElement::Before),
+ ],
specificity(0, 0, 1) | HAS_PSEUDO_BIT,
)]))
);
@@ -2836,6 +2835,7 @@ pub mod tests {
parse("::before:hover"),
Ok(SelectorList::from_vec(vec![Selector::from_vec(
vec![
+ Component::Combinator(Combinator::PseudoElement),
Component::PseudoElement(PseudoElement::Before),
Component::NonTSPseudoClass(PseudoClass::Hover),
],
@@ -2846,6 +2846,7 @@ pub mod tests {
parse("::before:hover:hover"),
Ok(SelectorList::from_vec(vec![Selector::from_vec(
vec![
+ Component::Combinator(Combinator::PseudoElement),
Component::PseudoElement(PseudoElement::Before),
Component::NonTSPseudoClass(PseudoClass::Hover),
Component::NonTSPseudoClass(PseudoClass::Hover),
@@ -2958,6 +2959,7 @@ pub mod tests {
specificity(0, 0, 0),
)]))
);
+
assert_eq!(
parse_ns(":not(svg|*)", &parser),
Ok(SelectorList::from_vec(vec![Selector::from_vec(
@@ -3032,6 +3034,8 @@ pub mod tests {
Some(&Component::PseudoElement(PseudoElement::Before))
);
assert_eq!(iter.next(), None);
+ assert_eq!(iter.next_sequence(), Some(Combinator::PseudoElement));
+ assert_eq!(iter.next(), None);
assert_eq!(iter.next_sequence(), None);
}
diff --git a/components/selectors/tree.rs b/components/selectors/tree.rs
index 52599893d2f..611e40d6027 100644
--- a/components/selectors/tree.rs
+++ b/components/selectors/tree.rs
@@ -47,9 +47,13 @@ pub trait Element: Sized + Clone + Debug {
///
/// This is guaranteed to be called in a pseudo-element.
fn pseudo_element_originating_element(&self) -> Option<Self> {
+ debug_assert!(self.is_pseudo_element());
self.parent_element()
}
+ /// Whether we're matching on a pseudo-element.
+ fn is_pseudo_element(&self) -> bool;
+
/// Skips non-element nodes
fn prev_sibling_element(&self) -> Option<Self>;
diff --git a/components/servo_arc/lib.rs b/components/servo_arc/lib.rs
index f2f9fa00602..09f381c62df 100644
--- a/components/servo_arc/lib.rs
+++ b/components/servo_arc/lib.rs
@@ -612,16 +612,15 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
use std::mem::{align_of, size_of};
assert_ne!(size_of::<T>(), 0, "Need to think about ZST");
+ let inner_align = align_of::<ArcInner<HeaderSlice<H, [T; 0]>>>();
+ debug_assert!(inner_align >= align_of::<T>());
+
// Compute the required size for the allocation.
let num_items = items.len();
let size = {
- // First, determine the alignment of a hypothetical pointer to a
- // HeaderSlice.
- let fake_slice_ptr_align: usize = mem::align_of::<ArcInner<HeaderSlice<H, [T; 0]>>>();
-
// Next, synthesize a totally garbage (but properly aligned) pointer
// to a sequence of T.
- let fake_slice_ptr = fake_slice_ptr_align as *const T;
+ let fake_slice_ptr = inner_align as *const T;
// Convert that sequence to a fat pointer. The address component of
// the fat pointer will be garbage, but the length will be correct.
@@ -641,13 +640,13 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
let ptr: *mut ArcInner<HeaderSlice<H, [T]>>;
unsafe {
// Allocate the buffer.
- let layout = if mem::align_of::<T>() <= mem::align_of::<usize>() {
- Layout::from_size_align_unchecked(size, mem::align_of::<usize>())
- } else if mem::align_of::<T>() <= mem::align_of::<u64>() {
- // On 32-bit platforms <T> may have 8 byte alignment while usize has 4 byte aligment.
- // Use u64 to avoid over-alignment.
+ let layout = if inner_align <= align_of::<usize>() {
+ Layout::from_size_align_unchecked(size, align_of::<usize>())
+ } else if inner_align <= align_of::<u64>() {
+ // On 32-bit platforms <T> may have 8 byte alignment while usize
+ // has 4 byte aligment. Use u64 to avoid over-alignment.
// This branch will compile away in optimized builds.
- Layout::from_size_align_unchecked(size, mem::align_of::<u64>())
+ Layout::from_size_align_unchecked(size, align_of::<u64>())
} else {
panic!("Over-aligned type not handled");
};
@@ -689,7 +688,7 @@ impl<H, T> Arc<HeaderSlice<H, [T]>> {
// for some padding from the alignment.
debug_assert!(
(buffer.offset(size as isize) as usize - current as *mut u8 as usize) <
- align_of::<Self>()
+ inner_align
);
}
assert!(
diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml
index bf953a13f8f..4d5f3e2e94d 100644
--- a/components/style/Cargo.toml
+++ b/components/style/Cargo.toml
@@ -22,6 +22,7 @@ servo = ["serde", "style_traits/servo", "servo_atoms", "servo_config", "html5eve
"cssparser/serde", "encoding_rs", "malloc_size_of/servo", "arrayvec/use_union",
"servo_url", "string_cache", "crossbeam-channel", "to_shmem/servo", "servo_arc/servo"]
gecko_debug = []
+gecko_profiler = []
[dependencies]
app_units = "0.7"
@@ -79,7 +80,7 @@ void = "1.0.2"
[build-dependencies]
lazy_static = "1"
log = "0.4"
-bindgen = { version = "0.49", optional = true, default-features = false }
+bindgen = {version = "0.49", optional = true, default-features = false}
regex = {version = "1.1", optional = true}
walkdir = "2.1.4"
toml = {version = "0.4.5", optional = true, default-features = false}
diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs
index 77de5f52d2b..289281011c3 100644
--- a/components/style/counter_style/mod.rs
+++ b/components/style/counter_style/mod.rs
@@ -19,7 +19,6 @@ use selectors::parser::SelectorParseErrorKind;
use std::fmt::{self, Write};
use std::mem;
use std::num::Wrapping;
-use std::ops::Range;
use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError};
use style_traits::{StyleParseErrorKind, ToCss};
@@ -261,7 +260,7 @@ counter_style_descriptors! {
"suffix" suffix / set_suffix [_]: Symbol,
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-range>
- "range" range / set_range [_]: Ranges,
+ "range" range / set_range [_]: CounterRanges,
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-pad>
"pad" pad / set_pad [_]: Pad,
@@ -371,7 +370,7 @@ impl Parse for System {
"additive" => Ok(System::Additive),
"fixed" => {
let first_symbol_value = input.try(|i| Integer::parse(context, i)).ok();
- Ok(System::Fixed { first_symbol_value: first_symbol_value })
+ Ok(System::Fixed { first_symbol_value })
}
"extends" => {
let other = parse_counter_style_name(input)?;
@@ -409,11 +408,10 @@ impl ToCss for System {
}
/// <https://drafts.csswg.org/css-counter-styles/#typedef-symbol>
-#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)]
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
pub enum Symbol {
/// <string>
- String(String),
+ String(crate::OwnedStr),
/// <custom-ident>
Ident(CustomIdent),
// Not implemented:
@@ -428,7 +426,7 @@ impl Parse for Symbol {
) -> Result<Self, ParseError<'i>> {
let location = input.current_source_location();
match *input.next()? {
- Token::QuotedString(ref s) => Ok(Symbol::String(s.as_ref().to_owned())),
+ Token::QuotedString(ref s) => Ok(Symbol::String(s.as_ref().to_owned().into())),
Token::Ident(ref s) => Ok(Symbol::Ident(CustomIdent::from_ident(location, s, &[])?)),
ref t => Err(location.new_unexpected_token_error(t.clone())),
}
@@ -463,12 +461,22 @@ impl Parse for Negative {
}
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-range>
+#[derive(Clone, Debug, ToCss, ToShmem)]
+pub struct CounterRange {
+ /// The start of the range.
+ pub start: CounterBound,
+ /// The end of the range.
+ pub end: CounterBound,
+}
+
+/// <https://drafts.csswg.org/css-counter-styles/#counter-style-range>
///
-/// Empty Vec represents 'auto'
-#[derive(Clone, Debug, ToShmem)]
-pub struct Ranges(pub Vec<Range<CounterBound>>);
+/// Empty represents 'auto'
+#[derive(Clone, Debug, ToCss, ToShmem)]
+#[css(comma)]
+pub struct CounterRanges(#[css(iterable, if_empty = "auto")] pub crate::OwnedSlice<CounterRange>);
-/// A bound found in `Ranges`.
+/// A bound found in `CounterRanges`.
#[derive(Clone, Copy, Debug, ToCss, ToShmem)]
pub enum CounterBound {
/// An integer bound.
@@ -477,7 +485,7 @@ pub enum CounterBound {
Infinite,
}
-impl Parse for Ranges {
+impl Parse for CounterRanges {
fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
@@ -486,25 +494,21 @@ impl Parse for Ranges {
.try(|input| input.expect_ident_matching("auto"))
.is_ok()
{
- Ok(Ranges(Vec::new()))
- } else {
- input
- .parse_comma_separated(|input| {
- let opt_start = parse_bound(context, input)?;
- let opt_end = parse_bound(context, input)?;
- if let (CounterBound::Integer(start), CounterBound::Integer(end)) =
- (opt_start, opt_end)
- {
- if start > end {
- return Err(
- input.new_custom_error(StyleParseErrorKind::UnspecifiedError)
- );
- }
- }
- Ok(opt_start..opt_end)
- })
- .map(Ranges)
+ return Ok(CounterRanges(Default::default()));
}
+
+ let ranges = input.parse_comma_separated(|input| {
+ let start = parse_bound(context, input)?;
+ let end = parse_bound(context, input)?;
+ if let (CounterBound::Integer(start), CounterBound::Integer(end)) = (start, end) {
+ if start > end {
+ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
+ }
+ }
+ Ok(CounterRange { start, end })
+ })?;
+
+ Ok(CounterRanges(ranges.into()))
}
}
@@ -519,34 +523,6 @@ fn parse_bound<'i, 't>(
Ok(CounterBound::Infinite)
}
-impl ToCss for Ranges {
- fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
- where
- W: Write,
- {
- let mut iter = self.0.iter();
- if let Some(first) = iter.next() {
- range_to_css(first, dest)?;
- for item in iter {
- dest.write_str(", ")?;
- range_to_css(item, dest)?;
- }
- Ok(())
- } else {
- dest.write_str("auto")
- }
- }
-}
-
-fn range_to_css<W>(range: &Range<CounterBound>, dest: &mut CssWriter<W>) -> fmt::Result
-where
- W: Write,
-{
- range.start.to_css(dest)?;
- dest.write_char(' ')?;
- range.end.to_css(dest)
-}
-
/// <https://drafts.csswg.org/css-counter-styles/#counter-style-pad>
#[derive(Clone, Debug, ToCss, ToShmem)]
pub struct Pad(pub Integer, pub Symbol);
@@ -572,14 +548,13 @@ impl Parse for Fallback {
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
- parse_counter_style_name(input).map(Fallback)
+ Ok(Fallback(parse_counter_style_name(input)?))
}
}
/// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-symbols>
-#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)]
-pub struct Symbols(#[css(iterable)] pub Vec<Symbol>);
+#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)]
+pub struct Symbols(#[css(iterable)] pub crate::OwnedSlice<Symbol>);
impl Parse for Symbols {
fn parse<'i, 't>(
@@ -587,23 +562,20 @@ impl Parse for Symbols {
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> {
let mut symbols = Vec::new();
- loop {
- if let Ok(s) = input.try(|input| Symbol::parse(context, input)) {
- symbols.push(s)
- } else {
- if symbols.is_empty() {
- return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
- } else {
- return Ok(Symbols(symbols));
- }
- }
+ while let Ok(s) = input.try(|input| Symbol::parse(context, input)) {
+ symbols.push(s);
+ }
+ if symbols.is_empty() {
+ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
+ Ok(Symbols(symbols.into()))
}
}
/// <https://drafts.csswg.org/css-counter-styles/#descdef-counter-style-additive-symbols>
#[derive(Clone, Debug, ToCss, ToShmem)]
-pub struct AdditiveSymbols(pub Vec<AdditiveTuple>);
+#[css(comma)]
+pub struct AdditiveSymbols(#[css(iterable)] pub crate::OwnedSlice<AdditiveTuple>);
impl Parse for AdditiveSymbols {
fn parse<'i, 't>(
@@ -618,7 +590,7 @@ impl Parse for AdditiveSymbols {
{
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
- Ok(AdditiveSymbols(tuples))
+ Ok(AdditiveSymbols(tuples.into()))
}
}
@@ -643,10 +615,7 @@ impl Parse for AdditiveTuple {
let symbol = input.try(|input| Symbol::parse(context, input));
let weight = Integer::parse_non_negative(context, input)?;
let symbol = symbol.or_else(|_| Symbol::parse(context, input))?;
- Ok(AdditiveTuple {
- weight: weight,
- symbol: symbol,
- })
+ Ok(Self { weight, symbol })
}
}
diff --git a/components/style/dom.rs b/components/style/dom.rs
index 9a81e2ec774..5ee8443b91d 100644
--- a/components/style/dom.rs
+++ b/components/style/dom.rs
@@ -779,7 +779,7 @@ pub trait TElement:
/// element-backed pseudo-element, in which case we return the originating
/// element.
fn rule_hash_target(&self) -> Self {
- if self.implemented_pseudo_element().is_some() {
+ if self.is_pseudo_element() {
self.pseudo_element_originating_element()
.expect("Trying to collect rules for a detached pseudo-element")
} else {
@@ -801,24 +801,29 @@ pub trait TElement:
{
use rule_collector::containing_shadow_ignoring_svg_use;
- let mut doc_rules_apply = self.matches_user_and_author_rules();
+ let target = self.rule_hash_target();
+ if !target.matches_user_and_author_rules() {
+ return false;
+ }
+
+ let mut doc_rules_apply = true;
// Use the same rules to look for the containing host as we do for rule
// collection.
- if let Some(shadow) = containing_shadow_ignoring_svg_use(*self) {
+ if let Some(shadow) = containing_shadow_ignoring_svg_use(target) {
doc_rules_apply = false;
if let Some(data) = shadow.style_data() {
f(data, shadow.host());
}
}
- if let Some(shadow) = self.shadow_root() {
+ if let Some(shadow) = target.shadow_root() {
if let Some(data) = shadow.style_data() {
f(data, shadow.host());
}
}
- let mut current = self.assigned_slot();
+ let mut current = target.assigned_slot();
while let Some(slot) = current {
// Slots can only have assigned nodes when in a shadow tree.
let shadow = slot.containing_shadow().unwrap();
diff --git a/components/style/driver.rs b/components/style/driver.rs
index e9433f73a03..6b05bc85281 100644
--- a/components/style/driver.rs
+++ b/components/style/driver.rs
@@ -134,6 +134,7 @@ pub fn traverse_dom<E, D>(
let drain = discovered.drain(..);
pool.install(|| {
rayon::scope(|scope| {
+ profiler_label!(Style);
parallel::traverse_nodes(
drain,
DispatchMode::TailCall,
diff --git a/components/style/gecko/arc_types.rs b/components/style/gecko/arc_types.rs
index 309f2395085..7aed10b6568 100644
--- a/components/style/gecko/arc_types.rs
+++ b/components/style/gecko/arc_types.rs
@@ -23,7 +23,6 @@ use crate::gecko_bindings::structs::RawServoMediaRule;
use crate::gecko_bindings::structs::RawServoMozDocumentRule;
use crate::gecko_bindings::structs::RawServoNamespaceRule;
use crate::gecko_bindings::structs::RawServoPageRule;
-use crate::gecko_bindings::structs::RawServoQuotes;
use crate::gecko_bindings::structs::RawServoStyleRule;
use crate::gecko_bindings::structs::RawServoStyleSheetContents;
use crate::gecko_bindings::structs::RawServoSupportsRule;
@@ -40,7 +39,6 @@ use crate::stylesheets::{NamespaceRule, PageRule};
use crate::stylesheets::{StyleRule, StylesheetContents, SupportsRule};
use servo_arc::{Arc, ArcBorrow};
use std::{mem, ptr};
-use values::computed::QuotePair;
macro_rules! impl_arc_ffi {
($servo_type:ty => $gecko_type:ty[$addref:ident, $release:ident]) => {
@@ -115,9 +113,6 @@ 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]);
-
// ComputedStyle is not an opaque type on any side of FFI.
// This means that doing the HasArcFFI type trick is actually unsound,
// since it gives us a way to construct an Arc<ComputedStyle> from
diff --git a/components/style/gecko/boxed_types.rs b/components/style/gecko/boxed_types.rs
index b61c7708b2a..47fc4fe57dc 100644
--- a/components/style/gecko/boxed_types.rs
+++ b/components/style/gecko/boxed_types.rs
@@ -5,6 +5,7 @@
//! FFI implementations for types listed in ServoBoxedTypeList.h.
use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
+use crate::properties::animated_properties::AnimationValueMap;
use to_shmem::SharedMemoryBuilder;
// TODO(heycam): The FFI impls for most of the types in ServoBoxedTypeList.h are spread across
@@ -12,6 +13,15 @@ use to_shmem::SharedMemoryBuilder;
// them more succinctly, like we do in arc_types.rs.
#[cfg(feature = "gecko")]
+unsafe impl HasFFI for AnimationValueMap {
+ type FFIType = crate::gecko_bindings::bindings::RawServoAnimationValueMap;
+}
+#[cfg(feature = "gecko")]
+unsafe impl HasSimpleFFI for AnimationValueMap {}
+#[cfg(feature = "gecko")]
+unsafe impl HasBoxFFI for AnimationValueMap {}
+
+#[cfg(feature = "gecko")]
unsafe impl HasFFI for SharedMemoryBuilder {
type FFIType = crate::gecko_bindings::bindings::RawServoSharedMemoryBuilder;
}
diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs
index 43082a7c04a..06e201bf2b5 100644
--- a/components/style/gecko/conversions.rs
+++ b/components/style/gecko/conversions.rs
@@ -383,7 +383,6 @@ impl nsStyleImage {
let atom = bindings::Gecko_GetImageElement(self);
Some(GenericImage::Element(Atom::from_raw(atom)))
},
- _ => panic!("Unexpected image type"),
}
}
@@ -535,10 +534,8 @@ pub mod basic_shape {
use crate::gecko_bindings::structs::{
StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
};
- use crate::gecko_bindings::sugar::refptr::RefPtr;
use crate::values::computed::basic_shape::{BasicShape, ClippingShape, FloatAreaShape};
use crate::values::computed::motion::OffsetPath;
- use crate::values::computed::url::ComputedUrl;
use crate::values::generics::basic_shape::{GeometryBox, Path, ShapeBox, ShapeSource};
use crate::values::specified::SVGPathData;
@@ -564,7 +561,7 @@ pub mod basic_shape {
};
Some(ShapeSource::Shape(shape, reference_box))
},
- StyleShapeSourceType::URL | StyleShapeSourceType::Image => None,
+ StyleShapeSourceType::Image => None,
StyleShapeSourceType::Path => {
let path = self.to_svg_path().expect("expect an SVGPathData");
let fill = unsafe { &*self.__bindgen_anon_1.mSVGPath.as_ref().mPtr }.mFillRule;
@@ -587,16 +584,15 @@ pub mod basic_shape {
impl<'a> From<&'a StyleShapeSource> for ClippingShape {
fn from(other: &'a StyleShapeSource) -> Self {
+ use crate::values::generics::image::Image as GenericImage;
match other.mType {
- StyleShapeSourceType::URL => unsafe {
+ StyleShapeSourceType::Image => unsafe {
let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
- let other_url =
- RefPtr::new(*shape_image.__bindgen_anon_1.mURLValue.as_ref() as *mut _);
- let url = ComputedUrl::from_url_value(other_url);
- ShapeSource::ImageOrUrl(url)
- },
- StyleShapeSourceType::Image => {
- unreachable!("ClippingShape doesn't support Image!");
+ let image = shape_image.into_image().expect("Cannot convert to Image");
+ match image {
+ GenericImage::Url(url) => ShapeSource::ImageOrUrl(url.0),
+ _ => panic!("ClippingShape doesn't support non-url images"),
+ }
},
_ => other
.into_shape_source()
@@ -608,9 +604,6 @@ pub mod basic_shape {
impl<'a> From<&'a StyleShapeSource> for FloatAreaShape {
fn from(other: &'a StyleShapeSource) -> Self {
match other.mType {
- StyleShapeSourceType::URL => {
- unreachable!("FloatAreaShape doesn't support URL!");
- },
StyleShapeSourceType::Image => unsafe {
let shape_image = &*other.__bindgen_anon_1.mShapeImage.as_ref().mPtr;
let image = shape_image.into_image().expect("Cannot convert to Image");
@@ -632,7 +625,6 @@ pub mod basic_shape {
StyleShapeSourceType::None => OffsetPath::none(),
StyleShapeSourceType::Shape |
StyleShapeSourceType::Box |
- StyleShapeSourceType::URL |
StyleShapeSourceType::Image => unreachable!("Unsupported offset-path type"),
}
}
diff --git a/components/style/gecko/mod.rs b/components/style/gecko/mod.rs
index fb332dcce6e..3ff2cfcf140 100644
--- a/components/style/gecko/mod.rs
+++ b/components/style/gecko/mod.rs
@@ -13,9 +13,10 @@ pub mod conversions;
pub mod data;
pub mod media_features;
pub mod media_queries;
+#[cfg(feature = "gecko_profiler")]
+pub mod profiler;
pub mod pseudo_element;
pub mod restyle_damage;
-pub mod rules;
pub mod selector_parser;
pub mod snapshot;
pub mod snapshot_helpers;
diff --git a/components/style/gecko/profiler.rs b/components/style/gecko/profiler.rs
new file mode 100644
index 00000000000..1f25dde04e7
--- /dev/null
+++ b/components/style/gecko/profiler.rs
@@ -0,0 +1,75 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+//! Gecko profiler support.
+//!
+//! Use the `profiler_label!` macro from macros.rs.
+
+use crate::gecko_bindings::structs;
+
+/// A label describing a category of work that style threads can perform.
+pub enum ProfilerLabel {
+ /// Style computation.
+ Style,
+ /// Style sheet parsing.
+ Parse,
+}
+
+/// RAII object that constructs and destroys a C++ AutoProfilerLabel object
+/// pointed to be the specified reference.
+#[cfg(feature = "gecko_profiler")]
+pub struct AutoProfilerLabel<'a>(&'a mut structs::AutoProfilerLabel);
+
+#[cfg(feature = "gecko_profiler")]
+impl<'a> AutoProfilerLabel<'a> {
+ /// Creates a new AutoProfilerLabel with the specified label type.
+ ///
+ /// unsafe since the caller must ensure that `label` is allocated on the
+ /// stack.
+ #[inline]
+ pub unsafe fn new(
+ label: &mut structs::AutoProfilerLabel,
+ label_type: ProfilerLabel,
+ ) -> AutoProfilerLabel {
+ let category_pair = match label_type {
+ ProfilerLabel::Style => structs::JS::ProfilingCategoryPair_LAYOUT_StyleComputation,
+ ProfilerLabel::Parse => structs::JS::ProfilingCategoryPair_LAYOUT_CSSParsing,
+ };
+ structs::Gecko_Construct_AutoProfilerLabel(label, category_pair);
+ AutoProfilerLabel(label)
+ }
+}
+
+#[cfg(feature = "gecko_profiler")]
+impl<'a> Drop for AutoProfilerLabel<'a> {
+ #[inline]
+ fn drop(&mut self) {
+ unsafe {
+ structs::Gecko_Destroy_AutoProfilerLabel(self.0);
+ }
+ }
+}
+
+/// Whether the Gecko profiler is currently active.
+///
+/// This implementation must be kept in sync with
+/// `mozilla::profiler::detail::RacyFeatures::IsActive`.
+#[cfg(feature = "gecko_profiler")]
+#[inline]
+pub fn profiler_is_active() -> bool {
+ use self::structs::profiler::detail;
+ use std::mem;
+ use std::sync::atomic::{AtomicU32, Ordering};
+
+ let active_and_features: &AtomicU32 =
+ unsafe { mem::transmute(&detail::RacyFeatures_sActiveAndFeatures) };
+ (active_and_features.load(Ordering::Relaxed) & detail::RacyFeatures_Active) != 0
+}
+
+/// Always false when the Gecko profiler is disabled.
+#[cfg(not(feature = "gecko_profiler"))]
+#[inline]
+pub fn profiler_is_active() -> bool {
+ false
+}
diff --git a/components/style/gecko/rules.rs b/components/style/gecko/rules.rs
deleted file mode 100644
index 050a95754df..00000000000
--- a/components/style/gecko/rules.rs
+++ /dev/null
@@ -1,135 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-//! Bindings for CSS Rule objects
-
-use crate::counter_style::{self, CounterBound};
-use crate::gecko_bindings::structs::{self, nsCSSValue};
-use crate::gecko_bindings::sugar::ns_css_value::ToNsCssValue;
-
-impl<'a> ToNsCssValue for &'a counter_style::System {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- use crate::counter_style::System::*;
- match *self {
- Cyclic => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_CYCLIC as i32),
- Numeric => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_NUMERIC as i32),
- Alphabetic => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_ALPHABETIC as i32),
- Symbolic => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_SYMBOLIC as i32),
- Additive => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_ADDITIVE as i32),
- Fixed {
- ref first_symbol_value,
- } => {
- let mut a = nsCSSValue::null();
- let mut b = nsCSSValue::null();
- a.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_FIXED as i32);
- b.set_integer(first_symbol_value.map_or(1, |v| v.value()));
- nscssvalue.set_pair(&a, &b);
- },
- Extends(ref other) => {
- let mut a = nsCSSValue::null();
- let mut b = nsCSSValue::null();
- a.set_enum(structs::NS_STYLE_COUNTER_SYSTEM_EXTENDS as i32);
- b.set_atom_ident(other.0.clone());
- nscssvalue.set_pair(&a, &b);
- },
- }
- }
-}
-
-impl<'a> ToNsCssValue for &'a counter_style::Negative {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- if let Some(ref second) = self.1 {
- let mut a = nsCSSValue::null();
- let mut b = nsCSSValue::null();
- a.set_from(&self.0);
- b.set_from(second);
- nscssvalue.set_pair(&a, &b);
- } else {
- nscssvalue.set_from(&self.0)
- }
- }
-}
-
-impl<'a> ToNsCssValue for &'a counter_style::Symbol {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- match *self {
- counter_style::Symbol::String(ref s) => nscssvalue.set_string(s),
- counter_style::Symbol::Ident(ref s) => nscssvalue.set_ident_from_atom(&s.0),
- }
- }
-}
-
-impl<'a> ToNsCssValue for &'a counter_style::Ranges {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- if self.0.is_empty() {
- nscssvalue.set_auto();
- } else {
- nscssvalue.set_pair_list(self.0.iter().map(|range| {
- fn set_bound(bound: CounterBound, nscssvalue: &mut nsCSSValue) {
- if let CounterBound::Integer(finite) = bound {
- nscssvalue.set_integer(finite.value())
- } else {
- nscssvalue.set_enum(structs::NS_STYLE_COUNTER_RANGE_INFINITE as i32)
- }
- }
- let mut start = nsCSSValue::null();
- let mut end = nsCSSValue::null();
- set_bound(range.start, &mut start);
- set_bound(range.end, &mut end);
- (start, end)
- }));
- }
- }
-}
-
-impl<'a> ToNsCssValue for &'a counter_style::Pad {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- let mut min_length = nsCSSValue::null();
- let mut pad_with = nsCSSValue::null();
- min_length.set_integer(self.0.value());
- pad_with.set_from(&self.1);
- nscssvalue.set_pair(&min_length, &pad_with);
- }
-}
-
-impl<'a> ToNsCssValue for &'a counter_style::Fallback {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- nscssvalue.set_atom_ident(self.0 .0.clone())
- }
-}
-
-impl<'a> ToNsCssValue for &'a counter_style::Symbols {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- nscssvalue.set_list(self.0.iter().map(|item| {
- let mut value = nsCSSValue::null();
- value.set_from(item);
- value
- }));
- }
-}
-
-impl<'a> ToNsCssValue for &'a counter_style::AdditiveSymbols {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- nscssvalue.set_pair_list(self.0.iter().map(|tuple| {
- let mut weight = nsCSSValue::null();
- let mut symbol = nsCSSValue::null();
- weight.set_integer(tuple.weight.value());
- symbol.set_from(&tuple.symbol);
- (weight, symbol)
- }));
- }
-}
-
-impl<'a> ToNsCssValue for &'a counter_style::SpeakAs {
- fn convert(self, nscssvalue: &mut nsCSSValue) {
- use crate::counter_style::SpeakAs::*;
- match *self {
- Auto => nscssvalue.set_auto(),
- Bullets => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_BULLETS as i32),
- Numbers => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_NUMBERS as i32),
- Words => nscssvalue.set_enum(structs::NS_STYLE_COUNTER_SPEAKAS_WORDS as i32),
- Other(ref other) => nscssvalue.set_atom_ident(other.0.clone()),
- }
- }
-}
diff --git a/components/style/gecko/url.rs b/components/style/gecko/url.rs
index 2da16043779..dbbb3399da7 100644
--- a/components/style/gecko/url.rs
+++ b/components/style/gecko/url.rs
@@ -310,13 +310,13 @@ impl ToComputedValue for SpecifiedImageUrl {
type ComputedValue = ComputedImageUrl;
#[inline]
- fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
- ComputedImageUrl(self.clone())
+ fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
+ ComputedImageUrl(self.0.to_computed_value(context))
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- computed.0.clone()
+ SpecifiedImageUrl(ToComputedValue::from_computed_value(&computed.0))
}
}
@@ -378,7 +378,7 @@ impl ComputedUrl {
/// The computed value of a CSS image `url()`.
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq)]
-pub struct ComputedImageUrl(pub SpecifiedImageUrl);
+pub struct ComputedImageUrl(pub ComputedUrl);
impl ToCss for ComputedImageUrl {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
@@ -395,22 +395,17 @@ impl ComputedImageUrl {
/// Convert from nsStyleImageReques to ComputedImageUrl.
pub unsafe fn from_image_request(image_request: &nsStyleImageRequest) -> Self {
let url_value = image_request.mImageValue.to_safe();
- let css_url = &*url_value.mCssUrl.mRawPtr;
- let url = CssUrl(CssUrlData::as_arc(&css_url).clone_arc());
- ComputedImageUrl(SpecifiedImageUrl(SpecifiedUrl {
- url,
- url_value: Box::new(URLValueSource::URLValue(url_value)),
- }))
+ ComputedImageUrl(ComputedUrl::from_url_value(url_value))
}
/// Clone a new, strong reference to the Gecko URLValue.
pub fn clone_url_value(&self) -> RefPtr<URLValue> {
- (self.0).0.clone_url_value()
+ self.0.clone_url_value()
}
/// Get a raw pointer to the URLValue held by this ComputedImageUrl, for FFI.
pub fn url_value_ptr(&self) -> *mut URLValue {
- (self.0).0.url_value_ptr()
+ self.0.url_value_ptr()
}
}
diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs
index 98fe90fe3d0..8df85339265 100644
--- a/components/style/gecko/values.rs
+++ b/components/style/gecko/values.rs
@@ -12,7 +12,6 @@ use crate::gecko_bindings::structs::{nsStyleCoord, CounterStylePtr};
use crate::gecko_bindings::sugar::ns_style_coord::{CoordData, CoordDataMut, CoordDataValue};
use crate::values::computed::{Angle, Length, LengthPercentage};
use crate::values::computed::{Number, NumberOrPercentage, Percentage};
-use crate::values::generics::gecko::ScrollSnapPoint;
use crate::values::generics::grid::{TrackBreadth, TrackKeyword};
use crate::values::generics::length::LengthPercentageOrAuto;
use crate::values::generics::{CounterStyleOrNone, NonNegative};
@@ -217,27 +216,6 @@ impl GeckoStyleCoordConvertible for Angle {
}
}
-impl GeckoStyleCoordConvertible for ScrollSnapPoint<LengthPercentage> {
- fn to_gecko_style_coord<T: CoordDataMut>(&self, coord: &mut T) {
- match self.repeated() {
- None => coord.set_value(CoordDataValue::None),
- Some(l) => l.to_gecko_style_coord(coord),
- };
- }
-
- fn from_gecko_style_coord<T: CoordData>(coord: &T) -> Option<Self> {
- use crate::gecko_bindings::structs::root::nsStyleUnit;
-
- Some(match coord.unit() {
- nsStyleUnit::eStyleUnit_None => ScrollSnapPoint::None,
- _ => ScrollSnapPoint::Repeat(
- LengthPercentage::from_gecko_style_coord(coord)
- .expect("coord could not convert to LengthPercentage"),
- ),
- })
- }
-}
-
/// Convert a given RGBA value to `nscolor`.
pub fn convert_rgba_to_nscolor(rgba: &RGBA) -> u32 {
((rgba.alpha as u32) << 24) |
@@ -288,7 +266,7 @@ impl CounterStyleOrNone {
.0
.iter()
.map(|symbol| match *symbol {
- Symbol::String(ref s) => nsCStr::from(s),
+ Symbol::String(ref s) => nsCStr::from(&**s),
Symbol::Ident(_) => unreachable!("Should not have identifier in symbols()"),
})
.collect();
@@ -333,7 +311,7 @@ impl CounterStyleOrNone {
let symbol_type = SymbolsType::from_gecko_keyword(anonymous.mSystem as u32);
let symbols = symbols
.iter()
- .map(|gecko_symbol| Symbol::String(gecko_symbol.to_string()))
+ .map(|gecko_symbol| Symbol::String(gecko_symbol.to_string().into()))
.collect();
Either::First(CounterStyleOrNone::Symbols(symbol_type, Symbols(symbols)))
}
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index 9d987c56308..a1443d1ad8d 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -1098,7 +1098,7 @@ impl<'le> TElement for GeckoElement<'le> {
type TraversalChildrenIterator = GeckoChildrenIterator<'le>;
fn inheritance_parent(&self) -> Option<Self> {
- if self.implemented_pseudo_element().is_some() {
+ if self.is_pseudo_element() {
return self.pseudo_element_originating_element();
}
@@ -1405,7 +1405,7 @@ impl<'le> TElement for GeckoElement<'le> {
#[inline]
fn matches_user_and_author_rules(&self) -> bool {
- !self.rule_hash_target().is_in_native_anonymous_subtree()
+ !self.is_in_native_anonymous_subtree()
}
#[inline]
@@ -1471,7 +1471,7 @@ impl<'le> TElement for GeckoElement<'le> {
#[inline]
fn skip_item_display_fixup(&self) -> bool {
debug_assert!(
- self.implemented_pseudo_element().is_none(),
+ !self.is_pseudo_element(),
"Just don't call me if I'm a pseudo, you should know the answer already"
);
self.is_root_of_native_anonymous_subtree()
@@ -1919,8 +1919,13 @@ impl<'le> ::selectors::Element for GeckoElement<'le> {
}
#[inline]
+ fn is_pseudo_element(&self) -> bool {
+ self.implemented_pseudo_element().is_some()
+ }
+
+ #[inline]
fn pseudo_element_originating_element(&self) -> Option<Self> {
- debug_assert!(self.implemented_pseudo_element().is_some());
+ debug_assert!(self.is_pseudo_element());
let parent = self.closest_anon_subtree_root_parent()?;
// FIXME(emilio): Special-case for <input type="number">s
diff --git a/components/style/gecko_bindings/sugar/mod.rs b/components/style/gecko_bindings/sugar/mod.rs
index de981bd289a..338236c175a 100644
--- a/components/style/gecko_bindings/sugar/mod.rs
+++ b/components/style/gecko_bindings/sugar/mod.rs
@@ -6,9 +6,6 @@
mod ns_com_ptr;
mod ns_compatibility;
-mod ns_css_shadow_array;
-mod ns_css_shadow_item;
-pub mod ns_css_value;
mod ns_style_auto_array;
pub mod ns_style_coord;
mod ns_t_array;
diff --git a/components/style/gecko_bindings/sugar/ns_css_shadow_array.rs b/components/style/gecko_bindings/sugar/ns_css_shadow_array.rs
deleted file mode 100644
index c0c6c2d9e36..00000000000
--- a/components/style/gecko_bindings/sugar/ns_css_shadow_array.rs
+++ /dev/null
@@ -1,78 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-//! Rust helpers for Gecko's `nsCSSShadowArray`.
-
-use crate::gecko_bindings::bindings::Gecko_AddRefCSSShadowArrayArbitraryThread;
-use crate::gecko_bindings::bindings::Gecko_NewCSSShadowArray;
-use crate::gecko_bindings::bindings::Gecko_ReleaseCSSShadowArrayArbitraryThread;
-use crate::gecko_bindings::structs::{nsCSSShadowArray, nsCSSShadowItem, RefPtr};
-use std::ops::{Deref, DerefMut};
-use std::{ptr, slice};
-
-impl RefPtr<nsCSSShadowArray> {
- /// Replaces the current `nsCSSShadowArray` with a new one of len `len`.
- pub fn replace_with_new(&mut self, len: u32) {
- unsafe {
- if !self.mRawPtr.is_null() {
- Gecko_ReleaseCSSShadowArrayArbitraryThread(self.mRawPtr);
- }
-
- self.mRawPtr = if len == 0 {
- ptr::null_mut()
- } else {
- Gecko_NewCSSShadowArray(len)
- }
- }
- }
-
- /// Sets the value to other `nsCSSShadowArray`, bumping and decreasing
- /// refcounts as needed.
- ///
- /// TODO(emilio): Seems like this could move to `refptr.rs`, and be more
- /// generic.
- pub fn copy_from(&mut self, other: &Self) {
- unsafe {
- if !self.mRawPtr.is_null() {
- Gecko_ReleaseCSSShadowArrayArbitraryThread(self.mRawPtr);
- }
- if !other.mRawPtr.is_null() {
- Gecko_AddRefCSSShadowArrayArbitraryThread(other.mRawPtr);
- }
-
- self.mRawPtr = other.mRawPtr;
- }
- }
-}
-
-impl Deref for RefPtr<nsCSSShadowArray> {
- type Target = [nsCSSShadowItem];
- fn deref(&self) -> &[nsCSSShadowItem] {
- if self.mRawPtr.is_null() {
- &[]
- } else {
- unsafe {
- slice::from_raw_parts(
- (*self.mRawPtr).mArray.as_ptr(),
- (*self.mRawPtr).mLength as usize,
- )
- }
- }
- }
-}
-
-impl DerefMut for RefPtr<nsCSSShadowArray> {
- fn deref_mut(&mut self) -> &mut [nsCSSShadowItem] {
- if self.mRawPtr.is_null() {
- &mut []
- } else {
- unsafe {
- slice::from_raw_parts_mut(
- (*self.mRawPtr).mArray.as_mut_ptr(),
- (*self.mRawPtr).mLength as usize,
- )
- }
- }
- }
-}
diff --git a/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs b/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs
deleted file mode 100644
index 03d68576dea..00000000000
--- a/components/style/gecko_bindings/sugar/ns_css_shadow_item.rs
+++ /dev/null
@@ -1,59 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-//! Rust helpers for Gecko's `nsCSSShadowItem`.
-
-use crate::gecko_bindings::structs::nsCSSShadowItem;
-use crate::values::computed::effects::{BoxShadow, SimpleShadow};
-use app_units::Au;
-
-impl nsCSSShadowItem {
- /// Sets this item from the given box shadow.
- #[inline]
- pub fn set_from_box_shadow(&mut self, shadow: BoxShadow) {
- self.set_from_simple_shadow(shadow.base);
- self.mSpread = shadow.spread.to_i32_au();
- self.mInset = shadow.inset;
- }
-
- /// Returns this item as a box shadow.
- #[inline]
- pub fn to_box_shadow(&self) -> BoxShadow {
- BoxShadow {
- base: self.extract_simple_shadow(),
- spread: Au(self.mSpread).into(),
- inset: self.mInset,
- }
- }
-
- /// Sets this item from the given simple shadow.
- #[inline]
- pub fn set_from_simple_shadow(&mut self, shadow: SimpleShadow) {
- self.mXOffset = shadow.horizontal.to_i32_au();
- self.mYOffset = shadow.vertical.to_i32_au();
- self.mRadius = shadow.blur.0.to_i32_au();
- self.mSpread = 0;
- self.mInset = false;
- self.mColor = shadow.color.into();
- }
-
- /// Gets a simple shadow from this item.
- #[inline]
- fn extract_simple_shadow(&self) -> SimpleShadow {
- SimpleShadow {
- color: self.mColor.into(),
- horizontal: Au(self.mXOffset).into(),
- vertical: Au(self.mYOffset).into(),
- blur: Au(self.mRadius).into(),
- }
- }
-
- /// Returns this item as a simple shadow.
- #[inline]
- pub fn to_simple_shadow(&self) -> SimpleShadow {
- debug_assert_eq!(self.mSpread, 0);
- debug_assert_eq!(self.mInset, false);
- self.extract_simple_shadow()
- }
-}
diff --git a/components/style/gecko_bindings/sugar/ns_css_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs
deleted file mode 100644
index b59732bcc8e..00000000000
--- a/components/style/gecko_bindings/sugar/ns_css_value.rs
+++ /dev/null
@@ -1,424 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-//! Little helpers for `nsCSSValue`.
-
-use crate::gecko_bindings::bindings;
-use crate::gecko_bindings::structs;
-use crate::gecko_bindings::structs::{nsCSSUnit, nsCSSValue};
-use crate::gecko_bindings::structs::{nsCSSValueList, nsCSSValue_Array};
-use crate::gecko_string_cache::Atom;
-use crate::values::computed::{Angle, Length, LengthPercentage, Percentage};
-use crate::Zero;
-use std::marker::PhantomData;
-use std::mem;
-use std::ops::{Index, IndexMut};
-use std::slice;
-
-impl nsCSSValue {
- /// Create a CSSValue with null unit, useful to be used as a return value.
- #[inline]
- pub fn null() -> Self {
- unsafe { mem::zeroed() }
- }
-
- /// Returns true if this nsCSSValue is none.
- #[inline]
- pub fn is_none(&self) -> bool {
- self.mUnit == nsCSSUnit::eCSSUnit_None
- }
-
- /// Returns this nsCSSValue value as an integer, unchecked in release
- /// builds.
- pub fn integer_unchecked(&self) -> i32 {
- debug_assert!(
- self.mUnit == nsCSSUnit::eCSSUnit_Integer ||
- self.mUnit == nsCSSUnit::eCSSUnit_Enumerated
- );
- unsafe { *self.mValue.mInt.as_ref() }
- }
-
- /// Checks if it is an integer and returns it if so
- pub fn integer(&self) -> Option<i32> {
- if self.mUnit == nsCSSUnit::eCSSUnit_Integer || self.mUnit == nsCSSUnit::eCSSUnit_Enumerated
- {
- Some(unsafe { *self.mValue.mInt.as_ref() })
- } else {
- None
- }
- }
-
- /// Returns this nsCSSValue value as a floating point value, unchecked in
- /// release builds.
- pub fn float_unchecked(&self) -> f32 {
- debug_assert!(nsCSSUnit::eCSSUnit_Number as u32 <= self.mUnit as u32);
- unsafe { *self.mValue.mFloat.as_ref() }
- }
-
- /// Returns this nsCSSValue as a nsCSSValue::Array, unchecked in release
- /// builds.
- pub unsafe fn array_unchecked(&self) -> &nsCSSValue_Array {
- debug_assert!(
- nsCSSUnit::eCSSUnit_Array as u32 <= self.mUnit as u32 &&
- self.mUnit as u32 <= nsCSSUnit::eCSSUnit_Calc_Plus as u32
- );
- let array = *self.mValue.mArray.as_ref();
- debug_assert!(!array.is_null());
- &*array
- }
-
- /// Sets LengthPercentage value to this nsCSSValue.
- pub unsafe fn set_length_percentage(&mut self, lp: LengthPercentage) {
- if lp.was_calc {
- return bindings::Gecko_CSSValue_SetCalc(self, lp.into());
- }
- debug_assert!(!lp.has_percentage || lp.unclamped_length() == Length::zero());
- if lp.has_percentage {
- return self.set_percentage(lp.percentage());
- }
- self.set_px(lp.unclamped_length().px());
- }
-
- /// Sets a px value to this nsCSSValue.
- pub unsafe fn set_px(&mut self, px: f32) {
- bindings::Gecko_CSSValue_SetPixelLength(self, px)
- }
-
- /// Sets a percentage value to this nsCSSValue.
- pub unsafe fn set_percentage(&mut self, unit_value: f32) {
- bindings::Gecko_CSSValue_SetPercentage(self, unit_value)
- }
-
- /// Returns LengthPercentage value.
- pub unsafe fn get_length_percentage(&self) -> LengthPercentage {
- match self.mUnit {
- nsCSSUnit::eCSSUnit_Pixel => {
- LengthPercentage::new(Length::new(bindings::Gecko_CSSValue_GetNumber(self)), None)
- },
- nsCSSUnit::eCSSUnit_Percent => LengthPercentage::new_percent(Percentage(
- bindings::Gecko_CSSValue_GetPercentage(self),
- )),
- nsCSSUnit::eCSSUnit_Calc => bindings::Gecko_CSSValue_GetCalc(self).into(),
- _ => panic!("Unexpected unit"),
- }
- }
-
- /// Returns Length value.
- pub unsafe fn get_length(&self) -> Length {
- match self.mUnit {
- nsCSSUnit::eCSSUnit_Pixel => Length::new(bindings::Gecko_CSSValue_GetNumber(self)),
- _ => panic!("Unexpected unit"),
- }
- }
-
- fn set_valueless_unit(&mut self, unit: nsCSSUnit) {
- debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_Null);
- debug_assert!(
- unit as u32 <= nsCSSUnit::eCSSUnit_DummyInherit as u32,
- "Not a valueless unit"
- );
- self.mUnit = unit;
- }
-
- /// Set to an auto value
- ///
- /// This method requires the current value to be null.
- pub fn set_auto(&mut self) {
- self.set_valueless_unit(nsCSSUnit::eCSSUnit_Auto);
- }
-
- /// Set to a normal value
- ///
- /// This method requires the current value to be null.
- pub fn set_normal(&mut self) {
- self.set_valueless_unit(nsCSSUnit::eCSSUnit_Normal);
- }
-
- fn set_string_internal(&mut self, s: &str, unit: nsCSSUnit) {
- unsafe { bindings::Gecko_CSSValue_SetString(self, s.as_ptr(), s.len() as u32, unit) }
- }
-
- fn set_string_from_atom_internal(&mut self, s: &Atom, unit: nsCSSUnit) {
- unsafe { bindings::Gecko_CSSValue_SetStringFromAtom(self, s.as_ptr(), unit) }
- }
-
- /// Set to a string value
- pub fn set_string(&mut self, s: &str) {
- self.set_string_internal(s, nsCSSUnit::eCSSUnit_String)
- }
-
- /// Set to a string value from the given atom
- pub fn set_string_from_atom(&mut self, s: &Atom) {
- self.set_string_from_atom_internal(s, nsCSSUnit::eCSSUnit_String)
- }
-
- /// Set to a ident value from the given atom
- pub fn set_ident_from_atom(&mut self, s: &Atom) {
- self.set_string_from_atom_internal(s, nsCSSUnit::eCSSUnit_Ident)
- }
-
- /// Set to an identifier value
- pub fn set_ident(&mut self, s: &str) {
- self.set_string_internal(s, nsCSSUnit::eCSSUnit_Ident)
- }
-
- /// Set to an atom identifier value
- pub fn set_atom_ident(&mut self, s: Atom) {
- unsafe { bindings::Gecko_CSSValue_SetAtomIdent(self, s.into_addrefed()) }
- }
-
- fn set_int_internal(&mut self, value: i32, unit: nsCSSUnit) {
- unsafe { bindings::Gecko_CSSValue_SetInt(self, value, unit) }
- }
-
- /// Set to an integer value
- pub fn set_integer(&mut self, value: i32) {
- self.set_int_internal(value, nsCSSUnit::eCSSUnit_Integer)
- }
-
- /// Set to an enumerated value
- pub fn set_enum<T: Into<i32>>(&mut self, value: T) {
- self.set_int_internal(value.into(), nsCSSUnit::eCSSUnit_Enumerated);
- }
-
- /// Set to a number value
- pub fn set_number(&mut self, number: f32) {
- unsafe { bindings::Gecko_CSSValue_SetFloat(self, number, nsCSSUnit::eCSSUnit_Number) }
- }
-
- /// 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) }
- unsafe { self.mValue.mArray.as_mut().as_mut() }.unwrap()
- }
-
- /// Generic set from any value that implements the ToNsCssValue trait.
- pub fn set_from<T: ToNsCssValue>(&mut self, value: T) {
- value.convert(self)
- }
-
- /// Returns an `Angle` value from this `nsCSSValue`.
- ///
- /// Panics if the unit is not `eCSSUnit_Degree`.
- #[inline]
- pub fn get_angle(&self) -> Angle {
- debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_Degree);
- Angle::from_degrees(self.float_unchecked())
- }
-
- /// Sets Angle value to this nsCSSValue.
- pub fn set_angle(&mut self, angle: Angle) {
- debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_Null);
- self.mUnit = nsCSSUnit::eCSSUnit_Degree;
- unsafe {
- *self.mValue.mFloat.as_mut() = angle.degrees();
- }
- }
-
- /// Set to a pair value
- ///
- /// This is only supported on the main thread.
- pub fn set_pair(&mut self, x: &nsCSSValue, y: &nsCSSValue) {
- unsafe { bindings::Gecko_CSSValue_SetPair(self, x, y) }
- }
-
- /// Set to a list value
- ///
- /// This is only supported on the main thread.
- pub fn set_list<I>(&mut self, values: I)
- where
- I: ExactSizeIterator<Item = nsCSSValue>,
- {
- debug_assert!(values.len() > 0, "Empty list is not supported");
- unsafe {
- bindings::Gecko_CSSValue_SetList(self, values.len() as u32);
- }
- debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_List);
- let list: &mut structs::nsCSSValueList = &mut unsafe {
- self.mValue
- .mList
- .as_ref() // &*nsCSSValueList_heap
- .as_mut()
- .expect("List pointer should be non-null")
- }
- ._base;
- for (item, new_value) in list.into_iter().zip(values) {
- *item = new_value;
- }
- }
-
- /// Set to a pair list value
- ///
- /// This is only supported on the main thread.
- pub fn set_pair_list<I>(&mut self, mut values: I)
- where
- I: ExactSizeIterator<Item = (nsCSSValue, nsCSSValue)>,
- {
- debug_assert!(values.len() > 0, "Empty list is not supported");
- unsafe {
- bindings::Gecko_CSSValue_SetPairList(self, values.len() as u32);
- }
- debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_PairList);
- let mut item_ptr = &mut unsafe {
- self.mValue
- .mPairList
- .as_ref() // &*nsCSSValuePairList_heap
- .as_mut()
- .expect("List pointer should be non-null")
- }
- ._base as *mut structs::nsCSSValuePairList;
- while let Some(item) = unsafe { item_ptr.as_mut() } {
- let value = values.next().expect("Values shouldn't have been exhausted");
- item.mXValue = value.0;
- item.mYValue = value.1;
- item_ptr = item.mNext;
- }
- debug_assert!(values.next().is_none(), "Values should have been exhausted");
- }
-
- /// Set a shared list
- pub fn set_shared_list<I>(&mut self, values: I)
- where
- I: ExactSizeIterator<Item = nsCSSValue>,
- {
- debug_assert!(values.len() > 0, "Empty list is not supported");
- unsafe { bindings::Gecko_CSSValue_InitSharedList(self, values.len() as u32) };
- debug_assert_eq!(self.mUnit, nsCSSUnit::eCSSUnit_SharedList);
- let list = unsafe {
- self.mValue
- .mSharedList
- .as_ref()
- .as_mut()
- .expect("List pointer should be non-null")
- .mHead
- .as_mut()
- };
- debug_assert!(list.is_some(), "New created shared list shouldn't be null");
- for (item, new_value) in list.unwrap().into_iter().zip(values) {
- *item = new_value;
- }
- }
-}
-
-impl Drop for nsCSSValue {
- fn drop(&mut self) {
- unsafe { bindings::Gecko_CSSValue_Drop(self) };
- }
-}
-
-/// Iterator of nsCSSValueList.
-#[allow(non_camel_case_types)]
-pub struct nsCSSValueListIterator<'a> {
- current: Option<&'a nsCSSValueList>,
-}
-
-impl<'a> Iterator for nsCSSValueListIterator<'a> {
- type Item = &'a nsCSSValue;
- fn next(&mut self) -> Option<Self::Item> {
- match self.current {
- Some(item) => {
- self.current = unsafe { item.mNext.as_ref() };
- Some(&item.mValue)
- },
- None => None,
- }
- }
-}
-
-impl<'a> IntoIterator for &'a nsCSSValueList {
- type Item = &'a nsCSSValue;
- type IntoIter = nsCSSValueListIterator<'a>;
-
- fn into_iter(self) -> Self::IntoIter {
- nsCSSValueListIterator {
- current: Some(self),
- }
- }
-}
-
-/// Mutable Iterator of nsCSSValueList.
-#[allow(non_camel_case_types)]
-pub struct nsCSSValueListMutIterator<'a> {
- current: *mut nsCSSValueList,
- phantom: PhantomData<&'a mut nsCSSValue>,
-}
-
-impl<'a> Iterator for nsCSSValueListMutIterator<'a> {
- type Item = &'a mut nsCSSValue;
- fn next(&mut self) -> Option<Self::Item> {
- match unsafe { self.current.as_mut() } {
- Some(item) => {
- self.current = item.mNext;
- Some(&mut item.mValue)
- },
- None => None,
- }
- }
-}
-
-impl<'a> IntoIterator for &'a mut nsCSSValueList {
- type Item = &'a mut nsCSSValue;
- type IntoIter = nsCSSValueListMutIterator<'a>;
-
- fn into_iter(self) -> Self::IntoIter {
- nsCSSValueListMutIterator {
- current: self as *mut nsCSSValueList,
- phantom: PhantomData,
- }
- }
-}
-
-impl nsCSSValue_Array {
- /// Return the length of this `nsCSSValue::Array`
- #[inline]
- pub fn len(&self) -> usize {
- self.mCount
- }
-
- #[inline]
- fn buffer(&self) -> *const nsCSSValue {
- self.mArray.as_ptr()
- }
-
- /// Get the array as a slice of nsCSSValues.
- #[inline]
- pub fn as_slice(&self) -> &[nsCSSValue] {
- unsafe { slice::from_raw_parts(self.buffer(), self.len()) }
- }
-
- /// Get the array as a mutable slice of nsCSSValues.
- #[inline]
- pub fn as_mut_slice(&mut self) -> &mut [nsCSSValue] {
- unsafe { slice::from_raw_parts_mut(self.buffer() as *mut _, self.len()) }
- }
-}
-
-impl Index<usize> for nsCSSValue_Array {
- type Output = nsCSSValue;
- #[inline]
- fn index(&self, i: usize) -> &nsCSSValue {
- &self.as_slice()[i]
- }
-}
-
-impl IndexMut<usize> for nsCSSValue_Array {
- #[inline]
- fn index_mut(&mut self, i: usize) -> &mut nsCSSValue {
- &mut self.as_mut_slice()[i]
- }
-}
-
-/// Generic conversion to nsCSSValue
-pub trait ToNsCssValue {
- /// Convert
- fn convert(self, nscssvalue: &mut nsCSSValue);
-}
-
-impl<T: ToNsCssValue> From<T> for nsCSSValue {
- fn from(value: T) -> nsCSSValue {
- let mut result = nsCSSValue::null();
- value.convert(&mut result);
- result
- }
-}
diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs
index 1ad71afa6bc..90cc5284bc4 100644
--- a/components/style/gecko_bindings/sugar/refptr.rs
+++ b/components/style/gecko_bindings/sugar/refptr.rs
@@ -290,11 +290,6 @@ impl_threadsafe_refcount!(
bindings::Gecko_ReleaseURLExtraDataArbitraryThread
);
impl_threadsafe_refcount!(
- structs::nsCSSValueSharedList,
- bindings::Gecko_AddRefCSSValueSharedListArbitraryThread,
- bindings::Gecko_ReleaseCSSValueSharedListArbitraryThread
-);
-impl_threadsafe_refcount!(
structs::mozilla::css::URLValue,
bindings::Gecko_AddRefCSSURLValueArbitraryThread,
bindings::Gecko_ReleaseCSSURLValueArbitraryThread
diff --git a/components/style/gecko_string_cache/mod.rs b/components/style/gecko_string_cache/mod.rs
index d71d192166a..b8f3ff7f048 100644
--- a/components/style/gecko_string_cache/mod.rs
+++ b/components/style/gecko_string_cache/mod.rs
@@ -53,6 +53,7 @@ macro_rules! local_name {
/// This is either a strong reference to a dynamic atom (an nsAtom pointer),
/// or an offset from gGkAtoms to the nsStaticAtom object.
#[derive(Eq, PartialEq)]
+#[repr(C)]
pub struct Atom(usize);
/// An atom *without* a strong reference.
diff --git a/components/style/invalidation/element/element_wrapper.rs b/components/style/invalidation/element/element_wrapper.rs
index 6e8e504c226..91f0705853c 100644
--- a/components/style/invalidation/element/element_wrapper.rs
+++ b/components/style/invalidation/element/element_wrapper.rs
@@ -366,6 +366,10 @@ where
self.element.is_root()
}
+ fn is_pseudo_element(&self) -> bool {
+ self.element.is_pseudo_element()
+ }
+
fn pseudo_element_originating_element(&self) -> Option<Self> {
self.element
.pseudo_element_originating_element()
diff --git a/components/style/lib.rs b/components/style/lib.rs
index 4d523d65c4f..587b926efc6 100644
--- a/components/style/lib.rs
+++ b/components/style/lib.rs
@@ -190,6 +190,7 @@ pub use servo_atoms::Atom;
pub use style_traits::arc_slice::ArcSlice;
pub use style_traits::owned_slice::OwnedSlice;
+pub use style_traits::owned_str::OwnedStr;
/// The CSS properties supported by the style system.
/// Generated from the properties.mako.rs template by build.rs
diff --git a/components/style/macros.rs b/components/style/macros.rs
index 22f1966071b..229e864977a 100644
--- a/components/style/macros.rs
+++ b/components/style/macros.rs
@@ -104,3 +104,32 @@ macro_rules! define_keyword_type {
}
};
}
+
+/// Place a Gecko profiler label on the stack.
+///
+/// The `label_type` argument must be the name of a variant of `ProfilerLabel`.
+#[cfg(feature = "gecko_profiler")]
+#[macro_export]
+macro_rules! profiler_label {
+ ($label_type:ident) => {
+ let mut _profiler_label: $crate::gecko_bindings::structs::AutoProfilerLabel =
+ unsafe { ::std::mem::uninitialized() };
+ let _profiler_label = if $crate::gecko::profiler::profiler_is_active() {
+ unsafe {
+ Some($crate::gecko::profiler::AutoProfilerLabel::new(
+ &mut _profiler_label,
+ $crate::gecko::profiler::ProfilerLabel::$label_type,
+ ))
+ }
+ } else {
+ None
+ };
+ };
+}
+
+/// No-op when the Gecko profiler is not available.
+#[cfg(not(feature = "gecko_profiler"))]
+#[macro_export]
+macro_rules! profiler_label {
+ ($label_type:ident) => {};
+}
diff --git a/components/style/parallel.rs b/components/style/parallel.rs
index 237453084df..619be351579 100644
--- a/components/style/parallel.rs
+++ b/components/style/parallel.rs
@@ -277,6 +277,7 @@ pub fn traverse_nodes<'a, 'scope, E, D, I>(
top_down_dom(&work, root, traversal_data, scope, pool, traversal, tls);
} else {
scope.spawn(move |scope| {
+ profiler_label!(Style);
let work = work;
top_down_dom(&work, root, traversal_data, scope, pool, traversal, tls);
});
@@ -286,6 +287,7 @@ pub fn traverse_nodes<'a, 'scope, E, D, I>(
let nodes: WorkUnit<E::ConcreteNode> = chunk.collect();
let traversal_data_copy = traversal_data.clone();
scope.spawn(move |scope| {
+ profiler_label!(Style);
let n = nodes;
top_down_dom(&*n, root, traversal_data_copy, scope, pool, traversal, tls)
});
diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs
index 1b76aefdd74..9b1cfb8ec04 100644
--- a/components/style/properties/cascade.rs
+++ b/components/style/properties/cascade.rs
@@ -628,10 +628,6 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> {
#[cfg(feature = "gecko")]
{
- if let Some(display) = builder.get_box_if_mutated() {
- display.generate_combined_transform();
- }
-
if let Some(bg) = builder.get_background_if_mutated() {
bg.fill_arrays();
}
diff --git a/components/style/properties/data.py b/components/style/properties/data.py
index ae307077690..e771607b6d9 100644
--- a/components/style/properties/data.py
+++ b/components/style/properties/data.py
@@ -172,8 +172,9 @@ class Longhand(object):
gecko_ffi_name=None,
allowed_in_keyframe_block=True, cast_type='u8',
logical=False, logical_group=None, alias=None, extra_prefixes=None, boxed=False,
- flags=None, allowed_in_page_rule=False, allow_quirks=False,
+ flags=None, allowed_in_page_rule=False, allow_quirks="No",
ignored_when_colors_disabled=False,
+ simple_vector_bindings=False,
vector=False, servo_restyle_damage="repaint"):
self.name = name
if not spec:
@@ -210,6 +211,7 @@ class Longhand(object):
self.allow_quirks = allow_quirks
self.ignored_when_colors_disabled = ignored_when_colors_disabled
self.is_vector = vector
+ self.simple_vector_bindings = simple_vector_bindings
# https://drafts.csswg.org/css-animations/#keyframes
# > The <declaration-list> inside of <keyframe-block> accepts any CSS property
@@ -323,12 +325,14 @@ class Longhand(object):
"JustifyContent",
"JustifyItems",
"JustifySelf",
+ "LineBreak",
"MozForceBrokenImageIcon",
"MozListReversed",
"MozScriptLevel",
"MozScriptMinSize",
"MozScriptSizeMultiplier",
"NonNegativeNumber",
+ "OffsetRotate",
"Opacity",
"OutlineStyle",
"Overflow",
diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs
index 1ce083c944f..fcbfb717aa8 100644
--- a/components/style/properties/declaration_block.rs
+++ b/components/style/properties/declaration_block.rs
@@ -1301,11 +1301,9 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
Ok(id) => id,
Err(..) => {
self.last_parsed_property_id = None;
- return Err(input.new_custom_error(if is_non_mozilla_vendor_identifier(&name) {
- StyleParseErrorKind::UnknownVendorProperty
- } else {
+ return Err(input.new_custom_error(
StyleParseErrorKind::UnknownProperty(name)
- }));
+ ));
}
};
if self.context.error_reporting_enabled() {
@@ -1326,6 +1324,13 @@ impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> {
type SmallParseErrorVec<'i> = SmallVec<[(ParseError<'i>, &'i str, Option<PropertyId>); 2]>;
+fn alias_of_known_property(name: &str) -> Option<PropertyId> {
+ let mut prefixed = String::with_capacity(name.len() + 5);
+ prefixed.push_str("-moz-");
+ prefixed.push_str(name);
+ PropertyId::parse_enabled_for_all_content(&prefixed).ok()
+}
+
#[cold]
fn report_one_css_error<'i>(
context: &ParserContext,
@@ -1352,10 +1357,22 @@ fn report_one_css_error<'i>(
}
}
- // If the unrecognized property looks like a vendor-specific property,
- // silently ignore it instead of polluting the error output.
- if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownVendorProperty) = error.kind {
- return;
+ if let ParseErrorKind::Custom(StyleParseErrorKind::UnknownProperty(ref name)) = error.kind {
+ if is_non_mozilla_vendor_identifier(name) {
+ // If the unrecognized property looks like a vendor-specific property,
+ // silently ignore it instead of polluting the error output.
+ return;
+ }
+ if let Some(alias) = alias_of_known_property(name) {
+ // This is an unknown property, but its -moz-* version is known.
+ // We don't want to report error if the -moz-* version is already
+ // specified.
+ if let Some(block) = block {
+ if all_properties_in_block(block, &alias) {
+ return;
+ }
+ }
+ }
}
if let Some(ref property) = property {
diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs
index 703cbed2c0b..dd5bcf2febf 100644
--- a/components/style/properties/gecko.mako.rs
+++ b/components/style/properties/gecko.mako.rs
@@ -28,7 +28,6 @@ use crate::gecko_bindings::bindings::Gecko_CopyListStyleImageFrom;
use crate::gecko_bindings::bindings::Gecko_EnsureImageLayersLength;
use crate::gecko_bindings::bindings::Gecko_SetCursorArrayLength;
use crate::gecko_bindings::bindings::Gecko_SetCursorImageValue;
-use crate::gecko_bindings::bindings::Gecko_NewCSSShadowArray;
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_SetLang;
use crate::gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom;
use crate::gecko_bindings::bindings::Gecko_SetListStyleImageNone;
@@ -50,17 +49,19 @@ use crate::rule_tree::StrongRuleNode;
use crate::selector_parser::PseudoElement;
use servo_arc::{Arc, RawOffsetArc};
use std::marker::PhantomData;
-use std::mem::{forget, uninitialized, zeroed};
+use std::mem::{forget, uninitialized, zeroed, ManuallyDrop};
use std::{cmp, ops, ptr};
use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
+use crate::values::computed::url::ComputedImageUrl;
use crate::values::computed::BorderStyle;
use crate::values::computed::font::FontSize;
-use crate::values::computed::effects::{BoxShadow, Filter, SimpleShadow};
+use crate::values::computed::effects::Filter;
use crate::values::generics::column::ColumnCount;
use crate::values::generics::transform::TransformStyle;
use crate::values::generics::url::UrlOrNone;
+
pub mod style_structs {
% for style_struct in data.style_structs:
pub use super::${style_struct.gecko_struct_name} as ${style_struct.name};
@@ -303,14 +304,14 @@ impl ${style_struct.gecko_struct_name} {
<%def name="impl_simple_clone(ident, gecko_ffi_name)">
#[allow(non_snake_case)]
pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
- From::from(self.gecko.${gecko_ffi_name})
+ From::from(self.gecko.${gecko_ffi_name}.clone())
}
</%def>
<%def name="impl_simple_copy(ident, gecko_ffi_name, *kwargs)">
#[allow(non_snake_case)]
pub fn copy_${ident}_from(&mut self, other: &Self) {
- self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name};
+ self.gecko.${gecko_ffi_name} = other.gecko.${gecko_ffi_name}.clone();
}
#[allow(non_snake_case)]
@@ -697,45 +698,6 @@ def set_gecko_property(ffi_name, expr):
}
</%def>
-<%def name="impl_style_coord(ident, gecko_ffi_name)">
- #[allow(non_snake_case)]
- pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
- v.to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name});
- }
- #[allow(non_snake_case)]
- pub fn copy_${ident}_from(&mut self, other: &Self) {
- self.gecko.${gecko_ffi_name}.copy_from(&other.gecko.${gecko_ffi_name});
- }
- #[allow(non_snake_case)]
- pub fn reset_${ident}(&mut self, other: &Self) {
- self.copy_${ident}_from(other)
- }
-
- #[allow(non_snake_case)]
- pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
- use crate::properties::longhands::${ident}::computed_value::T;
- T::from_gecko_style_coord(&self.gecko.${gecko_ffi_name})
- .expect("clone for ${ident} failed")
- }
-</%def>
-
-<%def name="impl_style_sides(ident)">
- <% gecko_ffi_name = "m" + to_camel_case(ident) %>
-
- #[allow(non_snake_case)]
- pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
- v.to_gecko_rect(&mut self.gecko.${gecko_ffi_name});
- }
-
- <%self:copy_sides_style_coord ident="${ident}"></%self:copy_sides_style_coord>
-
- #[allow(non_snake_case)]
- pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
- longhands::${ident}::computed_value::T::from_gecko_rect(&self.gecko.${gecko_ffi_name})
- .expect("clone for ${ident} failed")
- }
-</%def>
-
<%def name="copy_sides_style_coord(ident)">
<% gecko_ffi_name = "m" + to_camel_case(ident) %>
#[allow(non_snake_case)]
@@ -812,281 +774,6 @@ def set_gecko_property(ffi_name, expr):
}
</%def>
-<%
-transform_functions = [
- ("Matrix3D", "matrix3d", ["number"] * 16),
- ("Matrix", "matrix", ["number"] * 6),
- ("Translate", "translate", ["lp", "lp"]),
- ("Translate3D", "translate3d", ["lp", "lp", "length"]),
- ("TranslateX", "translatex", ["lp"]),
- ("TranslateY", "translatey", ["lp"]),
- ("TranslateZ", "translatez", ["length"]),
- ("Scale3D", "scale3d", ["number"] * 3),
- ("Scale", "scale", ["number", "number"]),
- ("ScaleX", "scalex", ["number"]),
- ("ScaleY", "scaley", ["number"]),
- ("ScaleZ", "scalez", ["number"]),
- ("Rotate", "rotate", ["angle"]),
- ("Rotate3D", "rotate3d", ["number"] * 3 + ["angle"]),
- ("RotateX", "rotatex", ["angle"]),
- ("RotateY", "rotatey", ["angle"]),
- ("RotateZ", "rotatez", ["angle"]),
- ("Skew", "skew", ["angle", "angle"]),
- ("SkewX", "skewx", ["angle"]),
- ("SkewY", "skewy", ["angle"]),
- ("Perspective", "perspective", ["length"]),
- ("InterpolateMatrix", "interpolatematrix", ["list"] * 2 + ["percentage"]),
- ("AccumulateMatrix", "accumulatematrix", ["list"] * 2 + ["integer_to_percentage"])
-]
-%>
-
-<%def name="transform_function_arm(name, keyword, items)">
- <%
- pattern = None
- if keyword == "matrix3d":
- # m11: number1, m12: number2, ..
- single_patterns = ["m%s: %s" % (str(a / 4 + 1) + str(a % 4 + 1), b + str(a + 1)) for (a, b)
- in enumerate(items)]
- pattern = "(Matrix3D { %s })" % ", ".join(single_patterns)
- elif keyword == "matrix":
- # a: number1, b: number2, ..
- single_patterns = ["%s: %s" % (chr(ord('a') + a), b + str(a + 1)) for (a, b)
- in enumerate(items)]
- pattern = "(Matrix { %s })" % ", ".join(single_patterns)
- elif keyword == "interpolatematrix":
- pattern = " { from_list: ref list1, to_list: ref list2, progress: percentage3 }"
- elif keyword == "accumulatematrix":
- pattern = " { from_list: ref list1, to_list: ref list2, count: integer_to_percentage3 }"
- else:
- # Generate contents of pattern from items
- pattern = "(%s)" % ", ".join([b + str(a+1) for (a,b) in enumerate(items)])
-
- # First %s substituted with the call to GetArrayItem, the second
- # %s substituted with the corresponding variable
- css_value_setters = {
- "length" : "bindings::Gecko_CSSValue_SetPixelLength(%s, %s.px())",
- "percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s.0)",
- # Note: This is an integer type, but we use it as a percentage value in Gecko, so
- # need to cast it to f32.
- "integer_to_percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s as f32)",
- "lp" : "%s.set_length_percentage(%s)",
- "angle" : "%s.set_angle(%s)",
- "number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
- # Note: We use nsCSSValueSharedList here, instead of nsCSSValueList_heap
- # because this function is not called on the main thread and
- # nsCSSValueList_heap is not thread safe.
- "list" : "%s.set_shared_list(%s.0.iter().map(&convert_to_ns_css_value));",
- }
- %>
- crate::values::generics::transform::TransformOperation::${name}${pattern} => {
- let len = ${len(items) + 1};
- bindings::Gecko_CSSValue_SetFunction(gecko_value, len);
- bindings::Gecko_CSSValue_SetKeyword(
- bindings::Gecko_CSSValue_GetArrayItem(gecko_value, 0),
- structs::nsCSSKeyword::eCSSKeyword_${keyword}
- );
- % for index, item in enumerate(items):
- % if item == "list":
- debug_assert!(!${item}${index + 1}.0.is_empty());
- % endif
- ${css_value_setters[item] % (
- "(&mut *bindings::Gecko_CSSValue_GetArrayItem(gecko_value, %d))" % (index + 1),
- item + str(index + 1)
- )};
- % endfor
- }
-</%def>
-
-<%def name="computed_operation_arm(name, keyword, items)">
- <%
- # %s is substituted with the call to GetArrayItem.
- css_value_getters = {
- "length" : "Length::new(bindings::Gecko_CSSValue_GetNumber(%s))",
- "lp" : "%s.get_length_percentage()",
- "angle" : "%s.get_angle()",
- "number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
- "percentage" : "Percentage(bindings::Gecko_CSSValue_GetPercentage(%s))",
- "integer_to_percentage" : "bindings::Gecko_CSSValue_GetPercentage(%s) as i32",
- "list" : "Transform(convert_shared_list_to_operations(%s))",
- }
- pre_symbols = "("
- post_symbols = ")"
- if keyword == "interpolatematrix" or keyword == "accumulatematrix":
- # We generate this like: "TransformOperation::InterpolateMatrix {", so the space is
- # between "InterpolateMatrix"/"AccumulateMatrix" and '{'
- pre_symbols = " {"
- post_symbols = "}"
- elif keyword == "matrix3d":
- pre_symbols = "(Matrix3D {"
- post_symbols = "})"
- elif keyword == "matrix":
- pre_symbols = "(Matrix {"
- post_symbols = "})"
- field_names = None
- if keyword == "interpolatematrix":
- field_names = ["from_list", "to_list", "progress"]
- elif keyword == "accumulatematrix":
- field_names = ["from_list", "to_list", "count"]
-
- %>
- structs::nsCSSKeyword::eCSSKeyword_${keyword} => {
- crate::values::generics::transform::TransformOperation::${name}${pre_symbols}
- % for index, item in enumerate(items):
- % if keyword == "matrix3d":
- m${index / 4 + 1}${index % 4 + 1}:
- % elif keyword == "matrix":
- ${chr(ord('a') + index)}:
- % elif keyword == "interpolatematrix" or keyword == "accumulatematrix":
- ${field_names[index]}:
- % endif
- <%
- getter = css_value_getters[item] % (
- "(&*bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, %d))" % (index + 1)
- )
- %>
- ${getter},
- % endfor
- ${post_symbols}
- },
-</%def>
-
-#[allow(unused_parens)]
-fn set_single_transform_function(
- servo_value: &values::computed::TransformOperation,
- gecko_value: &mut structs::nsCSSValue /* output */
-) {
- use crate::values::computed::TransformOperation;
- use crate::values::generics::transform::{Matrix, Matrix3D};
-
- let convert_to_ns_css_value = |item: &TransformOperation| -> structs::nsCSSValue {
- let mut value = structs::nsCSSValue::null();
- set_single_transform_function(item, &mut value);
- value
- };
-
- unsafe {
- match *servo_value {
- % for servo, gecko, format in transform_functions:
- ${transform_function_arm(servo, gecko, format)}
- % endfor
- }
- }
-}
-
-pub fn convert_transform(
- input: &[values::computed::TransformOperation],
- output: &mut structs::root::RefPtr<structs::root::nsCSSValueSharedList>
-) {
- use crate::gecko_bindings::sugar::refptr::RefPtr;
-
- unsafe { output.clear() };
-
- let list = unsafe {
- RefPtr::from_addrefed(bindings::Gecko_NewCSSValueSharedList(input.len() as u32))
- };
- let value_list = unsafe { list.mHead.as_mut() };
- if let Some(value_list) = value_list {
- for (gecko, servo) in value_list.into_iter().zip(input.into_iter()) {
- set_single_transform_function(servo, gecko);
- }
- }
- output.set_move(list);
-}
-
-#[allow(unused_parens)]
-fn clone_single_transform_function(
- gecko_value: &structs::nsCSSValue
-) -> values::computed::TransformOperation {
- use crate::values::computed::{Length, Percentage, TransformOperation};
- use crate::values::generics::transform::{Matrix, Matrix3D};
- use crate::values::generics::transform::Transform;
-
- let convert_shared_list_to_operations = |value: &structs::nsCSSValue|
- -> Vec<TransformOperation> {
- debug_assert_eq!(value.mUnit, structs::nsCSSUnit::eCSSUnit_SharedList);
- let value_list = unsafe {
- value.mValue.mSharedList.as_ref()
- .as_mut().expect("List pointer should be non-null").mHead.as_ref()
- };
- debug_assert!(value_list.is_some(), "An empty shared list is not allowed");
- value_list.unwrap().into_iter()
- .map(|item| clone_single_transform_function(item))
- .collect()
- };
-
- let transform_function = unsafe {
- bindings::Gecko_CSSValue_GetKeyword(bindings::Gecko_CSSValue_GetArrayItemConst(gecko_value, 0))
- };
-
- unsafe {
- match transform_function {
- % for servo, gecko, format in transform_functions:
- ${computed_operation_arm(servo, gecko, format)}
- % endfor
- _ => panic!("unacceptable transform function"),
- }
- }
-}
-
-pub fn clone_transform_from_list(
- list: Option< &structs::root::nsCSSValueList>
-) -> values::computed::Transform {
- use crate::values::generics::transform::Transform;
-
- let result = match list {
- Some(list) => {
- list.into_iter()
- .filter_map(|value| {
- // Handle none transform.
- if value.is_none() {
- None
- } else {
- Some(clone_single_transform_function(value))
- }
- })
- .collect::<Vec<_>>()
- },
- _ => vec![],
- };
- Transform(result)
-}
-
-<%def name="impl_transform(ident, gecko_ffi_name)">
- #[allow(non_snake_case)]
- pub fn set_${ident}(&mut self, other: values::computed::Transform) {
- use crate::gecko_properties::convert_transform;
- if other.0.is_empty() {
- unsafe {
- self.gecko.${gecko_ffi_name}.clear();
- }
- return;
- };
- convert_transform(&other.0, &mut self.gecko.${gecko_ffi_name});
- }
-
- #[allow(non_snake_case)]
- pub fn copy_${ident}_from(&mut self, other: &Self) {
- unsafe { self.gecko.${gecko_ffi_name}.set(&other.gecko.${gecko_ffi_name}); }
- }
-
- #[allow(non_snake_case)]
- pub fn reset_${ident}(&mut self, other: &Self) {
- self.copy_${ident}_from(other)
- }
-
- #[allow(non_snake_case)]
- pub fn clone_${ident}(&self) -> values::computed::Transform {
- use crate::gecko_properties::clone_transform_from_list;
- use crate::values::generics::transform::Transform;
-
- if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() {
- return Transform(vec!());
- }
- let list = unsafe { (*self.gecko.${gecko_ffi_name}.to_safe().get()).mHead.as_ref() };
- clone_transform_from_list(list)
- }
-</%def>
-
<%def name="impl_logical(name, **kwargs)">
${helpers.logical_setter(name)}
</%def>
@@ -1095,10 +782,10 @@ pub fn clone_transform_from_list(
impl ${style_struct.gecko_struct_name} {
#[allow(dead_code, unused_variables)]
pub fn default(document: &structs::Document) -> Arc<Self> {
- let mut result = Arc::new(${style_struct.gecko_struct_name} { gecko: unsafe { zeroed() } });
+ let mut result = Arc::new(${style_struct.gecko_struct_name} { gecko: ManuallyDrop::new(unsafe { zeroed() }) });
unsafe {
Gecko_Construct_Default_${style_struct.gecko_ffi_name}(
- &mut Arc::get_mut(&mut result).unwrap().gecko,
+ &mut *Arc::get_mut(&mut result).unwrap().gecko,
document,
);
}
@@ -1108,15 +795,15 @@ impl ${style_struct.gecko_struct_name} {
impl Drop for ${style_struct.gecko_struct_name} {
fn drop(&mut self) {
unsafe {
- Gecko_Destroy_${style_struct.gecko_ffi_name}(&mut self.gecko);
+ Gecko_Destroy_${style_struct.gecko_ffi_name}(&mut *self.gecko);
}
}
}
impl Clone for ${style_struct.gecko_struct_name} {
fn clone(&self) -> Self {
unsafe {
- let mut result = ${style_struct.gecko_struct_name} { gecko: zeroed() };
- Gecko_CopyConstruct_${style_struct.gecko_ffi_name}(&mut result.gecko, &self.gecko);
+ let mut result = ${style_struct.gecko_struct_name} { gecko: ManuallyDrop::new(zeroed()) };
+ Gecko_CopyConstruct_${style_struct.gecko_ffi_name}(&mut *result.gecko, &*self.gecko);
result
}
}
@@ -1192,7 +879,6 @@ impl Clone for ${style_struct.gecko_struct_name} {
"SVGOpacity": impl_svg_opacity,
"SVGPaint": impl_svg_paint,
"SVGWidth": impl_svg_length,
- "Transform": impl_transform,
"url::UrlOrNone": impl_css_url,
}
@@ -1266,7 +952,7 @@ fn static_assert() {
<%self:impl_trait style_struct_name="Border"
skip_longhands="${skip_border_longhands} border-image-source
- border-image-repeat border-image-width">
+ border-image-repeat">
% for side in SIDES:
pub fn set_border_${side.ident}_style(&mut self, v: BorderStyle) {
self.gecko.mBorderStyle[${side.index}] = v;
@@ -1405,8 +1091,6 @@ fn static_assert() {
% endfor
longhands::border_image_repeat::computed_value::T(servo_h, servo_v)
}
-
- <% impl_style_sides("border_image_width") %>
</%self:impl_trait>
<% skip_scroll_margin_longhands = " ".join(["scroll-margin-%s" % x.ident for x in SIDES]) %>
@@ -1545,8 +1229,9 @@ fn static_assert() {
% for kind in ["rows", "columns"]:
pub fn set_grid_auto_${kind}(&mut self, v: longhands::grid_auto_${kind}::computed_value::T) {
- v.to_gecko_style_coords(&mut self.gecko.mGridAuto${kind.title()}Min,
- &mut self.gecko.mGridAuto${kind.title()}Max)
+ let gecko = &mut *self.gecko;
+ v.to_gecko_style_coords(&mut gecko.mGridAuto${kind.title()}Min,
+ &mut gecko.mGridAuto${kind.title()}Max)
}
pub fn copy_grid_auto_${kind}_from(&mut self, other: &Self) {
@@ -1566,14 +1251,14 @@ fn static_assert() {
pub fn set_grid_template_${kind}(&mut self, v: longhands::grid_template_${kind}::computed_value::T) {
<% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
use crate::gecko_bindings::structs::{nsTArray, nsStyleGridLine_kMaxLine};
- use nsstring::nsStringRepr;
+ use nsstring::nsString;
use std::usize;
use crate::values::CustomIdent;
use crate::values::generics::grid::TrackListType::Auto;
use crate::values::generics::grid::{GridTemplateComponent, RepeatCount};
#[inline]
- fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray<nsStringRepr>) {
+ fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray<nsString>) {
unsafe {
bindings::Gecko_ResizeTArrayForStrings(gecko_names, servo_names.len() as u32);
}
@@ -1693,7 +1378,7 @@ fn static_assert() {
pub fn clone_grid_template_${kind}(&self) -> longhands::grid_template_${kind}::computed_value::T {
<% self_grid = "self.gecko.mGridTemplate%s" % kind.title() %>
use crate::gecko_bindings::structs::nsTArray;
- use nsstring::nsStringRepr;
+ use nsstring::nsString;
use crate::values::CustomIdent;
use crate::values::generics::grid::{GridTemplateComponent, LineNameList, RepeatCount};
use crate::values::generics::grid::{TrackList, TrackListType, TrackListValue, TrackRepeat, TrackSize};
@@ -1704,7 +1389,7 @@ fn static_assert() {
};
#[inline]
- fn to_boxed_customident_slice(gecko_names: &nsTArray<nsStringRepr>) -> Box<[CustomIdent]> {
+ fn to_boxed_customident_slice(gecko_names: &nsTArray<nsString>) -> Box<[CustomIdent]> {
let idents: Vec<CustomIdent> = gecko_names.iter().map(|gecko_name| {
CustomIdent(Atom::from(gecko_name.to_string()))
}).collect();
@@ -1712,7 +1397,7 @@ fn static_assert() {
}
#[inline]
- fn to_line_names_vec(gecko_line_names: &nsTArray<nsTArray<nsStringRepr>>)
+ fn to_line_names_vec(gecko_line_names: &nsTArray<nsTArray<nsString>>)
-> Vec<Box<[CustomIdent]>> {
gecko_line_names.iter().map(|gecko_names| {
to_boxed_customident_slice(gecko_names)
@@ -2129,14 +1814,14 @@ fn static_assert() {
let ptr = v.0.as_ptr();
forget(v);
unsafe {
- Gecko_nsStyleFont_SetLang(&mut self.gecko, ptr);
+ Gecko_nsStyleFont_SetLang(&mut *self.gecko, ptr);
}
}
#[allow(non_snake_case)]
pub fn copy__x_lang_from(&mut self, other: &Self) {
unsafe {
- Gecko_nsStyleFont_CopyLangFrom(&mut self.gecko, &other.gecko);
+ Gecko_nsStyleFont_CopyLangFrom(&mut *self.gecko, &*other.gecko);
}
}
@@ -2473,56 +2158,16 @@ fn static_assert() {
${impl_copy_animation_value(ident, gecko_ffi_name)}
</%def>
-<%def name="impl_individual_transform(ident, type, gecko_ffi_name)">
- pub fn set_${ident}(&mut self, other: values::computed::${type}) {
- unsafe { self.gecko.${gecko_ffi_name}.clear() };
-
- if let Some(operation) = other.to_transform_operation() {
- convert_transform(&[operation], &mut self.gecko.${gecko_ffi_name})
- }
- }
-
- pub fn copy_${ident}_from(&mut self, other: &Self) {
- unsafe { self.gecko.${gecko_ffi_name}.set(&other.gecko.${gecko_ffi_name}); }
- }
-
- pub fn reset_${ident}(&mut self, other: &Self) {
- self.copy_${ident}_from(other)
- }
-
- pub fn clone_${ident}(&self) -> values::computed::${type} {
- use crate::values::generics::transform::${type};
-
- if self.gecko.${gecko_ffi_name}.mRawPtr.is_null() {
- return ${type}::None;
- }
-
- let list = unsafe { (*self.gecko.${gecko_ffi_name}.to_safe().get()).mHead.as_ref() };
-
- let mut transform = clone_transform_from_list(list);
- debug_assert_eq!(transform.0.len(), 1);
- ${type}::from_transform_operation(&transform.0.pop().unwrap())
- }
-</%def>
-
<% skip_box_longhands= """display
animation-name animation-delay animation-duration
animation-direction animation-fill-mode animation-play-state
animation-iteration-count animation-timing-function
clear transition-duration transition-delay
transition-timing-function transition-property
- transform-style
- rotate scroll-snap-points-x scroll-snap-points-y
- scroll-snap-coordinate -moz-binding will-change
- offset-path shape-outside
- translate scale -webkit-line-clamp""" %>
+ transform-style -moz-binding shape-outside
+ -webkit-line-clamp""" %>
<%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}">
#[inline]
- pub fn generate_combined_transform(&mut self) {
- unsafe { bindings::Gecko_StyleDisplay_GenerateCombinedTransform(&mut self.gecko) };
- }
-
- #[inline]
pub fn set_display(&mut self, v: longhands::display::computed_value::T) {
self.gecko.mDisplay = v;
self.gecko.mOriginalDisplay = v;
@@ -2560,33 +2205,7 @@ fn static_assert() {
gecko_inexhaustive=True,
) %>
${impl_keyword('clear', 'mBreakType', clear_keyword)}
-
- ${impl_style_coord("scroll_snap_points_x", "mScrollSnapPointsX")}
- ${impl_style_coord("scroll_snap_points_y", "mScrollSnapPointsY")}
-
- pub fn set_scroll_snap_coordinate<I>(&mut self, v: I)
- where I: IntoIterator<Item = longhands::scroll_snap_coordinate::computed_value::single_value::T>,
- I::IntoIter: ExactSizeIterator
- {
- self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(v.into_iter());
- }
-
- pub fn copy_scroll_snap_coordinate_from(&mut self, other: &Self) {
- let iter = other.gecko.mScrollSnapCoordinate.iter().map(|c| *c);
- self.gecko.mScrollSnapCoordinate.assign_from_iter_pod(iter);
- }
-
- pub fn reset_scroll_snap_coordinate(&mut self, other: &Self) {
- self.copy_scroll_snap_coordinate_from(other)
- }
-
- pub fn clone_scroll_snap_coordinate(&self) -> longhands::scroll_snap_coordinate::computed_value::T {
- let vec = self.gecko.mScrollSnapCoordinate.iter().cloned().collect();
- longhands::scroll_snap_coordinate::computed_value::List(vec)
- }
-
${impl_css_url('_moz_binding', 'mBinding')}
-
${impl_transition_time_value('delay', 'Delay')}
${impl_transition_time_value('duration', 'Duration')}
${impl_transition_timing_function()}
@@ -2825,105 +2444,8 @@ fn static_assert() {
${impl_animation_timing_function()}
- ${impl_individual_transform('rotate', 'Rotate', 'mSpecifiedRotate')}
- ${impl_individual_transform('translate', 'Translate', 'mSpecifiedTranslate')}
- ${impl_individual_transform('scale', 'Scale', 'mSpecifiedScale')}
-
- pub fn set_will_change(&mut self, v: longhands::will_change::computed_value::T) {
- use crate::gecko_bindings::bindings::{Gecko_AppendWillChange, Gecko_ClearWillChange};
- use crate::values::specified::box_::{WillChangeBits, WillChange};
-
- match v {
- WillChange::AnimateableFeatures { features, bits } => {
- unsafe {
- Gecko_ClearWillChange(&mut self.gecko, features.len());
- }
-
- for feature in features.iter() {
- unsafe {
- Gecko_AppendWillChange(&mut self.gecko, feature.0.as_ptr())
- }
- }
-
- self.gecko.mWillChangeBitField = bits;
- },
- WillChange::Auto => {
- unsafe {
- Gecko_ClearWillChange(&mut self.gecko, 0);
- }
- self.gecko.mWillChangeBitField = WillChangeBits::empty();
- },
- };
- }
-
- pub fn copy_will_change_from(&mut self, other: &Self) {
- use crate::gecko_bindings::bindings::Gecko_CopyWillChangeFrom;
-
- self.gecko.mWillChangeBitField = other.gecko.mWillChangeBitField;
- unsafe {
- Gecko_CopyWillChangeFrom(&mut self.gecko, &other.gecko);
- }
- }
-
- pub fn reset_will_change(&mut self, other: &Self) {
- self.copy_will_change_from(other)
- }
-
- pub fn clone_will_change(&self) -> longhands::will_change::computed_value::T {
- use crate::values::CustomIdent;
- use crate::values::specified::box_::WillChange;
-
- if self.gecko.mWillChange.len() == 0 {
- return WillChange::Auto
- }
-
- let custom_idents: Vec<CustomIdent> = self.gecko.mWillChange.iter().map(|gecko_atom| {
- unsafe {
- CustomIdent(Atom::from_raw(gecko_atom.mRawPtr))
- }
- }).collect();
-
- WillChange::AnimateableFeatures {
- features: custom_idents.into_boxed_slice(),
- bits: self.gecko.mWillChangeBitField,
- }
- }
-
<% impl_shape_source("shape_outside", "mShapeOutside") %>
- pub fn set_offset_path(&mut self, v: longhands::offset_path::computed_value::T) {
- use crate::gecko_bindings::bindings::{Gecko_NewStyleMotion, Gecko_SetStyleMotion};
- use crate::gecko_bindings::structs::StyleShapeSourceType;
- use crate::values::generics::basic_shape::FillRule;
- use crate::values::specified::OffsetPath;
-
- let motion = unsafe { Gecko_NewStyleMotion().as_mut().unwrap() };
- match v {
- OffsetPath::None => motion.mOffsetPath.mType = StyleShapeSourceType::None,
- OffsetPath::Path(p) => {
- set_style_svg_path(&mut motion.mOffsetPath, p, FillRule::Nonzero)
- },
- }
- unsafe { Gecko_SetStyleMotion(&mut self.gecko.mMotion, motion) };
- }
-
- pub fn clone_offset_path(&self) -> longhands::offset_path::computed_value::T {
- use crate::values::specified::OffsetPath;
- match unsafe { self.gecko.mMotion.mPtr.as_ref() } {
- None => OffsetPath::none(),
- Some(v) => (&v.mOffsetPath).into()
- }
- }
-
- pub fn copy_offset_path_from(&mut self, other: &Self) {
- use crate::gecko_bindings::bindings::Gecko_CopyStyleMotions;
- unsafe { Gecko_CopyStyleMotions(&mut self.gecko.mMotion, other.gecko.mMotion.mPtr) };
- }
-
- pub fn reset_offset_path(&mut self, other: &Self) {
- self.copy_offset_path_from(other);
- }
-
#[allow(non_snake_case)]
pub fn set__webkit_line_clamp(&mut self, v: longhands::_webkit_line_clamp::computed_value::T) {
self.gecko.mLineClamp = match v {
@@ -3301,19 +2823,19 @@ fn static_assert() {
</%self:impl_trait>
<%self:impl_trait style_struct_name="List"
- skip_longhands="list-style-image list-style-type quotes -moz-image-region">
+ skip_longhands="list-style-image list-style-type -moz-image-region">
pub fn set_list_style_image(&mut self, image: longhands::list_style_image::computed_value::T) {
match image {
UrlOrNone::None => {
unsafe {
- Gecko_SetListStyleImageNone(&mut self.gecko);
+ Gecko_SetListStyleImageNone(&mut *self.gecko);
}
}
UrlOrNone::Url(ref url) => {
unsafe {
Gecko_SetListStyleImageImageValue(
- &mut self.gecko,
+ &mut *self.gecko,
url.url_value_ptr(),
);
}
@@ -3322,7 +2844,7 @@ fn static_assert() {
}
pub fn copy_list_style_image_from(&mut self, other: &Self) {
- unsafe { Gecko_CopyListStyleImageFrom(&mut self.gecko, &other.gecko); }
+ unsafe { Gecko_CopyListStyleImageFrom(&mut *self.gecko, &*other.gecko); }
}
pub fn reset_list_style_image(&mut self, other: &Self) {
@@ -3330,8 +2852,6 @@ fn static_assert() {
}
pub fn clone_list_style_image(&self) -> longhands::list_style_image::computed_value::T {
- use crate::values::computed::url::ComputedImageUrl;
-
if self.gecko.mListStyleImage.mRawPtr.is_null() {
return UrlOrNone::None;
}
@@ -3377,28 +2897,6 @@ fn static_assert() {
}
}
- pub fn set_quotes(&mut self, other: longhands::quotes::computed_value::T) {
- self.gecko.mQuotes.set_arc(other.0.clone());
- }
-
- pub fn copy_quotes_from(&mut self, other: &Self) {
- self.set_quotes(other.clone_quotes());
- }
-
- pub fn reset_quotes(&mut self, other: &Self) {
- self.copy_quotes_from(other)
- }
-
- pub fn clone_quotes(&self) -> longhands::quotes::computed_value::T {
- 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)]
pub fn set__moz_image_region(&mut self, v: longhands::_moz_image_region::computed_value::T) {
use crate::values::Either;
@@ -3476,31 +2974,7 @@ fn static_assert() {
</%self:impl_trait>
<%self:impl_trait style_struct_name="Effects"
- skip_longhands="box-shadow clip filter">
- pub fn set_box_shadow<I>(&mut self, v: I)
- where I: IntoIterator<Item = BoxShadow>,
- I::IntoIter: ExactSizeIterator
- {
- let v = v.into_iter();
- self.gecko.mBoxShadow.replace_with_new(v.len() as u32);
- for (servo, gecko_shadow) in v.zip(self.gecko.mBoxShadow.iter_mut()) {
- gecko_shadow.set_from_box_shadow(servo);
- }
- }
-
- pub fn copy_box_shadow_from(&mut self, other: &Self) {
- self.gecko.mBoxShadow.copy_from(&other.gecko.mBoxShadow);
- }
-
- pub fn reset_box_shadow(&mut self, other: &Self) {
- self.copy_box_shadow_from(other)
- }
-
- pub fn clone_box_shadow(&self) -> longhands::box_shadow::computed_value::T {
- let buf = self.gecko.mBoxShadow.iter().map(|v| v.to_box_shadow()).collect();
- longhands::box_shadow::computed_value::List(buf)
- }
-
+ skip_longhands="clip filter">
pub fn set_clip(&mut self, v: longhands::clip::computed_value::T) {
use crate::gecko_bindings::structs::NS_STYLE_CLIP_AUTO;
use crate::gecko_bindings::structs::NS_STYLE_CLIP_RECT;
@@ -3624,7 +3098,6 @@ fn static_assert() {
I::IntoIter: ExactSizeIterator,
{
use crate::values::generics::effects::Filter::*;
- use crate::gecko_bindings::structs::nsCSSShadowArray;
use crate::gecko_bindings::structs::nsStyleFilter;
use crate::gecko_bindings::structs::NS_STYLE_FILTER_BLUR;
use crate::gecko_bindings::structs::NS_STYLE_FILTER_BRIGHTNESS;
@@ -3644,7 +3117,7 @@ fn static_assert() {
let v = v.into_iter();
unsafe {
- Gecko_ResetFilters(&mut self.gecko, v.len());
+ Gecko_ResetFilters(&mut *self.gecko, v.len());
}
debug_assert_eq!(v.len(), self.gecko.mFilters.len());
@@ -3665,19 +3138,10 @@ fn static_assert() {
DropShadow(shadow) => {
gecko_filter.mType = NS_STYLE_FILTER_DROP_SHADOW;
-
- fn init_shadow(filter: &mut nsStyleFilter) -> &mut nsCSSShadowArray {
- unsafe {
- let ref mut union = filter.__bindgen_anon_1;
- let shadow_array: &mut *mut nsCSSShadowArray = union.mDropShadow.as_mut();
- *shadow_array = Gecko_NewCSSShadowArray(1);
-
- &mut **shadow_array
- }
+ unsafe {
+ let ref mut union = gecko_filter.__bindgen_anon_1;
+ ptr::write(union.mDropShadow.as_mut(), shadow);
}
-
- let gecko_shadow = init_shadow(gecko_filter);
- gecko_shadow.mArray[0].set_from_simple_shadow(shadow);
},
Url(ref url) => {
unsafe {
@@ -3690,7 +3154,7 @@ fn static_assert() {
pub fn copy_filter_from(&mut self, other: &Self) {
unsafe {
- Gecko_CopyFiltersFrom(&other.gecko as *const _ as *mut _, &mut self.gecko);
+ Gecko_CopyFiltersFrom(&other.gecko as *const _ as *mut _, &mut *self.gecko);
}
}
@@ -3713,42 +3177,41 @@ fn static_assert() {
use crate::gecko_bindings::structs::NS_STYLE_FILTER_DROP_SHADOW;
use crate::gecko_bindings::structs::NS_STYLE_FILTER_URL;
- let mut filters = Vec::new();
- for filter in self.gecko.mFilters.iter(){
+ longhands::filter::computed_value::List(self.gecko.mFilters.iter().map(|filter| {
match filter.mType {
% for func in FILTER_FUNCTIONS:
NS_STYLE_FILTER_${func.upper()} => {
- filters.push(Filter::${func}(
+ Filter::${func}(
GeckoStyleCoordConvertible::from_gecko_style_coord(
- &filter.mFilterParameter).unwrap()));
+ &filter.mFilterParameter
+ ).unwrap()
+ )
},
% endfor
NS_STYLE_FILTER_BLUR => {
- filters.push(Filter::Blur(NonNegativeLength::from_gecko_style_coord(
- &filter.mFilterParameter).unwrap()));
+ Filter::Blur(NonNegativeLength::from_gecko_style_coord(
+ &filter.mFilterParameter
+ ).unwrap())
},
NS_STYLE_FILTER_HUE_ROTATE => {
- filters.push(Filter::HueRotate(
- GeckoStyleCoordConvertible::from_gecko_style_coord(
- &filter.mFilterParameter).unwrap()));
+ Filter::HueRotate(GeckoStyleCoordConvertible::from_gecko_style_coord(
+ &filter.mFilterParameter,
+ ).unwrap())
},
NS_STYLE_FILTER_DROP_SHADOW => {
- filters.push(unsafe {
- Filter::DropShadow(
- (**filter.__bindgen_anon_1.mDropShadow.as_ref()).mArray[0].to_simple_shadow(),
- )
- });
+ Filter::DropShadow(unsafe {
+ (*filter.__bindgen_anon_1.mDropShadow.as_ref()).clone()
+ })
},
NS_STYLE_FILTER_URL => {
- filters.push(Filter::Url(unsafe {
+ Filter::Url(unsafe {
let url = RefPtr::new(*filter.__bindgen_anon_1.mURL.as_ref());
ComputedUrl::from_url_value(url)
- }));
+ })
}
- _ => {},
+ _ => unreachable!("Unknown filter function?"),
}
- }
- longhands::filter::computed_value::List(filters)
+ }).collect())
}
</%self:impl_trait>
@@ -3783,7 +3246,7 @@ fn static_assert() {
<%self:impl_trait style_struct_name="InheritedText"
- skip_longhands="text-align text-emphasis-style text-shadow
+ skip_longhands="text-align text-emphasis-style
-webkit-text-stroke-width text-emphasis-position">
<% text_align_keyword = Keyword("text-align",
@@ -3791,30 +3254,6 @@ fn static_assert() {
gecko_strip_moz_prefix=False) %>
${impl_keyword('text_align', 'mTextAlign', text_align_keyword)}
- pub fn set_text_shadow<I>(&mut self, v: I)
- where I: IntoIterator<Item = SimpleShadow>,
- I::IntoIter: ExactSizeIterator
- {
- let v = v.into_iter();
- self.gecko.mTextShadow.replace_with_new(v.len() as u32);
- for (servo, gecko_shadow) in v.zip(self.gecko.mTextShadow.iter_mut()) {
- gecko_shadow.set_from_simple_shadow(servo);
- }
- }
-
- pub fn copy_text_shadow_from(&mut self, other: &Self) {
- self.gecko.mTextShadow.copy_from(&other.gecko.mTextShadow);
- }
-
- pub fn reset_text_shadow(&mut self, other: &Self) {
- self.copy_text_shadow_from(other)
- }
-
- pub fn clone_text_shadow(&self) -> longhands::text_shadow::computed_value::T {
- let buf = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow()).collect();
- longhands::text_shadow::computed_value::List(buf)
- }
-
fn clear_text_emphasis_style_if_string(&mut self) {
if self.gecko.mTextEmphasisStyle == structs::NS_STYLE_TEXT_EMPHASIS_STYLE_STRING as u8 {
self.gecko.mTextEmphasisStyleString.truncate();
@@ -3903,83 +3342,7 @@ fn static_assert() {
</%self:impl_trait>
-<%self:impl_trait style_struct_name="Text"
- skip_longhands="text-overflow initial-letter">
-
- fn clear_overflow_sides_if_string(&mut self) {
- use crate::gecko_bindings::structs::nsStyleTextOverflowSide;
- fn clear_if_string(side: &mut nsStyleTextOverflowSide) {
- if side.mType == structs::NS_STYLE_TEXT_OVERFLOW_STRING as u8 {
- side.mString.truncate();
- side.mType = structs::NS_STYLE_TEXT_OVERFLOW_CLIP as u8;
- }
- }
- clear_if_string(&mut self.gecko.mTextOverflow.mLeft);
- clear_if_string(&mut self.gecko.mTextOverflow.mRight);
- }
-
- pub fn set_text_overflow(&mut self, v: longhands::text_overflow::computed_value::T) {
- use crate::gecko_bindings::structs::nsStyleTextOverflowSide;
- use crate::values::specified::text::TextOverflowSide;
-
- fn set(side: &mut nsStyleTextOverflowSide, value: &TextOverflowSide) {
- let ty = match *value {
- TextOverflowSide::Clip => structs::NS_STYLE_TEXT_OVERFLOW_CLIP,
- TextOverflowSide::Ellipsis => structs::NS_STYLE_TEXT_OVERFLOW_ELLIPSIS,
- TextOverflowSide::String(ref s) => {
- side.mString.assign_str(s);
- structs::NS_STYLE_TEXT_OVERFLOW_STRING
- }
- };
- side.mType = ty as u8;
- }
-
- self.clear_overflow_sides_if_string();
- self.gecko.mTextOverflow.mLogicalDirections = v.sides_are_logical;
-
- set(&mut self.gecko.mTextOverflow.mLeft, &v.first);
- set(&mut self.gecko.mTextOverflow.mRight, &v.second);
- }
-
- pub fn copy_text_overflow_from(&mut self, other: &Self) {
- use crate::gecko_bindings::structs::nsStyleTextOverflowSide;
- fn set(side: &mut nsStyleTextOverflowSide, other: &nsStyleTextOverflowSide) {
- if other.mType == structs::NS_STYLE_TEXT_OVERFLOW_STRING as u8 {
- side.mString.assign(&*other.mString)
- }
- side.mType = other.mType
- }
- self.clear_overflow_sides_if_string();
- set(&mut self.gecko.mTextOverflow.mLeft, &other.gecko.mTextOverflow.mLeft);
- set(&mut self.gecko.mTextOverflow.mRight, &other.gecko.mTextOverflow.mRight);
- self.gecko.mTextOverflow.mLogicalDirections = other.gecko.mTextOverflow.mLogicalDirections;
- }
-
- pub fn reset_text_overflow(&mut self, other: &Self) {
- self.copy_text_overflow_from(other)
- }
-
- pub fn clone_text_overflow(&self) -> longhands::text_overflow::computed_value::T {
- use crate::gecko_bindings::structs::nsStyleTextOverflowSide;
- use crate::values::specified::text::TextOverflowSide;
-
- fn to_servo(side: &nsStyleTextOverflowSide) -> TextOverflowSide {
- match side.mType as u32 {
- structs::NS_STYLE_TEXT_OVERFLOW_CLIP => TextOverflowSide::Clip,
- structs::NS_STYLE_TEXT_OVERFLOW_ELLIPSIS => TextOverflowSide::Ellipsis,
- structs::NS_STYLE_TEXT_OVERFLOW_STRING =>
- TextOverflowSide::String(side.mString.to_string().into_boxed_str()),
- _ => panic!("Found unexpected value in style struct for text_overflow property"),
- }
- }
-
- longhands::text_overflow::computed_value::T {
- first: to_servo(&self.gecko.mTextOverflow.mLeft),
- second: to_servo(&self.gecko.mTextOverflow.mRight),
- sides_are_logical: self.gecko.mTextOverflow.mLogicalDirections
- }
- }
-
+<%self:impl_trait style_struct_name="Text" skip_longhands="initial-letter">
pub fn set_initial_letter(&mut self, v: longhands::initial_letter::computed_value::T) {
use crate::values::generics::text::InitialLetter;
match v {
@@ -4050,25 +3413,19 @@ fn set_style_svg_path(
${ident}.mType = StyleShapeSourceType::None;
match v {
- % if ident == "clip_path":
- ShapeSource::ImageOrUrl(ref url) => {
- unsafe {
- bindings::Gecko_StyleShapeSource_SetURLValue(${ident}, url.url_value_ptr())
- }
- }
- % elif ident == "shape_outside":
+ ShapeSource::None => {} // don't change the type
ShapeSource::ImageOrUrl(image) => {
+ % if ident == "clip_path":
+ use crate::values::generics::image::Image;
+
+ let image = Image::Url(ComputedImageUrl(image));
+ % endif
unsafe {
bindings::Gecko_NewShapeImage(${ident});
let style_image = &mut *${ident}.__bindgen_anon_1.mShapeImage.as_mut().mPtr;
style_image.set(image);
}
}
- % else:
- <% raise Exception("Unknown property: %s" % ident) %>
- }
- % endif
- ShapeSource::None => {} // don't change the type
ShapeSource::Box(reference) => {
${ident}.mReferenceBox = reference.into();
${ident}.mType = StyleShapeSourceType::Box;
@@ -4118,7 +3475,7 @@ clip-path
</%self:impl_trait>
<%self:impl_trait style_struct_name="InheritedSVG"
- skip_longhands="paint-order stroke-dasharray -moz-context-properties">
+ skip_longhands="paint-order stroke-dasharray">
pub fn set_paint_order(&mut self, v: longhands::paint_order::computed_value::T) {
self.gecko.mPaintOrder = v.0;
}
@@ -4139,7 +3496,7 @@ clip-path
let v = v.into_iter();
self.gecko.mContextFlags &= !CONTEXT_VALUE;
unsafe {
- bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, v.len() as u32);
+ bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut *self.gecko, v.len() as u32);
}
for (gecko, servo) in self.gecko.mStrokeDasharray.iter_mut().zip(v) {
*gecko = servo;
@@ -4148,7 +3505,7 @@ clip-path
SVGStrokeDashArray::ContextValue => {
self.gecko.mContextFlags |= CONTEXT_VALUE;
unsafe {
- bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut self.gecko, 0);
+ bindings::Gecko_nsStyleSVG_SetDashArrayLength(&mut *self.gecko, 0);
}
}
}
@@ -4157,7 +3514,7 @@ clip-path
pub fn copy_stroke_dasharray_from(&mut self, other: &Self) {
use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE;
unsafe {
- bindings::Gecko_nsStyleSVG_CopyDashArray(&mut self.gecko, &other.gecko);
+ bindings::Gecko_nsStyleSVG_CopyDashArray(&mut *self.gecko, &*other.gecko);
}
self.gecko.mContextFlags =
(self.gecko.mContextFlags & !CONTEXT_VALUE) |
@@ -4178,61 +3535,6 @@ clip-path
}
SVGStrokeDashArray::Values(self.gecko.mStrokeDasharray.iter().cloned().collect())
}
-
- #[allow(non_snake_case)]
- pub fn _moz_context_properties_count(&self) -> usize {
- self.gecko.mContextProps.len()
- }
-
- #[allow(non_snake_case)]
- pub fn _moz_context_properties_at(
- &self,
- index: usize,
- ) -> longhands::_moz_context_properties::computed_value::single_value::T {
- longhands::_moz_context_properties::computed_value::single_value::T(
- CustomIdent(unsafe {
- Atom::from_raw(self.gecko.mContextProps[index].mRawPtr)
- })
- )
- }
-
- #[allow(non_snake_case)]
- pub fn set__moz_context_properties<I>(&mut self, v: I)
- where
- I: IntoIterator<Item = longhands::_moz_context_properties::computed_value::single_value::T>,
- I::IntoIter: ExactSizeIterator
- {
- let v = v.into_iter();
- unsafe {
- bindings::Gecko_nsStyleSVG_SetContextPropertiesLength(&mut self.gecko, v.len() as u32);
- }
-
- self.gecko.mContextPropsBits = 0;
- for (gecko, servo) in self.gecko.mContextProps.iter_mut().zip(v) {
- if (servo.0).0 == atom!("fill") {
- self.gecko.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_FILL as u8;
- } else if (servo.0).0 == atom!("stroke") {
- self.gecko.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_STROKE as u8;
- } else if (servo.0).0 == atom!("fill-opacity") {
- self.gecko.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_FILL_OPACITY as u8;
- } else if (servo.0).0 == atom!("stroke-opacity") {
- self.gecko.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_STROKE_OPACITY as u8;
- }
- gecko.mRawPtr = (servo.0).0.into_addrefed();
- }
- }
-
- #[allow(non_snake_case)]
- pub fn copy__moz_context_properties_from(&mut self, other: &Self) {
- unsafe {
- bindings::Gecko_nsStyleSVG_CopyContextProperties(&mut self.gecko, &other.gecko);
- }
- }
-
- #[allow(non_snake_case)]
- pub fn reset__moz_context_properties(&mut self, other: &Self) {
- self.copy__moz_context_properties_from(other)
- }
</%self:impl_trait>
<%self:impl_trait style_struct_name="Color">
@@ -4242,7 +3544,7 @@ clip-path
pub fn set_cursor(&mut self, v: longhands::cursor::computed_value::T) {
self.gecko.mCursor = v.keyword;
unsafe {
- Gecko_SetCursorArrayLength(&mut self.gecko, v.images.len());
+ Gecko_SetCursorArrayLength(&mut *self.gecko, v.images.len());
}
for i in 0..v.images.len() {
unsafe {
@@ -4268,7 +3570,7 @@ clip-path
pub fn copy_cursor_from(&mut self, other: &Self) {
self.gecko.mCursor = other.gecko.mCursor;
unsafe {
- Gecko_CopyCursorArrayFrom(&mut self.gecko, &other.gecko);
+ Gecko_CopyCursorArrayFrom(&mut *self.gecko, &*other.gecko);
}
}
@@ -4278,7 +3580,6 @@ clip-path
pub fn clone_cursor(&self) -> longhands::cursor::computed_value::T {
use crate::values::computed::ui::CursorImage;
- use crate::values::computed::url::ComputedImageUrl;
let keyword = self.gecko.mCursor;
@@ -4387,20 +3688,20 @@ clip-path
// Ensure destructors run, otherwise we could leak.
if !self.gecko.mContents.is_empty() {
unsafe {
- Gecko_ClearAndResizeStyleContents(&mut self.gecko, 0);
+ Gecko_ClearAndResizeStyleContents(&mut *self.gecko, 0);
}
}
},
Content::MozAltContent => {
unsafe {
- Gecko_ClearAndResizeStyleContents(&mut self.gecko, 1);
+ Gecko_ClearAndResizeStyleContents(&mut *self.gecko, 1);
*self.gecko.mContents[0].mContent.mString.as_mut() = ptr::null_mut();
}
self.gecko.mContents[0].mType = StyleContentType::AltContent;
},
Content::Items(items) => {
unsafe {
- Gecko_ClearAndResizeStyleContents(&mut self.gecko,
+ Gecko_ClearAndResizeStyleContents(&mut *self.gecko,
items.len() as u32);
}
for (i, item) in items.into_vec().into_iter().enumerate() {
@@ -4481,7 +3782,7 @@ clip-path
pub fn copy_content_from(&mut self, other: &Self) {
use crate::gecko_bindings::bindings::Gecko_CopyStyleContentsFrom;
unsafe {
- Gecko_CopyStyleContentsFrom(&mut self.gecko, &other.gecko)
+ Gecko_CopyStyleContentsFrom(&mut *self.gecko, &*other.gecko)
}
}
@@ -4494,7 +3795,6 @@ clip-path
use crate::gecko::conversions::string_from_chars_pointer;
use crate::gecko_bindings::structs::StyleContentType;
use crate::values::generics::counters::{Content, ContentItem};
- use crate::values::computed::url::ComputedImageUrl;
use crate::values::{CustomIdent, Either};
use crate::values::generics::CounterStyleOrNone;
use crate::values::specified::Attr;
@@ -4575,7 +3875,7 @@ clip-path
v: longhands::counter_${counter_property.lower()}::computed_value::T
) {
unsafe {
- bindings::Gecko_ClearAndResizeCounter${counter_property}s(&mut self.gecko, v.len() as u32);
+ bindings::Gecko_ClearAndResizeCounter${counter_property}s(&mut *self.gecko, v.len() as u32);
for (i, pair) in v.0.into_vec().into_iter().enumerate() {
self.gecko.m${counter_property}s[i].mCounter.set_move(
RefPtr::from_addrefed(pair.name.0.into_addrefed())
@@ -4587,7 +3887,7 @@ clip-path
pub fn copy_counter_${counter_property.lower()}_from(&mut self, other: &Self) {
unsafe {
- bindings::Gecko_CopyCounter${counter_property}sFrom(&mut self.gecko, &other.gecko)
+ bindings::Gecko_CopyCounter${counter_property}sFrom(&mut *self.gecko, &*other.gecko)
}
}
diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs
index 8310d537f36..800d50c6220 100644
--- a/components/style/properties/helpers.mako.rs
+++ b/components/style/properties/helpers.mako.rs
@@ -10,7 +10,7 @@
<%def name="predefined_type(name, type, initial_value, parse_method='parse',
needs_context=True, vector=False,
computed_type=None, initial_specified_value=None,
- allow_quirks=False, allow_empty=False, **kwargs)">
+ allow_quirks='No', allow_empty=False, **kwargs)">
<%def name="predefined_type_inner(name, type, initial_value, parse_method)">
#[allow(unused_imports)]
use app_units::Au;
@@ -42,8 +42,8 @@
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<SpecifiedValue, ParseError<'i>> {
- % if allow_quirks:
- specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::Yes)
+ % if allow_quirks != "No":
+ specified::${type}::${parse_method}_quirky(context, input, AllowQuirks::${allow_quirks})
% elif needs_context:
specified::${type}::${parse_method}(context, input)
% else:
@@ -80,12 +80,26 @@
We assume that the default/initial value is an empty vector for these.
`initial_value` need not be defined for these.
</%doc>
+
+// The setup here is roughly:
+//
+// * UnderlyingList is the list that is stored in the computed value. This may
+// be a shared ArcSlice if the property is inherited.
+// * UnderlyingOwnedList is the list that is used for animation.
+// * Specified values always use OwnedSlice, since it's more compact.
+// * computed_value::List is just a convenient alias that you can use for the
+// computed value list, since this is in the computed_value module.
+//
+// If simple_vector_bindings is true, then we don't use the complex iterator
+// machinery and set_foo_from, and just compute the value like any other
+// longhand.
<%def name="vector_longhand(name, animation_value_type=None,
vector_animation_type=None, allow_empty=False,
+ simple_vector_bindings=False,
separator='Comma',
**kwargs)">
<%call expr="longhand(name, animation_value_type=animation_value_type, vector=True,
- **kwargs)">
+ simple_vector_bindings=simple_vector_bindings, **kwargs)">
#[allow(unused_imports)]
use smallvec::SmallVec;
@@ -111,16 +125,46 @@
/// The definition of the computed value for ${name}.
pub mod computed_value {
+ #[allow(unused_imports)]
+ use crate::values::animated::ToAnimatedValue;
+ #[allow(unused_imports)]
+ use crate::values::resolved::ToResolvedValue;
pub use super::single_value::computed_value as single_value;
pub use self::single_value::T as SingleComputedValue;
- % if allow_empty and allow_empty != "NotInitial":
- use std::vec::IntoIter;
- % else:
- use smallvec::{IntoIter, SmallVec};
+ % if not allow_empty or allow_empty == "NotInitial":
+ use smallvec::SmallVec;
% endif
use crate::values::computed::ComputedVecIter;
- /// The generic type defining the value for this property.
+ <%
+ is_shared_list = allow_empty and allow_empty != "NotInitial" and \
+ data.longhands_by_name[name].style_struct.inherited
+ %>
+
+ // FIXME(emilio): Add an OwnedNonEmptySlice type, and figure out
+ // something for transition-name, which is the only remaining user
+ // of NotInitial.
+ pub type UnderlyingList<T> =
+ % if allow_empty and allow_empty != "NotInitial":
+ % if data.longhands_by_name[name].style_struct.inherited:
+ crate::ArcSlice<T>;
+ % else:
+ crate::OwnedSlice<T>;
+ % endif
+ % else:
+ SmallVec<[T; 1]>;
+ % endif
+
+ pub type UnderlyingOwnedList<T> =
+ % if allow_empty and allow_empty != "NotInitial":
+ crate::OwnedSlice<T>;
+ % else:
+ SmallVec<[T; 1]>;
+ % endif
+
+
+ /// The generic type defining the animated and resolved values for
+ /// this property.
///
/// Making this type generic allows the compiler to figure out the
/// animated value for us, instead of having to implement it
@@ -137,34 +181,115 @@
ToResolvedValue,
ToCss,
)]
- pub struct List<T>(
+ pub struct OwnedList<T>(
% if not allow_empty:
#[css(iterable)]
% else:
#[css(if_empty = "none", iterable)]
% endif
- % if allow_empty and allow_empty != "NotInitial":
- pub Vec<T>,
+ pub UnderlyingOwnedList<T>,
+ );
+
+ /// The computed value for this property.
+ % if not is_shared_list:
+ pub type ComputedList = OwnedList<single_value::T>;
+ pub use self::OwnedList as List;
+ % else:
+ pub use self::ComputedList as List;
+
+ % if separator == "Comma":
+ #[css(comma)]
+ % endif
+ #[derive(
+ Clone,
+ Debug,
+ MallocSizeOf,
+ PartialEq,
+ ToCss,
+ )]
+ pub struct ComputedList(
+ % if not allow_empty:
+ #[css(iterable)]
% else:
- pub SmallVec<[T; 1]>,
+ #[css(if_empty = "none", iterable)]
+ % endif
+ % if is_shared_list:
+ #[ignore_malloc_size_of = "Arc"]
% endif
+ pub UnderlyingList<single_value::T>,
);
+ type ResolvedList = OwnedList<<single_value::T as ToResolvedValue>::ResolvedValue>;
+ impl ToResolvedValue for ComputedList {
+ type ResolvedValue = ResolvedList;
+
+ fn to_resolved_value(self, context: &crate::values::resolved::Context) -> Self::ResolvedValue {
+ OwnedList(
+ self.0
+ .iter()
+ .cloned()
+ .map(|v| v.to_resolved_value(context))
+ .collect()
+ )
+ }
+
+ fn from_resolved_value(resolved: Self::ResolvedValue) -> Self {
+ % if not is_shared_list:
+ use std::iter::FromIterator;
+ % endif
+ let iter =
+ resolved.0.into_iter().map(ToResolvedValue::from_resolved_value);
+ ComputedList(UnderlyingList::from_iter(iter))
+ }
+ }
+ % endif
+
+ % if simple_vector_bindings:
+ impl From<ComputedList> for UnderlyingList<single_value::T> {
+ #[inline]
+ fn from(l: ComputedList) -> Self {
+ l.0
+ }
+ }
+ impl From<UnderlyingList<single_value::T>> for ComputedList {
+ #[inline]
+ fn from(l: UnderlyingList<single_value::T>) -> Self {
+ List(l)
+ }
+ }
+ % endif
- /// The computed value, effectively a list of single values.
% if vector_animation_type:
% if not animation_value_type:
Sorry, this is stupid but needed for now.
% endif
use crate::properties::animated_properties::ListAnimation;
- use crate::values::animated::{Animate, ToAnimatedValue, ToAnimatedZero, Procedure};
+ use crate::values::animated::{Animate, ToAnimatedZero, Procedure};
use crate::values::distance::{SquaredDistance, ComputeSquaredDistance};
// FIXME(emilio): For some reason rust thinks that this alias is
// unused, even though it's clearly used below?
#[allow(unused)]
- type AnimatedList = <List<single_value::T> as ToAnimatedValue>::AnimatedValue;
+ type AnimatedList = OwnedList<<single_value::T as ToAnimatedValue>::AnimatedValue>;
+
+ % if is_shared_list:
+ impl ToAnimatedValue for ComputedList {
+ type AnimatedValue = AnimatedList;
+
+ fn to_animated_value(self) -> Self::AnimatedValue {
+ OwnedList(
+ self.0.iter().map(|v| v.clone().to_animated_value()).collect()
+ )
+ }
+
+ fn from_animated_value(animated: Self::AnimatedValue) -> Self {
+ let iter =
+ animated.0.into_iter().map(ToAnimatedValue::from_animated_value);
+ ComputedList(UnderlyingList::from_iter(iter))
+ }
+ }
+ % endif
impl ToAnimatedZero for AnimatedList {
fn to_animated_zero(&self) -> Result<Self, ()> { Err(()) }
@@ -176,7 +301,7 @@
other: &Self,
procedure: Procedure,
) -> Result<Self, ()> {
- Ok(List(
+ Ok(OwnedList(
self.0.animate_${vector_animation_type}(&other.0, procedure)?
))
}
@@ -191,21 +316,10 @@
}
% endif
- pub type T = List<single_value::T>;
+ /// The computed value, effectively a list of single values.
+ pub use self::ComputedList as T;
pub type Iter<'a, 'cx, 'cx_a> = ComputedVecIter<'a, 'cx, 'cx_a, super::single_value::SpecifiedValue>;
-
- impl IntoIterator for T {
- type Item = single_value::T;
- % if allow_empty and allow_empty != "NotInitial":
- type IntoIter = IntoIter<single_value::T>;
- % else:
- type IntoIter = IntoIter<[single_value::T; 1]>;
- % endif
- fn into_iter(self) -> Self::IntoIter {
- self.0.into_iter()
- }
- }
}
/// The specified value of ${name}.
@@ -219,12 +333,12 @@
% else:
#[css(if_empty = "none", iterable)]
% endif
- pub Vec<single_value::SpecifiedValue>,
+ pub crate::OwnedSlice<single_value::SpecifiedValue>,
);
pub fn get_initial_value() -> computed_value::T {
% if allow_empty and allow_empty != "NotInitial":
- computed_value::List(vec![])
+ computed_value::List(Default::default())
% else:
let mut v = SmallVec::new();
v.push(single_value::get_initial_value());
@@ -239,40 +353,47 @@
use style_traits::Separator;
% if allow_empty:
- if input.try(|input| input.expect_ident_matching("none")).is_ok() {
- return Ok(SpecifiedValue(Vec::new()))
- }
+ if input.try(|input| input.expect_ident_matching("none")).is_ok() {
+ return Ok(SpecifiedValue(Default::default()))
+ }
% endif
- style_traits::${separator}::parse(input, |parser| {
+ let v = style_traits::${separator}::parse(input, |parser| {
single_value::parse(context, parser)
- }).map(SpecifiedValue)
+ })?;
+ Ok(SpecifiedValue(v.into()))
}
pub use self::single_value::SpecifiedValue as SingleSpecifiedValue;
+ % if not simple_vector_bindings and product == "gecko":
impl SpecifiedValue {
- pub fn compute_iter<'a, 'cx, 'cx_a>(
+ fn compute_iter<'a, 'cx, 'cx_a>(
&'a self,
context: &'cx Context<'cx_a>,
) -> computed_value::Iter<'a, 'cx, 'cx_a> {
computed_value::Iter::new(context, &self.0)
}
}
+ % endif
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
#[inline]
fn to_computed_value(&self, context: &Context) -> computed_value::T {
- computed_value::List(self.compute_iter(context).collect())
+ % if not is_shared_list:
+ use std::iter::FromIterator;
+ % endif
+ computed_value::List(computed_value::UnderlyingList::from_iter(
+ self.0.iter().map(|i| i.to_computed_value(context))
+ ))
}
#[inline]
fn from_computed_value(computed: &computed_value::T) -> Self {
- SpecifiedValue(computed.0.iter()
- .map(ToComputedValue::from_computed_value)
- .collect())
+ let iter = computed.0.iter().map(ToComputedValue::from_computed_value);
+ SpecifiedValue(iter.collect())
}
}
</%call>
@@ -375,7 +496,7 @@
.set_writing_mode_dependency(context.builder.writing_mode);
% endif
- % if property.is_vector:
+ % if property.is_vector and not property.simple_vector_bindings and product == "gecko":
// In the case of a vector property we want to pass down an
// iterator so that this can be computed without allocation.
//
@@ -405,8 +526,8 @@
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<PropertyDeclaration, ParseError<'i>> {
- % if property.allow_quirks:
- parse_quirky(context, input, specified::AllowQuirks::Yes)
+ % if property.allow_quirks != "No":
+ parse_quirky(context, input, specified::AllowQuirks::${property.allow_quirks})
% else:
parse(context, input)
% endif
@@ -868,7 +989,7 @@
</%def>
<%def name="four_sides_shorthand(name, sub_property_pattern, parser_function,
- needs_context=True, allow_quirks=False, **kwargs)">
+ needs_context=True, allow_quirks='No', **kwargs)">
<% sub_properties=' '.join(sub_property_pattern % side for side in PHYSICAL_SIDES) %>
<%call expr="self.shorthand(name, sub_properties=sub_properties, **kwargs)">
#[allow(unused_imports)]
@@ -881,8 +1002,8 @@
input: &mut Parser<'i, 't>,
) -> Result<Longhands, ParseError<'i>> {
let rect = Rect::parse_with(context, input, |_c, i| {
- % if allow_quirks:
- ${parser_function}_quirky(_c, i, specified::AllowQuirks::Yes)
+ % if allow_quirks != "No":
+ ${parser_function}_quirky(_c, i, specified::AllowQuirks::${allow_quirks})
% elif needs_context:
${parser_function}(_c, i)
% else:
diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs
index aa2d0247e82..d3b3ecd11e4 100644
--- a/components/style/properties/helpers/animated_properties.mako.rs
+++ b/components/style/properties/helpers/animated_properties.mako.rs
@@ -9,9 +9,7 @@
from itertools import groupby
%>
-#[cfg(feature = "gecko")] use crate::gecko_bindings::structs::RawServoAnimationValueMap;
#[cfg(feature = "gecko")] use crate::gecko_bindings::structs::nsCSSPropertyID;
-#[cfg(feature = "gecko")] use crate::gecko_bindings::sugar::ownership::{HasFFI, HasSimpleFFI};
use itertools::{EitherOrBoth, Itertools};
use crate::properties::{CSSWideKeyword, PropertyDeclaration};
use crate::properties::longhands;
@@ -190,13 +188,6 @@ impl AnimatedProperty {
/// composed for each TransitionProperty.
pub type AnimationValueMap = FxHashMap<LonghandId, AnimationValue>;
-#[cfg(feature = "gecko")]
-unsafe impl HasFFI for AnimationValueMap {
- type FFIType = RawServoAnimationValueMap;
-}
-#[cfg(feature = "gecko")]
-unsafe impl HasSimpleFFI for AnimationValueMap {}
-
/// An enum to represent a single computed value belonging to an animated
/// property in order to be interpolated with another one. When interpolating,
/// both values need to belong to the same property.
@@ -773,6 +764,7 @@ macro_rules! animated_list_impl {
}
}
+animated_list_impl!(<T> for crate::OwnedSlice<T>);
animated_list_impl!(<T> for SmallVec<[T; 1]>);
animated_list_impl!(<T> for Vec<T>);
diff --git a/components/style/properties/longhands/background.mako.rs b/components/style/properties/longhands/background.mako.rs
index 42344a18cb9..9c66e4676f9 100644
--- a/components/style/properties/longhands/background.mako.rs
+++ b/components/style/properties/longhands/background.mako.rs
@@ -14,7 +14,7 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-backgrounds/#background-color",
animation_value_type="AnimatedColor",
ignored_when_colors_disabled=True,
- allow_quirks=True,
+ allow_quirks="Yes",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER \
CAN_ANIMATE_ON_COMPOSITOR",
)}
diff --git a/components/style/properties/longhands/border.mako.rs b/components/style/properties/longhands/border.mako.rs
index 13a7f237350..7909372be17 100644
--- a/components/style/properties/longhands/border.mako.rs
+++ b/components/style/properties/longhands/border.mako.rs
@@ -28,7 +28,7 @@
animation_value_type="AnimatedColor",
logical=is_logical,
logical_group="border-color",
- allow_quirks=not is_logical,
+ allow_quirks="No" if is_logical else "Yes",
flags="APPLIES_TO_FIRST_LETTER",
ignored_when_colors_disabled=True,
)}
@@ -56,7 +56,7 @@
logical=is_logical,
logical_group="border-width",
flags="APPLIES_TO_FIRST_LETTER GETCS_NEEDS_LAYOUT_FLUSH",
- allow_quirks=not is_logical,
+ allow_quirks="No" if is_logical else "Yes",
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}
% endfor
@@ -159,60 +159,3 @@ ${helpers.predefined_type(
flags="APPLIES_TO_FIRST_LETTER",
boxed=True,
)}
-
-// FIXME(emilio): Why does this live here? ;_;
-#[cfg(feature = "gecko")]
-impl crate::values::computed::BorderImageWidth {
- pub fn to_gecko_rect(&self, sides: &mut crate::gecko_bindings::structs::nsStyleSides) {
- use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
- use crate::gecko::values::GeckoStyleCoordConvertible;
- use crate::values::generics::border::BorderImageSideWidth;
-
- % for i in range(0, 4):
- match self.${i} {
- BorderImageSideWidth::Auto => {
- sides.data_at_mut(${i}).set_value(CoordDataValue::Auto)
- },
- BorderImageSideWidth::Length(l) => {
- l.to_gecko_style_coord(&mut sides.data_at_mut(${i}))
- },
- BorderImageSideWidth::Number(n) => {
- sides.data_at_mut(${i}).set_value(CoordDataValue::Factor(n.0))
- },
- }
- % endfor
- }
-
- pub fn from_gecko_rect(
- sides: &crate::gecko_bindings::structs::nsStyleSides,
- ) -> Option<crate::values::computed::BorderImageWidth> {
- use crate::gecko_bindings::structs::nsStyleUnit::{eStyleUnit_Factor, eStyleUnit_Auto};
- use crate::gecko_bindings::sugar::ns_style_coord::CoordData;
- use crate::gecko::values::GeckoStyleCoordConvertible;
- use crate::values::computed::{LengthPercentage, Number};
- use crate::values::generics::border::BorderImageSideWidth;
- use crate::values::generics::NonNegative;
-
- Some(
- crate::values::computed::BorderImageWidth::new(
- % for i in range(0, 4):
- match sides.data_at(${i}).unit() {
- eStyleUnit_Auto => {
- BorderImageSideWidth::Auto
- },
- eStyleUnit_Factor => {
- BorderImageSideWidth::Number(
- NonNegative(Number::from_gecko_style_coord(&sides.data_at(${i}))
- .expect("sides[${i}] could not convert to Number")))
- },
- _ => {
- BorderImageSideWidth::Length(
- NonNegative(LengthPercentage::from_gecko_style_coord(&sides.data_at(${i}))
- .expect("sides[${i}] could not convert to LengthPercentage")))
- },
- },
- % endfor
- )
- )
- }
-}
diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs
index 6d754964ecc..da9e5b2e767 100644
--- a/components/style/properties/longhands/box.mako.rs
+++ b/components/style/properties/longhands/box.mako.rs
@@ -309,41 +309,6 @@ ${helpers.predefined_type(
allowed_in_keyframe_block=False,
)}
-% for axis in ["x", "y"]:
- ${helpers.predefined_type(
- "scroll-snap-points-" + axis,
- "ScrollSnapPoint",
- "computed::ScrollSnapPoint::none()",
- animation_value_type="discrete",
- gecko_pref="layout.css.scroll-snap.enabled",
- products="gecko",
- spec="Nonstandard (https://www.w3.org/TR/2015/WD-css-snappoints-1-20150326/#scroll-snap-points)",
- )}
-% endfor
-
-${helpers.predefined_type(
- "scroll-snap-destination",
- "Position",
- "computed::Position::zero()",
- products="gecko",
- gecko_pref="layout.css.scroll-snap.enabled",
- boxed=True,
- spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination)",
- animation_value_type="discrete",
-)}
-
-${helpers.predefined_type(
- "scroll-snap-coordinate",
- "Position",
- "computed::Position::zero()",
- vector=True,
- allow_empty=True,
- products="gecko",
- gecko_pref="layout.css.scroll-snap.enabled",
- spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/scroll-snap-destination)",
- animation_value_type="discrete",
-)}
-
<% transform_extra_prefixes = "moz:layout.css.prefixes.transforms webkit" %>
${helpers.predefined_type(
@@ -352,7 +317,6 @@ ${helpers.predefined_type(
"generics::transform::Transform::none()",
extra_prefixes=transform_extra_prefixes,
animation_value_type="ComputedValue",
- gecko_ffi_name="mSpecifiedTransform",
flags="CREATES_STACKING_CONTEXT FIXPOS_CB \
GETCS_NEEDS_LAYOUT_FLUSH CAN_ANIMATE_ON_COMPOSITOR",
spec="https://drafts.csswg.org/css-transforms/#propdef-transform",
@@ -405,6 +369,31 @@ ${helpers.predefined_type(
gecko_pref="layout.css.motion-path.enabled",
flags="CREATES_STACKING_CONTEXT FIXPOS_CB",
spec="https://drafts.fxtf.org/motion-1/#offset-path-property",
+ servo_restyle_damage="reflow_out_of_flow"
+)}
+
+// Motion Path Module Level 1
+${helpers.predefined_type(
+ "offset-distance",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ gecko_pref="layout.css.motion-path.enabled",
+ spec="https://drafts.fxtf.org/motion-1/#offset-distance-property",
+ servo_restyle_damage="reflow_out_of_flow"
+)}
+
+// Motion Path Module Level 1
+${helpers.predefined_type(
+ "offset-rotate",
+ "OffsetRotate",
+ "computed::OffsetRotate::auto()",
+ products="gecko",
+ animation_value_type="none",
+ gecko_pref="layout.css.motion-path.enabled",
+ spec="https://drafts.fxtf.org/motion-1/#offset-rotate-property",
+ servo_restyle_damage="reflow_out_of_flow"
)}
// CSSOM View Module
diff --git a/components/style/properties/longhands/color.mako.rs b/components/style/properties/longhands/color.mako.rs
index b367f2bbd86..a83787dd48e 100644
--- a/components/style/properties/longhands/color.mako.rs
+++ b/components/style/properties/longhands/color.mako.rs
@@ -35,6 +35,7 @@ pub mod system_colors {
-moz-eventreerow -moz-field -moz-fieldtext -moz-dialog -moz-dialogtext
-moz-dragtargetzone -moz-gtk-info-bar-text -moz-html-cellhighlight
-moz-html-cellhighlighttext -moz-mac-buttonactivetext
+ -moz-gtk-buttonactivetext
-moz-mac-chrome-active -moz-mac-chrome-inactive
-moz-mac-defaultbuttontext -moz-mac-focusring -moz-mac-menuselect
-moz-mac-menushadow -moz-mac-menutextdisable -moz-mac-menutextselect
diff --git a/components/style/properties/longhands/effects.mako.rs b/components/style/properties/longhands/effects.mako.rs
index 0b3f96f0dde..9bb8adda32e 100644
--- a/components/style/properties/longhands/effects.mako.rs
+++ b/components/style/properties/longhands/effects.mako.rs
@@ -23,6 +23,7 @@ ${helpers.predefined_type(
"BoxShadow",
None,
vector=True,
+ simple_vector_bindings=True,
animation_value_type="AnimatedBoxShadowList",
vector_animation_type="with_zero",
extra_prefixes="webkit",
@@ -37,7 +38,7 @@ ${helpers.predefined_type(
"computed::ClipRectOrAuto::auto()",
animation_value_type="ComputedValue",
boxed=True,
- allow_quirks=True,
+ allow_quirks="Yes",
spec="https://drafts.fxtf.org/css-masking/#clip-property",
)}
diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs
index c1d3d8fcc6c..8d84ef34cb3 100644
--- a/components/style/properties/longhands/font.mako.rs
+++ b/components/style/properties/longhands/font.mako.rs
@@ -64,7 +64,7 @@ ${helpers.predefined_type(
initial_value="computed::FontSize::medium()",
initial_specified_value="specified::FontSize::medium()",
animation_value_type="NonNegativeLength",
- allow_quirks=True,
+ allow_quirks="Yes",
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size",
servo_restyle_damage="rebuild_and_reflow",
diff --git a/components/style/properties/longhands/inherited_svg.mako.rs b/components/style/properties/longhands/inherited_svg.mako.rs
index 2bbdc2794c2..c3e16ee475f 100644
--- a/components/style/properties/longhands/inherited_svg.mako.rs
+++ b/components/style/properties/longhands/inherited_svg.mako.rs
@@ -194,11 +194,8 @@ ${helpers.predefined_type(
${helpers.predefined_type(
"-moz-context-properties",
"MozContextProperties",
- initial_value=None,
- vector=True,
- need_index=True,
- animation_value_type="none",
+ "computed::MozContextProperties::default()",
products="gecko",
+ animation_value_type="none",
spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)",
- allow_empty=True,
)}
diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs
index cdd7df93256..e8f56cf2cde 100644
--- a/components/style/properties/longhands/inherited_text.mako.rs
+++ b/components/style/properties/longhands/inherited_text.mako.rs
@@ -56,7 +56,7 @@ ${helpers.predefined_type(
"computed::LengthPercentage::zero()",
animation_value_type="ComputedValue",
spec="https://drafts.csswg.org/css-text/#propdef-text-indent",
- allow_quirks=True,
+ allow_quirks="Yes",
servo_restyle_damage = "reflow",
)}
@@ -218,6 +218,7 @@ ${helpers.predefined_type(
vector_animation_type="with_zero",
animation_value_type="AnimatedTextShadowList",
ignored_when_colors_disabled=True,
+ simple_vector_bindings=True,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
spec="https://drafts.csswg.org/css-text-decor-3/#text-shadow-property",
)}
@@ -263,6 +264,16 @@ ${helpers.predefined_type(
spec="https://drafts.csswg.org/css-text-3/#tab-size-property",
)}
+${helpers.predefined_type(
+ "line-break",
+ "LineBreak",
+ "computed::LineBreak::Auto",
+ products="gecko",
+ animation_value_type="discrete",
+ spec="https://drafts.csswg.org/css-text-3/#line-break-property",
+ needs_context=False,
+)}
+
// CSS Compatibility
// https://compat.spec.whatwg.org
${helpers.predefined_type(
diff --git a/components/style/properties/longhands/margin.mako.rs b/components/style/properties/longhands/margin.mako.rs
index d2a3be11d1d..c3289c34b7c 100644
--- a/components/style/properties/longhands/margin.mako.rs
+++ b/components/style/properties/longhands/margin.mako.rs
@@ -17,7 +17,7 @@
"LengthPercentageOrAuto",
"computed::LengthPercentageOrAuto::zero()",
alias=maybe_moz_logical_alias(product, side, "-moz-margin-%s"),
- allow_quirks=not side[1],
+ allow_quirks="No" if side[1] else "Yes",
animation_value_type="ComputedValue",
logical=side[1],
logical_group="margin",
diff --git a/components/style/properties/longhands/padding.mako.rs b/components/style/properties/longhands/padding.mako.rs
index a1262aee0fc..6142bbf901e 100644
--- a/components/style/properties/longhands/padding.mako.rs
+++ b/components/style/properties/longhands/padding.mako.rs
@@ -24,7 +24,7 @@
logical_group="padding",
spec=spec,
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_PLACEHOLDER GETCS_NEEDS_LAYOUT_FLUSH",
- allow_quirks=not side[1],
+ allow_quirks="No" if side[1] else "Yes",
servo_restyle_damage="reflow rebuild_and_reflow_inline"
)}
% endfor
diff --git a/components/style/properties/longhands/position.mako.rs b/components/style/properties/longhands/position.mako.rs
index 096349f4b1c..34216385fed 100644
--- a/components/style/properties/longhands/position.mako.rs
+++ b/components/style/properties/longhands/position.mako.rs
@@ -17,7 +17,7 @@
spec="https://www.w3.org/TR/CSS2/visuren.html#propdef-%s" % side,
flags="GETCS_NEEDS_LAYOUT_FLUSH",
animation_value_type="ComputedValue",
- allow_quirks=True,
+ allow_quirks="Yes",
servo_restyle_damage="reflow_out_of_flow",
logical_group="inset",
)}
@@ -253,7 +253,7 @@ ${helpers.predefined_type(
"computed::Size::auto()",
logical=logical,
logical_group="size",
- allow_quirks=not logical,
+ allow_quirks="No" if logical else "Yes",
spec=spec % size,
animation_value_type="Size",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
@@ -266,7 +266,7 @@ ${helpers.predefined_type(
"computed::Size::auto()",
logical=logical,
logical_group="min-size",
- allow_quirks=not logical,
+ allow_quirks="No" if logical else "Yes",
spec=spec % size,
animation_value_type="Size",
servo_restyle_damage="reflow",
@@ -277,7 +277,7 @@ ${helpers.predefined_type(
"computed::MaxSize::none()",
logical=logical,
logical_group="max-size",
- allow_quirks=not logical,
+ allow_quirks="No" if logical else "Yes",
spec=spec % size,
animation_value_type="MaxSize",
servo_restyle_damage="reflow",
diff --git a/components/style/properties/longhands/svg.mako.rs b/components/style/properties/longhands/svg.mako.rs
index 3e4d207397a..8e93d03dbb1 100644
--- a/components/style/properties/longhands/svg.mako.rs
+++ b/components/style/properties/longhands/svg.mako.rs
@@ -191,3 +191,66 @@ ${helpers.predefined_type(
animation_value_type="discrete",
flags="CREATES_STACKING_CONTEXT",
)}
+
+${helpers.predefined_type(
+ "x",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ spec="https://svgwg.org/svg2-draft/geometry.html#X",
+)}
+
+${helpers.predefined_type(
+ "y",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ spec="https://svgwg.org/svg2-draft/geometry.html#Y",
+)}
+
+${helpers.predefined_type(
+ "cx",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ spec="https://svgwg.org/svg2-draft/geometry.html#CX",
+)}
+
+${helpers.predefined_type(
+ "cy",
+ "LengthPercentage",
+ "computed::LengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="ComputedValue",
+ spec="https://svgwg.org/svg2-draft/geometry.html#CY",
+)}
+
+${helpers.predefined_type(
+ "rx",
+ "NonNegativeLengthPercentageOrAuto",
+ "computed::NonNegativeLengthPercentageOrAuto::auto()",
+ products="gecko",
+ animation_value_type="LengthPercentageOrAuto",
+ spec="https://svgwg.org/svg2-draft/geometry.html#RX",
+)}
+
+${helpers.predefined_type(
+ "ry",
+ "NonNegativeLengthPercentageOrAuto",
+ "computed::NonNegativeLengthPercentageOrAuto::auto()",
+ products="gecko",
+ animation_value_type="LengthPercentageOrAuto",
+ spec="https://svgwg.org/svg2-draft/geometry.html#RY",
+)}
+
+${helpers.predefined_type(
+ "r",
+ "NonNegativeLengthPercentage",
+ "computed::NonNegativeLengthPercentage::zero()",
+ products="gecko",
+ animation_value_type="LengthPercentage",
+ spec="https://svgwg.org/svg2-draft/geometry.html#R",
+)}
diff --git a/components/style/properties/longhands/ui.mako.rs b/components/style/properties/longhands/ui.mako.rs
index c54582e2584..5c51569089c 100644
--- a/components/style/properties/longhands/ui.mako.rs
+++ b/components/style/properties/longhands/ui.mako.rs
@@ -32,12 +32,11 @@ ${helpers.single_keyword(
)}
${helpers.predefined_type(
- "-moz-user-select",
+ "user-select",
"UserSelect",
"computed::UserSelect::Auto",
products="gecko",
- gecko_ffi_name="mUserSelect",
- alias="-webkit-user-select",
+ extra_prefixes="moz webkit",
animation_value_type="discrete",
needs_context=False,
spec="https://drafts.csswg.org/css-ui-4/#propdef-user-select",
@@ -81,7 +80,6 @@ ${helpers.predefined_type(
"Transform",
"generics::transform::Transform::none()",
products="gecko",
- gecko_ffi_name="mSpecifiedWindowTransform",
flags="GETCS_NEEDS_LAYOUT_FLUSH",
animation_value_type="ComputedValue",
spec="None (Nonstandard internal property)",
diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs
index a9fa35ba444..520b4a32b51 100644
--- a/components/style/properties/properties.mako.rs
+++ b/components/style/properties/properties.mako.rs
@@ -2337,6 +2337,14 @@ impl SourcePropertyDeclaration {
}
}
+ /// Create one with a single PropertyDeclaration.
+ #[inline]
+ pub fn with_one(decl: PropertyDeclaration) -> Self {
+ let mut result = Self::new();
+ result.declarations.push(decl);
+ result
+ }
+
/// Similar to Vec::drain: leaves this empty when the return value is dropped.
pub fn drain(&mut self) -> SourcePropertyDeclarationDrain {
SourcePropertyDeclarationDrain {
@@ -2474,20 +2482,7 @@ pub mod style_structs {
% if longhand.logical:
${helpers.logical_setter(name=longhand.name)}
% else:
- % if longhand.is_vector:
- /// Set ${longhand.name}.
- #[allow(non_snake_case)]
- #[inline]
- pub fn set_${longhand.ident}<I>(&mut self, v: I)
- where
- I: IntoIterator<Item = longhands::${longhand.ident}
- ::computed_value::single_value::T>,
- I::IntoIter: ExactSizeIterator
- {
- self.${longhand.ident} = longhands::${longhand.ident}::computed_value
- ::List(v.into_iter().collect());
- }
- % elif longhand.ident == "display":
+ % if longhand.ident == "display":
/// Set `display`.
///
/// We need to keep track of the original display for hypothetical boxes,
@@ -3101,7 +3096,7 @@ impl ComputedValuesInner {
pub fn transform_requires_layer(&self) -> bool {
use crate::values::generics::transform::TransformOperation;
// Check if the transform matrix is 2D or 3D
- for transform in &self.get_box().transform.0 {
+ for transform in &*self.get_box().transform.0 {
match *transform {
TransformOperation::Perspective(..) => {
return true;
@@ -3444,7 +3439,7 @@ impl<'a> StyleBuilder<'a> {
}
% endif
- % if not property.is_vector:
+ % if not property.is_vector or property.simple_vector_bindings or product != "gecko":
/// Set the `${property.ident}` to the computed value `value`.
#[allow(non_snake_case)]
pub fn set_${property.ident}(
diff --git a/components/style/properties/shorthands/background.mako.rs b/components/style/properties/shorthands/background.mako.rs
index c73009ab2ba..af98342bfe6 100644
--- a/components/style/properties/shorthands/background.mako.rs
+++ b/components/style/properties/shorthands/background.mako.rs
@@ -40,11 +40,11 @@
let mut background_color = None;
% for name in "image position_x position_y repeat size attachment origin clip".split():
- // Vec grows from 0 to 4 by default on first push(). So allocate
- // with capacity 1, so in the common case of only one item we don't
- // way overallocate. Note that we always push at least one item if
- // parsing succeeds.
- let mut background_${name} = background_${name}::SpecifiedValue(Vec::with_capacity(1));
+ // Vec grows from 0 to 4 by default on first push(). So allocate with
+ // capacity 1, so in the common case of only one item we don't way
+ // overallocate, then shrink. Note that we always push at least one
+ // item if parsing succeeds.
+ let mut background_${name} = Vec::with_capacity(1);
% endfor
input.parse_comma_separated(|input| {
// background-color can only be in the last element, so if it
@@ -99,17 +99,17 @@
any = any || background_color.is_some();
if any {
if let Some(position) = position {
- background_position_x.0.push(position.horizontal);
- background_position_y.0.push(position.vertical);
+ background_position_x.push(position.horizontal);
+ background_position_y.push(position.vertical);
} else {
- background_position_x.0.push(PositionComponent::zero());
- background_position_y.0.push(PositionComponent::zero());
+ background_position_x.push(PositionComponent::zero());
+ background_position_y.push(PositionComponent::zero());
}
% for name in "image repeat size attachment origin clip".split():
if let Some(bg_${name}) = ${name} {
- background_${name}.0.push(bg_${name});
+ background_${name}.push(bg_${name});
} else {
- background_${name}.0.push(background_${name}::single_value
+ background_${name}.push(background_${name}::single_value
::get_initial_specified_value());
}
% endfor
@@ -121,14 +121,9 @@
Ok(expanded! {
background_color: background_color.unwrap_or(Color::transparent()),
- background_image: background_image,
- background_position_x: background_position_x,
- background_position_y: background_position_y,
- background_repeat: background_repeat,
- background_attachment: background_attachment,
- background_size: background_size,
- background_origin: background_origin,
- background_clip: background_clip,
+ % for name in "image position_x position_y repeat size attachment origin clip".split():
+ background_${name}: background_${name}::SpecifiedValue(background_${name}.into()),
+ % endfor
})
}
@@ -209,16 +204,16 @@
) -> Result<Longhands, ParseError<'i>> {
// Vec grows from 0 to 4 by default on first push(). So allocate with
// capacity 1, so in the common case of only one item we don't way
- // overallocate. Note that we always push at least one item if parsing
- // succeeds.
- let mut position_x = background_position_x::SpecifiedValue(Vec::with_capacity(1));
- let mut position_y = background_position_y::SpecifiedValue(Vec::with_capacity(1));
+ // overallocate, then shrink. Note that we always push at least one
+ // item if parsing succeeds.
+ let mut position_x = Vec::with_capacity(1);
+ let mut position_y = Vec::with_capacity(1);
let mut any = false;
input.parse_comma_separated(|input| {
let value = Position::parse_quirky(context, input, AllowQuirks::Yes)?;
- position_x.0.push(value.horizontal);
- position_y.0.push(value.vertical);
+ position_x.push(value.horizontal);
+ position_y.push(value.vertical);
any = true;
Ok(())
})?;
@@ -227,8 +222,8 @@
}
Ok(expanded! {
- background_position_x: position_x,
- background_position_y: position_y,
+ background_position_x: background_position_x::SpecifiedValue(position_x.into()),
+ background_position_y: background_position_y::SpecifiedValue(position_y.into()),
})
}
diff --git a/components/style/properties/shorthands/border.mako.rs b/components/style/properties/shorthands/border.mako.rs
index cd472068793..1f8df0df6a1 100644
--- a/components/style/properties/shorthands/border.mako.rs
+++ b/components/style/properties/shorthands/border.mako.rs
@@ -7,7 +7,7 @@
${helpers.four_sides_shorthand("border-color", "border-%s-color", "specified::Color::parse",
spec="https://drafts.csswg.org/css-backgrounds/#border-color",
- allow_quirks=True)}
+ allow_quirks="Yes")}
${helpers.four_sides_shorthand(
"border-style",
diff --git a/components/style/properties/shorthands/box.mako.rs b/components/style/properties/shorthands/box.mako.rs
index 5c03dba8529..e69593f1cc1 100644
--- a/components/style/properties/shorthands/box.mako.rs
+++ b/components/style/properties/shorthands/box.mako.rs
@@ -137,7 +137,7 @@ macro_rules! try_parse_one {
Ok(expanded! {
% for prop in "property duration timing_function delay".split():
- transition_${prop}: transition_${prop}::SpecifiedValue(${prop}s),
+ transition_${prop}: transition_${prop}::SpecifiedValue(${prop}s.into()),
% endfor
})
}
@@ -266,7 +266,7 @@ macro_rules! try_parse_one {
Ok(expanded! {
% for prop in props:
- animation_${prop}: animation_${prop}::SpecifiedValue(${prop}s),
+ animation_${prop}: animation_${prop}::SpecifiedValue(${prop}s.into()),
% endfor
})
}
diff --git a/components/style/properties/shorthands/margin.mako.rs b/components/style/properties/shorthands/margin.mako.rs
index fd3124a6ae1..9b996abbe86 100644
--- a/components/style/properties/shorthands/margin.mako.rs
+++ b/components/style/properties/shorthands/margin.mako.rs
@@ -10,7 +10,7 @@ ${helpers.four_sides_shorthand(
"specified::LengthPercentageOrAuto::parse",
spec="https://drafts.csswg.org/css-box/#propdef-margin",
allowed_in_page_rule=True,
- allow_quirks=True,
+ allow_quirks="Yes",
)}
${helpers.two_properties_shorthand(
diff --git a/components/style/properties/shorthands/padding.mako.rs b/components/style/properties/shorthands/padding.mako.rs
index a4e013caabc..8d50c3b9e38 100644
--- a/components/style/properties/shorthands/padding.mako.rs
+++ b/components/style/properties/shorthands/padding.mako.rs
@@ -9,7 +9,7 @@ ${helpers.four_sides_shorthand(
"padding-%s",
"specified::NonNegativeLengthPercentage::parse",
spec="https://drafts.csswg.org/css-box-3/#propdef-padding",
- allow_quirks=True,
+ allow_quirks="Yes",
)}
${helpers.two_properties_shorthand(
diff --git a/components/style/properties/shorthands/position.mako.rs b/components/style/properties/shorthands/position.mako.rs
index 6fdbe1235cf..63298b86ba1 100644
--- a/components/style/properties/shorthands/position.mako.rs
+++ b/components/style/properties/shorthands/position.mako.rs
@@ -768,7 +768,7 @@ ${helpers.four_sides_shorthand(
"%s",
"specified::LengthPercentageOrAuto::parse",
spec="https://drafts.csswg.org/css-logical/#propdef-inset",
- allow_quirks=False,
+ allow_quirks="No",
)}
${helpers.two_properties_shorthand(
diff --git a/components/style/properties/shorthands/svg.mako.rs b/components/style/properties/shorthands/svg.mako.rs
index f6941c4e7f8..0acaff426cf 100644
--- a/components/style/properties/shorthands/svg.mako.rs
+++ b/components/style/properties/shorthands/svg.mako.rs
@@ -42,11 +42,11 @@
input: &mut Parser<'i, 't>,
) -> Result<Longhands, ParseError<'i>> {
% for name in "image mode position_x position_y size repeat origin clip composite".split():
- // Vec grows from 0 to 4 by default on first push(). So allocate
- // with capacity 1, so in the common case of only one item we don't
- // way overallocate. Note that we always push at least one item if
- // parsing succeeds.
- let mut mask_${name} = mask_${name}::SpecifiedValue(Vec::with_capacity(1));
+ // Vec grows from 0 to 4 by default on first push(). So allocate with
+ // capacity 1, so in the common case of only one item we don't way
+ // overallocate, then shrink. Note that we always push at least one
+ // item if parsing succeeds.
+ let mut mask_${name} = Vec::with_capacity(1);
% endfor
input.parse_comma_separated(|input| {
@@ -96,17 +96,17 @@
% endfor
if any {
if let Some(position) = position {
- mask_position_x.0.push(position.horizontal);
- mask_position_y.0.push(position.vertical);
+ mask_position_x.push(position.horizontal);
+ mask_position_y.push(position.vertical);
} else {
- mask_position_x.0.push(PositionComponent::zero());
- mask_position_y.0.push(PositionComponent::zero());
+ mask_position_x.push(PositionComponent::zero());
+ mask_position_y.push(PositionComponent::zero());
}
% for name in "image mode size repeat origin clip composite".split():
if let Some(m_${name}) = ${name} {
- mask_${name}.0.push(m_${name});
+ mask_${name}.push(m_${name});
} else {
- mask_${name}.0.push(mask_${name}::single_value
+ mask_${name}.push(mask_${name}::single_value
::get_initial_specified_value());
}
% endfor
@@ -118,7 +118,7 @@
Ok(expanded! {
% for name in "image mode position_x position_y size repeat origin clip composite".split():
- mask_${name}: mask_${name},
+ mask_${name}: mask_${name}::SpecifiedValue(mask_${name}.into()),
% endfor
})
}
@@ -209,16 +209,16 @@
) -> Result<Longhands, ParseError<'i>> {
// Vec grows from 0 to 4 by default on first push(). So allocate with
// capacity 1, so in the common case of only one item we don't way
- // overallocate. Note that we always push at least one item if parsing
- // succeeds.
- let mut position_x = mask_position_x::SpecifiedValue(Vec::with_capacity(1));
- let mut position_y = mask_position_y::SpecifiedValue(Vec::with_capacity(1));
+ // overallocate, then shrink. Note that we always push at least one
+ // item if parsing succeeds.
+ let mut position_x = Vec::with_capacity(1);
+ let mut position_y = Vec::with_capacity(1);
let mut any = false;
input.parse_comma_separated(|input| {
let value = Position::parse(context, input)?;
- position_x.0.push(value.horizontal);
- position_y.0.push(value.vertical);
+ position_x.push(value.horizontal);
+ position_y.push(value.vertical);
any = true;
Ok(())
})?;
@@ -227,9 +227,10 @@
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
+
Ok(expanded! {
- mask_position_x: position_x,
- mask_position_y: position_y,
+ mask_position_x: mask_position_x::SpecifiedValue(position_x.into()),
+ mask_position_y: mask_position_y::SpecifiedValue(position_y.into()),
})
}
diff --git a/components/style/rule_collector.rs b/components/style/rule_collector.rs
index e87a86c5e47..360b8101ef1 100644
--- a/components/style/rule_collector.rs
+++ b/components/style/rule_collector.rs
@@ -13,7 +13,7 @@ use crate::selector_parser::PseudoElement;
use crate::shared_lock::Locked;
use crate::stylesheets::Origin;
use crate::stylist::{AuthorStylesEnabled, Rule, RuleInclusion, Stylist};
-use selectors::matching::{ElementSelectorFlags, MatchingContext};
+use selectors::matching::{ElementSelectorFlags, MatchingContext, MatchingMode};
use servo_arc::ArcBorrow;
use smallvec::SmallVec;
@@ -97,8 +97,15 @@ where
context: &'a mut MatchingContext<'b, E::Impl>,
flags_setter: &'a mut F,
) -> Self {
- let rule_hash_target = element.rule_hash_target();
- let matches_user_and_author_rules = element.matches_user_and_author_rules();
+ // When we're matching with matching_mode =
+ // `ForStatelessPseudoeElement`, the "target" for the rule hash is the
+ // element itself, since it's what's generating the pseudo-element.
+ let rule_hash_target = match context.matching_mode() {
+ MatchingMode::ForStatelessPseudoElement => element,
+ MatchingMode::Normal => element.rule_hash_target(),
+ };
+
+ let matches_user_and_author_rules = rule_hash_target.matches_user_and_author_rules();
// Gecko definitely has pseudo-elements with style attributes, like
// ::-moz-color-swatch.
@@ -120,8 +127,8 @@ where
context,
flags_setter,
rules,
- matches_user_and_author_rules,
shadow_cascade_order: 0,
+ matches_user_and_author_rules,
matches_document_author_rules: matches_user_and_author_rules,
}
}
diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs
index 63af60e16ab..21b6fbd60ca 100644
--- a/components/style/style_adjuster.rs
+++ b/components/style/style_adjuster.rs
@@ -734,10 +734,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> {
E: TElement,
{
if cfg!(debug_assertions) {
- if element
- .and_then(|e| e.implemented_pseudo_element())
- .is_some()
- {
+ if element.map_or(false, |e| e.is_pseudo_element()) {
// It'd be nice to assert `self.style.pseudo == Some(&pseudo)`,
// but we do resolve ::-moz-list pseudos on ::before / ::after
// content, sigh.
diff --git a/components/style/style_resolver.rs b/components/style/style_resolver.rs
index 11c81283a13..180de3ff281 100644
--- a/components/style/style_resolver.rs
+++ b/components/style/style_resolver.rs
@@ -233,7 +233,7 @@ where
let mut pseudo_styles = EagerPseudoStyles::default();
- if self.element.implemented_pseudo_element().is_none() {
+ if !self.element.is_pseudo_element() {
let layout_parent_style_for_pseudo = if primary_style.style().is_display_contents() {
layout_parent_style
} else {
@@ -293,10 +293,6 @@ where
layout_parent_style: Option<&ComputedValues>,
pseudo: Option<&PseudoElement>,
) -> ResolvedStyle {
- debug_assert!(
- self.element.implemented_pseudo_element().is_none() || pseudo.is_none(),
- "Pseudo-elements can't have other pseudos!"
- );
debug_assert!(pseudo.map_or(true, |p| p.is_eager()));
let implemented_pseudo = self.element.implemented_pseudo_element();
@@ -477,8 +473,8 @@ where
);
debug_assert!(pseudo_element.is_eager());
debug_assert!(
- self.element.implemented_pseudo_element().is_none(),
- "Element pseudos can't have any other pseudo."
+ !self.element.is_pseudo_element(),
+ "Element pseudos can't have any other eager pseudo."
);
let mut applicable_declarations = ApplicableDeclarationList::new();
diff --git a/components/style/stylist.rs b/components/style/stylist.rs
index 2953e3f0671..cba1cbac524 100644
--- a/components/style/stylist.rs
+++ b/components/style/stylist.rs
@@ -1195,6 +1195,10 @@ impl Stylist {
// See [3] for the bug to implement whatever gets resolved, and related
// bugs for a bit more context.
//
+ // FIXME(emilio): This should probably work for pseudo-elements (i.e.,
+ // use rule_hash_target().shadow_root() instead of
+ // element.shadow_root()).
+ //
// [1]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/
// core/css/resolver/style_resolver.cc?l=1267&rcl=90f9f8680ebb4a87d177f3b0833372ae4e0c88d8
// [2]: https://github.com/w3c/csswg-drafts/issues/1995
diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs
index 87f58fb2f82..4c559cd4c30 100644
--- a/components/style/values/animated/effects.rs
+++ b/components/style/values/animated/effects.rs
@@ -9,22 +9,18 @@ use crate::values::computed::length::Length;
#[cfg(feature = "gecko")]
use crate::values::computed::url::ComputedUrl;
use crate::values::computed::{Angle, Number};
-use crate::values::generics::effects::BoxShadow as GenericBoxShadow;
use crate::values::generics::effects::Filter as GenericFilter;
use crate::values::generics::effects::SimpleShadow as GenericSimpleShadow;
#[cfg(not(feature = "gecko"))]
use crate::values::Impossible;
-/// An animated value for a single `box-shadow`.
-pub type BoxShadow = GenericBoxShadow<Color, Length, Length, Length>;
+/// An animated value for the `drop-shadow()` filter.
+pub type AnimatedSimpleShadow = GenericSimpleShadow<Color, Length, Length>;
/// An animated value for a single `filter`.
#[cfg(feature = "gecko")]
-pub type Filter = GenericFilter<Angle, Number, Length, SimpleShadow, ComputedUrl>;
+pub type Filter = GenericFilter<Angle, Number, Length, AnimatedSimpleShadow, ComputedUrl>;
/// An animated value for a single `filter`.
#[cfg(not(feature = "gecko"))]
pub type Filter = GenericFilter<Angle, Number, Length, Impossible, Impossible>;
-
-/// An animated value for the `drop-shadow()` filter.
-pub type SimpleShadow = GenericSimpleShadow<Color, Length, Length>;
diff --git a/components/style/values/animated/transform.rs b/components/style/values/animated/transform.rs
index 0c322d8fccc..9ac64c3f2a7 100644
--- a/components/style/values/animated/transform.rs
+++ b/components/style/values/animated/transform.rs
@@ -861,7 +861,7 @@ impl Animate for ComputedTransform {
// animation procedures so we treat it separately here rather than
// handling it in TransformOperation.
if procedure == Procedure::Add {
- let result = self.0.iter().chain(&other.0).cloned().collect::<Vec<_>>();
+ let result = self.0.iter().chain(&*other.0).cloned().collect();
return Ok(Transform(result));
}
@@ -898,15 +898,15 @@ impl Animate for ComputedTransform {
},
Procedure::Interpolate { progress } => {
result.push(TransformOperation::InterpolateMatrix {
- from_list: Transform(this_remainder.to_vec()),
- to_list: Transform(other_remainder.to_vec()),
+ from_list: Transform(this_remainder.to_vec().into()),
+ to_list: Transform(other_remainder.to_vec().into()),
progress: Percentage(progress as f32),
});
},
Procedure::Accumulate { count } => {
result.push(TransformOperation::AccumulateMatrix {
- from_list: Transform(this_remainder.to_vec()),
- to_list: Transform(other_remainder.to_vec()),
+ from_list: Transform(this_remainder.to_vec().into()),
+ to_list: Transform(other_remainder.to_vec().into()),
count: cmp::min(count, i32::max_value() as u64) as i32,
});
},
@@ -927,8 +927,8 @@ impl Animate for ComputedTransform {
// matrix. Instead we need to wrap it in another ___Matrix type.
TransformOperation::AccumulateMatrix { .. } |
TransformOperation::InterpolateMatrix { .. } => {
- let transform_list = Transform(vec![transform.clone()]);
- let identity_list = Transform(vec![identity]);
+ let transform_list = Transform(vec![transform.clone()].into());
+ let identity_list = Transform(vec![identity].into());
let (from_list, to_list) = if fill_right {
(transform_list, identity_list)
} else {
@@ -970,7 +970,7 @@ impl Animate for ComputedTransform {
(None, None) => {},
}
- Ok(Transform(result))
+ Ok(Transform(result.into()))
}
}
diff --git a/components/style/values/computed/angle.rs b/components/style/values/computed/angle.rs
index cdbc0006941..d8cdefb5263 100644
--- a/components/style/values/computed/angle.rs
+++ b/components/style/values/computed/angle.rs
@@ -26,6 +26,7 @@ use style_traits::{CssWriter, ToCss};
ToAnimatedZero,
ToResolvedValue,
)]
+#[repr(C)]
pub struct Angle(CSSFloat);
impl ToCss for Angle {
diff --git a/components/style/values/computed/border.rs b/components/style/values/computed/border.rs
index 62c8e3883f6..abdc28ad848 100644
--- a/components/style/values/computed/border.rs
+++ b/components/style/values/computed/border.rs
@@ -7,10 +7,10 @@
use crate::values::computed::length::{NonNegativeLength, NonNegativeLengthPercentage};
use crate::values::computed::{NonNegativeNumber, NonNegativeNumberOrPercentage};
use crate::values::generics::border::BorderCornerRadius as GenericBorderCornerRadius;
-use crate::values::generics::border::BorderImageSideWidth as GenericBorderImageSideWidth;
use crate::values::generics::border::BorderImageSlice as GenericBorderImageSlice;
use crate::values::generics::border::BorderRadius as GenericBorderRadius;
use crate::values::generics::border::BorderSpacing as GenericBorderSpacing;
+use crate::values::generics::border::GenericBorderImageSideWidth;
use crate::values::generics::rect::Rect;
use crate::values::generics::size::Size2D;
use crate::values::generics::NonNegative;
diff --git a/components/style/values/computed/gecko.rs b/components/style/values/computed/gecko.rs
deleted file mode 100644
index cbe0802eab8..00000000000
--- a/components/style/values/computed/gecko.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-//! Computed types for legacy Gecko-only properties.
-
-use crate::values::computed::length::LengthPercentage;
-use crate::values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
-
-/// A computed type for scroll snap points.
-pub type ScrollSnapPoint = GenericScrollSnapPoint<LengthPercentage>;
diff --git a/components/style/values/computed/list.rs b/components/style/values/computed/list.rs
index 2bde35e3b6b..3536aa656fe 100644
--- a/components/style/values/computed/list.rs
+++ b/components/style/values/computed/list.rs
@@ -9,21 +9,19 @@ pub use crate::values::specified::list::ListStyleType;
pub use crate::values::specified::list::MozListReversed;
pub use crate::values::specified::list::{QuotePair, Quotes};
-use servo_arc::Arc;
-
lazy_static! {
- static ref INITIAL_QUOTES: Arc<Box<[QuotePair]>> = Arc::new(
+ static ref INITIAL_QUOTES: crate::ArcSlice<QuotePair> = crate::ArcSlice::from_iter(
vec![
QuotePair {
- opening: "\u{201c}".to_owned().into_boxed_str(),
- closing: "\u{201d}".to_owned().into_boxed_str(),
+ opening: "\u{201c}".to_owned().into(),
+ closing: "\u{201d}".to_owned().into(),
},
QuotePair {
- opening: "\u{2018}".to_owned().into_boxed_str(),
- closing: "\u{2019}".to_owned().into_boxed_str(),
+ opening: "\u{2018}".to_owned().into(),
+ closing: "\u{2019}".to_owned().into(),
},
]
- .into_boxed_slice()
+ .into_iter()
);
}
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index 5bf0333dbfe..06579238e77 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -56,8 +56,6 @@ 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;
pub use self::image::{Gradient, GradientItem, Image, ImageLayer, LineDirection, MozImageRect};
pub use self::length::{CSSPixelLength, ExtremumLength, NonNegativeLength};
pub use self::length::{Length, LengthOrNumber, LengthPercentage, NonNegativeLengthOrNumber};
@@ -67,7 +65,7 @@ pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageO
pub use self::list::ListStyleType;
pub use self::list::MozListReversed;
pub use self::list::{QuotePair, Quotes};
-pub use self::motion::OffsetPath;
+pub use self::motion::{OffsetPath, OffsetRotate};
pub use self::outline::OutlineStyle;
pub use self::percentage::{NonNegativePercentage, Percentage};
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position, ZIndex};
@@ -77,7 +75,7 @@ pub use self::svg::MozContextProperties;
pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind};
pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
pub use self::table::XSpan;
-pub use self::text::{InitialLetter, LetterSpacing, LineHeight};
+pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight};
pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing};
pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle};
pub use self::time::Time;
@@ -106,8 +104,6 @@ pub mod easing;
pub mod effects;
pub mod flex;
pub mod font;
-#[cfg(feature = "gecko")]
-pub mod gecko;
pub mod image;
pub mod length;
pub mod list;
@@ -454,17 +450,12 @@ where
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
self.iter()
.map(|item| item.to_computed_value(context))
- .collect::<Vec<_>>()
- .into()
+ .collect()
}
#[inline]
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
- computed
- .iter()
- .map(T::from_computed_value)
- .collect::<Vec<_>>()
- .into()
+ computed.iter().map(T::from_computed_value).collect()
}
}
diff --git a/components/style/values/computed/motion.rs b/components/style/values/computed/motion.rs
index a5f1fa885c3..932d8074262 100644
--- a/components/style/values/computed/motion.rs
+++ b/components/style/values/computed/motion.rs
@@ -4,7 +4,41 @@
//! Computed types for CSS values that are related to motion path.
+use crate::values::computed::Angle;
+use crate::Zero;
+
/// A computed offset-path. The computed value is as specified value.
///
/// https://drafts.fxtf.org/motion-1/#offset-path-property
pub use crate::values::specified::motion::OffsetPath;
+
+#[inline]
+fn is_auto_zero_angle(auto: &bool, angle: &Angle) -> bool {
+ *auto && angle.is_zero()
+}
+
+/// A computed offset-rotate.
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)]
+#[repr(C)]
+pub struct OffsetRotate {
+ /// If auto is false, this is a fixed angle which indicates a
+ /// constant clockwise rotation transformation applied to it by this
+ /// specified rotation angle. Otherwise, the angle will be added to
+ /// the angle of the direction in layout.
+ #[css(represents_keyword)]
+ pub auto: bool,
+ /// The angle value.
+ #[css(contextual_skip_if = "is_auto_zero_angle")]
+ pub angle: Angle,
+}
+
+impl OffsetRotate {
+ /// Returns "auto 0deg".
+ #[inline]
+ pub fn auto() -> Self {
+ OffsetRotate {
+ auto: true,
+ angle: Zero::zero(),
+ }
+ }
+}
diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs
index c29d3d45210..bc4086a2b9c 100644
--- a/components/style/values/computed/text.rs
+++ b/components/style/values/computed/text.rs
@@ -20,7 +20,7 @@ use style_traits::{CssWriter, ToCss};
pub use crate::values::specified::TextAlignKeyword as TextAlign;
pub use crate::values::specified::TextTransform;
-pub use crate::values::specified::{OverflowWrap, WordBreak};
+pub use crate::values::specified::{LineBreak, OverflowWrap, WordBreak};
pub use crate::values::specified::{TextDecorationLine, TextEmphasisPosition};
/// A computed value for the `initial-letter` property.
@@ -105,6 +105,7 @@ impl ToComputedValue for specified::WordSpacing {
pub type LineHeight = GenericLineHeight<NonNegativeNumber, NonNegativeLength>;
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)]
+#[repr(C)]
/// text-overflow.
/// When the specified value only has one side, that's the "second"
/// side, and the sides are logical, so "second" means "end". The
diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs
index e23ec1524ff..9104a43ae5b 100644
--- a/components/style/values/computed/transform.rs
+++ b/components/style/values/computed/transform.rs
@@ -16,9 +16,9 @@ pub use crate::values::generics::transform::TransformStyle;
/// A single operation in a computed CSS `transform`
pub type TransformOperation =
- generic::TransformOperation<Angle, Number, Length, Integer, LengthPercentage>;
+ generic::GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>;
/// A computed CSS `transform`
-pub type Transform = generic::Transform<TransformOperation>;
+pub type Transform = generic::GenericTransform<TransformOperation>;
/// The computed value of a CSS `<transform-origin>`
pub type TransformOrigin =
@@ -540,88 +540,16 @@ impl ToAnimatedZero for Transform {
self.0
.iter()
.map(|op| op.to_animated_zero())
- .collect::<Result<Vec<_>, _>>()?,
+ .collect::<Result<crate::OwnedSlice<_>, _>>()?,
))
}
}
/// A computed CSS `rotate`
-pub type Rotate = generic::Rotate<Number, Angle>;
-
-impl Rotate {
- /// Convert TransformOperation to Rotate.
- pub fn to_transform_operation(&self) -> Option<TransformOperation> {
- match *self {
- generic::Rotate::None => None,
- generic::Rotate::Rotate(angle) => Some(generic::TransformOperation::Rotate(angle)),
- generic::Rotate::Rotate3D(rx, ry, rz, angle) => {
- Some(generic::TransformOperation::Rotate3D(rx, ry, rz, angle))
- },
- }
- }
-
- /// Convert Rotate to TransformOperation.
- pub fn from_transform_operation(operation: &TransformOperation) -> Rotate {
- match *operation {
- generic::TransformOperation::Rotate(angle) => generic::Rotate::Rotate(angle),
- generic::TransformOperation::Rotate3D(rx, ry, rz, angle) => {
- generic::Rotate::Rotate3D(rx, ry, rz, angle)
- },
- _ => unreachable!("Found unexpected value for rotate property"),
- }
- }
-}
+pub type Rotate = generic::GenericRotate<Number, Angle>;
/// A computed CSS `translate`
-pub type Translate = generic::Translate<LengthPercentage, Length>;
-
-impl Translate {
- /// Convert TransformOperation to Translate.
- pub fn to_transform_operation(&self) -> Option<TransformOperation> {
- match *self {
- generic::Translate::None => None,
- generic::Translate::Translate(tx, ty) => {
- Some(generic::TransformOperation::Translate(tx, ty))
- },
- generic::Translate::Translate3D(tx, ty, tz) => {
- Some(generic::TransformOperation::Translate3D(tx, ty, tz))
- },
- }
- }
-
- /// Convert Translate to TransformOperation.
- pub fn from_transform_operation(operation: &TransformOperation) -> Translate {
- match *operation {
- generic::TransformOperation::Translate(tx, ty) => generic::Translate::Translate(tx, ty),
- generic::TransformOperation::Translate3D(tx, ty, tz) => {
- generic::Translate::Translate3D(tx, ty, tz)
- },
- _ => unreachable!("Found unexpected value for translate"),
- }
- }
-}
+pub type Translate = generic::GenericTranslate<LengthPercentage, Length>;
/// A computed CSS `scale`
-pub type Scale = generic::Scale<Number>;
-
-impl Scale {
- /// Convert TransformOperation to Scale.
- pub fn to_transform_operation(&self) -> Option<TransformOperation> {
- match *self {
- generic::Scale::None => None,
- generic::Scale::Scale(sx, sy) => Some(generic::TransformOperation::Scale(sx, sy)),
- generic::Scale::Scale3D(sx, sy, sz) => {
- Some(generic::TransformOperation::Scale3D(sx, sy, sz))
- },
- }
- }
-
- /// Convert Scale to TransformOperation.
- pub fn from_transform_operation(operation: &TransformOperation) -> Scale {
- match *operation {
- generic::TransformOperation::Scale(sx, sy) => generic::Scale::Scale(sx, sy),
- generic::TransformOperation::Scale3D(sx, sy, sz) => generic::Scale::Scale3D(sx, sy, sz),
- _ => unreachable!("Found unexpected value for scale"),
- }
- }
-}
+pub type Scale = generic::GenericScale<Number>;
diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs
index ec0ab1c4b07..f36062ce39b 100644
--- a/components/style/values/generics/border.rs
+++ b/components/style/values/generics/border.rs
@@ -23,15 +23,18 @@ use style_traits::{CssWriter, ToCss};
ToResolvedValue,
ToShmem,
)]
-pub enum BorderImageSideWidth<LengthPercentage, Number> {
+#[repr(C, u8)]
+pub enum GenericBorderImageSideWidth<LP, N> {
/// `<length-or-percentage>`
- Length(LengthPercentage),
+ LengthPercentage(LP),
/// `<number>`
- Number(Number),
+ Number(N),
/// `auto`
Auto,
}
+pub use self::GenericBorderImageSideWidth as BorderImageSideWidth;
+
/// A generic value for the `border-image-slice` property.
#[derive(
Clone,
diff --git a/components/style/values/generics/effects.rs b/components/style/values/generics/effects.rs
index aa56fc1bbb3..a27adc49e52 100644
--- a/components/style/values/generics/effects.rs
+++ b/components/style/values/generics/effects.rs
@@ -19,9 +19,10 @@
ToResolvedValue,
ToShmem,
)]
-pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
+#[repr(C)]
+pub struct GenericBoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
/// The base shadow.
- pub base: SimpleShadow<Color, SizeLength, BlurShapeLength>,
+ pub base: GenericSimpleShadow<Color, SizeLength, BlurShapeLength>,
/// The spread radius.
pub spread: ShapeLength,
/// Whether this is an inset box shadow.
@@ -30,6 +31,8 @@ pub struct BoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> {
pub inset: bool,
}
+pub use self::GenericBoxShadow as BoxShadow;
+
/// A generic value for a single `filter`.
#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))]
#[animation(no_bound(Url))]
@@ -100,7 +103,8 @@ pub enum Filter<Angle, Factor, Length, DropShadow, Url> {
ToResolvedValue,
ToShmem,
)]
-pub struct SimpleShadow<Color, SizeLength, ShapeLength> {
+#[repr(C)]
+pub struct GenericSimpleShadow<Color, SizeLength, ShapeLength> {
/// Color.
pub color: Color,
/// Horizontal radius.
@@ -110,3 +114,5 @@ pub struct SimpleShadow<Color, SizeLength, ShapeLength> {
/// Blur radius.
pub blur: ShapeLength,
}
+
+pub use self::GenericSimpleShadow as SimpleShadow;
diff --git a/components/style/values/generics/gecko.rs b/components/style/values/generics/gecko.rs
deleted file mode 100644
index ccff3d2a76d..00000000000
--- a/components/style/values/generics/gecko.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-//! Generic types for legacy Gecko-only properties that should probably be
-//! un-shipped at some point in the future.
-
-/// A generic value for scroll snap points.
-#[cfg_attr(feature = "gecko", derive(MallocSizeOf))]
-#[derive(
- Clone,
- Copy,
- Debug,
- PartialEq,
- SpecifiedValueInfo,
- ToComputedValue,
- ToCss,
- ToResolvedValue,
- ToShmem,
-)]
-pub enum ScrollSnapPoint<LengthPercentage> {
- /// `none`
- None,
- /// `repeat(<length-or-percentage>)`
- #[css(function)]
- Repeat(LengthPercentage),
-}
-
-impl<L> ScrollSnapPoint<L> {
- /// Returns `none`.
- #[inline]
- pub fn none() -> Self {
- ScrollSnapPoint::None
- }
-
- /// Returns the repeat argument, if any.
- #[inline]
- pub fn repeated(&self) -> Option<&L> {
- match *self {
- ScrollSnapPoint::None => None,
- ScrollSnapPoint::Repeat(ref length) => Some(length),
- }
- }
-}
diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs
index d735e3bbdef..08ae15a4c2c 100644
--- a/components/style/values/generics/mod.rs
+++ b/components/style/values/generics/mod.rs
@@ -26,8 +26,6 @@ pub mod easing;
pub mod effects;
pub mod flex;
pub mod font;
-#[cfg(feature = "gecko")]
-pub mod gecko;
pub mod grid;
pub mod image;
pub mod length;
diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs
index 6c6374db941..ba0e320865a 100644
--- a/components/style/values/generics/transform.rs
+++ b/components/style/values/generics/transform.rs
@@ -30,8 +30,9 @@ use style_traits::{CssWriter, ToCss};
ToResolvedValue,
ToShmem,
)]
-#[css(comma, function)]
-pub struct Matrix<T> {
+#[css(comma, function = "matrix")]
+#[repr(C)]
+pub struct GenericMatrix<T> {
pub a: T,
pub b: T,
pub c: T,
@@ -40,6 +41,8 @@ pub struct Matrix<T> {
pub f: T,
}
+pub use self::GenericMatrix as Matrix;
+
#[allow(missing_docs)]
#[cfg_attr(rustfmt, rustfmt_skip)]
#[css(comma, function = "matrix3d")]
@@ -55,13 +58,16 @@ pub struct Matrix<T> {
ToResolvedValue,
ToShmem,
)]
-pub struct Matrix3D<T> {
+#[repr(C)]
+pub struct GenericMatrix3D<T> {
pub m11: T, pub m12: T, pub m13: T, pub m14: T,
pub m21: T, pub m22: T, pub m23: T, pub m24: T,
pub m31: T, pub m32: T, pub m33: T, pub m34: T,
pub m41: T, pub m42: T, pub m43: T, pub m44: T,
}
+pub use self::GenericMatrix3D as Matrix3D;
+
#[cfg_attr(rustfmt, rustfmt_skip)]
impl<T: Into<f64>> From<Matrix<T>> for Transform3D<f64> {
#[inline]
@@ -142,17 +148,19 @@ fn is_same<N: PartialEq>(x: &N, y: &N) -> bool {
ToResolvedValue,
ToShmem,
)]
+#[repr(C, u8)]
/// A single operation in the list of a `transform` value
-pub enum TransformOperation<Angle, Number, Length, Integer, LengthPercentage>
+/// cbindgen:derive-tagged-enum-copy-constructor=true
+pub enum GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>
where
Angle: Zero,
LengthPercentage: Zero,
Number: PartialEq,
{
/// Represents a 2D 2x3 matrix.
- Matrix(Matrix<Number>),
+ Matrix(GenericMatrix<Number>),
/// Represents a 3D 4x4 matrix.
- Matrix3D(Matrix3D<Number>),
+ Matrix3D(GenericMatrix3D<Number>),
/// A 2D skew.
///
/// If the second angle is not provided it is assumed zero.
@@ -232,20 +240,30 @@ where
#[allow(missing_docs)]
#[css(comma, function = "interpolatematrix")]
InterpolateMatrix {
- from_list: Transform<TransformOperation<Angle, Number, Length, Integer, LengthPercentage>>,
- to_list: Transform<TransformOperation<Angle, Number, Length, Integer, LengthPercentage>>,
+ from_list: GenericTransform<
+ GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>,
+ >,
+ to_list: GenericTransform<
+ GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>,
+ >,
progress: computed::Percentage,
},
/// A intermediate type for accumulation of mismatched transform lists.
#[allow(missing_docs)]
#[css(comma, function = "accumulatematrix")]
AccumulateMatrix {
- from_list: Transform<TransformOperation<Angle, Number, Length, Integer, LengthPercentage>>,
- to_list: Transform<TransformOperation<Angle, Number, Length, Integer, LengthPercentage>>,
+ from_list: GenericTransform<
+ GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>,
+ >,
+ to_list: GenericTransform<
+ GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage>,
+ >,
count: Integer,
},
}
+pub use self::GenericTransformOperation as TransformOperation;
+
#[derive(
Clone,
Debug,
@@ -257,8 +275,11 @@ where
ToResolvedValue,
ToShmem,
)]
+#[repr(C)]
/// A value of the `transform` property
-pub struct Transform<T>(#[css(if_empty = "none", iterable)] pub Vec<T>);
+pub struct GenericTransform<T>(#[css(if_empty = "none", iterable)] pub crate::OwnedSlice<T>);
+
+pub use self::GenericTransform as Transform;
impl<Angle, Number, Length, Integer, LengthPercentage>
TransformOperation<Angle, Number, Length, Integer, LengthPercentage>
@@ -497,7 +518,7 @@ where
impl<T> Transform<T> {
/// `none`
pub fn none() -> Self {
- Transform(vec![])
+ Transform(Default::default())
}
}
@@ -529,7 +550,7 @@ impl<T: ToMatrix> Transform<T> {
let mut transform = Transform3D::<f64>::identity();
let mut contain_3d = false;
- for operation in &self.0 {
+ for operation in &*self.0 {
let matrix = operation.to_3d_matrix(reference_box)?;
contain_3d |= operation.is_3d();
transform = transform.pre_mul(&matrix);
@@ -589,10 +610,11 @@ pub fn get_normalized_vector_and_angle<T: Zero>(
ToResolvedValue,
ToShmem,
)]
+#[repr(C, u8)]
/// A value of the `Rotate` property
///
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
-pub enum Rotate<Number, Angle> {
+pub enum GenericRotate<Number, Angle> {
/// 'none'
None,
/// '<angle>'
@@ -601,6 +623,8 @@ pub enum Rotate<Number, Angle> {
Rotate3D(Number, Number, Number, Angle),
}
+pub use self::GenericRotate as Rotate;
+
/// A trait to check if the current 3D vector is parallel to the DirectionVector.
/// This is especially for serialization on Rotate.
pub trait IsParallelTo {
@@ -660,10 +684,11 @@ where
ToResolvedValue,
ToShmem,
)]
+#[repr(C, u8)]
/// A value of the `Scale` property
///
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
-pub enum Scale<Number> {
+pub enum GenericScale<Number> {
/// 'none'
None,
/// '<number>{1,2}'
@@ -672,6 +697,8 @@ pub enum Scale<Number> {
Scale3D(Number, Number, Number),
}
+pub use self::GenericScale as Scale;
+
impl<Number: ToCss + PartialEq> ToCss for Scale<Number> {
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
@@ -710,6 +737,7 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> {
ToResolvedValue,
ToShmem,
)]
+#[repr(C, u8)]
/// A value of the `translate` property
///
/// https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization:
@@ -724,7 +752,7 @@ impl<Number: ToCss + PartialEq> ToCss for Scale<Number> {
/// related spec issue is https://github.com/w3c/csswg-drafts/issues/3305
///
/// <https://drafts.csswg.org/css-transforms-2/#individual-transforms>
-pub enum Translate<LengthPercentage, Length>
+pub enum GenericTranslate<LengthPercentage, Length>
where
LengthPercentage: Zero,
{
@@ -739,6 +767,8 @@ where
Translate3D(LengthPercentage, LengthPercentage, Length),
}
+pub use self::GenericTranslate as Translate;
+
#[allow(missing_docs)]
#[derive(
Clone,
diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs
index e2da4984084..36ea909ab87 100644
--- a/components/style/values/mod.rs
+++ b/components/style/values/mod.rs
@@ -174,6 +174,7 @@ impl<A: Debug, B: Debug> Debug for Either<A, B> {
ToResolvedValue,
ToShmem,
)]
+#[repr(C)]
pub struct CustomIdent(pub Atom);
impl CustomIdent {
diff --git a/components/style/values/specified/border.rs b/components/style/values/specified/border.rs
index 59f2f7aa284..338b0d18c27 100644
--- a/components/style/values/specified/border.rs
+++ b/components/style/values/specified/border.rs
@@ -183,7 +183,7 @@ impl Parse for BorderImageSideWidth {
}
if let Ok(len) = input.try(|i| NonNegativeLengthPercentage::parse(context, i)) {
- return Ok(GenericBorderImageSideWidth::Length(len));
+ return Ok(GenericBorderImageSideWidth::LengthPercentage(len));
}
let num = NonNegativeNumber::parse(context, input)?;
diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs
index 31a79c141e1..542976d45ba 100644
--- a/components/style/values/specified/box.rs
+++ b/components/style/values/specified/box.rs
@@ -642,6 +642,7 @@ pub enum OverflowClipBox {
#[derive(
Clone,
Debug,
+ Default,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
@@ -650,38 +651,38 @@ pub enum OverflowClipBox {
ToResolvedValue,
ToShmem,
)]
-/// Provides a rendering hint to the user agent,
-/// stating what kinds of changes the author expects
-/// to perform on the element
+#[css(comma)]
+#[repr(C)]
+/// Provides a rendering hint to the user agent, stating what kinds of changes
+/// the author expects to perform on the element.
+///
+/// `auto` is represented by an empty `features` list.
///
/// <https://drafts.csswg.org/css-will-change/#will-change>
-pub enum WillChange {
- /// Expresses no particular intent
- Auto,
- /// <custom-ident>
- #[css(comma)]
- AnimateableFeatures {
- /// The features that are supposed to change.
- #[css(iterable)]
- features: Box<[CustomIdent]>,
- /// A bitfield with the kind of change that the value will create, based
- /// on the above field.
- #[css(skip)]
- bits: WillChangeBits,
- },
+pub struct WillChange {
+ /// The features that are supposed to change.
+ ///
+ /// TODO(emilio): Consider using ArcSlice since we just clone them from the
+ /// specified value? That'd save an allocation, which could be worth it.
+ #[css(iterable, if_empty = "auto")]
+ features: crate::OwnedSlice<CustomIdent>,
+ /// A bitfield with the kind of change that the value will create, based
+ /// on the above field.
+ #[css(skip)]
+ bits: WillChangeBits,
}
impl WillChange {
#[inline]
/// Get default value of `will-change` as `auto`
- pub fn auto() -> WillChange {
- WillChange::Auto
+ pub fn auto() -> Self {
+ Self::default()
}
}
bitflags! {
/// The change bits that we care about.
- #[derive(MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
+ #[derive(Default, MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
#[repr(C)]
pub struct WillChangeBits: u8 {
/// Whether the stacking context will change.
@@ -746,7 +747,7 @@ impl Parse for WillChange {
.try(|input| input.expect_ident_matching("auto"))
.is_ok()
{
- return Ok(WillChange::Auto);
+ return Ok(Self::default());
}
let mut bits = WillChangeBits::empty();
@@ -767,8 +768,8 @@ impl Parse for WillChange {
Ok(ident)
})?;
- Ok(WillChange::AnimateableFeatures {
- features: custom_idents.into_boxed_slice(),
+ Ok(Self {
+ features: custom_idents.into(),
bits,
})
}
diff --git a/components/style/values/specified/effects.rs b/components/style/values/specified/effects.rs
index d8c378a8a7b..3ffad2fa89c 100644
--- a/components/style/values/specified/effects.rs
+++ b/components/style/values/specified/effects.rs
@@ -17,7 +17,7 @@ use crate::values::specified::color::Color;
use crate::values::specified::length::{Length, NonNegativeLength};
#[cfg(feature = "gecko")]
use crate::values::specified::url::SpecifiedUrl;
-use crate::values::specified::{Angle, NumberOrPercentage};
+use crate::values::specified::{Angle, Number, NumberOrPercentage};
#[cfg(not(feature = "gecko"))]
use crate::values::Impossible;
use crate::Zero;
@@ -62,6 +62,10 @@ impl Factor {
},
}
}
+
+ fn one() -> Self {
+ Factor(NumberOrPercentage::Number(Number::new(1.0)))
+ }
}
impl Parse for Factor {
@@ -209,34 +213,61 @@ impl Parse for Filter {
};
input.parse_nested_block(|i| {
match_ignore_ascii_case! { &*function,
- "blur" => Ok(GenericFilter::Blur((Length::parse_non_negative(context, i)?).into())),
- "brightness" => Ok(GenericFilter::Brightness(Factor::parse(context, i)?)),
- "contrast" => Ok(GenericFilter::Contrast(Factor::parse(context, i)?)),
+ "blur" => Ok(GenericFilter::Blur(
+ i.try(|i| NonNegativeLength::parse(context, i))
+ .unwrap_or(Zero::zero()),
+ )),
+ "brightness" => Ok(GenericFilter::Brightness(
+ i.try(|i| Factor::parse(context, i))
+ .unwrap_or(Factor::one()),
+ )),
+ "contrast" => Ok(GenericFilter::Contrast(
+ i.try(|i| Factor::parse(context, i))
+ .unwrap_or(Factor::one()),
+ )),
"grayscale" => {
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-grayscale
- Ok(GenericFilter::Grayscale(Factor::parse_with_clamping_to_one(context, i)?))
+ Ok(GenericFilter::Grayscale(
+ i.try(|i| Factor::parse_with_clamping_to_one(context, i))
+ .unwrap_or(Factor::one()),
+ ))
},
"hue-rotate" => {
// We allow unitless zero here, see:
// https://github.com/w3c/fxtf-drafts/issues/228
- Ok(GenericFilter::HueRotate(Angle::parse_with_unitless(context, i)?))
+ Ok(GenericFilter::HueRotate(
+ i.try(|i| Angle::parse_with_unitless(context, i))
+ .unwrap_or(Zero::zero()),
+ ))
},
"invert" => {
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-invert
- Ok(GenericFilter::Invert(Factor::parse_with_clamping_to_one(context, i)?))
+ Ok(GenericFilter::Invert(
+ i.try(|i| Factor::parse_with_clamping_to_one(context, i))
+ .unwrap_or(Factor::one()),
+ ))
},
"opacity" => {
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-opacity
- Ok(GenericFilter::Opacity(Factor::parse_with_clamping_to_one(context, i)?))
+ Ok(GenericFilter::Opacity(
+ i.try(|i| Factor::parse_with_clamping_to_one(context, i))
+ .unwrap_or(Factor::one()),
+ ))
},
- "saturate" => Ok(GenericFilter::Saturate(Factor::parse(context, i)?)),
+ "saturate" => Ok(GenericFilter::Saturate(
+ i.try(|i| Factor::parse(context, i))
+ .unwrap_or(Factor::one()),
+ )),
"sepia" => {
// Values of amount over 100% are allowed but UAs must clamp the values to 1.
// https://drafts.fxtf.org/filter-effects/#funcdef-filter-sepia
- Ok(GenericFilter::Sepia(Factor::parse_with_clamping_to_one(context, i)?))
+ Ok(GenericFilter::Sepia(
+ i.try(|i| Factor::parse_with_clamping_to_one(context, i))
+ .unwrap_or(Factor::one()),
+ ))
},
"drop-shadow" => Ok(GenericFilter::DropShadow(Parse::parse(context, i)?)),
_ => Err(location.new_custom_error(
diff --git a/components/style/values/specified/gecko.rs b/components/style/values/specified/gecko.rs
index 42ca5e3e2bf..131c2a1a314 100644
--- a/components/style/values/specified/gecko.rs
+++ b/components/style/values/specified/gecko.rs
@@ -7,33 +7,12 @@
use crate::parser::{Parse, ParserContext};
use crate::values::computed::length::CSSPixelLength;
use crate::values::computed::{self, LengthPercentage};
-use crate::values::generics::gecko::ScrollSnapPoint as GenericScrollSnapPoint;
use crate::values::generics::rect::Rect;
-use crate::values::specified::length::LengthPercentage as SpecifiedLengthPercentage;
use cssparser::{Parser, Token};
use std::fmt;
use style_traits::values::SequenceWriter;
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
-/// A specified type for scroll snap points.
-pub type ScrollSnapPoint = GenericScrollSnapPoint<SpecifiedLengthPercentage>;
-
-impl Parse for ScrollSnapPoint {
- fn parse<'i, 't>(
- context: &ParserContext,
- input: &mut Parser<'i, 't>,
- ) -> Result<Self, ParseError<'i>> {
- if input.try(|i| i.expect_ident_matching("none")).is_ok() {
- return Ok(GenericScrollSnapPoint::None);
- }
- input.expect_function_matching("repeat")?;
- // FIXME(emilio): This won't clamp properly when animating.
- let length = input
- .parse_nested_block(|i| SpecifiedLengthPercentage::parse_non_negative(context, i))?;
- Ok(GenericScrollSnapPoint::Repeat(length))
- }
-}
-
fn parse_pixel_or_percent<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs
index 8c1e9fa2ad4..0519053b902 100644
--- a/components/style/values/specified/list.rs
+++ b/components/style/values/specified/list.rs
@@ -10,7 +10,6 @@ use crate::values::generics::CounterStyleOrNone;
#[cfg(feature = "gecko")]
use crate::values::CustomIdent;
use cssparser::{Parser, Token};
-use servo_arc::Arc;
use style_traits::{ParseError, StyleParseErrorKind};
/// Specified and computed `list-style-type` property.
@@ -96,18 +95,20 @@ impl Parse for ListStyleType {
ToResolvedValue,
ToShmem,
)]
+#[repr(C)]
pub struct QuotePair {
/// The opening quote.
- pub opening: Box<str>,
+ pub opening: crate::OwnedStr,
/// The closing quote.
- pub closing: Box<str>,
+ pub closing: crate::OwnedStr,
}
/// Specified and computed `quotes` property.
#[derive(
Clone,
Debug,
+ Default,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
@@ -116,10 +117,11 @@ pub struct QuotePair {
ToResolvedValue,
ToShmem,
)]
+#[repr(C)]
pub struct Quotes(
#[css(iterable, if_empty = "none")]
#[ignore_malloc_size_of = "Arc"]
- pub Arc<Box<[QuotePair]>>,
+ pub crate::ArcSlice<QuotePair>,
);
impl Parse for Quotes {
@@ -131,24 +133,24 @@ impl Parse for Quotes {
.try(|input| input.expect_ident_matching("none"))
.is_ok()
{
- return Ok(Quotes(Arc::new(Box::new([]))));
+ return Ok(Self::default());
}
let mut quotes = Vec::new();
loop {
let location = input.current_source_location();
let opening = match input.next() {
- Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into_boxed_str(),
+ Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into(),
Ok(t) => return Err(location.new_unexpected_token_error(t.clone())),
Err(_) => break,
};
- let closing = input.expect_string()?.as_ref().to_owned().into_boxed_str();
+ let closing = input.expect_string()?.as_ref().to_owned().into();
quotes.push(QuotePair { opening, closing });
}
if !quotes.is_empty() {
- Ok(Quotes(Arc::new(quotes.into_boxed_slice())))
+ Ok(Quotes(crate::ArcSlice::from_iter(quotes.into_iter())))
} 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 83fc71444bb..409f5abe161 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -54,8 +54,6 @@ 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;
pub use self::image::{ColorStop, EndingShape as GradientEndingShape, Gradient};
pub use self::image::{GradientItem, GradientKind, Image, ImageLayer, MozImageRect};
pub use self::length::{AbsoluteLength, CalcLengthPercentage, CharacterWidth};
@@ -68,7 +66,7 @@ pub use self::length::{NonNegativeLengthPercentage, NonNegativeLengthPercentageO
pub use self::list::ListStyleType;
pub use self::list::MozListReversed;
pub use self::list::{QuotePair, Quotes};
-pub use self::motion::OffsetPath;
+pub use self::motion::{OffsetPath, OffsetRotate};
pub use self::outline::OutlineStyle;
pub use self::percentage::Percentage;
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position};
@@ -81,7 +79,7 @@ pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth};
pub use self::svg_path::SVGPathData;
pub use self::table::XSpan;
pub use self::text::TextTransform;
-pub use self::text::{InitialLetter, LetterSpacing, LineHeight, TextAlign};
+pub use self::text::{InitialLetter, LetterSpacing, LineBreak, LineHeight, TextAlign};
pub use self::text::{OverflowWrap, TextEmphasisPosition, TextEmphasisStyle, WordBreak};
pub use self::text::{TextAlignKeyword, TextDecorationLine, TextOverflow, WordSpacing};
pub use self::time::Time;
diff --git a/components/style/values/specified/motion.rs b/components/style/values/specified/motion.rs
index 7d72796397e..97609ea20b0 100644
--- a/components/style/values/specified/motion.rs
+++ b/components/style/values/specified/motion.rs
@@ -5,13 +5,17 @@
//! Specified types for CSS values that are related to motion path.
use crate::parser::{Parse, ParserContext};
-use crate::values::specified::SVGPathData;
+use crate::values::computed::motion::OffsetRotate as ComputedOffsetRotate;
+use crate::values::computed::{Context, ToComputedValue};
+use crate::values::specified::{Angle, SVGPathData};
+use crate::Zero;
use cssparser::Parser;
use style_traits::{ParseError, StyleParseErrorKind};
/// The offset-path value.
///
/// https://drafts.fxtf.org/motion-1/#offset-path-property
+/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(
Animate,
Clone,
@@ -26,6 +30,7 @@ use style_traits::{ParseError, StyleParseErrorKind};
ToResolvedValue,
ToShmem,
)]
+#[repr(C, u8)]
pub enum OffsetPath {
// We could merge SVGPathData into ShapeSource, so we could reuse them. However,
// we don't want to support other value for offset-path, so use SVGPathData only for now.
@@ -73,3 +78,104 @@ impl Parse for OffsetPath {
})
}
}
+
+/// The direction of offset-rotate.
+#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
+#[repr(u8)]
+pub enum OffsetRotateDirection {
+ /// Unspecified direction keyword.
+ #[css(skip)]
+ None,
+ /// 0deg offset (face forward).
+ Auto,
+ /// 180deg offset (face backward).
+ Reverse,
+}
+
+impl OffsetRotateDirection {
+ /// Returns true if it is none (i.e. the keyword is not specified).
+ #[inline]
+ fn is_none(&self) -> bool {
+ *self == OffsetRotateDirection::None
+ }
+}
+
+#[inline]
+fn direction_specified_and_angle_is_zero(direction: &OffsetRotateDirection, angle: &Angle) -> bool {
+ !direction.is_none() && angle.is_zero()
+}
+
+/// The specified offset-rotate.
+/// The syntax is: "[ auto | reverse ] || <angle>"
+///
+/// https://drafts.fxtf.org/motion-1/#offset-rotate-property
+#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
+pub struct OffsetRotate {
+ /// [auto | reverse].
+ #[css(skip_if = "OffsetRotateDirection::is_none")]
+ direction: OffsetRotateDirection,
+ /// <angle>.
+ /// If direction is None, this is a fixed angle which indicates a
+ /// constant clockwise rotation transformation applied to it by this
+ /// specified rotation angle. Otherwise, the angle will be added to
+ /// the angle of the direction in layout.
+ #[css(contextual_skip_if = "direction_specified_and_angle_is_zero")]
+ angle: Angle,
+}
+
+impl Parse for OffsetRotate {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ let location = input.current_source_location();
+ let mut direction = input.try(OffsetRotateDirection::parse);
+ let angle = input.try(|i| Angle::parse(context, i));
+ if direction.is_err() {
+ // The direction and angle could be any order, so give it a change to parse
+ // direction again.
+ direction = input.try(OffsetRotateDirection::parse);
+ }
+
+ if direction.is_err() && angle.is_err() {
+ return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
+ }
+
+ Ok(OffsetRotate {
+ direction: direction.unwrap_or(OffsetRotateDirection::None),
+ angle: angle.unwrap_or(Zero::zero()),
+ })
+ }
+}
+
+impl ToComputedValue for OffsetRotate {
+ type ComputedValue = ComputedOffsetRotate;
+
+ #[inline]
+ fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
+ use crate::values::computed::Angle as ComputedAngle;
+
+ ComputedOffsetRotate {
+ auto: !self.direction.is_none(),
+ angle: if self.direction == OffsetRotateDirection::Reverse {
+ // The computed value should always convert "reverse" into "auto".
+ // e.g. "reverse calc(20deg + 10deg)" => "auto 210deg"
+ self.angle.to_computed_value(context) + ComputedAngle::from_degrees(180.0)
+ } else {
+ self.angle.to_computed_value(context)
+ },
+ }
+ }
+
+ #[inline]
+ fn from_computed_value(computed: &Self::ComputedValue) -> Self {
+ OffsetRotate {
+ direction: if computed.auto {
+ OffsetRotateDirection::Auto
+ } else {
+ OffsetRotateDirection::None
+ },
+ angle: ToComputedValue::from_computed_value(&computed.angle),
+ }
+ }
+}
diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs
index dd4990782a0..578870a4a91 100644
--- a/components/style/values/specified/svg.rs
+++ b/components/style/values/specified/svg.rs
@@ -12,7 +12,7 @@ use crate::values::specified::AllowQuirks;
use crate::values::specified::LengthPercentage;
use crate::values::specified::{NonNegativeLengthPercentage, Opacity};
use crate::values::CustomIdent;
-use cssparser::Parser;
+use cssparser::{Parser, Token};
use std::fmt::{self, Write};
use style_traits::{CommaWithSpace, CssWriter, ParseError, Separator};
use style_traits::{StyleParseErrorKind, ToCss};
@@ -243,11 +243,28 @@ impl ToCss for SVGPaintOrder {
}
}
+bitflags! {
+ /// The context properties we understand.
+ #[derive(Default, MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)]
+ #[repr(C)]
+ pub struct ContextPropertyBits: u8 {
+ /// `fill`
+ const FILL = 1 << 0;
+ /// `stroke`
+ const STROKE = 1 << 1;
+ /// `fill-opacity`
+ const FILL_OPACITY = 1 << 2;
+ /// `stroke-opacity`
+ const STROKE_OPACITY = 1 << 3;
+ }
+}
+
/// Specified MozContextProperties value.
/// Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)
#[derive(
Clone,
Debug,
+ Default,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
@@ -256,19 +273,61 @@ impl ToCss for SVGPaintOrder {
ToResolvedValue,
ToShmem,
)]
-pub struct MozContextProperties(pub CustomIdent);
+#[repr(C)]
+pub struct MozContextProperties {
+ #[css(iterable, if_empty = "none")]
+ #[ignore_malloc_size_of = "Arc"]
+ idents: crate::ArcSlice<CustomIdent>,
+ #[css(skip)]
+ bits: ContextPropertyBits,
+}
impl Parse for MozContextProperties {
fn parse<'i, 't>(
_context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<MozContextProperties, ParseError<'i>> {
- let location = input.current_source_location();
- let i = input.expect_ident()?;
- Ok(MozContextProperties(CustomIdent::from_ident(
- location,
- i,
- &["all", "none", "auto"],
- )?))
+ let mut values = vec![];
+ let mut bits = ContextPropertyBits::empty();
+ loop {
+ {
+ let location = input.current_source_location();
+ let ident = input.expect_ident()?;
+
+ if ident.eq_ignore_ascii_case("none") && values.is_empty() {
+ return Ok(Self::default());
+ }
+
+ let ident = CustomIdent::from_ident(location, ident, &["all", "none", "auto"])?;
+
+ if ident.0 == atom!("fill") {
+ bits.insert(ContextPropertyBits::FILL);
+ } else if ident.0 == atom!("stroke") {
+ bits.insert(ContextPropertyBits::STROKE);
+ } else if ident.0 == atom!("fill-opacity") {
+ bits.insert(ContextPropertyBits::FILL_OPACITY);
+ } else if ident.0 == atom!("stroke-opacity") {
+ bits.insert(ContextPropertyBits::STROKE_OPACITY);
+ }
+
+ values.push(ident);
+ }
+
+ let location = input.current_source_location();
+ match input.next() {
+ Ok(&Token::Comma) => continue,
+ Err(..) => break,
+ Ok(other) => return Err(location.new_unexpected_token_error(other.clone())),
+ }
+ }
+
+ if values.is_empty() {
+ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
+ }
+
+ Ok(MozContextProperties {
+ idents: crate::ArcSlice::from_iter(values.into_iter()),
+ bits,
+ })
}
}
diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs
index 6be20f58618..188eb18f720 100644
--- a/components/style/values/specified/text.rs
+++ b/components/style/values/specified/text.rs
@@ -134,14 +134,16 @@ impl ToComputedValue for LineHeight {
}
/// A generic value for the `text-overflow` property.
+/// cbindgen:derive-tagged-enum-copy-constructor=true
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
+#[repr(C, u8)]
pub enum TextOverflowSide {
/// Clip inline content.
Clip,
/// Render ellipsis to represent clipped inline content.
Ellipsis,
/// Render a given string to represent clipped inline content.
- String(Box<str>),
+ String(crate::OwnedStr),
}
impl Parse for TextOverflowSide {
@@ -160,9 +162,9 @@ impl Parse for TextOverflowSide {
))
}
},
- Token::QuotedString(ref v) => Ok(TextOverflowSide::String(
- v.as_ref().to_owned().into_boxed_str(),
- )),
+ Token::QuotedString(ref v) => {
+ Ok(TextOverflowSide::String(v.as_ref().to_owned().into()))
+ },
ref t => Err(location.new_unexpected_token_error(t.clone())),
}
}
@@ -1005,6 +1007,31 @@ pub enum WordBreak {
BreakWord,
}
+/// Values for the `line-break` property.
+#[repr(u8)]
+#[derive(
+ Clone,
+ Copy,
+ Debug,
+ Eq,
+ MallocSizeOf,
+ Parse,
+ PartialEq,
+ SpecifiedValueInfo,
+ ToComputedValue,
+ ToCss,
+ ToResolvedValue,
+ ToShmem,
+)]
+#[allow(missing_docs)]
+pub enum LineBreak {
+ Auto,
+ Loose,
+ Normal,
+ Strict,
+ Anywhere,
+}
+
/// Values for the `overflow-wrap` property.
#[repr(u8)]
#[derive(
diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs
index a4dc87d3217..e942cf13085 100644
--- a/components/style/values/specified/transform.rs
+++ b/components/style/values/specified/transform.rs
@@ -42,183 +42,187 @@ impl Transform {
.try(|input| input.expect_ident_matching("none"))
.is_ok()
{
- return Ok(generic::Transform(Vec::new()));
+ return Ok(generic::Transform::none());
}
- Ok(generic::Transform(Space::parse(input, |input| {
- let function = input.expect_function()?.clone();
- input.parse_nested_block(|input| {
- let location = input.current_source_location();
- let result = match_ignore_ascii_case! { &function,
- "matrix" => {
- let a = Number::parse(context, input)?;
- input.expect_comma()?;
- let b = Number::parse(context, input)?;
- input.expect_comma()?;
- let c = Number::parse(context, input)?;
- input.expect_comma()?;
- let d = Number::parse(context, input)?;
- input.expect_comma()?;
- // Standard matrix parsing.
- let e = Number::parse(context, input)?;
- input.expect_comma()?;
- let f = Number::parse(context, input)?;
- Ok(generic::TransformOperation::Matrix(Matrix { a, b, c, d, e, f }))
- },
- "matrix3d" => {
- let m11 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m12 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m13 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m14 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m21 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m22 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m23 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m24 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m31 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m32 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m33 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m34 = Number::parse(context, input)?;
- input.expect_comma()?;
- // Standard matrix3d parsing.
- let m41 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m42 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m43 = Number::parse(context, input)?;
- input.expect_comma()?;
- let m44 = Number::parse(context, input)?;
- Ok(generic::TransformOperation::Matrix3D(Matrix3D {
- m11, m12, m13, m14,
- m21, m22, m23, m24,
- m31, m32, m33, m34,
- m41, m42, m43, m44,
- }))
- },
- "translate" => {
- let sx = specified::LengthPercentage::parse(context, input)?;
- if input.try(|input| input.expect_comma()).is_ok() {
- let sy = specified::LengthPercentage::parse(context, input)?;
- Ok(generic::TransformOperation::Translate(sx, sy))
- } else {
- Ok(generic::TransformOperation::Translate(sx, Zero::zero()))
- }
- },
- "translatex" => {
- let tx = specified::LengthPercentage::parse(context, input)?;
- Ok(generic::TransformOperation::TranslateX(tx))
- },
- "translatey" => {
- let ty = specified::LengthPercentage::parse(context, input)?;
- Ok(generic::TransformOperation::TranslateY(ty))
- },
- "translatez" => {
- let tz = specified::Length::parse(context, input)?;
- Ok(generic::TransformOperation::TranslateZ(tz))
- },
- "translate3d" => {
- let tx = specified::LengthPercentage::parse(context, input)?;
- input.expect_comma()?;
- let ty = specified::LengthPercentage::parse(context, input)?;
- input.expect_comma()?;
- let tz = specified::Length::parse(context, input)?;
- Ok(generic::TransformOperation::Translate3D(tx, ty, tz))
- },
- "scale" => {
- let sx = Number::parse(context, input)?;
- if input.try(|input| input.expect_comma()).is_ok() {
+ Ok(generic::Transform(
+ Space::parse(input, |input| {
+ let function = input.expect_function()?.clone();
+ input.parse_nested_block(|input| {
+ let location = input.current_source_location();
+ let result = match_ignore_ascii_case! { &function,
+ "matrix" => {
+ let a = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let b = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let c = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let d = Number::parse(context, input)?;
+ input.expect_comma()?;
+ // Standard matrix parsing.
+ let e = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let f = Number::parse(context, input)?;
+ Ok(generic::TransformOperation::Matrix(Matrix { a, b, c, d, e, f }))
+ },
+ "matrix3d" => {
+ let m11 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m12 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m13 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m14 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m21 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m22 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m23 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m24 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m31 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m32 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m33 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m34 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ // Standard matrix3d parsing.
+ let m41 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m42 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m43 = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let m44 = Number::parse(context, input)?;
+ Ok(generic::TransformOperation::Matrix3D(Matrix3D {
+ m11, m12, m13, m14,
+ m21, m22, m23, m24,
+ m31, m32, m33, m34,
+ m41, m42, m43, m44,
+ }))
+ },
+ "translate" => {
+ let sx = specified::LengthPercentage::parse(context, input)?;
+ if input.try(|input| input.expect_comma()).is_ok() {
+ let sy = specified::LengthPercentage::parse(context, input)?;
+ Ok(generic::TransformOperation::Translate(sx, sy))
+ } else {
+ Ok(generic::TransformOperation::Translate(sx, Zero::zero()))
+ }
+ },
+ "translatex" => {
+ let tx = specified::LengthPercentage::parse(context, input)?;
+ Ok(generic::TransformOperation::TranslateX(tx))
+ },
+ "translatey" => {
+ let ty = specified::LengthPercentage::parse(context, input)?;
+ Ok(generic::TransformOperation::TranslateY(ty))
+ },
+ "translatez" => {
+ let tz = specified::Length::parse(context, input)?;
+ Ok(generic::TransformOperation::TranslateZ(tz))
+ },
+ "translate3d" => {
+ let tx = specified::LengthPercentage::parse(context, input)?;
+ input.expect_comma()?;
+ let ty = specified::LengthPercentage::parse(context, input)?;
+ input.expect_comma()?;
+ let tz = specified::Length::parse(context, input)?;
+ Ok(generic::TransformOperation::Translate3D(tx, ty, tz))
+ },
+ "scale" => {
+ let sx = Number::parse(context, input)?;
+ if input.try(|input| input.expect_comma()).is_ok() {
+ let sy = Number::parse(context, input)?;
+ Ok(generic::TransformOperation::Scale(sx, sy))
+ } else {
+ Ok(generic::TransformOperation::Scale(sx, sx))
+ }
+ },
+ "scalex" => {
+ let sx = Number::parse(context, input)?;
+ Ok(generic::TransformOperation::ScaleX(sx))
+ },
+ "scaley" => {
let sy = Number::parse(context, input)?;
- Ok(generic::TransformOperation::Scale(sx, sy))
- } else {
- Ok(generic::TransformOperation::Scale(sx, sx))
- }
- },
- "scalex" => {
- let sx = Number::parse(context, input)?;
- Ok(generic::TransformOperation::ScaleX(sx))
- },
- "scaley" => {
- let sy = Number::parse(context, input)?;
- Ok(generic::TransformOperation::ScaleY(sy))
- },
- "scalez" => {
- let sz = Number::parse(context, input)?;
- Ok(generic::TransformOperation::ScaleZ(sz))
- },
- "scale3d" => {
- let sx = Number::parse(context, input)?;
- input.expect_comma()?;
- let sy = Number::parse(context, input)?;
- input.expect_comma()?;
- let sz = Number::parse(context, input)?;
- Ok(generic::TransformOperation::Scale3D(sx, sy, sz))
- },
- "rotate" => {
- let theta = specified::Angle::parse_with_unitless(context, input)?;
- Ok(generic::TransformOperation::Rotate(theta))
- },
- "rotatex" => {
- let theta = specified::Angle::parse_with_unitless(context, input)?;
- Ok(generic::TransformOperation::RotateX(theta))
- },
- "rotatey" => {
- let theta = specified::Angle::parse_with_unitless(context, input)?;
- Ok(generic::TransformOperation::RotateY(theta))
- },
- "rotatez" => {
- let theta = specified::Angle::parse_with_unitless(context, input)?;
- Ok(generic::TransformOperation::RotateZ(theta))
- },
- "rotate3d" => {
- let ax = Number::parse(context, input)?;
- input.expect_comma()?;
- let ay = Number::parse(context, input)?;
- input.expect_comma()?;
- let az = Number::parse(context, input)?;
- input.expect_comma()?;
- let theta = specified::Angle::parse_with_unitless(context, input)?;
- // TODO(gw): Check that the axis can be normalized.
- Ok(generic::TransformOperation::Rotate3D(ax, ay, az, theta))
- },
- "skew" => {
- let ax = specified::Angle::parse_with_unitless(context, input)?;
- if input.try(|input| input.expect_comma()).is_ok() {
- let ay = specified::Angle::parse_with_unitless(context, input)?;
- Ok(generic::TransformOperation::Skew(ax, ay))
- } else {
- Ok(generic::TransformOperation::Skew(ax, Zero::zero()))
- }
- },
- "skewx" => {
- let theta = specified::Angle::parse_with_unitless(context, input)?;
- Ok(generic::TransformOperation::SkewX(theta))
- },
- "skewy" => {
- let theta = specified::Angle::parse_with_unitless(context, input)?;
- Ok(generic::TransformOperation::SkewY(theta))
- },
- "perspective" => {
- let d = specified::Length::parse_non_negative(context, input)?;
- Ok(generic::TransformOperation::Perspective(d))
- },
- _ => Err(()),
- };
- result.map_err(|()| {
- location
- .new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone()))
+ Ok(generic::TransformOperation::ScaleY(sy))
+ },
+ "scalez" => {
+ let sz = Number::parse(context, input)?;
+ Ok(generic::TransformOperation::ScaleZ(sz))
+ },
+ "scale3d" => {
+ let sx = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let sy = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let sz = Number::parse(context, input)?;
+ Ok(generic::TransformOperation::Scale3D(sx, sy, sz))
+ },
+ "rotate" => {
+ let theta = specified::Angle::parse_with_unitless(context, input)?;
+ Ok(generic::TransformOperation::Rotate(theta))
+ },
+ "rotatex" => {
+ let theta = specified::Angle::parse_with_unitless(context, input)?;
+ Ok(generic::TransformOperation::RotateX(theta))
+ },
+ "rotatey" => {
+ let theta = specified::Angle::parse_with_unitless(context, input)?;
+ Ok(generic::TransformOperation::RotateY(theta))
+ },
+ "rotatez" => {
+ let theta = specified::Angle::parse_with_unitless(context, input)?;
+ Ok(generic::TransformOperation::RotateZ(theta))
+ },
+ "rotate3d" => {
+ let ax = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let ay = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let az = Number::parse(context, input)?;
+ input.expect_comma()?;
+ let theta = specified::Angle::parse_with_unitless(context, input)?;
+ // TODO(gw): Check that the axis can be normalized.
+ Ok(generic::TransformOperation::Rotate3D(ax, ay, az, theta))
+ },
+ "skew" => {
+ let ax = specified::Angle::parse_with_unitless(context, input)?;
+ if input.try(|input| input.expect_comma()).is_ok() {
+ let ay = specified::Angle::parse_with_unitless(context, input)?;
+ Ok(generic::TransformOperation::Skew(ax, ay))
+ } else {
+ Ok(generic::TransformOperation::Skew(ax, Zero::zero()))
+ }
+ },
+ "skewx" => {
+ let theta = specified::Angle::parse_with_unitless(context, input)?;
+ Ok(generic::TransformOperation::SkewX(theta))
+ },
+ "skewy" => {
+ let theta = specified::Angle::parse_with_unitless(context, input)?;
+ Ok(generic::TransformOperation::SkewY(theta))
+ },
+ "perspective" => {
+ let d = specified::Length::parse_non_negative(context, input)?;
+ Ok(generic::TransformOperation::Perspective(d))
+ },
+ _ => Err(()),
+ };
+ result.map_err(|()| {
+ location.new_custom_error(StyleParseErrorKind::UnexpectedFunction(
+ function.clone(),
+ ))
+ })
})
- })
- })?))
+ })?
+ .into(),
+ ))
}
}
diff --git a/components/style_traits/Cargo.toml b/components/style_traits/Cargo.toml
index 846579d462c..acf46422861 100644
--- a/components/style_traits/Cargo.toml
+++ b/components/style_traits/Cargo.toml
@@ -18,6 +18,7 @@ app_units = "0.7"
cssparser = "0.25"
bitflags = "1.0"
euclid = "0.19"
+lazy_static = "1"
malloc_size_of = { path = "../malloc_size_of" }
malloc_size_of_derive = "0.1"
selectors = { path = "../selectors" }
diff --git a/components/style_traits/arc_slice.rs b/components/style_traits/arc_slice.rs
index dd1b99d3424..6a151e3dc5a 100644
--- a/components/style_traits/arc_slice.rs
+++ b/components/style_traits/arc_slice.rs
@@ -5,16 +5,19 @@
//! A thin atomically-reference-counted slice.
use servo_arc::ThinArc;
-use std::mem;
use std::ops::Deref;
use std::ptr::NonNull;
+use std::{iter, mem};
/// A canary that we stash in ArcSlices.
///
/// Given we cannot use a zero-sized-type for the header, since well, C++
/// doesn't have zsts, and we want to use cbindgen for this type, we may as well
/// assert some sanity at runtime.
-const ARC_SLICE_CANARY: u32 = 0xf3f3f3f3;
+///
+/// We use an u64, to guarantee that we can use a single singleton for every
+/// empty slice, even if the types they hold are aligned differently.
+const ARC_SLICE_CANARY: u64 = 0xf3f3f3f3f3f3f3f3;
/// A wrapper type for a refcounted slice using ThinArc.
///
@@ -22,7 +25,7 @@ const ARC_SLICE_CANARY: u32 = 0xf3f3f3f3;
/// cbindgen:derive-neq=false
#[repr(C)]
#[derive(Clone, Debug, Eq, PartialEq, ToShmem)]
-pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u32, T>);
+pub struct ArcSlice<T>(#[shmem(field_bound)] ThinArc<u64, T>);
impl<T> Deref for ArcSlice<T> {
type Target = [T];
@@ -34,12 +37,28 @@ impl<T> Deref for ArcSlice<T> {
}
}
-/// The inner pointer of an ArcSlice<T>, to be sent via FFI.
-/// The type of the pointer is a bit of a lie, we just want to preserve the type
-/// but these pointers cannot be constructed outside of this crate, so we're
-/// good.
-#[repr(C)]
-pub struct ForgottenArcSlicePtr<T>(NonNull<T>);
+lazy_static! {
+ // ThinArc doesn't support alignments greater than align_of::<u64>.
+ static ref EMPTY_ARC_SLICE: ArcSlice<u64> = {
+ ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, iter::empty()))
+ };
+}
+
+impl<T> Default for ArcSlice<T> {
+ #[allow(unsafe_code)]
+ fn default() -> Self {
+ debug_assert!(
+ mem::align_of::<T>() <= mem::align_of::<u64>(),
+ "Need to increase the alignment of EMPTY_ARC_SLICE"
+ );
+ unsafe {
+ let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone();
+ let empty: Self = mem::transmute(empty);
+ debug_assert_eq!(empty.len(), 0);
+ empty
+ }
+ }
+}
impl<T> ArcSlice<T> {
/// Creates an Arc for a slice using the given iterator to generate the
@@ -49,6 +68,9 @@ impl<T> ArcSlice<T> {
where
I: Iterator<Item = T> + ExactSizeIterator,
{
+ if items.len() == 0 {
+ return Self::default();
+ }
ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items))
}
@@ -63,4 +85,21 @@ impl<T> ArcSlice<T> {
mem::forget(self);
ret
}
+
+ /// Leaks an empty arc slice pointer, and returns it. Only to be used to
+ /// construct ArcSlices from FFI.
+ #[inline]
+ pub fn leaked_empty_ptr() -> *mut std::os::raw::c_void {
+ let empty: ArcSlice<_> = EMPTY_ARC_SLICE.clone();
+ let ptr = empty.0.ptr();
+ std::mem::forget(empty);
+ ptr as *mut _
+ }
}
+
+/// The inner pointer of an ArcSlice<T>, to be sent via FFI.
+/// The type of the pointer is a bit of a lie, we just want to preserve the type
+/// but these pointers cannot be constructed outside of this crate, so we're
+/// good.
+#[repr(C)]
+pub struct ForgottenArcSlicePtr<T>(NonNull<T>);
diff --git a/components/style_traits/lib.rs b/components/style_traits/lib.rs
index d4a907fa956..4e89f6fdf67 100644
--- a/components/style_traits/lib.rs
+++ b/components/style_traits/lib.rs
@@ -16,6 +16,8 @@ extern crate bitflags;
#[macro_use]
extern crate cssparser;
extern crate euclid;
+#[macro_use]
+extern crate lazy_static;
extern crate malloc_size_of;
#[macro_use]
extern crate malloc_size_of_derive;
@@ -91,6 +93,7 @@ pub mod values;
#[macro_use]
pub mod viewport;
pub mod owned_slice;
+pub mod owned_str;
pub use crate::specified_value_info::{CssType, KeywordsCollectFn, SpecifiedValueInfo};
pub use crate::values::{
@@ -149,8 +152,6 @@ pub enum StyleParseErrorKind<'i> {
/// The property declaration was for an unknown property.
UnknownProperty(CowRcStr<'i>),
- /// An unknown vendor-specific identifier was encountered.
- UnknownVendorProperty,
/// The property declaration was for a disabled experimental property.
ExperimentalProperty,
/// The property declaration contained an invalid color value.
diff --git a/components/style_traits/owned_slice.rs b/components/style_traits/owned_slice.rs
index f2b0de4a4a0..33d3ac1c2ab 100644
--- a/components/style_traits/owned_slice.rs
+++ b/components/style_traits/owned_slice.rs
@@ -10,7 +10,7 @@ use malloc_size_of::{MallocShallowSizeOf, MallocSizeOf, MallocSizeOfOps};
use std::marker::PhantomData;
use std::ops::{Deref, DerefMut};
use std::ptr::NonNull;
-use std::{fmt, mem, slice};
+use std::{fmt, iter, mem, slice};
use to_shmem::{SharedMemoryBuilder, ToShmem};
/// A struct that basically replaces a `Box<[T]>`, but which cbindgen can
@@ -93,7 +93,7 @@ impl<T: Sized> OwnedSlice<T> {
/// Iterate over all the elements in the slice taking ownership of them.
#[inline]
- pub fn into_iter(self) -> impl Iterator<Item = T> {
+ pub fn into_iter(self) -> impl Iterator<Item = T> + ExactSizeIterator {
self.into_vec().into_iter()
}
@@ -164,3 +164,10 @@ impl<T: ToShmem + Sized> ToShmem for OwnedSlice<T> {
}
}
}
+
+impl<T> iter::FromIterator<T> for OwnedSlice<T> {
+ #[inline]
+ fn from_iter<I: IntoIterator<Item = T>>(iter: I) -> Self {
+ Vec::from_iter(iter).into()
+ }
+}
diff --git a/components/style_traits/owned_str.rs b/components/style_traits/owned_str.rs
new file mode 100644
index 00000000000..42a83a07713
--- /dev/null
+++ b/components/style_traits/owned_str.rs
@@ -0,0 +1,53 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
+
+#![allow(unsafe_code)]
+
+//! A replacement for `Box<str>` that has a defined layout for FFI.
+
+use crate::owned_slice::OwnedSlice;
+use std::fmt;
+use std::ops::{Deref, DerefMut};
+
+/// A struct that basically replaces a Box<str>, but with a defined layout,
+/// suitable for FFI.
+#[repr(C)]
+#[derive(Clone, Default, Eq, MallocSizeOf, PartialEq, ToShmem)]
+pub struct OwnedStr(OwnedSlice<u8>);
+
+impl fmt::Debug for OwnedStr {
+ fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
+ self.deref().fmt(formatter)
+ }
+}
+
+impl Deref for OwnedStr {
+ type Target = str;
+
+ #[inline(always)]
+ fn deref(&self) -> &Self::Target {
+ unsafe { std::str::from_utf8_unchecked(&*self.0) }
+ }
+}
+
+impl DerefMut for OwnedStr {
+ #[inline(always)]
+ fn deref_mut(&mut self) -> &mut Self::Target {
+ unsafe { std::str::from_utf8_unchecked_mut(&mut *self.0) }
+ }
+}
+
+impl From<Box<str>> for OwnedStr {
+ #[inline]
+ fn from(b: Box<str>) -> Self {
+ Self::from(b.into_string())
+ }
+}
+
+impl From<String> for OwnedStr {
+ #[inline]
+ fn from(s: String) -> Self {
+ OwnedStr(s.into_bytes().into())
+ }
+}
diff --git a/components/style_traits/specified_value_info.rs b/components/style_traits/specified_value_info.rs
index 63a7b71d990..5aaf64ac955 100644
--- a/components/style_traits/specified_value_info.rs
+++ b/components/style_traits/specified_value_info.rs
@@ -5,6 +5,7 @@
//! Value information for devtools.
use crate::arc_slice::ArcSlice;
+use crate::owned_slice::OwnedSlice;
use servo_arc::Arc;
use std::ops::Range;
use std::sync::Arc as StdArc;
@@ -83,6 +84,7 @@ impl SpecifiedValueInfo for u16 {}
impl SpecifiedValueInfo for u32 {}
impl SpecifiedValueInfo for str {}
impl SpecifiedValueInfo for String {}
+impl SpecifiedValueInfo for crate::owned_str::OwnedStr {}
#[cfg(feature = "servo")]
impl SpecifiedValueInfo for ::servo_atoms::Atom {}
@@ -114,6 +116,7 @@ macro_rules! impl_generic_specified_value_info {
};
}
impl_generic_specified_value_info!(Option<T>);
+impl_generic_specified_value_info!(OwnedSlice<T>);
impl_generic_specified_value_info!(Vec<T>);
impl_generic_specified_value_info!(Arc<T>);
impl_generic_specified_value_info!(StdArc<T>);
diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs
index 5c3f3ab255d..0c3166858a2 100644
--- a/components/style_traits/values.rs
+++ b/components/style_traits/values.rs
@@ -75,6 +75,16 @@ where
}
}
+impl ToCss for crate::owned_str::OwnedStr {
+ #[inline]
+ fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
+ where
+ W: Write,
+ {
+ serialize_string(self, dest)
+ }
+}
+
impl ToCss for str {
#[inline]
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
diff --git a/tests/unit/style/animated_properties.rs b/tests/unit/style/animated_properties.rs
index dd233f01b89..fd03a1904e8 100644
--- a/tests/unit/style/animated_properties.rs
+++ b/tests/unit/style/animated_properties.rs
@@ -4,7 +4,6 @@
use cssparser::RGBA;
use style::values::animated::{Animate, Procedure, ToAnimatedValue};
-use style::values::generics::transform::{Transform, TransformOperation};
fn interpolate_rgba(from: RGBA, to: RGBA, progress: f64) -> RGBA {
let from = from.to_animated_value();
@@ -81,14 +80,3 @@ fn test_rgba_color_interepolation_out_of_range_clamped_2() {
RGBA::from_floats(0.0, 0.0, 0.0, 0.0)
);
}
-
-#[test]
-fn test_transform_interpolation_on_scale() {
- let from = Transform(vec![TransformOperation::Scale3D(1.0, 2.0, 1.0)]);
- let to = Transform(vec![TransformOperation::Scale3D(2.0, 4.0, 2.0)]);
- assert_eq!(
- from.animate(&to, Procedure::Interpolate { progress: 0.5 })
- .unwrap(),
- Transform(vec![TransformOperation::Scale3D(1.5, 3.0, 1.5)])
- );
-}
diff --git a/tests/unit/style/parsing/animation.rs b/tests/unit/style/parsing/animation.rs
deleted file mode 100644
index f67d77e9afd..00000000000
--- a/tests/unit/style/parsing/animation.rs
+++ /dev/null
@@ -1,43 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
-
-use crate::parsing::parse;
-use servo_atoms::Atom;
-use style::parser::Parse;
-use style::properties::longhands::animation_name;
-use style::values::specified::AnimationIterationCount;
-use style::values::{CustomIdent, KeyframesName};
-use style_traits::ToCss;
-
-#[test]
-fn test_animation_name() {
- use self::animation_name::single_value::SpecifiedValue as SingleValue;
- let other_name = Atom::from("other-name");
- assert_eq!(
- parse_longhand!(animation_name, "none"),
- animation_name::SpecifiedValue(vec![SingleValue(None)])
- );
- assert_eq!(
- parse_longhand!(
- animation_name,
- "other-name, none, 'other-name', \"other-name\""
- ),
- animation_name::SpecifiedValue(vec![
- SingleValue(Some(KeyframesName::Ident(CustomIdent(other_name.clone())))),
- SingleValue(None),
- SingleValue(Some(KeyframesName::QuotedString(other_name.clone()))),
- SingleValue(Some(KeyframesName::QuotedString(other_name.clone())))
- ])
- );
-}
-
-#[test]
-fn test_animation_iteration() {
- assert_roundtrip_with_context!(AnimationIterationCount::parse, "0", "0");
- assert_roundtrip_with_context!(AnimationIterationCount::parse, "0.1", "0.1");
- assert_roundtrip_with_context!(AnimationIterationCount::parse, "infinite", "infinite");
-
- // Negative numbers are invalid
- assert!(parse(AnimationIterationCount::parse, "-1").is_err());
-}
diff --git a/tests/unit/style/parsing/mod.rs b/tests/unit/style/parsing/mod.rs
index 095f74c9603..aff8d1fc47c 100644
--- a/tests/unit/style/parsing/mod.rs
+++ b/tests/unit/style/parsing/mod.rs
@@ -133,7 +133,6 @@ macro_rules! parse_longhand {
};
}
-mod animation;
mod background;
mod border;
mod box_;
diff --git a/tests/unit/style/stylesheets.rs b/tests/unit/style/stylesheets.rs
index fe8a7b84269..c6b02f37eda 100644
--- a/tests/unit/style/stylesheets.rs
+++ b/tests/unit/style/stylesheets.rs
@@ -194,7 +194,7 @@ fn test_parse_stylesheet() {
PropertyDeclaration::BackgroundPositionX(
longhands::background_position_x::SpecifiedValue(vec![
PositionComponent::zero(),
- ]),
+ ].into()),
),
Importance::Normal,
),
@@ -202,7 +202,7 @@ fn test_parse_stylesheet() {
PropertyDeclaration::BackgroundPositionY(
longhands::background_position_y::SpecifiedValue(vec![
PositionComponent::zero(),
- ]),
+ ].into()),
),
Importance::Normal,
),
@@ -210,7 +210,7 @@ fn test_parse_stylesheet() {
PropertyDeclaration::BackgroundRepeat(
longhands::background_repeat::SpecifiedValue(
vec![longhands::background_repeat::single_value
- ::get_initial_specified_value()],
+ ::get_initial_specified_value()].into(),
),
),
Importance::Normal,
@@ -219,7 +219,7 @@ fn test_parse_stylesheet() {
PropertyDeclaration::BackgroundAttachment(
longhands::background_attachment::SpecifiedValue(
vec![longhands::background_attachment::single_value
- ::get_initial_specified_value()],
+ ::get_initial_specified_value()].into(),
),
),
Importance::Normal,
@@ -228,7 +228,7 @@ fn test_parse_stylesheet() {
PropertyDeclaration::BackgroundImage(
longhands::background_image::SpecifiedValue(
vec![longhands::background_image::single_value
- ::get_initial_specified_value()],
+ ::get_initial_specified_value()].into(),
),
),
Importance::Normal,
@@ -237,7 +237,7 @@ fn test_parse_stylesheet() {
PropertyDeclaration::BackgroundSize(
longhands::background_size::SpecifiedValue(
vec![longhands::background_size::single_value
- ::get_initial_specified_value()],
+ ::get_initial_specified_value()].into(),
),
),
Importance::Normal,
@@ -246,7 +246,7 @@ fn test_parse_stylesheet() {
PropertyDeclaration::BackgroundOrigin(
longhands::background_origin::SpecifiedValue(
vec![longhands::background_origin::single_value
- ::get_initial_specified_value()],
+ ::get_initial_specified_value()].into(),
),
),
Importance::Normal,
@@ -255,7 +255,7 @@ fn test_parse_stylesheet() {
PropertyDeclaration::BackgroundClip(
longhands::background_clip::SpecifiedValue(
vec![longhands::background_clip::single_value
- ::get_initial_specified_value()],
+ ::get_initial_specified_value()].into(),
),
),
Importance::Normal,
diff --git a/tests/wpt/metadata/css/filter-effects/filters-test-brightness-003.html.ini b/tests/wpt/metadata/css/filter-effects/filters-test-brightness-003.html.ini
deleted file mode 100644
index df5382158af..00000000000
--- a/tests/wpt/metadata/css/filter-effects/filters-test-brightness-003.html.ini
+++ /dev/null
@@ -1,2 +0,0 @@
-[filters-test-brightness-003.html]
- expected: FAIL
diff --git a/tests/wpt/metadata/css/filter-effects/parsing/filter-computed.html.ini b/tests/wpt/metadata/css/filter-effects/parsing/filter-computed.html.ini
index 5ba47d10857..9b57d470e5b 100644
--- a/tests/wpt/metadata/css/filter-effects/parsing/filter-computed.html.ini
+++ b/tests/wpt/metadata/css/filter-effects/parsing/filter-computed.html.ini
@@ -2,42 +2,15 @@
[Property filter value 'brightness()' computes to 'brightness(0)']
expected: FAIL
- [Property filter value 'sepia()' computes to 'sepia(1)']
- expected: FAIL
-
- [Property filter value 'saturate()' computes to 'saturate(1)']
- expected: FAIL
-
- [Property filter value 'grayscale()' computes to 'grayscale(1)']
- expected: FAIL
-
[Property filter value 'invert()' computes to 'invert(0)']
expected: FAIL
- [Property filter value 'hue-rotate()' computes to 'hue-rotate(0deg)']
- expected: FAIL
-
[Property filter value 'drop-shadow(1px 2px)' computes to 'drop-shadow(rgb(0, 255, 0) 1px 2px 0px)']
expected: FAIL
- [Property filter value 'blur()' computes to 'blur(0px)']
- expected: FAIL
-
[Property filter value 'drop-shadow(rgb(4, 5, 6) 1px 2px 0px)' computes to 'drop-shadow(rgb(4, 5, 6) 1px 2px 0px)']
expected: FAIL
[Property filter value 'blur(10px) url("https://www.example.com/picture.svg#f") contrast(20) brightness(30)' computes to 'blur(10px) url("https://www.example.com/picture.svg#f") contrast(20) brightness(30)']
expected: FAIL
- [Property filter value 'opacity()' computes to 'opacity(1)']
- expected: FAIL
-
- [Property filter value 'contrast()' computes to 'contrast(1)']
- expected: FAIL
-
- [Property filter value 'brightness()' computes to 'brightness(1)']
- expected: FAIL
-
- [Property filter value 'invert()' computes to 'invert(1)']
- expected: FAIL
-
diff --git a/tests/wpt/metadata/css/filter-effects/parsing/filter-parsing-valid.html.ini b/tests/wpt/metadata/css/filter-effects/parsing/filter-parsing-valid.html.ini
index 274ce737462..b8ca47ff7b3 100644
--- a/tests/wpt/metadata/css/filter-effects/parsing/filter-parsing-valid.html.ini
+++ b/tests/wpt/metadata/css/filter-effects/parsing/filter-parsing-valid.html.ini
@@ -59,30 +59,3 @@
[Serialization should round-trip after setting e.style['filter'\] = "drop-shadow(rgba(4, 5, 6, 0.75) 1px 2px 3px)"]
expected: FAIL
- [e.style['filter'\] = "saturate()" should set the property value]
- expected: FAIL
-
- [e.style['filter'\] = "grayscale()" should set the property value]
- expected: FAIL
-
- [e.style['filter'\] = "sepia()" should set the property value]
- expected: FAIL
-
- [e.style['filter'\] = "blur()" should set the property value]
- expected: FAIL
-
- [e.style['filter'\] = "contrast()" should set the property value]
- expected: FAIL
-
- [e.style['filter'\] = "invert()" should set the property value]
- expected: FAIL
-
- [e.style['filter'\] = "brightness()" should set the property value]
- expected: FAIL
-
- [e.style['filter'\] = "opacity()" should set the property value]
- expected: FAIL
-
- [e.style['filter'\] = "hue-rotate()" should set the property value]
- expected: FAIL
-