From 3a22bb6c495182f6607a90e20b88deb05cb558f6 Mon Sep 17 00:00:00 2001 From: Cameron McCormack Date: Tue, 14 May 2019 05:00:45 +0000 Subject: [PATCH 01/44] style: Add Gecko profiler labels for when the style threads are doing work. Differential Revision: https://phabricator.services.mozilla.com/D30869 --- components/style/Cargo.toml | 1 + components/style/driver.rs | 1 + components/style/gecko/mod.rs | 2 + components/style/gecko/profiler.rs | 76 ++++++++++++++++++++++++++++++ components/style/macros.rs | 30 ++++++++++++ components/style/parallel.rs | 2 + 6 files changed, 112 insertions(+) create mode 100644 components/style/gecko/profiler.rs diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index bf953a13f8f..ed6e76907fd 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" 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( let drain = discovered.drain(..); pool.install(|| { rayon::scope(|scope| { + profiler_label!(Style); parallel::traverse_nodes( drain, DispatchMode::TailCall, diff --git a/components/style/gecko/mod.rs b/components/style/gecko/mod.rs index fb332dcce6e..43d38d7dbc1 100644 --- a/components/style/gecko/mod.rs +++ b/components/style/gecko/mod.rs @@ -13,6 +13,8 @@ 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; diff --git a/components/style/gecko/profiler.rs b/components/style/gecko/profiler.rs new file mode 100644 index 00000000000..92ad068284e --- /dev/null +++ b/components/style/gecko/profiler.rs @@ -0,0 +1,76 @@ +/* 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/macros.rs b/components/style/macros.rs index 22f1966071b..1ab2fe0720e 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -104,3 +104,33 @@ 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 = 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) }); From b61eb84d96af471f1df2558fb746f46598104df7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 15 May 2019 08:57:36 +0000 Subject: [PATCH 02/44] style: Use ManuallyDrop for style structs. We destroy them manually, so it's the right thing to do. This allows us to not run destructors of any members of nsStyle*, which in turn allows us to: * Remove the hack that replaced all nsStrings for nsStringReprs. * Remove ns{,C}StringRepr (followup) * Add members with destructors to the style structs (you see where I'm going :)). Differential Revision: https://phabricator.services.mozilla.com/D30450 --- components/style/properties/gecko.mako.rs | 90 ++++++++++++----------- 1 file changed, 46 insertions(+), 44 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 703cbed2c0b..fb651e7eb62 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -50,7 +50,7 @@ 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}; @@ -1095,10 +1095,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 { - 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 +1108,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 } } @@ -1545,8 +1545,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 +1567,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) { + fn set_line_names(servo_names: &[CustomIdent], gecko_names: &mut nsTArray) { unsafe { bindings::Gecko_ResizeTArrayForStrings(gecko_names, servo_names.len() as u32); } @@ -1693,7 +1694,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 +1705,7 @@ fn static_assert() { }; #[inline] - fn to_boxed_customident_slice(gecko_names: &nsTArray) -> Box<[CustomIdent]> { + fn to_boxed_customident_slice(gecko_names: &nsTArray) -> Box<[CustomIdent]> { let idents: Vec = gecko_names.iter().map(|gecko_name| { CustomIdent(Atom::from(gecko_name.to_string())) }).collect(); @@ -1712,7 +1713,7 @@ fn static_assert() { } #[inline] - fn to_line_names_vec(gecko_line_names: &nsTArray>) + fn to_line_names_vec(gecko_line_names: &nsTArray>) -> Vec> { gecko_line_names.iter().map(|gecko_names| { to_boxed_customident_slice(gecko_names) @@ -2129,14 +2130,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); } } @@ -2519,7 +2520,7 @@ fn static_assert() { <%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) }; + unsafe { bindings::Gecko_StyleDisplay_GenerateCombinedTransform(&mut *self.gecko) }; } #[inline] @@ -2836,12 +2837,12 @@ fn static_assert() { match v { WillChange::AnimateableFeatures { features, bits } => { unsafe { - Gecko_ClearWillChange(&mut self.gecko, features.len()); + Gecko_ClearWillChange(&mut *self.gecko, features.len()); } for feature in features.iter() { unsafe { - Gecko_AppendWillChange(&mut self.gecko, feature.0.as_ptr()) + Gecko_AppendWillChange(&mut *self.gecko, feature.0.as_ptr()) } } @@ -2849,7 +2850,7 @@ fn static_assert() { }, WillChange::Auto => { unsafe { - Gecko_ClearWillChange(&mut self.gecko, 0); + Gecko_ClearWillChange(&mut *self.gecko, 0); } self.gecko.mWillChangeBitField = WillChangeBits::empty(); }, @@ -2861,7 +2862,7 @@ fn static_assert() { self.gecko.mWillChangeBitField = other.gecko.mWillChangeBitField; unsafe { - Gecko_CopyWillChangeFrom(&mut self.gecko, &other.gecko); + Gecko_CopyWillChangeFrom(&mut *self.gecko, &*other.gecko); } } @@ -3307,13 +3308,13 @@ fn static_assert() { 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 +3323,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) { @@ -3644,7 +3645,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()); @@ -3690,7 +3691,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); } } @@ -4139,7 +4140,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 +4149,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 +4158,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) | @@ -4204,19 +4205,20 @@ clip-path { let v = v.into_iter(); unsafe { - bindings::Gecko_nsStyleSVG_SetContextPropertiesLength(&mut self.gecko, v.len() as u32); + 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) { + let s = &mut *self.gecko; + s.mContextPropsBits = 0; + for (gecko, servo) in s.mContextProps.iter_mut().zip(v) { if (servo.0).0 == atom!("fill") { - self.gecko.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_FILL as u8; + s.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; + s.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; + s.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; + s.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_STROKE_OPACITY as u8; } gecko.mRawPtr = (servo.0).0.into_addrefed(); } @@ -4225,7 +4227,7 @@ clip-path #[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); + bindings::Gecko_nsStyleSVG_CopyContextProperties(&mut *self.gecko, &*other.gecko); } } @@ -4242,7 +4244,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 +4270,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); } } @@ -4387,20 +4389,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 +4483,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) } } @@ -4575,7 +4577,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 +4589,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) } } From ab8776a144baea462b9ad182855cdd62a6c000be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:21:37 +0000 Subject: [PATCH 03/44] style: Use OwnedSlice in the specified and computed values of most vector properties. This is just a refactor in the right direction. Eventual goal is: * All inherited properties use ArcSlice<>. * All reset properties use OwnedSlice<> (or ThinVec<>). No conversion happens at all, so we can remove all that glue, and also compute_iter and co. Of course there's work to do, but this is a step towards that. Differential Revision: https://phabricator.services.mozilla.com/D30127 --- components/style/properties/gecko.mako.rs | 46 ++++++++--------- components/style/properties/helpers.mako.rs | 49 +++++++------------ .../helpers/animated_properties.mako.rs | 1 + .../properties/shorthands/background.mako.rs | 49 +++++++++---------- .../style/properties/shorthands/box.mako.rs | 4 +- .../style/properties/shorthands/svg.mako.rs | 41 ++++++++-------- components/style/values/computed/mod.rs | 6 +-- components/style_traits/owned_slice.rs | 9 +++- .../style_traits/specified_value_info.rs | 2 + 9 files changed, 100 insertions(+), 107 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index fb651e7eb62..85345cb141b 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3714,42 +3714,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()).mArray[0].to_simple_shadow() + }) }, 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()) } @@ -3793,8 +3792,9 @@ fn static_assert() { ${impl_keyword('text_align', 'mTextAlign', text_align_keyword)} pub fn set_text_shadow(&mut self, v: I) - where I: IntoIterator, - I::IntoIter: ExactSizeIterator + where + I: IntoIterator, + I::IntoIter: ExactSizeIterator { let v = v.into_iter(); self.gecko.mTextShadow.replace_with_new(v.len() as u32); @@ -3812,8 +3812,8 @@ fn static_assert() { } 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) + let buf = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow()).collect::>(); + longhands::text_shadow::computed_value::List(buf.into()) } fn clear_text_emphasis_style_if_string(&mut self) { diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 8310d537f36..f7effdc5077 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -113,10 +113,8 @@ pub mod computed_value { 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; @@ -144,14 +142,16 @@ #[css(if_empty = "none", iterable)] % endif % if allow_empty and allow_empty != "NotInitial": - pub Vec, + pub crate::OwnedSlice, % else: + // FIXME(emilio): Add an OwnedNonEmptySlice type, and figure out + // something for transition-name, which is the only remaining + // user of NotInitial. pub SmallVec<[T; 1]>, % 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. @@ -191,21 +191,10 @@ } % endif + /// The computed value, effectively a list of single values. pub type T = List; 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; - % 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 +208,12 @@ % else: #[css(if_empty = "none", iterable)] % endif - pub Vec, + pub crate::OwnedSlice, ); 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,20 +228,21 @@ 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; 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> { @@ -265,14 +255,13 @@ #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - computed_value::List(self.compute_iter(context).collect()) + computed_value::List(self.0.iter().map(|i| i.to_computed_value(context)).collect()) } #[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()) } } diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index aa2d0247e82..1b536d24e8b 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -773,6 +773,7 @@ macro_rules! animated_list_impl { } } +animated_list_impl!( for crate::OwnedSlice); animated_list_impl!( for SmallVec<[T; 1]>); animated_list_impl!( for Vec); 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> { // 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/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/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> { % 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> { // 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/values/computed/mod.rs b/components/style/values/computed/mod.rs index 5bf0333dbfe..993af4177ad 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -454,8 +454,7 @@ where fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { self.iter() .map(|item| item.to_computed_value(context)) - .collect::>() - .into() + .collect() } #[inline] @@ -463,8 +462,7 @@ where computed .iter() .map(T::from_computed_value) - .collect::>() - .into() + .collect() } } diff --git a/components/style_traits/owned_slice.rs b/components/style_traits/owned_slice.rs index f2b0de4a4a0..9ddd56fc7e1 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 @@ -164,3 +164,10 @@ impl ToShmem for OwnedSlice { } } } + +impl iter::FromIterator for OwnedSlice { + #[inline] + fn from_iter>(iter: I) -> Self { + Vec::from_iter(iter).into() + } +} diff --git a/components/style_traits/specified_value_info.rs b/components/style_traits/specified_value_info.rs index 63a7b71d990..95f8821cef5 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; @@ -114,6 +115,7 @@ macro_rules! impl_generic_specified_value_info { }; } impl_generic_specified_value_info!(Option); +impl_generic_specified_value_info!(OwnedSlice); impl_generic_specified_value_info!(Vec); impl_generic_specified_value_info!(Arc); impl_generic_specified_value_info!(StdArc); From 5e4fdf647df1e8186d35f06786eb92f607fff436 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:22:04 +0000 Subject: [PATCH 04/44] style: Implement ArcSlice::default(). Share a singleton to avoid allocating for empty lists. Differential Revision: https://phabricator.services.mozilla.com/D30543 --- components/servo_arc/lib.rs | 23 +++++++------- components/style_traits/Cargo.toml | 1 + components/style_traits/arc_slice.rs | 47 ++++++++++++++++++++++------ components/style_traits/lib.rs | 2 ++ 4 files changed, 52 insertions(+), 21 deletions(-) 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 Arc> { use std::mem::{align_of, size_of}; assert_ne!(size_of::(), 0, "Need to think about ZST"); + let inner_align = align_of::>>(); + debug_assert!(inner_align >= align_of::()); + // 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::>>(); - // 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 Arc> { let ptr: *mut ArcInner>; unsafe { // Allocate the buffer. - let layout = if mem::align_of::() <= mem::align_of::() { - Layout::from_size_align_unchecked(size, mem::align_of::()) - } else if mem::align_of::() <= mem::align_of::() { - // On 32-bit platforms may have 8 byte alignment while usize has 4 byte aligment. - // Use u64 to avoid over-alignment. + let layout = if inner_align <= align_of::() { + Layout::from_size_align_unchecked(size, align_of::()) + } else if inner_align <= align_of::() { + // On 32-bit platforms 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::()) + Layout::from_size_align_unchecked(size, align_of::()) } else { panic!("Over-aligned type not handled"); }; @@ -689,7 +688,7 @@ impl Arc> { // for some padding from the alignment. debug_assert!( (buffer.offset(size as isize) as usize - current as *mut u8 as usize) < - align_of::() + inner_align ); } assert!( 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..1541d4be3d9 100644 --- a/components/style_traits/arc_slice.rs +++ b/components/style_traits/arc_slice.rs @@ -5,7 +5,7 @@ //! A thin atomically-reference-counted slice. use servo_arc::ThinArc; -use std::mem; +use std::{iter, mem}; use std::ops::Deref; use std::ptr::NonNull; @@ -14,7 +14,10 @@ use std::ptr::NonNull; /// 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(#[shmem(field_bound)] ThinArc); +pub struct ArcSlice(#[shmem(field_bound)] ThinArc); impl Deref for ArcSlice { type Target = [T]; @@ -34,12 +37,28 @@ impl Deref for ArcSlice { } } -/// The inner pointer of an ArcSlice, 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(NonNull); +lazy_static! { + // ThinArc doesn't support alignments greater than align_of::. + static ref EMPTY_ARC_SLICE: ArcSlice = { + ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, iter::empty())) + }; +} + +impl Default for ArcSlice { + #[allow(unsafe_code)] + fn default() -> Self { + debug_assert!( + mem::align_of::() <= mem::align_of::(), + "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 ArcSlice { /// Creates an Arc for a slice using the given iterator to generate the @@ -49,6 +68,9 @@ impl ArcSlice { where I: Iterator + ExactSizeIterator, { + if items.len() == 0 { + return Self::default(); + } ArcSlice(ThinArc::from_header_and_iter(ARC_SLICE_CANARY, items)) } @@ -64,3 +86,10 @@ impl ArcSlice { ret } } + +/// The inner pointer of an ArcSlice, 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(NonNull); diff --git a/components/style_traits/lib.rs b/components/style_traits/lib.rs index d4a907fa956..0ba13082fc3 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; From 2bc4c42d4533db11759b49a2159082343f34ec52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:03:27 +0000 Subject: [PATCH 05/44] style: Use an ArcSlice as the computed value representation of inherited list properties. This adds a bit of complexity, which I think will pay off in the end. Removals incoming. Differential Revision: https://phabricator.services.mozilla.com/D30544 --- components/style/properties/gecko.mako.rs | 21 ++- components/style/properties/helpers.mako.rs | 139 ++++++++++++++++-- .../longhands/inherited_svg.mako.rs | 1 - components/style_traits/owned_slice.rs | 2 +- 4 files changed, 135 insertions(+), 28 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 85345cb141b..2f223fd971a 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3811,9 +3811,10 @@ fn static_assert() { self.copy_text_shadow_from(other) } + // FIXME(emilio): Remove by sharing representation. 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.into()) + let iter = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow()); + longhands::text_shadow::computed_value::List(crate::ArcSlice::from_iter(iter)) } fn clear_text_emphasis_style_if_string(&mut self) { @@ -4185,16 +4186,14 @@ clip-path self.gecko.mContextProps.len() } + // FIXME(emilio): Remove by sharing representation. #[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) - }) - ) + pub fn clone__moz_context_properties(&self) -> longhands::_moz_context_properties::computed_value::T { + use crate::values::specified::svg::MozContextProperties; + let buf = self.gecko.mContextProps.iter().map(|v| { + MozContextProperties(CustomIdent(unsafe { Atom::from_raw(v.mRawPtr) })) + }).collect::>(); + longhands::_moz_context_properties::computed_value::List(crate::ArcSlice::from_iter(buf.into_iter())) } #[allow(non_snake_case)] diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index f7effdc5077..808c10b0504 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -80,6 +80,16 @@ We assume that the default/initial value is an empty vector for these. `initial_value` need not be defined for these. + +// 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. +// <%def name="vector_longhand(name, animation_value_type=None, vector_animation_type=None, allow_empty=False, separator='Comma', @@ -111,6 +121,10 @@ /// 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 not allow_empty or allow_empty == "NotInitial": @@ -118,7 +132,32 @@ % 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 = + % if allow_empty and allow_empty != "NotInitial": + % if data.longhands_by_name[name].style_struct.inherited: + crate::ArcSlice; + % else: + crate::OwnedSlice; + % endif + % else: + SmallVec<[T; 1]>; + % endif + + pub type UnderlyingOwnedList = + % if allow_empty and allow_empty != "NotInitial": + crate::OwnedSlice; + % 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 @@ -135,22 +174,69 @@ ToResolvedValue, ToCss, )] - pub struct List( + pub struct OwnedList( % if not allow_empty: #[css(iterable)] % else: #[css(if_empty = "none", iterable)] % endif - % if allow_empty and allow_empty != "NotInitial": - pub crate::OwnedSlice, - % else: - // FIXME(emilio): Add an OwnedNonEmptySlice type, and figure out - // something for transition-name, which is the only remaining - // user of NotInitial. - pub SmallVec<[T; 1]>, - % endif + pub UnderlyingOwnedList, ); + /// The computed value for this property. + % if not is_shared_list: + pub type ComputedList = OwnedList; + 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: + #[css(if_empty = "none", iterable)] + % endif + % if is_shared_list: + #[ignore_malloc_size_of = "Arc"] + % endif + pub UnderlyingList, + ); + + type ResolvedList = OwnedList<::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 vector_animation_type: % if not animation_value_type: @@ -158,13 +244,31 @@ % 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 = as ToAnimatedValue>::AnimatedValue; + type AnimatedList = OwnedList<::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 { Err(()) } @@ -176,7 +280,7 @@ other: &Self, procedure: Procedure, ) -> Result { - Ok(List( + Ok(OwnedList( self.0.animate_${vector_animation_type}(&other.0, procedure)? )) } @@ -192,7 +296,7 @@ % endif /// The computed value, effectively a list of single values. - pub type T = List; + pub use self::ComputedList as T; pub type Iter<'a, 'cx, 'cx_a> = ComputedVecIter<'a, 'cx, 'cx_a, super::single_value::SpecifiedValue>; } @@ -255,7 +359,12 @@ #[inline] fn to_computed_value(&self, context: &Context) -> computed_value::T { - computed_value::List(self.0.iter().map(|i| i.to_computed_value(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] diff --git a/components/style/properties/longhands/inherited_svg.mako.rs b/components/style/properties/longhands/inherited_svg.mako.rs index 2bbdc2794c2..b4ad07f4dc0 100644 --- a/components/style/properties/longhands/inherited_svg.mako.rs +++ b/components/style/properties/longhands/inherited_svg.mako.rs @@ -196,7 +196,6 @@ ${helpers.predefined_type( "MozContextProperties", initial_value=None, vector=True, - need_index=True, animation_value_type="none", products="gecko", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)", diff --git a/components/style_traits/owned_slice.rs b/components/style_traits/owned_slice.rs index 9ddd56fc7e1..33d3ac1c2ab 100644 --- a/components/style_traits/owned_slice.rs +++ b/components/style_traits/owned_slice.rs @@ -93,7 +93,7 @@ impl OwnedSlice { /// Iterate over all the elements in the slice taking ownership of them. #[inline] - pub fn into_iter(self) -> impl Iterator { + pub fn into_iter(self) -> impl Iterator + ExactSizeIterator { self.into_vec().into_iter() } From bbc77e39773e7c3ca37e177998d3e4c4059ac5c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:03:29 +0000 Subject: [PATCH 06/44] style: Share computed and specified value representation of -moz-context-properties. Differential Revision: https://phabricator.services.mozilla.com/D30545 --- components/style/gecko_string_cache/mod.rs | 1 + components/style/properties/gecko.mako.rs | 60 +------------- .../longhands/inherited_svg.mako.rs | 6 +- components/style/values/mod.rs | 1 + components/style/values/specified/svg.rs | 81 ++++++++++++++++--- components/style_traits/arc_slice.rs | 10 +++ 6 files changed, 89 insertions(+), 70 deletions(-) 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/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 2f223fd971a..79a258b2d9a 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -303,14 +303,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 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)] @@ -4120,7 +4120,7 @@ clip-path <%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; } @@ -4180,60 +4180,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() - } - - // FIXME(emilio): Remove by sharing representation. - #[allow(non_snake_case)] - pub fn clone__moz_context_properties(&self) -> longhands::_moz_context_properties::computed_value::T { - use crate::values::specified::svg::MozContextProperties; - let buf = self.gecko.mContextProps.iter().map(|v| { - MozContextProperties(CustomIdent(unsafe { Atom::from_raw(v.mRawPtr) })) - }).collect::>(); - longhands::_moz_context_properties::computed_value::List(crate::ArcSlice::from_iter(buf.into_iter())) - } - - #[allow(non_snake_case)] - pub fn set__moz_context_properties(&mut self, v: I) - where - I: IntoIterator, - I::IntoIter: ExactSizeIterator - { - let v = v.into_iter(); - unsafe { - bindings::Gecko_nsStyleSVG_SetContextPropertiesLength(&mut *self.gecko, v.len() as u32); - } - - let s = &mut *self.gecko; - s.mContextPropsBits = 0; - for (gecko, servo) in s.mContextProps.iter_mut().zip(v) { - if (servo.0).0 == atom!("fill") { - s.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_FILL as u8; - } else if (servo.0).0 == atom!("stroke") { - s.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_STROKE as u8; - } else if (servo.0).0 == atom!("fill-opacity") { - s.mContextPropsBits |= structs::NS_STYLE_CONTEXT_PROPERTY_FILL_OPACITY as u8; - } else if (servo.0).0 == atom!("stroke-opacity") { - s.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 style_struct_name="Color"> diff --git a/components/style/properties/longhands/inherited_svg.mako.rs b/components/style/properties/longhands/inherited_svg.mako.rs index b4ad07f4dc0..c3e16ee475f 100644 --- a/components/style/properties/longhands/inherited_svg.mako.rs +++ b/components/style/properties/longhands/inherited_svg.mako.rs @@ -194,10 +194,8 @@ ${helpers.predefined_type( ${helpers.predefined_type( "-moz-context-properties", "MozContextProperties", - initial_value=None, - vector=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/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 Debug for Either { ToResolvedValue, ToShmem, )] +#[repr(C)] pub struct CustomIdent(pub Atom); impl CustomIdent { diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index dd4990782a0..88604924deb 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,65 @@ 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, + #[css(skip)] + bits: ContextPropertyBits, +} impl Parse for MozContextProperties { fn parse<'i, 't>( _context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - 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_traits/arc_slice.rs b/components/style_traits/arc_slice.rs index 1541d4be3d9..be50e21c0bb 100644 --- a/components/style_traits/arc_slice.rs +++ b/components/style_traits/arc_slice.rs @@ -85,6 +85,16 @@ impl ArcSlice { 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, to be sent via FFI. From a109fbb7c8dbcc234461b65f79e4e3f5f2ad56dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:04:31 +0000 Subject: [PATCH 07/44] style: Use ArcSlice for quotes. This saves the intermediate allocation. Differential Revision: https://phabricator.services.mozilla.com/D30546 --- components/style/gecko/arc_types.rs | 5 -- components/style/lib.rs | 1 + components/style/properties/gecko.mako.rs | 24 +-------- components/style/values/computed/list.rs | 14 +++-- components/style/values/specified/list.rs | 20 ++++--- components/style_traits/lib.rs | 1 + components/style_traits/owned_str.rs | 53 +++++++++++++++++++ .../style_traits/specified_value_info.rs | 1 + components/style_traits/values.rs | 10 ++++ 9 files changed, 85 insertions(+), 44 deletions(-) create mode 100644 components/style_traits/owned_str.rs 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 => 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 from 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/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 79a258b2d9a..6f37f889e6b 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3302,7 +3302,7 @@ fn static_assert() { <%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 { @@ -3378,28 +3378,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("e_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; 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> = Arc::new( + static ref INITIAL_QUOTES: crate::ArcSlice = 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/specified/list.rs b/components/style/values/specified/list.rs index 8c1e9fa2ad4..566b84bbb16 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, + pub opening: crate::OwnedStr, /// The closing quote. - pub closing: Box, + 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>, + pub crate::ArcSlice, ); impl Parse for Quotes { @@ -131,24 +133,26 @@ 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_traits/lib.rs b/components/style_traits/lib.rs index 0ba13082fc3..cc87ff36cff 100644 --- a/components/style_traits/lib.rs +++ b/components/style_traits/lib.rs @@ -93,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::{ diff --git a/components/style_traits/owned_str.rs b/components/style_traits/owned_str.rs new file mode 100644 index 00000000000..e5fe1065712 --- /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` 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, but with a defined layout, +/// suitable for FFI. +#[repr(C)] +#[derive(Default, Clone, PartialEq, Eq, MallocSizeOf, ToShmem)] +pub struct OwnedStr(OwnedSlice); + +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> for OwnedStr { + #[inline] + fn from(b: Box) -> Self { + Self::from(b.into_string()) + } +} + +impl From 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 95f8821cef5..5aaf64ac955 100644 --- a/components/style_traits/specified_value_info.rs +++ b/components/style_traits/specified_value_info.rs @@ -84,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 {} 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(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + serialize_string(self, dest) + } +} + impl ToCss for str { #[inline] fn to_css(&self, dest: &mut CssWriter) -> fmt::Result From 5f6c8d906085504424dea17582e3cb8b44c47c60 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:04:32 +0000 Subject: [PATCH 08/44] style: Add bindings for box shadows, and remove nsCSSShadowArray and friends. Differential Revision: https://phabricator.services.mozilla.com/D30547 --- components/style/gecko_bindings/sugar/mod.rs | 2 - .../sugar/ns_css_shadow_array.rs | 78 ------------------- .../sugar/ns_css_shadow_item.rs | 59 -------------- components/style/properties/data.py | 2 + components/style/properties/gecko.mako.rs | 75 ++---------------- components/style/properties/helpers.mako.rs | 24 +++++- .../properties/longhands/effects.mako.rs | 1 + .../longhands/inherited_text.mako.rs | 1 + .../style/properties/properties.mako.rs | 2 +- components/style/values/animated/effects.rs | 10 +-- components/style/values/generics/effects.rs | 12 ++- 11 files changed, 46 insertions(+), 220 deletions(-) delete mode 100644 components/style/gecko_bindings/sugar/ns_css_shadow_array.rs delete mode 100644 components/style/gecko_bindings/sugar/ns_css_shadow_item.rs diff --git a/components/style/gecko_bindings/sugar/mod.rs b/components/style/gecko_bindings/sugar/mod.rs index de981bd289a..7811cf73d06 100644 --- a/components/style/gecko_bindings/sugar/mod.rs +++ b/components/style/gecko_bindings/sugar/mod.rs @@ -6,8 +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; 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 { - /// 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 { - 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 { - 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/properties/data.py b/components/style/properties/data.py index ae307077690..12bd3ce38ae 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -174,6 +174,7 @@ class Longhand(object): logical=False, logical_group=None, alias=None, extra_prefixes=None, boxed=False, flags=None, allowed_in_page_rule=False, allow_quirks=False, 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 inside of accepts any CSS property diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 6f37f889e6b..85befa09a3c 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; @@ -56,7 +55,7 @@ use crate::values::{self, CustomIdent, Either, KeyframesName, None_}; use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty}; 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; @@ -3455,31 +3454,7 @@ fn static_assert() { <%self:impl_trait style_struct_name="Effects" - skip_longhands="box-shadow clip filter"> - pub fn set_box_shadow(&mut self, v: I) - where I: IntoIterator, - 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; @@ -3603,7 +3578,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,19 +3618,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 { @@ -3715,7 +3680,7 @@ fn static_assert() { }, NS_STYLE_FILTER_DROP_SHADOW => { Filter::DropShadow(unsafe { - (**filter.__bindgen_anon_1.mDropShadow.as_ref()).mArray[0].to_simple_shadow() + (*filter.__bindgen_anon_1.mDropShadow.as_ref()).clone() }) }, NS_STYLE_FILTER_URL => { @@ -3761,7 +3726,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", @@ -3769,32 +3734,6 @@ fn static_assert() { gecko_strip_moz_prefix=False) %> ${impl_keyword('text_align', 'mTextAlign', text_align_keyword)} - pub fn set_text_shadow(&mut self, v: I) - where - I: IntoIterator, - 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) - } - - // FIXME(emilio): Remove by sharing representation. - pub fn clone_text_shadow(&self) -> longhands::text_shadow::computed_value::T { - let iter = self.gecko.mTextShadow.iter().map(|v| v.to_simple_shadow()); - longhands::text_shadow::computed_value::List(crate::ArcSlice::from_iter(iter)) - } - 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(); diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 808c10b0504..a890534518f 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -90,12 +90,16 @@ // * 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; @@ -237,6 +241,20 @@ } % endif + % if simple_vector_bindings: + impl From for UnderlyingList { + #[inline] + fn from(l: ComputedList) -> Self { + l.0 + } + } + impl From> for ComputedList { + #[inline] + fn from(l: UnderlyingList) -> Self { + List(l) + } + } + % endif % if vector_animation_type: % if not animation_value_type: @@ -345,6 +363,7 @@ pub use self::single_value::SpecifiedValue as SingleSpecifiedValue; + % if not simple_vector_bindings: impl SpecifiedValue { fn compute_iter<'a, 'cx, 'cx_a>( &'a self, @@ -353,6 +372,7 @@ computed_value::Iter::new(context, &self.0) } } + % endif impl ToComputedValue for SpecifiedValue { type ComputedValue = computed_value::T; @@ -473,7 +493,7 @@ .set_writing_mode_dependency(context.builder.writing_mode); % endif - % if property.is_vector: + % if property.is_vector and not property.simple_vector_bindings: // In the case of a vector property we want to pass down an // iterator so that this can be computed without allocation. // diff --git a/components/style/properties/longhands/effects.mako.rs b/components/style/properties/longhands/effects.mako.rs index 0b3f96f0dde..aead5f56508 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", diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index cdd7df93256..b864bc483f9 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -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", )} diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index a9fa35ba444..1e92066c765 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -3444,7 +3444,7 @@ impl<'a> StyleBuilder<'a> { } % endif - % if not property.is_vector: + % if not property.is_vector or property.simple_vector_bindings: /// Set the `${property.ident}` to the computed value `value`. #[allow(non_snake_case)] pub fn set_${property.ident}( diff --git a/components/style/values/animated/effects.rs b/components/style/values/animated/effects.rs index 87f58fb2f82..2f11e1b994d 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; +/// An animated value for the `drop-shadow()` filter. +type AnimatedSimpleShadow = GenericSimpleShadow; /// An animated value for a single `filter`. #[cfg(feature = "gecko")] -pub type Filter = GenericFilter; +pub type Filter = GenericFilter; /// An animated value for a single `filter`. #[cfg(not(feature = "gecko"))] pub type Filter = GenericFilter; - -/// An animated value for the `drop-shadow()` filter. -pub type SimpleShadow = GenericSimpleShadow; 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 { +#[repr(C)] +pub struct GenericBoxShadow { /// The base shadow. - pub base: SimpleShadow, + pub base: GenericSimpleShadow, /// The spread radius. pub spread: ShapeLength, /// Whether this is an inset box shadow. @@ -30,6 +31,8 @@ pub struct BoxShadow { 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 { ToResolvedValue, ToShmem, )] -pub struct SimpleShadow { +#[repr(C)] +pub struct GenericSimpleShadow { /// Color. pub color: Color, /// Horizontal radius. @@ -110,3 +114,5 @@ pub struct SimpleShadow { /// Blur radius. pub blur: ShapeLength, } + +pub use self::GenericSimpleShadow as SimpleShadow; From 85752fa479064678238c66913f44667428860f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:23:28 +0000 Subject: [PATCH 09/44] style: Use OwnedSlice for will-change. We could use ArcSlice if wanted I guess, your call. Though will change is not supposed to be used very frequently. Differential Revision: https://phabricator.services.mozilla.com/D30548 --- components/style/properties/gecko.mako.rs | 62 +---------------------- components/style/values/specified/box.rs | 47 ++++++++--------- 2 files changed, 25 insertions(+), 84 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 85befa09a3c..13b30b53b1b 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2513,7 +2513,7 @@ fn static_assert() { transition-timing-function transition-property transform-style rotate scroll-snap-points-x scroll-snap-points-y - scroll-snap-coordinate -moz-binding will-change + scroll-snap-coordinate -moz-binding offset-path shape-outside translate scale -webkit-line-clamp""" %> <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}"> @@ -2829,66 +2829,6 @@ fn static_assert() { ${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 = 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) { 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. /// /// -pub enum WillChange { - /// Expresses no particular intent - Auto, - /// - #[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, + /// 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, }) } From 3034d66eefe18a069a3da52ec9c9886b65b33928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:25:10 +0000 Subject: [PATCH 10/44] style: Use cbindgen to back CSS transforms. This avoids the expensive conversion, and cleans up a bunch. Further cleanup is possible, just not done yet to avoid growing the patch even more. Differential Revision: https://phabricator.services.mozilla.com/D30748 --- .../gecko_bindings/sugar/ns_css_value.rs | 23 -- .../style/gecko_bindings/sugar/refptr.rs | 5 - components/style/properties/cascade.rs | 4 - components/style/properties/gecko.mako.rs | 294 +----------------- .../style/properties/longhands/box.mako.rs | 1 - .../style/properties/longhands/ui.mako.rs | 1 - components/style/values/animated/transform.rs | 16 +- components/style/values/computed/angle.rs | 1 + components/style/values/computed/transform.rs | 12 +- components/style/values/generics/transform.rs | 54 +++- .../style/values/specified/transform.rs | 4 +- 11 files changed, 59 insertions(+), 356 deletions(-) diff --git a/components/style/gecko_bindings/sugar/ns_css_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs index b59732bcc8e..96b48061c8a 100644 --- a/components/style/gecko_bindings/sugar/ns_css_value.rs +++ b/components/style/gecko_bindings/sugar/ns_css_value.rs @@ -276,29 +276,6 @@ impl nsCSSValue { } debug_assert!(values.next().is_none(), "Values should have been exhausted"); } - - /// Set a shared list - pub fn set_shared_list(&mut self, values: I) - where - I: ExactSizeIterator, - { - 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 { 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 @@ -289,11 +289,6 @@ impl_threadsafe_refcount!( bindings::Gecko_AddRefURLExtraDataArbitraryThread, bindings::Gecko_ReleaseURLExtraDataArbitraryThread ); -impl_threadsafe_refcount!( - structs::nsCSSValueSharedList, - bindings::Gecko_AddRefCSSValueSharedListArbitraryThread, - bindings::Gecko_ReleaseCSSValueSharedListArbitraryThread -); impl_threadsafe_refcount!( structs::mozilla::css::URLValue, bindings::Gecko_AddRefCSSURLValueArbitraryThread, 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/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 13b30b53b1b..cffc1e50de7 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -811,281 +811,6 @@ def set_gecko_property(ffi_name, expr): } -<% -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 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} - }, - - -#[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 -) { - 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 { - 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![], - }; - 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 name="impl_logical(name, **kwargs)"> ${helpers.logical_setter(name)} @@ -1191,7 +916,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, } @@ -2511,17 +2235,11 @@ fn static_assert() { 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 - offset-path shape-outside - translate scale -webkit-line-clamp""" %> + transform-style scroll-snap-points-x + scroll-snap-points-y scroll-snap-coordinate + -moz-binding offset-path 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; @@ -2825,10 +2543,6 @@ 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')} - <% impl_shape_source("shape_outside", "mShapeOutside") %> pub fn set_offset_path(&mut self, v: longhands::offset_path::computed_value::T) { diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index 6d754964ecc..0324062740f 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -352,7 +352,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", diff --git a/components/style/properties/longhands/ui.mako.rs b/components/style/properties/longhands/ui.mako.rs index c54582e2584..6d525825762 100644 --- a/components/style/properties/longhands/ui.mako.rs +++ b/components/style/properties/longhands/ui.mako.rs @@ -81,7 +81,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/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::>(); + 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/transform.rs b/components/style/values/computed/transform.rs index e23ec1524ff..baa5cbfd5d2 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; + generic::GenericTransformOperation; /// A computed CSS `transform` -pub type Transform = generic::Transform; +pub type Transform = generic::GenericTransform; /// The computed value of a CSS `` pub type TransformOrigin = @@ -540,13 +540,13 @@ impl ToAnimatedZero for Transform { self.0 .iter() .map(|op| op.to_animated_zero()) - .collect::, _>>()?, + .collect::, _>>()?, )) } } /// A computed CSS `rotate` -pub type Rotate = generic::Rotate; +pub type Rotate = generic::GenericRotate; impl Rotate { /// Convert TransformOperation to Rotate. @@ -573,7 +573,7 @@ impl Rotate { } /// A computed CSS `translate` -pub type Translate = generic::Translate; +pub type Translate = generic::GenericTranslate; impl Translate { /// Convert TransformOperation to Translate. @@ -602,7 +602,7 @@ impl Translate { } /// A computed CSS `scale` -pub type Scale = generic::Scale; +pub type Scale = generic::GenericScale; impl Scale { /// Convert TransformOperation to Scale. diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 6c6374db941..87f4403057f 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 { +#[css(comma, function = "matrix")] +#[repr(C)] +pub struct GenericMatrix { pub a: T, pub b: T, pub c: T, @@ -40,6 +41,8 @@ pub struct Matrix { 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 { ToResolvedValue, ToShmem, )] -pub struct Matrix3D { +#[repr(C)] +pub struct GenericMatrix3D { 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> From> for Transform3D { #[inline] @@ -142,17 +148,19 @@ fn is_same(x: &N, y: &N) -> bool { ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// A single operation in the list of a `transform` value -pub enum TransformOperation +/// cbindgen:derive-tagged-enum-copy-constructor=true +pub enum GenericTransformOperation where Angle: Zero, LengthPercentage: Zero, Number: PartialEq, { /// Represents a 2D 2x3 matrix. - Matrix(Matrix), + Matrix(GenericMatrix), /// Represents a 3D 4x4 matrix. - Matrix3D(Matrix3D), + Matrix3D(GenericMatrix3D), /// A 2D skew. /// /// If the second angle is not provided it is assumed zero. @@ -232,20 +240,22 @@ where #[allow(missing_docs)] #[css(comma, function = "interpolatematrix")] InterpolateMatrix { - from_list: Transform>, - to_list: Transform>, + from_list: GenericTransform>, + to_list: GenericTransform>, progress: computed::Percentage, }, /// A intermediate type for accumulation of mismatched transform lists. #[allow(missing_docs)] #[css(comma, function = "accumulatematrix")] AccumulateMatrix { - from_list: Transform>, - to_list: Transform>, + from_list: GenericTransform>, + to_list: GenericTransform>, count: Integer, }, } +pub use self::GenericTransformOperation as TransformOperation; + #[derive( Clone, Debug, @@ -257,8 +267,11 @@ where ToResolvedValue, ToShmem, )] +#[repr(C)] /// A value of the `transform` property -pub struct Transform(#[css(if_empty = "none", iterable)] pub Vec); +pub struct GenericTransform(#[css(if_empty = "none", iterable)] pub crate::OwnedSlice); + +pub use self::GenericTransform as Transform; impl TransformOperation @@ -497,7 +510,7 @@ where impl Transform { /// `none` pub fn none() -> Self { - Transform(vec![]) + Transform(Default::default()) } } @@ -529,7 +542,7 @@ impl Transform { let mut transform = Transform3D::::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 +602,11 @@ pub fn get_normalized_vector_and_angle( ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// A value of the `Rotate` property /// /// -pub enum Rotate { +pub enum GenericRotate { /// 'none' None, /// '' @@ -601,6 +615,8 @@ pub enum Rotate { 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 +676,11 @@ where ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// A value of the `Scale` property /// /// -pub enum Scale { +pub enum GenericScale { /// 'none' None, /// '{1,2}' @@ -672,6 +689,8 @@ pub enum Scale { Scale3D(Number, Number, Number), } +pub use self::GenericScale as Scale; + impl ToCss for Scale { fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where @@ -710,6 +729,7 @@ impl ToCss for Scale { ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// A value of the `translate` property /// /// https://drafts.csswg.org/css-transforms-2/#individual-transform-serialization: @@ -724,7 +744,7 @@ impl ToCss for Scale { /// related spec issue is https://github.com/w3c/csswg-drafts/issues/3305 /// /// -pub enum Translate +pub enum GenericTranslate where LengthPercentage: Zero, { @@ -739,6 +759,8 @@ where Translate3D(LengthPercentage, LengthPercentage, Length), } +pub use self::GenericTranslate as Translate; + #[allow(missing_docs)] #[derive( Clone, diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index a4dc87d3217..4c083e896a2 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -42,7 +42,7 @@ 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| { @@ -218,7 +218,7 @@ impl Transform { .new_custom_error(StyleParseErrorKind::UnexpectedFunction(function.clone())) }) }) - })?)) + })?.into())) } } From 7d3997d7ef23f7d68035fff65dfa14ac23404260 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:05:00 +0000 Subject: [PATCH 11/44] style: Cleanup a bit the counter style code. Use more compact types, and remove some manual implementations that can be derived. Differential Revision: https://phabricator.services.mozilla.com/D31315 --- components/style/counter_style/mod.rs | 134 +++++++++++--------------- components/style/gecko/values.rs | 4 +- 2 files changed, 57 insertions(+), 81 deletions(-) diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 77de5f52d2b..9e2bc096e2d 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, /// - "range" range / set_range [_]: Ranges, + "range" range / set_range [_]: CounterRanges, /// "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 { } /// -#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)] +#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem, MallocSizeOf)] pub enum Symbol { /// - String(String), + String(crate::OwnedStr), /// Ident(CustomIdent), // Not implemented: @@ -428,7 +426,7 @@ impl Parse for Symbol { ) -> Result> { 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,25 @@ impl Parse for Negative { } /// -/// -/// Empty Vec represents 'auto' -#[derive(Clone, Debug, ToShmem)] -pub struct Ranges(pub Vec>); +#[derive(Clone, Debug, ToShmem, ToCss)] +pub struct CounterRange { + /// The start of the range. + pub start: CounterBound, + /// The end of the range. + pub end: CounterBound, +} -/// A bound found in `Ranges`. +/// +/// +/// Empty represents 'auto' +#[derive(Clone, Debug, ToShmem, ToCss)] +#[css(comma)] +pub struct CounterRanges( + #[css(iterable, if_empty = "auto")] + pub crate::OwnedSlice, +); + +/// A bound found in `CounterRanges`. #[derive(Clone, Copy, Debug, ToCss, ToShmem)] pub enum CounterBound { /// An integer bound. @@ -477,7 +488,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 +497,25 @@ 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 +530,6 @@ fn parse_bound<'i, 't>( Ok(CounterBound::Infinite) } -impl ToCss for Ranges { - fn to_css(&self, dest: &mut CssWriter) -> 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(range: &Range, dest: &mut CssWriter) -> fmt::Result -where - W: Write, -{ - range.start.to_css(dest)?; - dest.write_char(' ')?; - range.end.to_css(dest) -} - /// #[derive(Clone, Debug, ToCss, ToShmem)] pub struct Pad(pub Integer, pub Symbol); @@ -572,14 +555,13 @@ impl Parse for Fallback { _context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - parse_counter_style_name(input).map(Fallback) + Ok(Fallback(parse_counter_style_name(input)?)) } } /// -#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem)] -pub struct Symbols(#[css(iterable)] pub Vec); +#[derive(Clone, Debug, Eq, PartialEq, MallocSizeOf, ToComputedValue, ToCss, ToShmem)] +pub struct Symbols(#[css(iterable)] pub crate::OwnedSlice); impl Parse for Symbols { fn parse<'i, 't>( @@ -587,23 +569,20 @@ impl Parse for Symbols { input: &mut Parser<'i, 't>, ) -> Result> { 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())) } } /// #[derive(Clone, Debug, ToCss, ToShmem)] -pub struct AdditiveSymbols(pub Vec); +#[css(comma)] +pub struct AdditiveSymbols(#[css(iterable)] pub crate::OwnedSlice); impl Parse for AdditiveSymbols { fn parse<'i, 't>( @@ -618,7 +597,7 @@ impl Parse for AdditiveSymbols { { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } - Ok(AdditiveSymbols(tuples)) + Ok(AdditiveSymbols(tuples.into())) } } @@ -643,10 +622,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/gecko/values.rs b/components/style/gecko/values.rs index 98fe90fe3d0..8f777b9f782 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -288,7 +288,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 +333,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))) } From 57998eacc583b998b5644bf3b4cddaba12872f66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 16 May 2019 23:06:17 +0000 Subject: [PATCH 12/44] style: Remove nsCSSValue bindings. Depends on D31320 Differential Revision: https://phabricator.services.mozilla.com/D31321 --- components/style/gecko/mod.rs | 1 - components/style/gecko/rules.rs | 135 ------ components/style/gecko_bindings/sugar/mod.rs | 1 - .../gecko_bindings/sugar/ns_css_value.rs | 401 ------------------ 4 files changed, 538 deletions(-) delete mode 100644 components/style/gecko/rules.rs delete mode 100644 components/style/gecko_bindings/sugar/ns_css_value.rs diff --git a/components/style/gecko/mod.rs b/components/style/gecko/mod.rs index 43d38d7dbc1..3ff2cfcf140 100644 --- a/components/style/gecko/mod.rs +++ b/components/style/gecko/mod.rs @@ -17,7 +17,6 @@ pub mod media_queries; 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/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_bindings/sugar/mod.rs b/components/style/gecko_bindings/sugar/mod.rs index 7811cf73d06..338236c175a 100644 --- a/components/style/gecko_bindings/sugar/mod.rs +++ b/components/style/gecko_bindings/sugar/mod.rs @@ -6,7 +6,6 @@ mod ns_com_ptr; mod ns_compatibility; -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_value.rs b/components/style/gecko_bindings/sugar/ns_css_value.rs deleted file mode 100644 index 96b48061c8a..00000000000 --- a/components/style/gecko_bindings/sugar/ns_css_value.rs +++ /dev/null @@ -1,401 +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 { - 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>(&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(&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(&mut self, values: I) - where - I: ExactSizeIterator, - { - 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(&mut self, mut values: I) - where - I: ExactSizeIterator, - { - 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"); - } -} - -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 { - 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 { - 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 for nsCSSValue_Array { - type Output = nsCSSValue; - #[inline] - fn index(&self, i: usize) -> &nsCSSValue { - &self.as_slice()[i] - } -} - -impl IndexMut 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 From for nsCSSValue { - fn from(value: T) -> nsCSSValue { - let mut result = nsCSSValue::null(); - value.convert(&mut result); - result - } -} From 8c8ef22e6bab37beb0a5ac10561ed1c9f067f332 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 18 May 2019 04:48:16 +0000 Subject: [PATCH 13/44] style: Remove some more individual-transform dead code. Differential Revision: https://phabricator.services.mozilla.com/D31705 --- components/style/properties/gecko.mako.rs | 32 --------- components/style/values/computed/transform.rs | 72 ------------------- 2 files changed, 104 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index cffc1e50de7..8c629bc44ce 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2197,38 +2197,6 @@ fn static_assert() { ${impl_copy_animation_value(ident, gecko_ffi_name)} -<%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()) - } - - <% skip_box_longhands= """display animation-name animation-delay animation-duration animation-direction animation-fill-mode animation-play-state diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index baa5cbfd5d2..9104a43ae5b 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -548,80 +548,8 @@ impl ToAnimatedZero for Transform { /// A computed CSS `rotate` pub type Rotate = generic::GenericRotate; -impl Rotate { - /// Convert TransformOperation to Rotate. - pub fn to_transform_operation(&self) -> Option { - 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"), - } - } -} - /// A computed CSS `translate` pub type Translate = generic::GenericTranslate; -impl Translate { - /// Convert TransformOperation to Translate. - pub fn to_transform_operation(&self) -> Option { - 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"), - } - } -} - /// A computed CSS `scale` pub type Scale = generic::GenericScale; - -impl Scale { - /// Convert TransformOperation to Scale. - pub fn to_transform_operation(&self) -> Option { - 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"), - } - } -} From 86524c3765a009ba747a5f02895f4d96dd2508c4 Mon Sep 17 00:00:00 2001 From: violet Date: Mon, 20 May 2019 07:01:29 +0000 Subject: [PATCH 14/44] style: Accept empty argument for some filters. Filters blur(), invert(), etc. can omit argument. Computed/specified style serialization is a little tricky w.r.t the shortest serialization principle. Ideally we should serialize `invert(1)` to `invert()`, but that will be a breaking change, so we always serialize them with an argument. Note, Blink/WetKit treat specified (but not computed) style serialization differently when the specified one is originally without argument. Our current behavior is the same as pre-Chromium Edge. Differential Revision: https://phabricator.services.mozilla.com/D31720 --- components/style/values/specified/effects.rs | 51 ++++++++++++++++---- 1 file changed, 41 insertions(+), 10 deletions(-) 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( From eba393cc824275ae3837803150e8ce2201f34d75 Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Mon, 20 May 2019 06:04:23 +0000 Subject: [PATCH 15/44] Implement Animation.commitStyles. Differential Revision: https://phabricator.services.mozilla.com/D30327 --- components/style/gecko/boxed_types.rs | 10 ++++++++++ .../properties/helpers/animated_properties.mako.rs | 9 --------- 2 files changed, 10 insertions(+), 9 deletions(-) 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,12 +5,22 @@ //! 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 // various files at the moment, but should probably all move here, and use macros to define // 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/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index 1b536d24e8b..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; -#[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. From 7cf2e38bb7957a14093d21b1e2911acf8797c9da Mon Sep 17 00:00:00 2001 From: Brian Birtles Date: Mon, 20 May 2019 05:22:39 +0000 Subject: [PATCH 16/44] style: Use update() to update declarations from Servo_DeclarationBlock_SetPropertyToAnimationValue. This method is used when updating the SMIL override style and from Web Animations' Animation.commitStyles method. By using update we accurately return false when no change is made to a declaration block. For SMIL this simply acts as an optimization, meaning we can avoid updating the SMIL override style ub some cases. For Animation.commitStyles, however, this allows us to avoid generating a mutation record. Normally making a redundant change to an attribute *does* generate a mutation record but the style attribute is different. All browsers avoid generating a mutation record for a redundant change to inline style. This is specified in the behavior for setProperty[1] which does not update the style attribute if updated is false. [1] https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-setproperty Differential Revision: https://phabricator.services.mozilla.com/D30871 --- components/style/properties/properties.mako.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 1e92066c765..ed71019b390 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 { From 67909022a060ccea7d7937cae258d05fcc7f783a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 17 May 2019 02:43:59 +0000 Subject: [PATCH 17/44] style: Unprefix user-select. The CSSWG decided that our behavior regarding inheritance is what we want, see [1]. [1]: https://github.com/w3c/csswg-drafts/issues/3344 Differential Revision: https://phabricator.services.mozilla.com/D11585 --- components/style/properties/longhands/ui.mako.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/components/style/properties/longhands/ui.mako.rs b/components/style/properties/longhands/ui.mako.rs index 6d525825762..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", From 0dc70cf7f26e2c1e3a62a86c21936ad25e1f5f17 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Mon, 20 May 2019 20:46:07 +0000 Subject: [PATCH 18/44] style: Implement the CSS line-break property, with values "auto | anywhere". Note that the "loose | normal | strict" values are not yet parsed/implemented. Differential Revision: https://phabricator.services.mozilla.com/D29817 --- components/style/properties/data.py | 1 + .../longhands/inherited_text.mako.rs | 10 +++++++ components/style/values/computed/mod.rs | 2 +- components/style/values/computed/text.rs | 2 +- components/style/values/specified/mod.rs | 2 +- components/style/values/specified/text.rs | 26 +++++++++++++++++++ 6 files changed, 40 insertions(+), 3 deletions(-) diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 12bd3ce38ae..daeb82ffab9 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -325,6 +325,7 @@ class Longhand(object): "JustifyContent", "JustifyItems", "JustifySelf", + "LineBreak", "MozForceBrokenImageIcon", "MozListReversed", "MozScriptLevel", diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index b864bc483f9..94af642713e 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -264,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/values/computed/mod.rs b/components/style/values/computed/mod.rs index 993af4177ad..aa3963db804 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -77,7 +77,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; diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index c29d3d45210..7395cf71bb2 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. diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 83fc71444bb..7c59f66e318 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -81,7 +81,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/text.rs b/components/style/values/specified/text.rs index 6be20f58618..a78cb4135c3 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -1005,6 +1005,32 @@ 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, + /// TODO: additional values not yet implemented + /// Loose, + /// Normal, + /// Strict, + Anywhere, +} + /// Values for the `overflow-wrap` property. #[repr(u8)] #[derive( From 8ee516b681a948414abf03255a8297d76ae617cd Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Mon, 20 May 2019 20:46:28 +0000 Subject: [PATCH 19/44] style: Add parsing of the loose|normal|strict values of the CSS line-break property. Differential Revision: https://phabricator.services.mozilla.com/D30785 --- components/style/values/specified/text.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index a78cb4135c3..1ab805cdcfb 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -1024,10 +1024,9 @@ pub enum WordBreak { #[allow(missing_docs)] pub enum LineBreak { Auto, - /// TODO: additional values not yet implemented - /// Loose, - /// Normal, - /// Strict, + Loose, + Normal, + Strict, Anywhere, } From d80a5d9196d59e5e699d35d13929b0489535978e Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Mon, 20 May 2019 23:42:50 +0000 Subject: [PATCH 20/44] style: Unpack StyleMotion and use cbindgen for OffsetPath. Unpack StyleMotion and move its members into nsStyleDisplay, use cbindgen to generate StyleOffsetPath. Differential Revision: https://phabricator.services.mozilla.com/D31164 --- components/style/properties/gecko.mako.rs | 36 +-------------------- components/style/values/specified/motion.rs | 2 ++ 2 files changed, 3 insertions(+), 35 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 8c629bc44ce..21e0c8d75fc 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -2205,8 +2205,7 @@ fn static_assert() { transition-timing-function transition-property transform-style scroll-snap-points-x scroll-snap-points-y scroll-snap-coordinate - -moz-binding offset-path shape-outside - -webkit-line-clamp""" %> + -moz-binding shape-outside -webkit-line-clamp""" %> <%self:impl_trait style_struct_name="Box" skip_longhands="${skip_box_longhands}"> #[inline] pub fn set_display(&mut self, v: longhands::display::computed_value::T) { @@ -2513,39 +2512,6 @@ fn static_assert() { <% 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 { diff --git a/components/style/values/specified/motion.rs b/components/style/values/specified/motion.rs index 7d72796397e..73072ac6199 100644 --- a/components/style/values/specified/motion.rs +++ b/components/style/values/specified/motion.rs @@ -12,6 +12,7 @@ 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 +27,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. From c50829bf6edefd3c689d62f8a76735f7cd1b3995 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Mon, 20 May 2019 23:42:52 +0000 Subject: [PATCH 21/44] style: Implement offset-distance. Define the offset-distance property in style system. Differential Revision: https://phabricator.services.mozilla.com/D30582 --- components/style/properties/longhands/box.mako.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index 0324062740f..a5c3b38b34d 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -404,6 +404,19 @@ ${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="none", + gecko_pref="layout.css.motion-path.enabled", + spec="https://drafts.fxtf.org/motion-1/#offset-distance-property", + servo_restyle_damage="reflow_out_of_flow" )} // CSSOM View Module From f8a2172d4214203a6d95c734147191c17da6e150 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Mon, 20 May 2019 23:42:56 +0000 Subject: [PATCH 22/44] style: Make offset-distance animatable. Use ComputedValue to animate offset-distance. Differential Revision: https://phabricator.services.mozilla.com/D30584 --- components/style/properties/longhands/box.mako.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index a5c3b38b34d..bddc56da848 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -413,7 +413,7 @@ ${helpers.predefined_type( "LengthPercentage", "computed::LengthPercentage::zero()", products="gecko", - animation_value_type="none", + 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" From d552969ca14baf142f913993aa7bc4cf2401654e Mon Sep 17 00:00:00 2001 From: violet Date: Thu, 16 May 2019 00:44:51 +0000 Subject: [PATCH 23/44] style: Support AllowQuirks::Always option in helpers.mako.rs Differential Revision: https://phabricator.services.mozilla.com/D29936 --- components/style/properties/data.py | 2 +- components/style/properties/helpers.mako.rs | 16 ++++++++-------- .../properties/longhands/background.mako.rs | 2 +- .../style/properties/longhands/border.mako.rs | 4 ++-- .../style/properties/longhands/effects.mako.rs | 2 +- .../style/properties/longhands/font.mako.rs | 2 +- .../properties/longhands/inherited_text.mako.rs | 2 +- .../style/properties/longhands/margin.mako.rs | 2 +- .../style/properties/longhands/padding.mako.rs | 2 +- .../style/properties/longhands/position.mako.rs | 8 ++++---- .../style/properties/shorthands/border.mako.rs | 2 +- .../style/properties/shorthands/margin.mako.rs | 2 +- .../style/properties/shorthands/padding.mako.rs | 2 +- .../style/properties/shorthands/position.mako.rs | 2 +- 14 files changed, 25 insertions(+), 25 deletions(-) diff --git a/components/style/properties/data.py b/components/style/properties/data.py index daeb82ffab9..a7a3479974b 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -172,7 +172,7 @@ 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"): diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index a890534518f..56637af9463 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> { - % 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: @@ -523,8 +523,8 @@ context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - % 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 @@ -986,7 +986,7 @@ <%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)] @@ -999,8 +999,8 @@ input: &mut Parser<'i, 't>, ) -> Result> { 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/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..7ea8b8dd0eb 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 diff --git a/components/style/properties/longhands/effects.mako.rs b/components/style/properties/longhands/effects.mako.rs index aead5f56508..9bb8adda32e 100644 --- a/components/style/properties/longhands/effects.mako.rs +++ b/components/style/properties/longhands/effects.mako.rs @@ -38,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_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index 94af642713e..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", )} 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/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/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( From bd1481039faa10c47472538291884fbf5d456e59 Mon Sep 17 00:00:00 2001 From: violet Date: Thu, 16 May 2019 13:21:19 +0000 Subject: [PATCH 24/44] style: Add SVG geometry property support in CSS. This patch adds SVG geometry properties to CSS, it doesn't deal with how SVG handles them. Differential Revision: https://phabricator.services.mozilla.com/D29937 --- .../style/properties/longhands/svg.mako.rs | 63 +++++++++++++++++++ 1 file changed, 63 insertions(+) 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", +)} From af8e8e6a34cb2a6fa93c8ea998c6cd3a0c8c0536 Mon Sep 17 00:00:00 2001 From: violet Date: Tue, 21 May 2019 15:35:41 +0000 Subject: [PATCH 25/44] style: Do not report error for unknown property if its known moz prefixed version is specified. Suppose that `prop` is a property that we haven't supported yet, while its `-moz-prop` version is already supported. If an author specifies in a declaration block this property in its standard form as well as multiple verdor specific forms, as long as `-moz-prop` is specified, we shouldn't report error for unknown property `prop`. Because that's just noise. Differential Revision: https://phabricator.services.mozilla.com/D31998 --- .../style/properties/declaration_block.rs | 33 ++++++++++++++----- components/style_traits/lib.rs | 2 -- 2 files changed, 25 insertions(+), 10 deletions(-) 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); 2]>; +fn alias_of_known_property(name: &str) -> Option { + 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_traits/lib.rs b/components/style_traits/lib.rs index cc87ff36cff..4e89f6fdf67 100644 --- a/components/style_traits/lib.rs +++ b/components/style_traits/lib.rs @@ -152,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. From 44926adde721176240bb62a9c883cc1c5d6bfd64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 21 May 2019 21:07:55 +0000 Subject: [PATCH 26/44] style: Use cbindgen for border-image-width. Differential Revision: https://phabricator.services.mozilla.com/D32032 --- components/style/properties/gecko.mako.rs | 21 +------ .../style/properties/longhands/border.mako.rs | 57 ------------------- components/style/values/computed/border.rs | 2 +- components/style/values/generics/border.rs | 9 ++- components/style/values/specified/border.rs | 2 +- 5 files changed, 9 insertions(+), 82 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 21e0c8d75fc..41fac1bd57a 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -718,23 +718,6 @@ def set_gecko_property(ffi_name, expr): } -<%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}"> - - #[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 name="copy_sides_style_coord(ident)"> <% gecko_ffi_name = "m" + to_camel_case(ident) %> #[allow(non_snake_case)] @@ -989,7 +972,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; @@ -1128,8 +1111,6 @@ fn static_assert() { % endfor longhands::border_image_repeat::computed_value::T(servo_h, servo_v) } - - <% impl_style_sides("border_image_width") %> <% skip_scroll_margin_longhands = " ".join(["scroll-margin-%s" % x.ident for x in SIDES]) %> diff --git a/components/style/properties/longhands/border.mako.rs b/components/style/properties/longhands/border.mako.rs index 7ea8b8dd0eb..7909372be17 100644 --- a/components/style/properties/longhands/border.mako.rs +++ b/components/style/properties/longhands/border.mako.rs @@ -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 { - 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/values/computed/border.rs b/components/style/values/computed/border.rs index 62c8e3883f6..908fd1436ac 100644 --- a/components/style/values/computed/border.rs +++ b/components/style/values/computed/border.rs @@ -7,7 +7,7 @@ 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::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; 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 { +#[repr(C, u8)] +pub enum GenericBorderImageSideWidth { /// `` - Length(LengthPercentage), + LengthPercentage(LP), /// `` - 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/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)?; From 8bf0f82ddcb3b9a10796a0714cda5d2e423593f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Tue, 21 May 2019 22:51:54 +0000 Subject: [PATCH 27/44] style: Remove old CSS scroll snap implementation. This will save us some time from figuring out what's the best thing to do in bug 1552587, so that other patches I have in flight (mainly bug 1552708) can land, since we cannot add a single byte to nsStyleDisplay right now otherwise. The code removed here is well isolated and not that complicated, so it seems to me that should be easy to bring back should we have an emergency (and I commit to doing that while preserving the nsStyleDisplay size limit if we need to :)). Differential Revision: https://phabricator.services.mozilla.com/D32026 --- components/style/gecko/values.rs | 22 -------- components/style/properties/gecko.mako.rs | 53 +------------------ .../style/properties/longhands/box.mako.rs | 35 ------------ components/style/values/computed/gecko.rs | 11 ---- components/style/values/computed/mod.rs | 4 -- components/style/values/generics/gecko.rs | 44 --------------- components/style/values/generics/mod.rs | 2 - components/style/values/specified/gecko.rs | 21 -------- components/style/values/specified/mod.rs | 2 - 9 files changed, 2 insertions(+), 192 deletions(-) delete mode 100644 components/style/values/computed/gecko.rs delete mode 100644 components/style/values/generics/gecko.rs diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 8f777b9f782..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 { - fn to_gecko_style_coord(&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(coord: &T) -> Option { - 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) | diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 41fac1bd57a..980abeafa47 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -696,28 +696,6 @@ def set_gecko_property(ffi_name, expr): } -<%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 name="copy_sides_style_coord(ident)"> <% gecko_ffi_name = "m" + to_camel_case(ident) %> #[allow(non_snake_case)] @@ -2184,9 +2162,8 @@ fn static_assert() { animation-iteration-count animation-timing-function clear transition-duration transition-delay transition-timing-function transition-property - transform-style scroll-snap-points-x - scroll-snap-points-y scroll-snap-coordinate - -moz-binding shape-outside -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 set_display(&mut self, v: longhands::display::computed_value::T) { @@ -2226,33 +2203,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(&mut self, v: I) - where I: IntoIterator, - 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()} diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index bddc56da848..d6c3366c4b7 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( 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; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index aa3963db804..b8e3c0eca17 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}; @@ -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; 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 { - /// `none` - None, - /// `repeat()` - #[css(function)] - Repeat(LengthPercentage), -} - -impl ScrollSnapPoint { - /// 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/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; - -impl Parse for ScrollSnapPoint { - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - 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/mod.rs b/components/style/values/specified/mod.rs index 7c59f66e318..4cb7305fab8 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}; From 431b9d00f5208bae539f776df24c18f6257a8d2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 22 May 2019 11:34:23 +0000 Subject: [PATCH 28/44] style: Remove eStyleImageType_URL. It was introduced in bug 1352096 to reduce complexity with Stylo (apparently). Right now it doesn't look like it reduces any complexity, and it's a bit annoying with some of the patches that I'm writing at the moment. So unless there's any objection I think it should go away. Differential Revision: https://phabricator.services.mozilla.com/D31708 --- components/style/gecko/conversions.rs | 24 ++++++++--------------- components/style/gecko/url.rs | 19 +++++++----------- components/style/properties/gecko.mako.rs | 24 ++++++++--------------- components/style/values/animated/mod.rs | 3 ++- 4 files changed, 25 insertions(+), 45 deletions(-) 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/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(&self, dest: &mut CssWriter) -> 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 { - (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/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 980abeafa47..2c83e8cf656 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -53,6 +53,7 @@ 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::Filter; @@ -60,6 +61,7 @@ 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}; @@ -2850,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; } @@ -3489,25 +3489,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; @@ -3662,7 +3656,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; @@ -3878,7 +3871,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; diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 267ef0c8e6f..23c314a57a4 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -10,7 +10,7 @@ use crate::properties::PropertyId; use crate::values::computed::length::LengthPercentage; -use crate::values::computed::url::ComputedUrl; +use crate::values::computed::url::{ComputedUrl, ComputedImageUrl}; use crate::values::computed::Angle as ComputedAngle; use crate::values::computed::Image; use crate::values::specified::SVGPathData; @@ -380,6 +380,7 @@ trivial_to_animated_value!(Au); trivial_to_animated_value!(LengthPercentage); trivial_to_animated_value!(ComputedAngle); trivial_to_animated_value!(ComputedUrl); +trivial_to_animated_value!(ComputedImageUrl); trivial_to_animated_value!(bool); trivial_to_animated_value!(f32); // Note: This implementation is for ToAnimatedValue of ShapeSource. From 272d9758d7c4c07e2409d5e0ac7d5c152f49e7b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 22 May 2019 13:28:01 +0000 Subject: [PATCH 29/44] style: Fix nested-pseudo-elements matching author rules better. This makes *|*::marker do the intended thing in UA sheets, so I think it's better, and it's a bit less special-casey. We may want to re-introduce the changes for pseudo-elements at some point, depending on the WG decision, but this patch makes each_non_document_style_data consistent with the rule collector. The changes of each_non_document_style_data on their own should fix some bugs, but it doesn't because: * This is only hit for pseudos that allow user-action-state pseudo-classes. * The containing shadow check worked for them anyway. * We don't allow any pseudo after ::slotted() or that isn't tree-abiding per the CSS specs (we should maybe enable one of the moz-range stuff to be tree-abiding). So ::placeholder is the only one that right now fits the bill to trigger the bugs this would fix, but it doesn't since I couldn't make ::placeholder match :hover / :active / :focus anyhow (inside or outside a shadow tree). I've left the ProbeMarkerPseudoStyle changes for now since they are technically a bit more consistent than what was there before, but we could revert those if they cause trouble, we could rely on the UA rule matching, but we would need to change that if we allow the ::foo::before and such to match. Differential Revision: https://phabricator.services.mozilla.com/D29542 --- components/style/dom.rs | 13 +++++++++---- components/style/gecko/wrapper.rs | 2 +- components/style/rule_collector.rs | 16 ++++++++++++---- components/style/stylist.rs | 4 ++++ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/components/style/dom.rs b/components/style/dom.rs index 9a81e2ec774..633dce83655 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -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/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 9d987c56308..cec55130c4a 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -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] diff --git a/components/style/rule_collector.rs b/components/style/rule_collector.rs index e87a86c5e47..2e8ffe5d858 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,16 @@ 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 +128,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/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 From 43444db8a80f8312122b6629cb7d050ac4f065c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 24 May 2019 01:09:15 +0000 Subject: [PATCH 30/44] style: Cleanup selector-matching for nested pseudo-elements, match ::slotted correctly when there's no selector before it, and add tests. D29542 fixed the bogus checks that was making nested pseudo-elements match author rules. This adds tests and ends up being just a cleanup, though as it turns out we it also fixes an issue with ::slotted() matched from Element.matches. Differential Revision: https://phabricator.services.mozilla.com/D27529 --- components/selectors/builder.rs | 6 ------ components/selectors/matching.rs | 13 +++---------- components/selectors/parser.rs | 18 +++++++++++------- components/selectors/tree.rs | 4 ++++ components/style/dom.rs | 2 +- components/style/gecko/wrapper.rs | 11 ++++++++--- .../invalidation/element/element_wrapper.rs | 4 ++++ components/style/style_adjuster.rs | 5 +---- components/style/style_resolver.rs | 10 +++------- 9 files changed, 35 insertions(+), 38 deletions(-) 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 SelectorBuilder { 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) => { // 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 { + 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; diff --git a/components/style/dom.rs b/components/style/dom.rs index 633dce83655..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 { diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index cec55130c4a..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 { - if self.implemented_pseudo_element().is_some() { + if self.is_pseudo_element() { return self.pseudo_element_originating_element(); } @@ -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() @@ -1918,9 +1918,14 @@ impl<'le> ::selectors::Element for GeckoElement<'le> { Some(shadow.host()) } + #[inline] + fn is_pseudo_element(&self) -> bool { + self.implemented_pseudo_element().is_some() + } + #[inline] fn pseudo_element_originating_element(&self) -> Option { - 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 s 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.element .pseudo_element_originating_element() 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(); From 73b0b7c4778c6dc5a33e08235057eb4811f85139 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Fri, 24 May 2019 03:42:03 +0000 Subject: [PATCH 31/44] style: Implement offset-rotate. This includes style system and layout update. I add 3 extra reftests because the original tests use ray() function as the offset-path, but we don't support it. It'd be better to add tests using a different type of offset-path. The spec issue about the serialization: https://github.com/w3c/fxtf-drafts/issues/340 Differential Revision: https://phabricator.services.mozilla.com/D32212 --- components/style/properties/data.py | 1 + .../style/properties/longhands/box.mako.rs | 12 ++ components/style/values/computed/mod.rs | 2 +- components/style/values/computed/motion.rs | 34 ++++++ components/style/values/specified/mod.rs | 2 +- components/style/values/specified/motion.rs | 106 +++++++++++++++++- 6 files changed, 154 insertions(+), 3 deletions(-) diff --git a/components/style/properties/data.py b/components/style/properties/data.py index a7a3479974b..e771607b6d9 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -332,6 +332,7 @@ class Longhand(object): "MozScriptMinSize", "MozScriptSizeMultiplier", "NonNegativeNumber", + "OffsetRotate", "Opacity", "OutlineStyle", "Overflow", diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index d6c3366c4b7..da9e5b2e767 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -384,6 +384,18 @@ ${helpers.predefined_type( 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 // https://www.w3.org/TR/cssom-view-1/ ${helpers.single_keyword( diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index b8e3c0eca17..add2ad1a40a 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -65,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}; 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/specified/mod.rs b/components/style/values/specified/mod.rs index 4cb7305fab8..409f5abe161 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -66,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}; diff --git a/components/style/values/specified/motion.rs b/components/style/values/specified/motion.rs index 73072ac6199..97609ea20b0 100644 --- a/components/style/values/specified/motion.rs +++ b/components/style/values/specified/motion.rs @@ -5,7 +5,10 @@ //! 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}; @@ -75,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 ] || " +/// +/// 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, + /// . + /// 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> { + 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), + } + } +} From e66e612452d48f3edafcaf7855f2dabb8fb152c7 Mon Sep 17 00:00:00 2001 From: violet Date: Fri, 24 May 2019 04:48:46 +0000 Subject: [PATCH 32/44] style: Use cbindgen for text-overflow. Differential Revision: https://phabricator.services.mozilla.com/D32285 --- components/style/properties/gecko.mako.rs | 78 +---------------------- components/style/values/computed/text.rs | 1 + components/style/values/specified/text.rs | 6 +- 3 files changed, 6 insertions(+), 79 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 2c83e8cf656..dd5bcf2febf 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -3342,83 +3342,7 @@ fn static_assert() { -<%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 { diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index 7395cf71bb2..bc4086a2b9c 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -105,6 +105,7 @@ impl ToComputedValue for specified::WordSpacing { pub type LineHeight = GenericLineHeight; #[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/specified/text.rs b/components/style/values/specified/text.rs index 1ab805cdcfb..165462c8175 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), + String(crate::OwnedStr), } impl Parse for TextOverflowSide { @@ -161,7 +163,7 @@ impl Parse for TextOverflowSide { } }, Token::QuotedString(ref v) => Ok(TextOverflowSide::String( - v.as_ref().to_owned().into_boxed_str(), + v.as_ref().to_owned().into(), )), ref t => Err(location.new_unexpected_token_error(t.clone())), } From 90d20f27b313ae492a69594e7c31e74ccd6a0565 Mon Sep 17 00:00:00 2001 From: Martin Stransky Date: Fri, 24 May 2019 08:51:48 +0000 Subject: [PATCH 33/44] [Linux/Gtk] Get and use Gtk theme text color for active/pressed button, - Follow Gtk and get theme button text color directly from "button" CSS node instead of "button label" - Provide new -moz-gtk-buttonactivetext color for active/pressed button text color - Replace ButtonText color with -moz-gtk-buttonactivetext when it's appropriate Differential Revision: https://phabricator.services.mozilla.com/D30566 --- components/style/properties/longhands/color.mako.rs | 1 + 1 file changed, 1 insertion(+) 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 From 87ec2cefc5c1593494754af9db49c9142716394b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 02:36:51 +0200 Subject: [PATCH 34/44] style: Tweak whitespace in Cargo.toml to match surrounding code and Gecko. --- components/style/Cargo.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index ed6e76907fd..4d5f3e2e94d 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -80,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} From 81f40a57e45900f6c23c8539f9e7356ffc54e12d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 03:11:41 +0200 Subject: [PATCH 35/44] style: Reformat recent style system changes. --- components/style/counter_style/mod.rs | 13 +- components/style/gecko/profiler.rs | 5 +- components/style/macros.rs | 9 +- components/style/rule_collector.rs | 3 +- components/style/values/animated/mod.rs | 2 +- components/style/values/computed/border.rs | 2 +- components/style/values/computed/mod.rs | 5 +- components/style/values/generics/transform.rs | 16 +- components/style/values/specified/list.rs | 4 +- components/style/values/specified/svg.rs | 6 +- components/style/values/specified/text.rs | 6 +- .../style/values/specified/transform.rs | 348 +++++++++--------- components/style_traits/arc_slice.rs | 2 +- 13 files changed, 207 insertions(+), 214 deletions(-) diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 9e2bc096e2d..72ccbd94634 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -474,10 +474,7 @@ pub struct CounterRange { /// Empty represents 'auto' #[derive(Clone, Debug, ToShmem, ToCss)] #[css(comma)] -pub struct CounterRanges( - #[css(iterable, if_empty = "auto")] - pub crate::OwnedSlice, -); +pub struct CounterRanges(#[css(iterable, if_empty = "auto")] pub crate::OwnedSlice); /// A bound found in `CounterRanges`. #[derive(Clone, Copy, Debug, ToCss, ToShmem)] @@ -503,13 +500,9 @@ impl Parse for CounterRanges { 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 let (CounterBound::Integer(start), CounterBound::Integer(end)) = (start, end) { if start > end { - return Err( - input.new_custom_error(StyleParseErrorKind::UnspecifiedError) - ); + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } } Ok(CounterRange { start, end }) diff --git a/components/style/gecko/profiler.rs b/components/style/gecko/profiler.rs index 92ad068284e..1f25dde04e7 100644 --- a/components/style/gecko/profiler.rs +++ b/components/style/gecko/profiler.rs @@ -62,9 +62,8 @@ pub fn profiler_is_active() -> bool { use std::mem; use std::sync::atomic::{AtomicU32, Ordering}; - let active_and_features: &AtomicU32 = unsafe { - mem::transmute(&detail::RacyFeatures_sActiveAndFeatures) - }; + let active_and_features: &AtomicU32 = + unsafe { mem::transmute(&detail::RacyFeatures_sActiveAndFeatures) }; (active_and_features.load(Ordering::Relaxed) & detail::RacyFeatures_Active) != 0 } diff --git a/components/style/macros.rs b/components/style/macros.rs index 1ab2fe0720e..229e864977a 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -112,9 +112,8 @@ macro_rules! define_keyword_type { #[macro_export] macro_rules! profiler_label { ($label_type:ident) => { - let mut _profiler_label: $crate::gecko_bindings::structs::AutoProfilerLabel = unsafe { - ::std::mem::uninitialized() - }; + 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( @@ -125,12 +124,12 @@ macro_rules! profiler_label { } 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) => {} + ($label_type:ident) => {}; } diff --git a/components/style/rule_collector.rs b/components/style/rule_collector.rs index 2e8ffe5d858..360b8101ef1 100644 --- a/components/style/rule_collector.rs +++ b/components/style/rule_collector.rs @@ -105,8 +105,7 @@ where MatchingMode::Normal => element.rule_hash_target(), }; - let matches_user_and_author_rules = - rule_hash_target.matches_user_and_author_rules(); + 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. diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 23c314a57a4..40edbce73ff 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -10,7 +10,7 @@ use crate::properties::PropertyId; use crate::values::computed::length::LengthPercentage; -use crate::values::computed::url::{ComputedUrl, ComputedImageUrl}; +use crate::values::computed::url::{ComputedImageUrl, ComputedUrl}; use crate::values::computed::Angle as ComputedAngle; use crate::values::computed::Image; use crate::values::specified::SVGPathData; diff --git a/components/style/values/computed/border.rs b/components/style/values/computed/border.rs index 908fd1436ac..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::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/mod.rs b/components/style/values/computed/mod.rs index add2ad1a40a..06579238e77 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -455,10 +455,7 @@ where #[inline] fn from_computed_value(computed: &Self::ComputedValue) -> Self { - computed - .iter() - .map(T::from_computed_value) - .collect() + computed.iter().map(T::from_computed_value).collect() } } diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 87f4403057f..ba0e320865a 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -240,16 +240,24 @@ where #[allow(missing_docs)] #[css(comma, function = "interpolatematrix")] InterpolateMatrix { - from_list: GenericTransform>, - to_list: GenericTransform>, + from_list: GenericTransform< + GenericTransformOperation, + >, + to_list: GenericTransform< + GenericTransformOperation, + >, progress: computed::Percentage, }, /// A intermediate type for accumulation of mismatched transform lists. #[allow(missing_docs)] #[css(comma, function = "accumulatematrix")] AccumulateMatrix { - from_list: GenericTransform>, - to_list: GenericTransform>, + from_list: GenericTransform< + GenericTransformOperation, + >, + to_list: GenericTransform< + GenericTransformOperation, + >, count: Integer, }, } diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs index 566b84bbb16..0519053b902 100644 --- a/components/style/values/specified/list.rs +++ b/components/style/values/specified/list.rs @@ -140,9 +140,7 @@ impl Parse for Quotes { loop { let location = input.current_source_location(); let opening = match input.next() { - Ok(&Token::QuotedString(ref value)) => { - value.as_ref().to_owned().into() - }, + Ok(&Token::QuotedString(ref value)) => value.as_ref().to_owned().into(), Ok(t) => return Err(location.new_unexpected_token_error(t.clone())), Err(_) => break, }; diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index 88604924deb..578870a4a91 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -298,11 +298,7 @@ impl Parse for MozContextProperties { return Ok(Self::default()); } - let ident = CustomIdent::from_ident( - location, - ident, - &["all", "none", "auto"], - )?; + let ident = CustomIdent::from_ident(location, ident, &["all", "none", "auto"])?; if ident.0 == atom!("fill") { bits.insert(ContextPropertyBits::FILL); diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index 165462c8175..188eb18f720 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -162,9 +162,9 @@ impl Parse for TextOverflowSide { )) } }, - Token::QuotedString(ref v) => Ok(TextOverflowSide::String( - v.as_ref().to_owned().into(), - )), + Token::QuotedString(ref v) => { + Ok(TextOverflowSide::String(v.as_ref().to_owned().into())) + }, ref t => Err(location.new_unexpected_token_error(t.clone())), } } diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index 4c083e896a2..e942cf13085 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -45,180 +45,184 @@ impl Transform { 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())) + })? + .into(), + )) } } diff --git a/components/style_traits/arc_slice.rs b/components/style_traits/arc_slice.rs index be50e21c0bb..6a151e3dc5a 100644 --- a/components/style_traits/arc_slice.rs +++ b/components/style_traits/arc_slice.rs @@ -5,9 +5,9 @@ //! A thin atomically-reference-counted slice. use servo_arc::ThinArc; -use std::{iter, mem}; use std::ops::Deref; use std::ptr::NonNull; +use std::{iter, mem}; /// A canary that we stash in ArcSlices. /// From e3e826d4fbfff49e43076d636af5de6cfbf3dffd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 03:19:12 +0200 Subject: [PATCH 36/44] style: Appease tidy. --- components/style/counter_style/mod.rs | 8 ++++---- components/style/properties/helpers.mako.rs | 5 ++++- components/style_traits/owned_str.rs | 2 +- 3 files changed, 9 insertions(+), 6 deletions(-) diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 72ccbd94634..289281011c3 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -408,7 +408,7 @@ impl ToCss for System { } /// -#[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToShmem, MallocSizeOf)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)] pub enum Symbol { /// String(crate::OwnedStr), @@ -461,7 +461,7 @@ impl Parse for Negative { } /// -#[derive(Clone, Debug, ToShmem, ToCss)] +#[derive(Clone, Debug, ToCss, ToShmem)] pub struct CounterRange { /// The start of the range. pub start: CounterBound, @@ -472,7 +472,7 @@ pub struct CounterRange { /// /// /// Empty represents 'auto' -#[derive(Clone, Debug, ToShmem, ToCss)] +#[derive(Clone, Debug, ToCss, ToShmem)] #[css(comma)] pub struct CounterRanges(#[css(iterable, if_empty = "auto")] pub crate::OwnedSlice); @@ -553,7 +553,7 @@ impl Parse for Fallback { } /// -#[derive(Clone, Debug, Eq, PartialEq, MallocSizeOf, ToComputedValue, ToCss, ToShmem)] +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss, ToShmem)] pub struct Symbols(#[css(iterable)] pub crate::OwnedSlice); impl Parse for Symbols { diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index 56637af9463..ca9700737fe 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -136,7 +136,10 @@ % endif use crate::values::computed::ComputedVecIter; - <% is_shared_list = allow_empty and allow_empty != "NotInitial" and data.longhands_by_name[name].style_struct.inherited %> + <% + 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 diff --git a/components/style_traits/owned_str.rs b/components/style_traits/owned_str.rs index e5fe1065712..42a83a07713 100644 --- a/components/style_traits/owned_str.rs +++ b/components/style_traits/owned_str.rs @@ -13,7 +13,7 @@ use std::ops::{Deref, DerefMut}; /// A struct that basically replaces a Box, but with a defined layout, /// suitable for FFI. #[repr(C)] -#[derive(Default, Clone, PartialEq, Eq, MallocSizeOf, ToShmem)] +#[derive(Clone, Default, Eq, MallocSizeOf, PartialEq, ToShmem)] pub struct OwnedStr(OwnedSlice); impl fmt::Debug for OwnedStr { From f1c24a203efbe1ddf3927990ecfa88803103d161 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 03:19:52 +0200 Subject: [PATCH 37/44] Update lockfile. --- Cargo.lock | 1 + 1 file changed, 1 insertion(+) 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", From 1994dbb1c8c74861e2660f3a04994d8d99c04a12 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 03:22:21 +0200 Subject: [PATCH 38/44] style: Revert a change that ended up not being needed and busts the servo build. --- components/style/values/animated/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/style/values/animated/mod.rs b/components/style/values/animated/mod.rs index 40edbce73ff..267ef0c8e6f 100644 --- a/components/style/values/animated/mod.rs +++ b/components/style/values/animated/mod.rs @@ -10,7 +10,7 @@ use crate::properties::PropertyId; use crate::values::computed::length::LengthPercentage; -use crate::values::computed::url::{ComputedImageUrl, ComputedUrl}; +use crate::values::computed::url::ComputedUrl; use crate::values::computed::Angle as ComputedAngle; use crate::values::computed::Image; use crate::values::specified::SVGPathData; @@ -380,7 +380,6 @@ trivial_to_animated_value!(Au); trivial_to_animated_value!(LengthPercentage); trivial_to_animated_value!(ComputedAngle); trivial_to_animated_value!(ComputedUrl); -trivial_to_animated_value!(ComputedImageUrl); trivial_to_animated_value!(bool); trivial_to_animated_value!(f32); // Note: This implementation is for ToAnimatedValue of ShapeSource. From cd2ac08eb9e0f2984a2d5d515cd5172e0053b9f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 03:23:42 +0200 Subject: [PATCH 39/44] atoms: Add some static atoms in code that is shared with gecko. --- components/atoms/static_atoms.txt | 4 ++++ 1 file changed, 4 insertions(+) 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 From 4671ef524330ea835d1ebe9eb1500974d68c4b25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 03:48:50 +0200 Subject: [PATCH 40/44] style: Fix servo build. --- components/style/properties/helpers.mako.rs | 4 ++-- .../style/properties/properties.mako.rs | 19 +++---------------- components/style/values/animated/effects.rs | 2 +- 3 files changed, 6 insertions(+), 19 deletions(-) diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index ca9700737fe..800d50c6220 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -366,7 +366,7 @@ pub use self::single_value::SpecifiedValue as SingleSpecifiedValue; - % if not simple_vector_bindings: + % if not simple_vector_bindings and product == "gecko": impl SpecifiedValue { fn compute_iter<'a, 'cx, 'cx_a>( &'a self, @@ -496,7 +496,7 @@ .set_writing_mode_dependency(context.builder.writing_mode); % endif - % if property.is_vector and not property.simple_vector_bindings: + % 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. // diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index ed71019b390..520b4a32b51 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -2482,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}(&mut self, v: I) - where - I: IntoIterator, - 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, @@ -3109,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; @@ -3452,7 +3439,7 @@ impl<'a> StyleBuilder<'a> { } % endif - % if not property.is_vector or property.simple_vector_bindings: + % 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/values/animated/effects.rs b/components/style/values/animated/effects.rs index 2f11e1b994d..4c559cd4c30 100644 --- a/components/style/values/animated/effects.rs +++ b/components/style/values/animated/effects.rs @@ -15,7 +15,7 @@ use crate::values::generics::effects::SimpleShadow as GenericSimpleShadow; use crate::values::Impossible; /// An animated value for the `drop-shadow()` filter. -type AnimatedSimpleShadow = GenericSimpleShadow; +pub type AnimatedSimpleShadow = GenericSimpleShadow; /// An animated value for a single `filter`. #[cfg(feature = "gecko")] From ac01c76e5e82d2a2ecbc06962658bf788d05976d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 03:48:56 +0200 Subject: [PATCH 41/44] style: Remove useless unit tests, and fix not-so-useless ones. --- tests/unit/style/animated_properties.rs | 12 ------- tests/unit/style/parsing/animation.rs | 43 ------------------------- tests/unit/style/parsing/mod.rs | 1 - tests/unit/style/stylesheets.rs | 16 ++++----- 4 files changed, 8 insertions(+), 64 deletions(-) delete mode 100644 tests/unit/style/parsing/animation.rs 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, From 70635e78157208e74c3d09966f525dae84126154 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 03:55:18 +0200 Subject: [PATCH 42/44] layout: Fix servo build. --- components/layout/display_list/border.rs | 2 +- components/layout/fragment.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) 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), From 66056bd4d554e3e65bc63cb5d6ccfb632d29c8b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 04:14:23 +0200 Subject: [PATCH 43/44] script: Fix Servo build. --- components/layout_thread/dom_wrapper.rs | 8 ++++++++ components/script/dom/element.rs | 10 +++++++--- 2 files changed, 15 insertions(+), 3 deletions(-) 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 { 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 { 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 { } } + fn is_pseudo_element(&self) -> bool { + false + } + fn match_pseudo_element( &self, _pseudo: &PseudoElement, From 324aed53f1d3852caadf33c4c611cb7ed6985996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 25 May 2019 23:24:32 +0200 Subject: [PATCH 44/44] style: Update wpt expectations. --- .../filters-test-brightness-003.html.ini | 2 -- .../parsing/filter-computed.html.ini | 27 ------------------- .../parsing/filter-parsing-valid.html.ini | 27 ------------------- 3 files changed, 56 deletions(-) delete mode 100644 tests/wpt/metadata/css/filter-effects/filters-test-brightness-003.html.ini 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 -