diff options
49 files changed, 1120 insertions, 1188 deletions
diff --git a/components/layout/display_list/builder.rs b/components/layout/display_list/builder.rs index cba26fe05a4..f951bd3f8f2 100644 --- a/components/layout/display_list/builder.rs +++ b/components/layout/display_list/builder.rs @@ -61,11 +61,11 @@ use style::properties::{style_structs, ComputedValues}; use style::servo::restyle_damage::ServoRestyleDamage; use style::values::computed::effects::SimpleShadow; use style::values::computed::image::{Image, ImageLayer}; -use style::values::computed::{Gradient, LengthOrAuto}; +use style::values::computed::{ClipRectOrAuto, Gradient, LengthOrAuto}; use style::values::generics::background::BackgroundSize; use style::values::generics::image::{GradientKind, PaintWorklet}; use style::values::specified::ui::CursorKind; -use style::values::{Either, RGBA}; +use style::values::RGBA; use style_traits::ToCss; use webrender_api::units::{LayoutRect, LayoutSize, LayoutTransform, LayoutVector2D}; use webrender_api::{self, BorderDetails, BorderRadius, BorderSide, BoxShadowClipMode, ColorF}; @@ -2632,8 +2632,8 @@ impl BlockFlow { ) { // Account for `clip` per CSS 2.1 § 11.1.2. let style_clip_rect = match self.fragment.style().get_effects().clip { - Either::First(style_clip_rect) => style_clip_rect, - _ => return, + ClipRectOrAuto::Rect(ref r) => r, + ClipRectOrAuto::Auto => return, }; // CSS `clip` should only apply to position:absolute or positione:fixed elements. diff --git a/components/layout_thread/lib.rs b/components/layout_thread/lib.rs index e24360db2dc..f03ca9f9d03 100644 --- a/components/layout_thread/lib.rs +++ b/components/layout_thread/lib.rs @@ -1497,11 +1497,10 @@ impl LayoutThread { // Create a layout context for use throughout the following passes. let mut layout_context = self.build_layout_context(guards.clone(), true, &map); + let pool; let (thread_pool, num_threads) = if self.parallel_flag { - ( - STYLE_THREAD_POOL.style_thread_pool.as_ref(), - STYLE_THREAD_POOL.num_threads, - ) + pool = STYLE_THREAD_POOL.pool(); + (pool.as_ref(), STYLE_THREAD_POOL.num_threads) } else { (None, 1) }; @@ -1859,8 +1858,10 @@ impl LayoutThread { || { let profiler_metadata = self.profiler_metadata(); + let pool; let thread_pool = if self.parallel_flag { - STYLE_THREAD_POOL.style_thread_pool.as_ref() + pool = STYLE_THREAD_POOL.pool(); + pool.as_ref() } else { None }; diff --git a/components/selectors/bloom.rs b/components/selectors/bloom.rs index c4b19e59ea8..98461d1ba24 100644 --- a/components/selectors/bloom.rs +++ b/components/selectors/bloom.rs @@ -64,7 +64,7 @@ pub type BloomFilter = CountingBloomFilter<BloomStorageU8>; /// Similarly, using a KeySize of 10 would lead to a 4% false /// positive rate for N == 100 and to quite bad false positive /// rates for larger N. -#[derive(Clone)] +#[derive(Clone, Default)] pub struct CountingBloomFilter<S> where S: BloomStorage, @@ -79,9 +79,7 @@ where /// Creates a new bloom filter. #[inline] pub fn new() -> Self { - CountingBloomFilter { - storage: Default::default(), - } + Default::default() } #[inline] diff --git a/components/style/bloom.rs b/components/style/bloom.rs index 23493e3e86a..a24dac42b2a 100644 --- a/components/style/bloom.rs +++ b/components/style/bloom.rs @@ -13,13 +13,20 @@ use owning_ref::OwningHandle; use selectors::bloom::BloomFilter; use servo_arc::Arc; use smallvec::SmallVec; +use std::mem::ManuallyDrop; thread_local! { /// Bloom filters are large allocations, so we store them in thread-local storage /// such that they can be reused across style traversals. StyleBloom is responsible /// for ensuring that the bloom filter is zeroed when it is dropped. - static BLOOM_KEY: Arc<AtomicRefCell<BloomFilter>> = - Arc::new_leaked(AtomicRefCell::new(BloomFilter::new())); + /// + /// We intentionally leak this from TLS because we don't have the guarantee + /// of TLS destructors to run in worker threads. + /// + /// We could change this once https://github.com/rayon-rs/rayon/issues/688 + /// is fixed, hopefully. + static BLOOM_KEY: ManuallyDrop<Arc<AtomicRefCell<BloomFilter>>> = + ManuallyDrop::new(Arc::new_leaked(Default::default())); } /// A struct that allows us to fast-reject deep descendant selectors avoiding @@ -128,7 +135,7 @@ impl<E: TElement> StyleBloom<E> { // See https://github.com/servo/servo/pull/18420#issuecomment-328769322 #[inline(never)] pub fn new() -> Self { - let bloom_arc = BLOOM_KEY.with(|b| b.clone()); + let bloom_arc = BLOOM_KEY.with(|b| Arc::clone(&*b)); let filter = OwningHandle::new_with_fn(bloom_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); debug_assert!( @@ -136,7 +143,7 @@ impl<E: TElement> StyleBloom<E> { "Forgot to zero the bloom filter last time" ); StyleBloom { - filter: filter, + filter, elements: Default::default(), pushed_hashes: Default::default(), } diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs index a80c486a6c3..ce084c9d16b 100644 --- a/components/style/gecko/media_features.rs +++ b/components/style/gecko/media_features.rs @@ -104,7 +104,7 @@ where }; let size = get_size(device); - let value = AspectRatio(size.width.0 as u32, size.height.0 as u32); + let value = AspectRatio(size.width.0 as f32, size.height.0 as f32); RangeOrOperator::evaluate_with_query_value(range_or_operator, query_value, value) } @@ -559,7 +559,7 @@ lazy_static! { feature!( atom!("aspect-ratio"), AllowsRanges::Yes, - Evaluator::IntRatio(eval_aspect_ratio), + Evaluator::NumberRatio(eval_aspect_ratio), ParsingRequirements::empty(), ), feature!( @@ -583,7 +583,7 @@ lazy_static! { feature!( atom!("device-aspect-ratio"), AllowsRanges::Yes, - Evaluator::IntRatio(eval_device_aspect_ratio), + Evaluator::NumberRatio(eval_device_aspect_ratio), ParsingRequirements::empty(), ), feature!( diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index f0c998f8f08..b31485345b6 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -8,7 +8,7 @@ use crate::counter_style::{Symbol, Symbols}; use crate::gecko_bindings::structs::CounterStylePtr; -use crate::values::generics::CounterStyleOrNone; +use crate::values::generics::CounterStyle; use crate::values::Either; use crate::Atom; use app_units::Au; @@ -49,19 +49,17 @@ pub fn round_border_to_device_pixels(width: Au, au_per_device_px: Au) -> Au { } } -impl CounterStyleOrNone { +impl CounterStyle { /// Convert this counter style to a Gecko CounterStylePtr. pub fn to_gecko_value(self, gecko_value: &mut CounterStylePtr) { use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToName as set_name; use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToSymbols as set_symbols; match self { - CounterStyleOrNone::None => unsafe { - set_name(gecko_value, atom!("none").into_addrefed()); - }, - CounterStyleOrNone::Name(name) => unsafe { + CounterStyle::Name(name) => unsafe { + debug_assert_ne!(name.0, atom!("none")); set_name(gecko_value, name.0.into_addrefed()); }, - CounterStyleOrNone::Symbols(symbols_type, symbols) => { + CounterStyle::Symbols(symbols_type, symbols) => { let symbols: Vec<_> = symbols .0 .iter() @@ -86,7 +84,7 @@ impl CounterStyleOrNone { } } - /// Convert Gecko CounterStylePtr to CounterStyleOrNone or String. + /// Convert Gecko CounterStylePtr to CounterStyle or String. pub fn from_gecko_value(gecko_value: &CounterStylePtr) -> Either<Self, String> { use crate::gecko_bindings::bindings; use crate::values::generics::SymbolsType; @@ -95,11 +93,8 @@ impl CounterStyleOrNone { let name = unsafe { bindings::Gecko_CounterStyle_GetName(gecko_value) }; if !name.is_null() { let name = unsafe { Atom::from_raw(name) }; - if name == atom!("none") { - Either::First(CounterStyleOrNone::None) - } else { - Either::First(CounterStyleOrNone::Name(CustomIdent(name))) - } + debug_assert_ne!(name, atom!("none")); + Either::First(CounterStyle::Name(CustomIdent(name))) } else { let anonymous = unsafe { bindings::Gecko_CounterStyle_GetAnonymous(gecko_value).as_ref() }.unwrap(); @@ -113,7 +108,7 @@ impl CounterStyleOrNone { .iter() .map(|gecko_symbol| Symbol::String(gecko_symbol.to_string().into())) .collect(); - Either::First(CounterStyleOrNone::Symbols(symbol_type, Symbols(symbols))) + Either::First(CounterStyle::Symbols(symbol_type, Symbols(symbols))) } } } diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 39e3678eebc..68c0473bf12 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -706,44 +706,6 @@ impl<'le> GeckoElement<'le> { !self.xbl_binding_with_content().is_none() } - /// This duplicates the logic in Gecko's virtual nsINode::GetBindingParent - /// function, which only has two implementations: one for XUL elements, and - /// one for other elements. - /// - /// We just hard code in our knowledge of those two implementations here. - fn xbl_binding_parent(&self) -> Option<Self> { - if self.is_xul_element() { - // FIXME(heycam): Having trouble with bindgen on nsXULElement, - // where the binding parent is stored in a member variable - // rather than in slots. So just get it through FFI for now. - unsafe { - bindings::Gecko_GetBindingParent(self.0) - .as_ref() - .map(GeckoElement) - } - } else { - let binding_parent = - unsafe { self.non_xul_xbl_binding_parent().as_ref() }.map(GeckoElement); - - debug_assert!( - binding_parent == - unsafe { - bindings::Gecko_GetBindingParent(self.0) - .as_ref() - .map(GeckoElement) - } - ); - binding_parent - } - } - - #[inline] - fn non_xul_xbl_binding_parent(&self) -> *mut RawGeckoElement { - debug_assert!(!self.is_xul_element()); - self.extended_slots() - .map_or(ptr::null_mut(), |slots| slots._base.mBindingParent.mRawPtr) - } - #[inline] fn namespace_id(&self) -> i32 { self.as_node().node_info().mInner.mNamespaceID @@ -865,19 +827,9 @@ impl<'le> GeckoElement<'le> { return self.flags() & (NODE_IS_NATIVE_ANONYMOUS_ROOT as u32) != 0; } - /// This logic is duplicated in Gecko's nsIContent::IsInAnonymousSubtree. #[inline] fn is_in_anonymous_subtree(&self) -> bool { - if self.is_in_native_anonymous_subtree() { - return true; - } - - let binding_parent = match self.xbl_binding_parent() { - Some(p) => p, - None => return false, - }; - - binding_parent.shadow_root().is_none() + unsafe { bindings::Gecko_IsInAnonymousSubtree(self.0) } } /// Returns true if this node is the shadow root of an use-element shadow tree. diff --git a/components/style/global_style_data.rs b/components/style/global_style_data.rs index eff53078c9e..a9e79bf6820 100644 --- a/components/style/global_style_data.rs +++ b/components/style/global_style_data.rs @@ -10,8 +10,10 @@ use crate::gecko_bindings::bindings; use crate::parallel::STYLE_THREAD_STACK_SIZE_KB; use crate::shared_lock::SharedRwLock; use crate::thread_state; +use parking_lot::{RwLock, RwLockReadGuard}; use rayon; use std::env; +use std::sync::atomic::{AtomicUsize, Ordering}; /// Global style data pub struct GlobalStyleData { @@ -22,20 +24,28 @@ pub struct GlobalStyleData { pub options: StyleSystemOptions, } -/// Global thread pool +/// Global thread pool. pub struct StyleThreadPool { /// How many threads parallel styling can use. pub num_threads: usize, /// The parallel styling thread pool. - pub style_thread_pool: Option<rayon::ThreadPool>, + /// + /// For leak-checking purposes, we want to terminate the thread-pool, which + /// waits for all the async jobs to complete. Thus the RwLock. + style_thread_pool: RwLock<Option<rayon::ThreadPool>>, } fn thread_name(index: usize) -> String { format!("StyleThread#{}", index) } +// A counter so that we can wait for shutdown of all threads. See +// StyleThreadPool::shutdown. +static ALIVE_WORKER_THREADS: AtomicUsize = AtomicUsize::new(0); + fn thread_startup(_index: usize) { + ALIVE_WORKER_THREADS.fetch_add(1, Ordering::Relaxed); thread_state::initialize_layout_worker_thread(); #[cfg(feature = "gecko")] unsafe { @@ -55,6 +65,43 @@ fn thread_shutdown(_: usize) { bindings::Gecko_UnregisterProfilerThread(); bindings::Gecko_SetJemallocThreadLocalArena(false); } + ALIVE_WORKER_THREADS.fetch_sub(1, Ordering::Relaxed); +} + +impl StyleThreadPool { + /// Shuts down the thread pool, waiting for all work to complete. + pub fn shutdown() { + if ALIVE_WORKER_THREADS.load(Ordering::Relaxed) == 0 { + return; + } + { + // Drop the pool. + let _ = STYLE_THREAD_POOL.style_thread_pool.write().take(); + } + // Spin until all our threads are done. This will usually be pretty + // fast, as on shutdown there should be basically no threads left + // running. + // + // This still _technically_ doesn't give us the guarantee of TLS + // destructors running on the worker threads. For that we'd need help + // from rayon to properly join the threads. + // + // See https://github.com/rayon-rs/rayon/issues/688 + // + // So we instead intentionally leak TLS stuff (see BLOOM_KEY and co) for + // now until that's fixed. + while ALIVE_WORKER_THREADS.load(Ordering::Relaxed) != 0 { + std::thread::yield_now(); + } + } + + /// Returns a reference to the thread pool. + /// + /// We only really want to give read-only access to the pool, except + /// for shutdown(). + pub fn pool(&self) -> RwLockReadGuard<Option<rayon::ThreadPool>> { + self.style_thread_pool.read() + } } lazy_static! { @@ -113,10 +160,11 @@ lazy_static! { }; StyleThreadPool { - num_threads: num_threads, - style_thread_pool: pool, + num_threads, + style_thread_pool: RwLock::new(pool), } }; + /// Global style data pub static ref GLOBAL_STYLE_DATA: GlobalStyleData = GlobalStyleData { shared_lock: SharedRwLock::new_leaked(), diff --git a/components/style/invalidation/element/state_and_attributes.rs b/components/style/invalidation/element/state_and_attributes.rs index eccc5f60bbf..30521fb8c00 100644 --- a/components/style/invalidation/element/state_and_attributes.rs +++ b/components/style/invalidation/element/state_and_attributes.rs @@ -16,7 +16,7 @@ use crate::invalidation::element::invalidator::{Invalidation, InvalidationProces use crate::invalidation::element::restyle_hints::RestyleHint; use crate::selector_map::SelectorMap; use crate::selector_parser::Snapshot; -use crate::stylesheets::origin::{Origin, OriginSet}; +use crate::stylesheets::origin::OriginSet; use crate::{Atom, WeakAtom}; use selectors::attr::CaseSensitivity; use selectors::matching::matches_selector; @@ -246,7 +246,7 @@ where }; let document_origins = if !matches_document_author_rules { - Origin::UserAgent.into() + OriginSet::ORIGIN_USER_AGENT | OriginSet::ORIGIN_USER } else { OriginSet::all() }; diff --git a/components/style/logical_geometry.rs b/components/style/logical_geometry.rs index 3817c12dcf0..38ffb25a740 100644 --- a/components/style/logical_geometry.rs +++ b/components/style/logical_geometry.rs @@ -26,16 +26,48 @@ pub enum InlineBaseDirection { // TODO: improve the readability of the WritingMode serialization, refer to the Debug:fmt() bitflags!( #[cfg_attr(feature = "servo", derive(MallocSizeOf, Serialize))] + #[repr(C)] pub struct WritingMode: u8 { - const RTL = 1 << 0; - const VERTICAL = 1 << 1; + /// A vertical writing mode; writing-mode is vertical-rl, + /// vertical-lr, sideways-lr, or sideways-rl. + const VERTICAL = 1 << 0; + /// The inline flow direction is reversed against the physical + /// direction (i.e. right-to-left or bottom-to-top); writing-mode is + /// sideways-lr or direction is rtl (but not both). + /// + /// (This bit can be derived from the others, but we store it for + /// convenience.) + const INLINE_REVERSED = 1 << 1; + /// A vertical writing mode whose block progression direction is left- + /// to-right; writing-mode is vertical-lr or sideways-lr. + /// + /// Never set without VERTICAL. const VERTICAL_LR = 1 << 2; - /// For vertical writing modes only. When set, line-over/line-under - /// sides are inverted from block-start/block-end. This flag is - /// set when sideways-lr is used. + /// The line-over/line-under sides are inverted with respect to the + /// block-start/block-end edge; writing-mode is vertical-lr. + /// + /// Never set without VERTICAL and VERTICAL_LR. const LINE_INVERTED = 1 << 3; - const SIDEWAYS = 1 << 4; - const UPRIGHT = 1 << 5; + /// direction is rtl. + const RTL = 1 << 4; + /// Horizontal text within a vertical writing mode is displayed sideways + /// and runs top-to-bottom or bottom-to-top; set in these cases: + /// + /// * writing-mode: vertical-rl; text-orientation: sideways; + /// * writing-mode: vertical-lr; text-orientation: sideways; + /// * writing-mode: sideways-rl; + /// * writing-mode: sideways-lr; + /// + /// Never set without VERTICAL. + const SIDEWAYS = 1 << 5; + /// Horizontal text within a vertical writing mode is displayed with each + /// glyph upright; set in these cases: + /// + /// * writing-mode: vertical-rl; text-orientation: upright; + /// * writing-mode: vertical-lr: text-orientation: upright; + /// + /// Never set without VERTICAL. + const UPRIGHT = 1 << 6; } ); @@ -47,33 +79,52 @@ impl WritingMode { let mut flags = WritingMode::empty(); - match inheritedbox_style.clone_direction() { + let direction = inheritedbox_style.clone_direction(); + let writing_mode = inheritedbox_style.clone_writing_mode(); + + match direction { Direction::Ltr => {}, Direction::Rtl => { flags.insert(WritingMode::RTL); }, } - match inheritedbox_style.clone_writing_mode() { - SpecifiedWritingMode::HorizontalTb => {}, + match writing_mode { + SpecifiedWritingMode::HorizontalTb => { + if direction == Direction::Rtl { + flags.insert(WritingMode::INLINE_REVERSED); + } + }, SpecifiedWritingMode::VerticalRl => { flags.insert(WritingMode::VERTICAL); + if direction == Direction::Rtl { + flags.insert(WritingMode::INLINE_REVERSED); + } }, SpecifiedWritingMode::VerticalLr => { flags.insert(WritingMode::VERTICAL); flags.insert(WritingMode::VERTICAL_LR); + flags.insert(WritingMode::LINE_INVERTED); + if direction == Direction::Rtl { + flags.insert(WritingMode::INLINE_REVERSED); + } }, #[cfg(feature = "gecko")] SpecifiedWritingMode::SidewaysRl => { flags.insert(WritingMode::VERTICAL); flags.insert(WritingMode::SIDEWAYS); + if direction == Direction::Rtl { + flags.insert(WritingMode::INLINE_REVERSED); + } }, #[cfg(feature = "gecko")] SpecifiedWritingMode::SidewaysLr => { flags.insert(WritingMode::VERTICAL); flags.insert(WritingMode::VERTICAL_LR); - flags.insert(WritingMode::LINE_INVERTED); flags.insert(WritingMode::SIDEWAYS); + if direction == Direction::Ltr { + flags.insert(WritingMode::INLINE_REVERSED); + } }, } @@ -81,19 +132,21 @@ impl WritingMode { { use crate::properties::longhands::text_orientation::computed_value::T as TextOrientation; - // If FLAG_SIDEWAYS is already set, this means writing-mode is - // either sideways-rl or sideways-lr, and for both of these values, - // text-orientation has no effect. - if !flags.intersects(WritingMode::SIDEWAYS) { - match inheritedbox_style.clone_text_orientation() { - TextOrientation::Mixed => {}, - TextOrientation::Upright => { - flags.insert(WritingMode::UPRIGHT); - }, - TextOrientation::Sideways => { - flags.insert(WritingMode::SIDEWAYS); - }, - } + // text-orientation only has an effect for vertical-rl and + // vertical-lr values of writing-mode. + match writing_mode { + SpecifiedWritingMode::VerticalRl | SpecifiedWritingMode::VerticalLr => { + match inheritedbox_style.clone_text_orientation() { + TextOrientation::Mixed => {}, + TextOrientation::Upright => { + flags.insert(WritingMode::UPRIGHT); + }, + TextOrientation::Sideways => { + flags.insert(WritingMode::SIDEWAYS); + }, + } + }, + _ => {}, } } @@ -115,7 +168,7 @@ impl WritingMode { #[inline] pub fn is_inline_tb(&self) -> bool { // https://drafts.csswg.org/css-writing-modes-3/#logical-to-physical - self.intersects(WritingMode::RTL) == self.intersects(WritingMode::LINE_INVERTED) + !self.intersects(WritingMode::INLINE_REVERSED) } #[inline] diff --git a/components/style/media_queries/media_feature.rs b/components/style/media_queries/media_feature.rs index d5e015b3b07..c5251f7419f 100644 --- a/components/style/media_queries/media_feature.rs +++ b/components/style/media_queries/media_feature.rs @@ -44,8 +44,8 @@ pub enum Evaluator { Integer(MediaFeatureEvaluator<u32>), Float(MediaFeatureEvaluator<f32>), BoolInteger(MediaFeatureEvaluator<bool>), - /// An integer ratio, such as the one from device-pixel-ratio. - IntRatio(MediaFeatureEvaluator<AspectRatio>), + /// A non-negative number ratio, such as the one from device-pixel-ratio. + NumberRatio(MediaFeatureEvaluator<AspectRatio>), /// A resolution. Resolution(MediaFeatureEvaluator<Resolution>), /// A keyword value. diff --git a/components/style/media_queries/media_feature_expression.rs b/components/style/media_queries/media_feature_expression.rs index 98c7d59c7e1..1eef9e57ebc 100644 --- a/components/style/media_queries/media_feature_expression.rs +++ b/components/style/media_queries/media_feature_expression.rs @@ -16,6 +16,8 @@ use crate::parser::{Parse, ParserContext}; use crate::servo::media_queries::MEDIA_FEATURES; use crate::str::{starts_with_ignore_ascii_case, string_as_ascii_lowercase}; use crate::values::computed::{self, ToComputedValue}; +#[cfg(feature = "gecko")] +use crate::values::specified::NonNegativeNumber; use crate::values::specified::{Integer, Length, Number, Resolution}; use crate::values::{serialize_atom_identifier, CSSFloat}; use crate::{Atom, Zero}; @@ -25,8 +27,8 @@ use std::fmt::{self, Write}; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; /// An aspect ratio, with a numerator and denominator. -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)] -pub struct AspectRatio(pub u32, pub u32); +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToShmem)] +pub struct AspectRatio(pub CSSFloat, pub CSSFloat); impl ToCss for AspectRatio { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result @@ -41,9 +43,9 @@ impl ToCss for AspectRatio { impl PartialOrd for AspectRatio { fn partial_cmp(&self, other: &AspectRatio) -> Option<Ordering> { - u64::partial_cmp( - &(self.0 as u64 * other.1 as u64), - &(self.1 as u64 * other.0 as u64), + f64::partial_cmp( + &(self.0 as f64 * other.1 as f64), + &(self.1 as f64 * other.0 as f64), ) } } @@ -429,9 +431,11 @@ impl MediaFeatureExpression { eval(device, expect!(Integer).cloned(), self.range_or_operator) }, Evaluator::Float(eval) => eval(device, expect!(Float).cloned(), self.range_or_operator), - Evaluator::IntRatio(eval) => { - eval(device, expect!(IntRatio).cloned(), self.range_or_operator) - }, + Evaluator::NumberRatio(eval) => eval( + device, + expect!(NumberRatio).cloned(), + self.range_or_operator, + ), Evaluator::Resolution(eval) => { let computed = expect!(Resolution).map(|specified| { computed::Context::for_media_query_evaluation(device, quirks_mode, |context| { @@ -456,7 +460,7 @@ impl MediaFeatureExpression { /// A value found or expected in a media expression. /// /// FIXME(emilio): How should calc() serialize in the Number / Integer / -/// BoolInteger / IntRatio case, as computed or as specified value? +/// BoolInteger / NumberRatio case, as computed or as specified value? /// /// If the first, this would need to store the relevant values. /// @@ -471,9 +475,9 @@ pub enum MediaExpressionValue { Float(CSSFloat), /// A boolean value, specified as an integer (i.e., either 0 or 1). BoolInteger(bool), - /// Two integers separated by '/', with optional whitespace on either side - /// of the '/'. - IntRatio(AspectRatio), + /// A single non-negative number or two non-negative numbers separated by '/', + /// with optional whitespace on either side of the '/'. + NumberRatio(AspectRatio), /// A resolution. Resolution(Resolution), /// An enumerated value, defined by the variant keyword table in the @@ -493,7 +497,7 @@ impl MediaExpressionValue { MediaExpressionValue::Integer(v) => v.to_css(dest), MediaExpressionValue::Float(v) => v.to_css(dest), MediaExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }), - MediaExpressionValue::IntRatio(ratio) => ratio.to_css(dest), + MediaExpressionValue::NumberRatio(ratio) => ratio.to_css(dest), MediaExpressionValue::Resolution(ref r) => r.to_css(dest), MediaExpressionValue::Ident(ref ident) => serialize_atom_identifier(ident, dest), MediaExpressionValue::Enumerated(value) => match for_expr.feature().evaluator { @@ -529,11 +533,26 @@ impl MediaExpressionValue { let number = Number::parse(context, input)?; MediaExpressionValue::Float(number.get()) }, - Evaluator::IntRatio(..) => { + Evaluator::NumberRatio(..) => { + #[cfg(feature = "gecko")] + { + if static_prefs::pref!("layout.css.aspect-ratio-number.enabled") { + let a = NonNegativeNumber::parse(context, input)?.0.get(); + let b = match input.try_parse(|input| input.expect_delim('/')) { + Ok(()) => NonNegativeNumber::parse(context, input)?.0.get(), + _ => 1.0, + }; + return Ok(MediaExpressionValue::NumberRatio(AspectRatio(a, b))); + } + } + let a = Integer::parse_positive(context, input)?; input.expect_delim('/')?; let b = Integer::parse_positive(context, input)?; - MediaExpressionValue::IntRatio(AspectRatio(a.value() as u32, b.value() as u32)) + MediaExpressionValue::NumberRatio(AspectRatio( + a.value() as CSSFloat, + b.value() as CSSFloat, + )) }, Evaluator::Resolution(..) => { MediaExpressionValue::Resolution(Resolution::parse(context, input)?) diff --git a/components/style/properties/counted_unknown_properties.py b/components/style/properties/counted_unknown_properties.py new file mode 100644 index 00000000000..628d7463ded --- /dev/null +++ b/components/style/properties/counted_unknown_properties.py @@ -0,0 +1,128 @@ +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +# The following properties are under development, so they are not in this list. +# FIXME: We should handle the developing properties properly by Bug 1577358: +# "backdrop-filter", +# "text-decoration-skip-ink", +# "column-span", +# "offset-distance", +# "offset-path", +# "offset-rotate" +COUNTED_UNKNOWN_PROPERTIES = [ + "-webkit-font-smoothing", + "zoom", + "-webkit-tap-highlight-color", + "speak", + "text-size-adjust", + "-webkit-font-feature-settings", + "-webkit-user-drag", + "size", + "-webkit-clip-path", + "orphans", + "widows", + "-webkit-user-modify", + "-webkit-margin-before", + "-webkit-margin-after", + "tab-size", + "-webkit-margin-start", + "-webkit-column-break-inside", + "-webkit-padding-start", + "-webkit-margin-end", + "-webkit-box-reflect", + "-webkit-print-color-adjust", + "-webkit-mask-box-image", + "-webkit-line-break", + "-webkit-text-security", + "alignment-baseline", + "-webkit-writing-mode", + "baseline-shift", + "-webkit-hyphenate-character", + "page", + "text-underline-position", + "-webkit-highlight", + "background-repeat-x", + "-webkit-padding-end", + "background-repeat-y", + "-webkit-text-emphasis-color", + "-webkit-margin-top-collapse", + "-webkit-rtl-ordering", + "-webkit-padding-before", + "-webkit-text-decorations-in-effect", + "-webkit-border-vertical-spacing", + "-webkit-locale", + "-webkit-padding-after", + "-webkit-border-horizontal-spacing", + "color-rendering", + "-webkit-column-break-before", + "-webkit-transform-origin-x", + "-webkit-transform-origin-y", + "-webkit-text-emphasis-position", + "buffered-rendering", + "-webkit-text-orientation", + "-webkit-text-combine", + "-webkit-text-emphasis-style", + "-webkit-text-emphasis", + "d", + "-webkit-mask-box-image-width", + "-webkit-mask-box-image-source", + "-webkit-mask-box-image-outset", + "-webkit-mask-box-image-slice", + "-webkit-mask-box-image-repeat", + "-webkit-margin-after-collapse", + "-webkit-border-before-color", + "-webkit-border-before-width", + "-webkit-perspective-origin-x", + "-webkit-perspective-origin-y", + "-webkit-margin-before-collapse", + "-webkit-border-before-style", + "scroll-snap-stop", + "-webkit-margin-bottom-collapse", + "-webkit-ruby-position", + "-webkit-column-break-after", + "-webkit-margin-collapse", + "offset", + "-webkit-border-before", + "-webkit-border-end", + "-webkit-border-after", + "-webkit-border-start", + "-webkit-min-logical-width", + "-webkit-logical-height", + "-webkit-transform-origin-z", + "-webkit-font-size-delta", + "-webkit-logical-width", + "-webkit-max-logical-width", + "-webkit-min-logical-height", + "-webkit-max-logical-height", + "-webkit-border-end-color", + "-webkit-border-end-width", + "-webkit-border-start-color", + "-webkit-border-start-width", + "-webkit-border-after-color", + "-webkit-border-after-width", + "-webkit-border-end-style", + "-webkit-border-after-style", + "-webkit-border-start-style", + "-webkit-mask-repeat-x", + "-webkit-mask-repeat-y", + "user-zoom", + "min-zoom", + "-webkit-box-decoration-break", + "orientation", + "max-zoom", + "-webkit-app-region", + "-webkit-column-rule", + "-webkit-column-span", + "-webkit-column-gap", + "-webkit-shape-outside", + "-webkit-column-rule-width", + "-webkit-column-count", + "-webkit-opacity", + "-webkit-column-width", + "-webkit-shape-image-threshold", + "-webkit-column-rule-style", + "-webkit-columns", + "-webkit-column-rule-color", + "-webkit-shape-margin", +] diff --git a/components/style/properties/data.py b/components/style/properties/data.py index d1e78e6648c..d1876a5ea02 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -3,6 +3,7 @@ # file, You can obtain one at https://mozilla.org/MPL/2.0/. import re +from counted_unknown_properties import COUNTED_UNKNOWN_PROPERTIES PHYSICAL_SIDES = ["top", "right", "bottom", "left"] LOGICAL_SIDES = ["block-start", "block-end", "inline-start", "inline-end"] @@ -574,6 +575,7 @@ class PropertiesData(object): self.shorthands = [] self.shorthands_by_name = {} self.shorthand_aliases = [] + self.counted_unknown_properties = [CountedUnknownProperty(p) for p in COUNTED_UNKNOWN_PROPERTIES] def new_style_struct(self, *args, **kwargs): style_struct = StyleStruct(*args, **kwargs) @@ -794,3 +796,10 @@ class PropertyRestrictions: + PropertyRestrictions.shorthand(data, "background") + PropertyRestrictions.shorthand(data, "outline") + PropertyRestrictions.shorthand(data, "font")) + + +class CountedUnknownProperty: + def __init__(self, name): + self.name = name + self.ident = to_rust_ident(name) + self.camel_case = to_camel_case(self.ident) diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 6078f6712a7..930d4400d3d 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -6,34 +6,36 @@ #![deny(missing_docs)] +use super::*; use crate::context::QuirksMode; -use cssparser::{DeclarationListParser, parse_important, ParserInput, CowRcStr}; -use cssparser::{Parser, AtRuleParser, DeclarationParser, Delimiter, ParseErrorKind}; -use crate::custom_properties::{CustomPropertiesBuilder, CssEnvironment}; -use crate::error_reporting::{ParseErrorReporter, ContextualParseError}; -use itertools::Itertools; +use crate::custom_properties::{CssEnvironment, CustomPropertiesBuilder}; +use crate::error_reporting::{ContextualParseError, ParseErrorReporter}; use crate::parser::ParserContext; use crate::properties::animated_properties::{AnimationValue, AnimationValueMap}; +use crate::selector_parser::SelectorImpl; use crate::shared_lock::Locked; +use crate::str::{CssString, CssStringBorrow, CssStringWriter}; +use crate::stylesheets::{CssRuleType, Origin, UrlExtraData}; +use crate::values::computed::Context; +use cssparser::{parse_important, CowRcStr, DeclarationListParser, ParserInput}; +use cssparser::{AtRuleParser, DeclarationParser, Delimiter, ParseErrorKind, Parser}; +use itertools::Itertools; +use selectors::SelectorList; use smallbitvec::{self, SmallBitVec}; use smallvec::SmallVec; use std::fmt::{self, Write}; use std::iter::{DoubleEndedIterator, Zip}; use std::slice::Iter; -use crate::str::{CssString, CssStringBorrow, CssStringWriter}; use style_traits::{CssWriter, ParseError, ParsingMode, StyleParseErrorKind, ToCss}; -use crate::stylesheets::{CssRuleType, Origin, UrlExtraData}; -use super::*; -use crate::values::computed::Context; -use crate::selector_parser::SelectorImpl; -use selectors::SelectorList; /// The animation rules. /// /// The first one is for Animation cascade level, and the second one is for /// Transition cascade level. -pub struct AnimationRules(pub Option<Arc<Locked<PropertyDeclarationBlock>>>, - pub Option<Arc<Locked<PropertyDeclarationBlock>>>); +pub struct AnimationRules( + pub Option<Arc<Locked<PropertyDeclarationBlock>>>, + pub Option<Arc<Locked<PropertyDeclarationBlock>>>, +); impl AnimationRules { /// Returns whether these animation rules represents an actual rule or not. @@ -122,8 +124,16 @@ impl<'a> Iterator for DeclarationImportanceIterator<'a> { #[inline] fn next(&mut self) -> Option<Self::Item> { - self.iter.next().map(|(decl, important)| - (decl, if important { Importance::Important } else { Importance::Normal })) + self.iter.next().map(|(decl, important)| { + ( + decl, + if important { + Importance::Important + } else { + Importance::Normal + }, + ) + }) } #[inline] @@ -135,13 +145,21 @@ impl<'a> Iterator for DeclarationImportanceIterator<'a> { impl<'a> DoubleEndedIterator for DeclarationImportanceIterator<'a> { #[inline(always)] fn next_back(&mut self) -> Option<Self::Item> { - self.iter.next_back().map(|(decl, important)| - (decl, if important { Importance::Important } else { Importance::Normal })) + self.iter.next_back().map(|(decl, important)| { + ( + decl, + if important { + Importance::Important + } else { + Importance::Normal + }, + ) + }) } } /// Iterator for AnimationValue to be generated from PropertyDeclarationBlock. -pub struct AnimationValueIterator<'a, 'cx, 'cx_a:'cx> { +pub struct AnimationValueIterator<'a, 'cx, 'cx_a: 'cx> { iter: DeclarationImportanceIterator<'a>, context: &'cx mut Context<'cx_a>, default_values: &'a ComputedValues, @@ -149,7 +167,7 @@ pub struct AnimationValueIterator<'a, 'cx, 'cx_a:'cx> { extra_custom_properties: Option<&'a Arc<crate::custom_properties::CustomPropertiesMap>>, } -impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> { +impl<'a, 'cx, 'cx_a: 'cx> AnimationValueIterator<'a, 'cx, 'cx_a> { fn new( declarations: &'a PropertyDeclarationBlock, context: &'cx mut Context<'cx_a>, @@ -165,7 +183,7 @@ impl<'a, 'cx, 'cx_a:'cx> AnimationValueIterator<'a, 'cx, 'cx_a> { } } -impl<'a, 'cx, 'cx_a:'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> { +impl<'a, 'cx, 'cx_a: 'cx> Iterator for AnimationValueIterator<'a, 'cx, 'cx_a> { type Item = AnimationValue; #[inline] fn next(&mut self) -> Option<Self::Item> { @@ -256,7 +274,7 @@ impl PropertyDeclarationBlock { /// Return an iterator of (AnimatableLonghand, AnimationValue). #[inline] - pub fn to_animation_value_iter<'a, 'cx, 'cx_a:'cx>( + pub fn to_animation_value_iter<'a, 'cx, 'cx_a: 'cx>( &'a self, context: &'cx mut Context<'cx_a>, default_values: &'a ComputedValues, @@ -300,7 +318,10 @@ impl PropertyDeclarationBlock { /// NOTE: This is linear time in the case of custom properties or in the /// case the longhand is actually in the declaration block. #[inline] - pub fn get(&self, property: PropertyDeclarationId) -> Option<(&PropertyDeclaration, Importance)> { + pub fn get( + &self, + property: PropertyDeclarationId, + ) -> Option<(&PropertyDeclaration, Importance)> { if let PropertyDeclarationId::Longhand(id) = property { if !self.contains(id) { return None; @@ -350,9 +371,7 @@ impl PropertyDeclarationBlock { // We don't print !important when serializing individual properties, // so we treat this as a normal-importance property match shorthand.get_shorthand_appendable_value(list.iter().cloned()) { - Some(appendable_value) => { - append_declaration_value(dest, appendable_value) - } + Some(appendable_value) => append_declaration_value(dest, appendable_value), None => return Ok(()), } } @@ -360,7 +379,11 @@ impl PropertyDeclarationBlock { /// Find the value of the given property in this block and serialize it /// /// <https://drafts.csswg.org/cssom/#dom-cssstyledeclaration-getpropertyvalue> - pub fn property_value_to_css(&self, property: &PropertyId, dest: &mut CssStringWriter) -> fmt::Result { + pub fn property_value_to_css( + &self, + property: &PropertyId, + dest: &mut CssStringWriter, + ) -> fmt::Result { // Step 1.1: done when parsing a string to PropertyId // Step 1.2 @@ -394,11 +417,12 @@ impl PropertyDeclarationBlock { } else { Importance::Normal } - } + }, Err(longhand_or_custom) => { // Step 3 - self.get(longhand_or_custom).map_or(Importance::Normal, |(_, importance)| importance) - } + self.get(longhand_or_custom) + .map_or(Importance::Normal, |(_, importance)| importance) + }, } } @@ -407,7 +431,9 @@ impl PropertyDeclarationBlock { /// and it doesn't exist in the block, and returns false otherwise. #[inline] fn is_definitely_new(&self, decl: &PropertyDeclaration) -> bool { - decl.id().as_longhand().map_or(false, |id| !self.longhands.contains(id)) + decl.id() + .as_longhand() + .map_or(false, |id| !self.longhands.contains(id)) } /// Adds or overrides the declaration for a given property in this block. @@ -421,11 +447,11 @@ impl PropertyDeclarationBlock { ) -> bool { let all_shorthand_len = match drain.all_shorthand { AllShorthand::NotSet => 0, - AllShorthand::CSSWideKeyword(_) | - AllShorthand::WithVariables(_) => shorthands::ALL_SHORTHAND_MAX_LEN, + AllShorthand::CSSWideKeyword(_) | AllShorthand::WithVariables(_) => { + shorthands::ALL_SHORTHAND_MAX_LEN + }, }; - let push_calls_count = - drain.declarations.len() + all_shorthand_len; + let push_calls_count = drain.declarations.len() + all_shorthand_len; // With deduplication the actual length increase may be less than this. self.declarations.reserve(push_calls_count); @@ -434,9 +460,12 @@ impl PropertyDeclarationBlock { for decl in &mut drain.declarations { changed |= self.push(decl, importance); } - drain.all_shorthand.declarations().fold(changed, |changed, decl| { - changed | self.push(decl, importance) - }) + drain + .all_shorthand + .declarations() + .fold(changed, |changed, decl| { + changed | self.push(decl, importance) + }) } /// Adds or overrides the declaration for a given property in this block. @@ -444,11 +473,7 @@ impl PropertyDeclarationBlock { /// Returns whether the declaration has changed. /// /// This is only used for parsing and internal use. - pub fn push( - &mut self, - declaration: PropertyDeclaration, - importance: Importance, - ) -> bool { + pub fn push(&mut self, declaration: PropertyDeclaration, importance: Importance) -> bool { if !self.is_definitely_new(&declaration) { let mut index_to_remove = None; for (i, slot) in self.declarations.iter_mut().enumerate() { @@ -498,78 +523,92 @@ impl PropertyDeclarationBlock { // Check whether we are updating for an all shorthand change. if !matches!(source_declarations.all_shorthand, AllShorthand::NotSet) { debug_assert!(source_declarations.declarations.is_empty()); - return source_declarations.all_shorthand.declarations().any(|decl| { - self.is_definitely_new(&decl) || - self.declarations.iter().enumerate() - .find(|&(_, ref d)| d.id() == decl.id()) - .map_or(true, |(i, d)| { - let important = self.declarations_importance[i]; - *d != decl || important != importance.important() - }) - }); + return source_declarations + .all_shorthand + .declarations() + .any(|decl| { + self.is_definitely_new(&decl) || + self.declarations + .iter() + .enumerate() + .find(|&(_, ref d)| d.id() == decl.id()) + .map_or(true, |(i, d)| { + let important = self.declarations_importance[i]; + *d != decl || important != importance.important() + }) + }); } // Fill `updates` with update information. let mut any_update = false; let new_count = &mut updates.new_count; let any_removal = &mut updates.any_removal; let updates = &mut updates.updates; - updates.extend(source_declarations.declarations.iter().map(|declaration| { - if self.is_definitely_new(declaration) { - return DeclarationUpdate::Append; - } - let longhand_id = declaration.id().as_longhand(); - if let Some(longhand_id) = longhand_id { - if let Some(logical_group) = longhand_id.logical_group() { - let mut needs_append = false; - for (pos, decl) in self.declarations.iter().enumerate().rev() { - let id = match decl.id().as_longhand() { - Some(id) => id, - None => continue, - }; - if id == longhand_id { - if needs_append { - return DeclarationUpdate::AppendAndRemove { pos }; + updates.extend( + source_declarations + .declarations + .iter() + .map(|declaration| { + if self.is_definitely_new(declaration) { + return DeclarationUpdate::Append; + } + let longhand_id = declaration.id().as_longhand(); + if let Some(longhand_id) = longhand_id { + if let Some(logical_group) = longhand_id.logical_group() { + let mut needs_append = false; + for (pos, decl) in self.declarations.iter().enumerate().rev() { + let id = match decl.id().as_longhand() { + Some(id) => id, + None => continue, + }; + if id == longhand_id { + if needs_append { + return DeclarationUpdate::AppendAndRemove { pos }; + } + let important = self.declarations_importance[pos]; + if decl == declaration && important == importance.important() { + return DeclarationUpdate::None; + } + return DeclarationUpdate::UpdateInPlace { pos }; + } + if !needs_append && + id.logical_group() == Some(logical_group) && + id.is_logical() != longhand_id.is_logical() + { + needs_append = true; + } } + unreachable!("Longhand should be found in loop above"); + } + } + self.declarations + .iter() + .enumerate() + .find(|&(_, ref decl)| decl.id() == declaration.id()) + .map_or(DeclarationUpdate::Append, |(pos, decl)| { let important = self.declarations_importance[pos]; if decl == declaration && important == importance.important() { - return DeclarationUpdate::None; + DeclarationUpdate::None + } else { + DeclarationUpdate::UpdateInPlace { pos } } - return DeclarationUpdate::UpdateInPlace { pos }; - } - if !needs_append && - id.logical_group() == Some(logical_group) && - id.is_logical() != longhand_id.is_logical() { - needs_append = true; - } + }) + }) + .inspect(|update| { + if matches!(update, DeclarationUpdate::None) { + return; } - unreachable!("Longhand should be found in loop above"); - } - } - self.declarations.iter().enumerate() - .find(|&(_, ref decl)| decl.id() == declaration.id()) - .map_or(DeclarationUpdate::Append, |(pos, decl)| { - let important = self.declarations_importance[pos]; - if decl == declaration && important == importance.important() { - DeclarationUpdate::None - } else { - DeclarationUpdate::UpdateInPlace { pos } + any_update = true; + match update { + DeclarationUpdate::Append => { + *new_count += 1; + }, + DeclarationUpdate::AppendAndRemove { .. } => { + *any_removal = true; + }, + _ => {}, } - }) - }).inspect(|update| { - if matches!(update, DeclarationUpdate::None) { - return; - } - any_update = true; - match update { - DeclarationUpdate::Append => { - *new_count += 1; - } - DeclarationUpdate::AppendAndRemove { .. } => { - *any_removal = true; - } - _ => {} - } - })); + }), + ); any_update } @@ -590,8 +629,12 @@ impl PropertyDeclarationBlock { self.declarations_importance.push(important); self.longhands.insert(longhand_id); } else { - let (idx, slot) = self.declarations.iter_mut() - .enumerate().find(|&(_, ref d)| d.id() == decl.id()).unwrap(); + let (idx, slot) = self + .declarations + .iter_mut() + .enumerate() + .find(|&(_, ref d)| d.id() == decl.id()) + .unwrap(); *slot = decl; self.declarations_importance.set(idx, important); } @@ -607,19 +650,24 @@ impl PropertyDeclarationBlock { pos: usize, remove: bool, } - let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = - updates.updates.iter_mut().filter_map(|item| { + let mut updates_and_removals: SubpropertiesVec<UpdateOrRemoval> = updates + .updates + .iter_mut() + .filter_map(|item| { let (pos, remove) = match *item { DeclarationUpdate::UpdateInPlace { pos } => (pos, false), DeclarationUpdate::AppendAndRemove { pos } => (pos, true), _ => return None, }; Some(UpdateOrRemoval { item, pos, remove }) - }).collect(); + }) + .collect(); // Execute removals. It's important to do it in reverse index order, // so that removing doesn't invalidate following positions. updates_and_removals.sort_unstable_by_key(|update| update.pos); - updates_and_removals.iter().rev() + updates_and_removals + .iter() + .rev() .filter(|update| update.remove) .for_each(|update| { self.declarations.remove(update.pos); @@ -637,7 +685,7 @@ impl PropertyDeclarationBlock { DeclarationUpdate::UpdateInPlace { pos: update.pos } ); *update.item = DeclarationUpdate::UpdateInPlace { - pos: update.pos - removed_count + pos: update.pos - removed_count, }; } } @@ -645,18 +693,17 @@ impl PropertyDeclarationBlock { for (decl, update) in drain.declarations.zip_eq(updates.updates.iter()) { match *update { DeclarationUpdate::None => {}, - DeclarationUpdate::Append | - DeclarationUpdate::AppendAndRemove { .. } => { + DeclarationUpdate::Append | DeclarationUpdate::AppendAndRemove { .. } => { if let Some(id) = decl.id().as_longhand() { self.longhands.insert(id); } self.declarations.push(decl); self.declarations_importance.push(important); - } + }, DeclarationUpdate::UpdateInPlace { pos } => { self.declarations[pos] = decl; self.declarations_importance.set(pos, important); - } + }, } } updates.updates.clear(); @@ -665,19 +712,16 @@ impl PropertyDeclarationBlock { /// Returns the first declaration that would be removed by removing /// `property`. #[inline] - pub fn first_declaration_to_remove( - &self, - property: &PropertyId, - ) -> Option<usize> { + pub fn first_declaration_to_remove(&self, property: &PropertyId) -> Option<usize> { if let Some(id) = property.longhand_id() { if !self.longhands.contains(id) { return None; } } - self.declarations.iter().position(|declaration| { - declaration.id().is_or_is_longhand_of(property) - }) + self.declarations + .iter() + .position(|declaration| declaration.id().is_or_is_longhand_of(property)) } /// Removes a given declaration at a given index. @@ -698,16 +742,14 @@ impl PropertyDeclarationBlock { /// `first_declaration` needs to be the result of /// `first_declaration_to_remove`. #[inline] - pub fn remove_property( - &mut self, - property: &PropertyId, - first_declaration: usize, - ) { + pub fn remove_property(&mut self, property: &PropertyId, first_declaration: usize) { debug_assert_eq!( Some(first_declaration), self.first_declaration_to_remove(property) ); - debug_assert!(self.declarations[first_declaration].id().is_or_is_longhand_of(property)); + debug_assert!(self.declarations[first_declaration] + .id() + .is_or_is_longhand_of(property)); self.remove_declaration_at(first_declaration); @@ -776,16 +818,16 @@ impl PropertyDeclarationBlock { // getKeyframes() implementation for CSS animations, if // |computed_values| is supplied, we use it to expand such variable // declarations. This will be fixed properly in Gecko bug 1391537. - ( - &PropertyDeclaration::WithVariables(ref declaration), - Some(ref _computed_values), - ) => { - declaration.value.substitute_variables( - declaration.id, - custom_properties.as_ref(), - QuirksMode::NoQuirks, - &env, - ).to_css(dest) + (&PropertyDeclaration::WithVariables(ref declaration), Some(ref _computed_values)) => { + declaration + .value + .substitute_variables( + declaration.id, + custom_properties.as_ref(), + QuirksMode::NoQuirks, + &env, + ) + .to_css(dest) }, (ref d, _) => d.to_css(dest), } @@ -798,8 +840,8 @@ impl PropertyDeclarationBlock { let mut longhands = LonghandIdSet::new(); for (property, animation_value) in animation_value_map.iter() { - longhands.insert(*property); - declarations.push(animation_value.uncompute()); + longhands.insert(*property); + declarations.push(animation_value.uncompute()); } PropertyDeclarationBlock { @@ -814,13 +856,12 @@ impl PropertyDeclarationBlock { pub fn has_css_wide_keyword(&self, property: &PropertyId) -> bool { if let Some(id) = property.longhand_id() { if !self.longhands.contains(id) { - return false + return false; } } - self.declarations.iter().any(|decl| - decl.id().is_or_is_longhand_of(property) && - decl.get_css_wide_keyword().is_some() - ) + self.declarations.iter().any(|decl| { + decl.id().is_or_is_longhand_of(property) && decl.get_css_wide_keyword().is_some() + }) } /// Returns a custom properties map which is the result of cascading custom @@ -844,10 +885,7 @@ impl PropertyDeclarationBlock { inherited_custom_properties: Option<&Arc<crate::custom_properties::CustomPropertiesMap>>, environment: &CssEnvironment, ) -> Option<Arc<crate::custom_properties::CustomPropertiesMap>> { - let mut builder = CustomPropertiesBuilder::new( - inherited_custom_properties, - environment, - ); + let mut builder = CustomPropertiesBuilder::new(inherited_custom_properties, environment); for declaration in self.normal_declaration_iter() { if let PropertyDeclaration::Custom(ref declaration) = *declaration { @@ -899,7 +937,7 @@ impl PropertyDeclarationBlock { &mut is_first_serialization, )?; continue; - } + }, }; // Step 3.2 @@ -928,22 +966,19 @@ impl PropertyDeclarationBlock { let mut important_count = 0; let mut found_system = None; - let is_system_font = - shorthand == ShorthandId::Font && - self.declarations.iter().any(|l| { - match l.id() { - PropertyDeclarationId::Longhand(id) => { - if already_serialized.contains(id.into()) { - return false; - } - - l.get_system().is_some() - } - PropertyDeclarationId::Custom(..) => { - debug_assert!(l.get_system().is_none()); - false + let is_system_font = shorthand == ShorthandId::Font && + self.declarations.iter().any(|l| match l.id() { + PropertyDeclarationId::Longhand(id) => { + if already_serialized.contains(id.into()) { + return false; } - } + + l.get_system().is_some() + }, + PropertyDeclarationId::Custom(..) => { + debug_assert!(l.get_system().is_none()); + false + }, }); if is_system_font { @@ -951,7 +986,7 @@ impl PropertyDeclarationBlock { if longhand.get_system().is_some() || longhand.is_default_line_height() { current_longhands.push(longhand); if found_system.is_none() { - found_system = longhand.get_system(); + found_system = longhand.get_system(); } if importance.important() { important_count += 1; @@ -967,11 +1002,11 @@ impl PropertyDeclarationBlock { if importance.important() { important_count += 1; } - } + }, None => { contains_all_longhands = false; break; - } + }, } } @@ -994,23 +1029,30 @@ impl PropertyDeclarationBlock { // Substep 5 - Let value be the result of invoking serialize // a CSS value of current longhands. - let appendable_value = - match shorthand.get_shorthand_appendable_value(current_longhands.iter().cloned()) { - None => continue, - Some(appendable_value) => appendable_value, - }; + let appendable_value = match shorthand + .get_shorthand_appendable_value(current_longhands.iter().cloned()) + { + None => continue, + Some(appendable_value) => appendable_value, + }; // We avoid re-serializing if we're already an // AppendableValue::Css. let mut v = CssString::new(); let value = match (appendable_value, found_system) { - (AppendableValue::Css { css, with_variables }, _) => { + ( + AppendableValue::Css { + css, + with_variables, + }, + _, + ) => { debug_assert!(!css.is_empty()); AppendableValue::Css { css: css, with_variables: with_variables, } - } + }, #[cfg(feature = "gecko")] (_, Some(sys)) => { sys.to_css(&mut CssWriter::new(&mut v))?; @@ -1018,7 +1060,7 @@ impl PropertyDeclarationBlock { css: CssStringBorrow::from(&v), with_variables: false, } - } + }, (other, _) => { append_declaration_value(&mut v, other)?; @@ -1031,7 +1073,7 @@ impl PropertyDeclarationBlock { css: CssStringBorrow::from(&v), with_variables: false, } - } + }, }; // Substeps 7 and 8 @@ -1091,7 +1133,8 @@ impl PropertyDeclarationBlock { /// A convenient enum to represent different kinds of stuff that can represent a /// _value_ in the serialization of a property declaration. pub enum AppendableValue<'a, I> - where I: Iterator<Item=&'a PropertyDeclaration>, +where + I: Iterator<Item = &'a PropertyDeclaration>, { /// A given declaration, of which we'll serialize just the value. Declaration(&'a PropertyDeclaration), @@ -1107,14 +1150,11 @@ pub enum AppendableValue<'a, I> css: CssStringBorrow<'a>, /// Whether the original serialization contained variables or not. with_variables: bool, - } + }, } /// Potentially appends whitespace after the first (property: value;) pair. -fn handle_first_serialization<W>( - dest: &mut W, - is_first_serialization: &mut bool, -) -> fmt::Result +fn handle_first_serialization<W>(dest: &mut W, is_first_serialization: &mut bool) -> fmt::Result where W: Write, { @@ -1132,18 +1172,14 @@ pub fn append_declaration_value<'a, I>( appendable_value: AppendableValue<'a, I>, ) -> fmt::Result where - I: Iterator<Item=&'a PropertyDeclaration>, + I: Iterator<Item = &'a PropertyDeclaration>, { match appendable_value { - AppendableValue::Css { css, .. } => { - css.append_to(dest) - }, - AppendableValue::Declaration(decl) => { - decl.to_css(dest) - }, + AppendableValue::Css { css, .. } => css.append_to(dest), + AppendableValue::Declaration(decl) => decl.to_css(dest), AppendableValue::DeclarationsForShorthand(shorthand, decls) => { shorthand.longhands_to_css(decls, &mut CssWriter::new(dest)) - } + }, } } @@ -1153,10 +1189,10 @@ pub fn append_serialization<'a, I, N>( property_name: &N, appendable_value: AppendableValue<'a, I>, importance: Importance, - is_first_serialization: &mut bool + is_first_serialization: &mut bool, ) -> fmt::Result where - I: Iterator<Item=&'a PropertyDeclaration>, + I: Iterator<Item = &'a PropertyDeclaration>, N: ToCss, { handle_first_serialization(dest, is_first_serialization)?; @@ -1176,7 +1212,7 @@ where if !with_variables { dest.write_str(" ")? } - } + }, // Currently append_serialization is only called with a Css or // a Declaration AppendableValue. AppendableValue::DeclarationsForShorthand(..) => unreachable!(), @@ -1228,7 +1264,7 @@ pub fn parse_one_declaration_into( url_data: &UrlExtraData, error_reporter: Option<&dyn ParseErrorReporter>, parsing_mode: ParsingMode, - quirks_mode: QuirksMode + quirks_mode: QuirksMode, ) -> Result<(), ()> { let context = ParserContext::new( Origin::Author, @@ -1249,20 +1285,22 @@ pub fn parse_one_declaration_into( let mut input = ParserInput::new(input); let mut parser = Parser::new(&mut input); let start_position = parser.position(); - parser.parse_entirely(|parser| { - PropertyDeclaration::parse_into(declarations, id, &context, parser) - }).map_err(|err| { - if context.error_reporting_enabled() { - report_one_css_error( - &context, - None, - None, - err, - parser.slice_from(start_position), - property_id_for_error_reporting, - ) - } - }) + parser + .parse_entirely(|parser| { + PropertyDeclaration::parse_into(declarations, id, &context, parser) + }) + .map_err(|err| { + if context.error_reporting_enabled() { + report_one_css_error( + &context, + None, + None, + err, + parser.slice_from(start_position), + property_id_for_error_reporting, + ) + } + }) } /// A struct to parse property declarations. @@ -1273,7 +1311,6 @@ struct PropertyDeclarationParser<'a, 'b: 'a> { last_parsed_property_id: Option<PropertyId>, } - /// Default methods reject all at rules. impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> { type PreludeNoBlock = (); @@ -1284,8 +1321,7 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for PropertyDeclarationParser<'a, 'b> { /// Based on NonMozillaVendorIdentifier from Gecko's CSS parser. fn is_non_mozilla_vendor_identifier(name: &str) -> bool { - (name.starts_with("-") && !name.starts_with("-moz-")) || - name.starts_with("_") + (name.starts_with("-") && !name.starts_with("-moz-")) || name.starts_with("_") } impl<'a, 'b, 'i> DeclarationParser<'i> for PropertyDeclarationParser<'a, 'b> { @@ -1301,10 +1337,8 @@ 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( - StyleParseErrorKind::UnknownProperty(name) - )); - } + return Err(input.new_custom_error(StyleParseErrorKind::UnknownProperty(name))); + }, }; if self.context.error_reporting_enabled() { self.last_parsed_property_id = Some(id.clone()); @@ -1344,10 +1378,8 @@ fn report_one_css_error<'i>( fn all_properties_in_block(block: &PropertyDeclarationBlock, property: &PropertyId) -> bool { match *property { - PropertyId::LonghandAlias(id, _) | - PropertyId::Longhand(id) => block.contains(id), - PropertyId::ShorthandAlias(id, _) | - PropertyId::Shorthand(id) => { + PropertyId::LonghandAlias(id, _) | PropertyId::Longhand(id) => block.contains(id), + PropertyId::ShorthandAlias(id, _) | PropertyId::Shorthand(id) => { id.longhands().all(|longhand| block.contains(longhand)) }, // NOTE(emilio): We could do this, but it seems of limited utility, @@ -1382,7 +1414,9 @@ fn report_one_css_error<'i>( } } error = match *property { - PropertyId::Custom(ref c) => StyleParseErrorKind::new_invalid(format!("--{}", c), error), + PropertyId::Custom(ref c) => { + StyleParseErrorKind::new_invalid(format!("--{}", c), error) + }, _ => StyleParseErrorKind::new_invalid(property.non_custom_id().unwrap().name(), error), }; } @@ -1409,7 +1443,7 @@ fn report_css_errors( pub fn parse_property_declaration_list( context: &ParserContext, input: &mut Parser, - selectors: Option<&SelectorList<SelectorImpl>> + selectors: Option<&SelectorList<SelectorImpl>>, ) -> PropertyDeclarationBlock { let mut declarations = SourcePropertyDeclaration::new(); let mut block = PropertyDeclarationBlock::new(); @@ -1423,11 +1457,8 @@ pub fn parse_property_declaration_list( while let Some(declaration) = iter.next() { match declaration { Ok(importance) => { - block.extend( - iter.parser.declarations.drain(), - importance, - ); - } + block.extend(iter.parser.declarations.drain(), importance); + }, Err((error, slice)) => { iter.parser.declarations.clear(); @@ -1435,7 +1466,7 @@ pub fn parse_property_declaration_list( let property = iter.parser.last_parsed_property_id.take(); errors.push((error, slice, property)); } - } + }, } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 1f3e862df49..97321fcbd38 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -321,18 +321,6 @@ impl ${style_struct.gecko_struct_name} { } </%def> -<%def name="impl_coord_copy(ident, 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) - } -</%def> - <%! def get_gecko_property(ffi_name, self_param = "self"): return "%s.gecko.%s" % (self_param, ffi_name) @@ -357,10 +345,7 @@ def set_gecko_property(ffi_name, expr): </%def> <%def name="impl_keyword_clone(ident, gecko_ffi_name, keyword, cast_type='u8')"> - // FIXME: We introduced non_upper_case_globals for -moz-appearance only - // since the prefix of Gecko value starts with ThemeWidgetType_NS_THEME. - // We should remove this after fix bug 1371809. - #[allow(non_snake_case, non_upper_case_globals)] + #[allow(non_snake_case)] pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { use crate::properties::longhands::${ident}::computed_value::T as Keyword; // FIXME(bholley): Align binary representations and ditch |match| for cast + static_asserts @@ -1146,7 +1131,7 @@ fn static_assert() { } pub fn set_font_size(&mut self, v: FontSize) { - use crate::values::generics::font::KeywordSize; + use crate::values::specified::font::KeywordSize; let size = v.size(); self.gecko.mScriptUnconstrainedSize = size.0; @@ -1167,7 +1152,7 @@ fn static_assert() { KeywordSize::XXXLarge => structs::NS_STYLE_FONT_SIZE_XXXLARGE, } as u8; self.gecko.mFontSizeFactor = info.factor; - self.gecko.mFontSizeOffset = info.offset.0.to_i32_au(); + self.gecko.mFontSizeOffset = info.offset.to_i32_au(); } else { self.gecko.mFontSizeKeyword = structs::NS_STYLE_FONT_SIZE_NO_KEYWORD as u8; self.gecko.mFontSizeFactor = 1.; @@ -1176,7 +1161,7 @@ fn static_assert() { } pub fn clone_font_size(&self) -> FontSize { - use crate::values::generics::font::{KeywordInfo, KeywordSize}; + use crate::values::specified::font::{KeywordInfo, KeywordSize}; let size = Au(self.gecko.mSize).into(); let kw = match self.gecko.mFontSizeKeyword as u32 { structs::NS_STYLE_FONT_SIZE_XXSMALL => KeywordSize::XXSmall, @@ -1259,6 +1244,8 @@ fn static_assert() { ${impl_simple_type_with_conversion("font_synthesis", "mFont.synthesis")} + ${impl_simple("font_variant_alternates", "mFont.variantAlternates")} + pub fn set_font_size_adjust(&mut self, v: longhands::font_size_adjust::computed_value::T) { use crate::properties::longhands::font_size_adjust::computed_value::T; match v { @@ -1331,122 +1318,6 @@ fn static_assert() { ${impl_simple("_moz_script_level", "mScriptLevel")} <% impl_simple_type_with_conversion("font_language_override", "mFont.languageOverride") %> - pub fn set_font_variant_alternates( - &mut self, - v: values::computed::font::FontVariantAlternates, - ) { - use crate::gecko_bindings::bindings::{Gecko_ClearAlternateValues, Gecko_AppendAlternateValues}; - % for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split(): - use crate::gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()}; - % endfor - use crate::values::specified::font::VariantAlternates; - - unsafe { - Gecko_ClearAlternateValues(&mut self.gecko.mFont, v.len()); - } - - if v.0.is_empty() { - self.gecko.mFont.variantAlternates = NS_FONT_VARIANT_ALTERNATES_NORMAL as u16; - return; - } - - for val in v.0.iter() { - match *val { - % for value in "Swash Stylistic Ornaments Annotation".split(): - VariantAlternates::${value}(ref ident) => { - self.gecko.mFont.variantAlternates |= NS_FONT_VARIANT_ALTERNATES_${value.upper()} as u16; - unsafe { - Gecko_AppendAlternateValues(&mut self.gecko.mFont, - NS_FONT_VARIANT_ALTERNATES_${value.upper()}, - ident.0.as_ptr()); - } - }, - % endfor - % for value in "styleset character_variant".split(): - VariantAlternates::${to_camel_case(value)}(ref slice) => { - self.gecko.mFont.variantAlternates |= NS_FONT_VARIANT_ALTERNATES_${value.upper()} as u16; - for ident in slice.iter() { - unsafe { - Gecko_AppendAlternateValues(&mut self.gecko.mFont, - NS_FONT_VARIANT_ALTERNATES_${value.upper()}, - ident.0.as_ptr()); - } - } - }, - % endfor - VariantAlternates::HistoricalForms => { - self.gecko.mFont.variantAlternates |= NS_FONT_VARIANT_ALTERNATES_HISTORICAL as u16; - } - } - } - } - - #[allow(non_snake_case)] - pub fn copy_font_variant_alternates_from(&mut self, other: &Self) { - use crate::gecko_bindings::bindings::Gecko_CopyAlternateValuesFrom; - - self.gecko.mFont.variantAlternates = other.gecko.mFont.variantAlternates; - unsafe { - Gecko_CopyAlternateValuesFrom(&mut self.gecko.mFont, &other.gecko.mFont); - } - } - - pub fn reset_font_variant_alternates(&mut self, other: &Self) { - self.copy_font_variant_alternates_from(other) - } - - pub fn clone_font_variant_alternates(&self) -> values::computed::font::FontVariantAlternates { - % for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split(): - use crate::gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()}; - % endfor - use crate::values::specified::font::VariantAlternates; - use crate::values::specified::font::VariantAlternatesList; - use crate::values::CustomIdent; - - if self.gecko.mFont.variantAlternates == NS_FONT_VARIANT_ALTERNATES_NORMAL as u16 { - return VariantAlternatesList(vec![].into_boxed_slice()); - } - - let mut alternates = Vec::with_capacity(self.gecko.mFont.alternateValues.len()); - if self.gecko.mFont.variantAlternates & (NS_FONT_VARIANT_ALTERNATES_HISTORICAL as u16) != 0 { - alternates.push(VariantAlternates::HistoricalForms); - } - - <% - property_need_ident_list = "styleset character_variant".split() - %> - % for value in property_need_ident_list: - let mut ${value}_list = Vec::new(); - % endfor - - for gecko_alternate_value in self.gecko.mFont.alternateValues.iter() { - let ident = Atom::from(gecko_alternate_value.value.to_string()); - match gecko_alternate_value.alternate { - % for value in "Swash Stylistic Ornaments Annotation".split(): - NS_FONT_VARIANT_ALTERNATES_${value.upper()} => { - alternates.push(VariantAlternates::${value}(CustomIdent(ident))); - }, - % endfor - % for value in property_need_ident_list: - NS_FONT_VARIANT_ALTERNATES_${value.upper()} => { - ${value}_list.push(CustomIdent(ident)); - }, - % endfor - _ => { - panic!("Found unexpected value for font-variant-alternates"); - } - } - } - - % for value in property_need_ident_list: - if !${value}_list.is_empty() { - alternates.push(VariantAlternates::${to_camel_case(value)}(${value}_list.into_boxed_slice())); - } - % endfor - - VariantAlternatesList(alternates.into_boxed_slice()) - } - ${impl_simple_type_with_conversion("font_variant_ligatures", "mFont.variantLigatures")} ${impl_simple_type_with_conversion("font_variant_east_asian", "mFont.variantEastAsian")} ${impl_simple_type_with_conversion("font_variant_numeric", "mFont.variantNumeric")} @@ -2291,7 +2162,7 @@ fn static_assert() { </%self:impl_trait> <%self:impl_trait style_struct_name="List" - skip_longhands="list-style-image list-style-type -moz-image-region"> + skip_longhands="list-style-image list-style-type"> pub fn set_list_style_image(&mut self, image: longhands::list_style_image::computed_value::T) { match image { @@ -2328,10 +2199,15 @@ fn static_assert() { } pub fn set_list_style_type(&mut self, v: longhands::list_style_type::computed_value::T) { + use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToName; use crate::gecko_bindings::bindings::Gecko_SetCounterStyleToString; use nsstring::{nsACString, nsCStr}; use self::longhands::list_style_type::computed_value::T; match v { + T::None => unsafe { + Gecko_SetCounterStyleToName(&mut self.gecko.mCounterStyle, + atom!("none").into_addrefed()); + } T::CounterStyle(s) => s.to_gecko_value(&mut self.gecko.mCounterStyle), T::String(s) => unsafe { Gecko_SetCounterStyleToString(&mut self.gecko.mCounterStyle, @@ -2353,199 +2229,30 @@ fn static_assert() { pub fn clone_list_style_type(&self) -> longhands::list_style_type::computed_value::T { use self::longhands::list_style_type::computed_value::T; use crate::values::Either; - use crate::values::generics::CounterStyleOrNone; + use crate::values::generics::CounterStyle; + use crate::gecko_bindings::bindings; - let result = CounterStyleOrNone::from_gecko_value(&self.gecko.mCounterStyle); + let name = unsafe { + bindings::Gecko_CounterStyle_GetName(&self.gecko.mCounterStyle) + }; + if !name.is_null() { + let name = unsafe { Atom::from_raw(name) }; + if name == atom!("none") { + return T::None; + } + } + let result = CounterStyle::from_gecko_value(&self.gecko.mCounterStyle); match result { Either::First(counter_style) => T::CounterStyle(counter_style), Either::Second(string) => T::String(string), } } - - #[allow(non_snake_case)] - pub fn set__moz_image_region(&mut self, v: longhands::_moz_image_region::computed_value::T) { - use crate::values::Either; - use crate::values::generics::length::LengthPercentageOrAuto::*; - - match v { - Either::Second(_auto) => { - self.gecko.mImageRegion.x = 0; - self.gecko.mImageRegion.y = 0; - self.gecko.mImageRegion.width = 0; - self.gecko.mImageRegion.height = 0; - } - Either::First(rect) => { - self.gecko.mImageRegion.x = match rect.left { - LengthPercentage(v) => v.to_i32_au(), - Auto => 0, - }; - self.gecko.mImageRegion.y = match rect.top { - LengthPercentage(v) => v.to_i32_au(), - Auto => 0, - }; - self.gecko.mImageRegion.height = match rect.bottom { - LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.y)).0, - Auto => 0, - }; - self.gecko.mImageRegion.width = match rect.right { - LengthPercentage(value) => (Au::from(value) - Au(self.gecko.mImageRegion.x)).0, - Auto => 0, - }; - } - } - } - - #[allow(non_snake_case)] - pub fn clone__moz_image_region(&self) -> longhands::_moz_image_region::computed_value::T { - use crate::values::{Auto, Either}; - use crate::values::generics::length::LengthPercentageOrAuto::*; - use crate::values::computed::ClipRect; - - // There is no ideal way to detect auto type for structs::nsRect and its components, so - // if all components are zero, we use Auto. - if self.gecko.mImageRegion.x == 0 && - self.gecko.mImageRegion.y == 0 && - self.gecko.mImageRegion.width == 0 && - self.gecko.mImageRegion.height == 0 { - return Either::Second(Auto); - } - - Either::First(ClipRect { - top: LengthPercentage(Au(self.gecko.mImageRegion.y).into()), - right: LengthPercentage(Au(self.gecko.mImageRegion.width + self.gecko.mImageRegion.x).into()), - bottom: LengthPercentage(Au(self.gecko.mImageRegion.height + self.gecko.mImageRegion.y).into()), - left: LengthPercentage(Au(self.gecko.mImageRegion.x).into()), - }) - } - - ${impl_simple_copy('_moz_image_region', 'mImageRegion')} - </%self:impl_trait> -<%self:impl_trait style_struct_name="Table" skip_longhands="-x-span"> - #[allow(non_snake_case)] - pub fn set__x_span(&mut self, v: longhands::_x_span::computed_value::T) { - self.gecko.mSpan = v.0 - } - - #[allow(non_snake_case)] - pub fn clone__x_span(&self) -> longhands::_x_span::computed_value::T { - longhands::_x_span::computed_value::T( - self.gecko.mSpan - ) - } - - ${impl_simple_copy('_x_span', 'mSpan')} +<%self:impl_trait style_struct_name="Table"> </%self:impl_trait> -<%self:impl_trait style_struct_name="Effects" skip_longhands="clip"> - 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; - use crate::gecko_bindings::structs::NS_STYLE_CLIP_LEFT_AUTO; - use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO; - use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO; - use crate::gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO; - use crate::values::generics::length::LengthPercentageOrAuto::*; - use crate::values::Either; - - match v { - Either::First(rect) => { - self.gecko.mClipFlags = NS_STYLE_CLIP_RECT as u8; - self.gecko.mClip.x = match rect.left { - LengthPercentage(l) => l.to_i32_au(), - Auto => { - self.gecko.mClipFlags |= NS_STYLE_CLIP_LEFT_AUTO as u8; - 0 - } - }; - - self.gecko.mClip.y = match rect.top { - LengthPercentage(l) => l.to_i32_au(), - Auto => { - self.gecko.mClipFlags |= NS_STYLE_CLIP_TOP_AUTO as u8; - 0 - } - }; - - self.gecko.mClip.height = match rect.bottom { - LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.y)).0, - Auto => { - self.gecko.mClipFlags |= NS_STYLE_CLIP_BOTTOM_AUTO as u8; - 1 << 30 // NS_MAXSIZE - } - }; - - self.gecko.mClip.width = match rect.right { - LengthPercentage(l) => (Au::from(l) - Au(self.gecko.mClip.x)).0, - Auto => { - self.gecko.mClipFlags |= NS_STYLE_CLIP_RIGHT_AUTO as u8; - 1 << 30 // NS_MAXSIZE - } - }; - }, - Either::Second(_auto) => { - self.gecko.mClipFlags = NS_STYLE_CLIP_AUTO as u8; - self.gecko.mClip.x = 0; - self.gecko.mClip.y = 0; - self.gecko.mClip.width = 0; - self.gecko.mClip.height = 0; - } - } - } - - pub fn copy_clip_from(&mut self, other: &Self) { - self.gecko.mClip = other.gecko.mClip; - self.gecko.mClipFlags = other.gecko.mClipFlags; - } - - pub fn reset_clip(&mut self, other: &Self) { - self.copy_clip_from(other) - } - - pub fn clone_clip(&self) -> longhands::clip::computed_value::T { - use crate::gecko_bindings::structs::NS_STYLE_CLIP_AUTO; - use crate::gecko_bindings::structs::NS_STYLE_CLIP_BOTTOM_AUTO; - use crate::gecko_bindings::structs::NS_STYLE_CLIP_LEFT_AUTO; - use crate::gecko_bindings::structs::NS_STYLE_CLIP_RIGHT_AUTO; - use crate::gecko_bindings::structs::NS_STYLE_CLIP_TOP_AUTO; - use crate::values::generics::length::LengthPercentageOrAuto::*; - use crate::values::computed::{ClipRect, ClipRectOrAuto}; - use crate::values::Either; - - if self.gecko.mClipFlags == NS_STYLE_CLIP_AUTO as u8 { - return ClipRectOrAuto::auto() - } - let left = if self.gecko.mClipFlags & NS_STYLE_CLIP_LEFT_AUTO as u8 != 0 { - debug_assert_eq!(self.gecko.mClip.x, 0); - Auto - } else { - LengthPercentage(Au(self.gecko.mClip.x).into()) - }; - - let top = if self.gecko.mClipFlags & NS_STYLE_CLIP_TOP_AUTO as u8 != 0 { - debug_assert_eq!(self.gecko.mClip.y, 0); - Auto - } else { - LengthPercentage(Au(self.gecko.mClip.y).into()) - }; - - let bottom = if self.gecko.mClipFlags & NS_STYLE_CLIP_BOTTOM_AUTO as u8 != 0 { - debug_assert_eq!(self.gecko.mClip.height, 1 << 30); // NS_MAXSIZE - Auto - } else { - LengthPercentage(Au(self.gecko.mClip.y + self.gecko.mClip.height).into()) - }; - - let right = if self.gecko.mClipFlags & NS_STYLE_CLIP_RIGHT_AUTO as u8 != 0 { - debug_assert_eq!(self.gecko.mClip.width, 1 << 30); // NS_MAXSIZE - Auto - } else { - LengthPercentage(Au(self.gecko.mClip.x + self.gecko.mClip.width).into()) - }; - - Either::First(ClipRect { top, right, bottom, left }) - } +<%self:impl_trait style_struct_name="Effects"> </%self:impl_trait> <%self:impl_trait style_struct_name="InheritedBox"> @@ -2725,18 +2432,7 @@ clip-path </%self:impl_trait> <%self:impl_trait style_struct_name="InheritedSVG" - 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; - } - - ${impl_simple_copy('paint_order', 'mPaintOrder')} - - pub fn clone_paint_order(&self) -> longhands::paint_order::computed_value::T { - use crate::properties::longhands::paint_order::computed_value::T; - T(self.gecko.mPaintOrder) - } - + skip_longhands="stroke-dasharray"> pub fn set_stroke_dasharray(&mut self, v: longhands::stroke_dasharray::computed_value::T) { use crate::gecko_bindings::structs::nsStyleSVG_STROKE_DASHARRAY_CONTEXT as CONTEXT_VALUE; use crate::values::generics::svg::SVGStrokeDashArray; @@ -2883,8 +2579,7 @@ clip-path ${impl_simple('column_rule_style', 'mColumnRuleStyle')} </%self:impl_trait> -<%self:impl_trait style_struct_name="Counters" - skip_longhands="content counter-increment counter-reset counter-set"> +<%self:impl_trait style_struct_name="Counters" skip_longhands="content"> pub fn ineffective_content_property(&self) -> bool { self.gecko.mContents.is_empty() } @@ -2892,7 +2587,7 @@ clip-path pub fn set_content(&mut self, v: longhands::content::computed_value::T) { use crate::values::CustomIdent; use crate::values::generics::counters::{Content, ContentItem}; - use crate::values::generics::CounterStyleOrNone; + use crate::values::generics::CounterStyle; use crate::gecko_bindings::structs::nsStyleContentData; use crate::gecko_bindings::structs::nsStyleContentAttr; use crate::gecko_bindings::structs::StyleContentType; @@ -2913,7 +2608,7 @@ clip-path content_type: StyleContentType, name: CustomIdent, sep: &str, - style: CounterStyleOrNone, + style: CounterStyle, ) { debug_assert!(content_type == StyleContentType::Counter || content_type == StyleContentType::Counters); @@ -3043,7 +2738,7 @@ clip-path use crate::gecko_bindings::structs::StyleContentType; use crate::values::generics::counters::{Content, ContentItem}; use crate::values::{CustomIdent, Either}; - use crate::values::generics::CounterStyleOrNone; + use crate::values::generics::CounterStyle; use crate::values::specified::Attr; if self.gecko.mContents.is_empty() { @@ -3088,7 +2783,7 @@ clip-path Atom::from_raw(gecko_function.mIdent.mRawPtr) }); let style = - CounterStyleOrNone::from_gecko_value(&gecko_function.mCounterStyle); + CounterStyle::from_gecko_value(&gecko_function.mCounterStyle); let style = match style { Either::First(counter_style) => counter_style, Either::Second(_) => @@ -3115,70 +2810,13 @@ clip-path }).collect::<Vec<_>>().into_boxed_slice() ) } - - % for counter_property in ["Increment", "Reset", "Set"]: - pub fn set_counter_${counter_property.lower()}( - &mut self, - v: longhands::counter_${counter_property.lower()}::computed_value::T - ) { - unsafe { - 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()) - ); - self.gecko.m${counter_property}s[i].mValue = pair.value; - } - } - } - - pub fn copy_counter_${counter_property.lower()}_from(&mut self, other: &Self) { - unsafe { - bindings::Gecko_CopyCounter${counter_property}sFrom(&mut *self.gecko, &*other.gecko) - } - } - - pub fn reset_counter_${counter_property.lower()}(&mut self, other: &Self) { - self.copy_counter_${counter_property.lower()}_from(other) - } - - pub fn clone_counter_${counter_property.lower()}( - &self - ) -> longhands::counter_${counter_property.lower()}::computed_value::T { - use crate::values::generics::counters::CounterPair; - use crate::values::CustomIdent; - - longhands::counter_${counter_property.lower()}::computed_value::T::new( - self.gecko.m${counter_property}s.iter().map(|ref gecko_counter| { - CounterPair { - name: CustomIdent(unsafe { - Atom::from_raw(gecko_counter.mCounter.mRawPtr) - }), - value: gecko_counter.mValue, - } - }).collect() - ) - } - % endfor </%self:impl_trait> <%self:impl_trait style_struct_name="UI" skip_longhands="-moz-force-broken-image-icon"> ${impl_simple_type_with_conversion("_moz_force_broken_image_icon", "mForceBrokenImageIcon")} </%self:impl_trait> -<%self:impl_trait style_struct_name="XUL" - skip_longhands="-moz-box-ordinal-group"> - #[allow(non_snake_case)] - pub fn set__moz_box_ordinal_group(&mut self, v: i32) { - self.gecko.mBoxOrdinal = v as u32; - } - - ${impl_simple_copy("_moz_box_ordinal_group", "mBoxOrdinal")} - - #[allow(non_snake_case)] - pub fn clone__moz_box_ordinal_group(&self) -> i32 { - self.gecko.mBoxOrdinal as i32 - } +<%self:impl_trait style_struct_name="XUL"> </%self:impl_trait> % for style_struct in data.style_structs: diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs index b8ce027be4e..b4b2ab0598c 100644 --- a/components/style/properties/longhands/font.mako.rs +++ b/components/style/properties/longhands/font.mako.rs @@ -80,7 +80,7 @@ ${helpers.predefined_type( engines="gecko", initial_value="computed::FontSizeAdjust::none()", initial_specified_value="specified::FontSizeAdjust::none()", - animation_value_type="ComputedValue", + animation_value_type="FontSizeAdjust", spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust", )} @@ -401,7 +401,7 @@ ${helpers.predefined_type( is_system_font: true, }, font_size: FontSize { - size: cx.maybe_zoom_text(Au(system.size).into()), + size: NonNegative(cx.maybe_zoom_text(Au(system.size).into())), keyword_info: None }, font_weight, diff --git a/components/style/properties/longhands/list.mako.rs b/components/style/properties/longhands/list.mako.rs index 0de69c952de..202c7839d69 100644 --- a/components/style/properties/longhands/list.mako.rs +++ b/components/style/properties/longhands/list.mako.rs @@ -76,6 +76,7 @@ ${helpers.predefined_type( "ClipRectOrAuto", "computed::ClipRectOrAuto::auto()", engines="gecko", + gecko_ffi_name="mImageRegion", animation_value_type="ComputedValue", boxed=True, spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-image-region)", diff --git a/components/style/properties/longhands/table.mako.rs b/components/style/properties/longhands/table.mako.rs index 4475faaee37..0564942fc0a 100644 --- a/components/style/properties/longhands/table.mako.rs +++ b/components/style/properties/longhands/table.mako.rs @@ -18,8 +18,8 @@ ${helpers.single_keyword( ${helpers.predefined_type( "-x-span", - "XSpan", - "computed::XSpan(1)", + "Integer", + "1", engines="gecko", spec="Internal-only (for `<col span>` pres attr)", animation_value_type="none", diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 72ae381f5d9..a1b4cedcfed 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -38,6 +38,7 @@ use style_traits::{CssWriter, KeywordsCollectFn, ParseError, ParsingMode}; use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; use to_shmem::impl_trivial_to_shmem; use crate::stylesheets::{CssRuleType, Origin, UrlExtraData}; +use crate::use_counters::UseCounters; use crate::values::generics::text::LineHeight; use crate::values::{computed, resolved}; use crate::values::computed::NonNegativeLength; @@ -427,6 +428,9 @@ pub struct NonCustomPropertyId(usize); pub const NON_CUSTOM_PROPERTY_ID_COUNT: usize = ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}; +/// The length of all counted unknown properties. +pub const COUNTED_UNKNOWN_PROPERTY_COUNT: usize = ${len(data.counted_unknown_properties)}; + % if engine == "gecko": #[allow(dead_code)] unsafe fn static_assert_nscsspropertyid() { @@ -1788,6 +1792,45 @@ impl ToCss for PropertyId { } } +/// The counted unknown property list which is used for css use counters. +#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)] +#[repr(u8)] +pub enum CountedUnknownProperty { + % for prop in data.counted_unknown_properties: + /// ${prop.name} + ${prop.camel_case}, + % endfor +} + +impl CountedUnknownProperty { + /// Parse the counted unknown property. + pub fn parse_for_test(property_name: &str) -> Option<Self> { + ascii_case_insensitive_phf_map! { + unknown_id -> CountedUnknownProperty = { + % for property in data.counted_unknown_properties: + "${property.name}" => CountedUnknownProperty::${property.camel_case}, + % endfor + } + } + unknown_id(property_name).cloned() + } + + /// Returns the underlying index, used for use counter. + pub fn bit(self) -> usize { + self as usize + } +} + +#[cfg(feature = "gecko")] +fn is_counted_unknown_use_counters_enabled() -> bool { + static_prefs::pref!("layout.css.use-counters-unimplemented.enabled") +} + +#[cfg(feature = "servo")] +fn is_counted_unknown_use_counters_enabled() -> bool { + false +} + impl PropertyId { /// Return the longhand id that this property id represents. #[inline] @@ -1801,16 +1844,30 @@ impl PropertyId { /// Returns a given property from the string `s`. /// - /// Returns Err(()) for unknown non-custom properties. - fn parse_unchecked(property_name: &str) -> Result<Self, ()> { + /// Returns Err(()) for unknown properties. + fn parse_unchecked( + property_name: &str, + use_counters: Option< &UseCounters>, + ) -> Result<Self, ()> { + // A special id for css use counters. + // ShorthandAlias is not used in the Servo build. + // That's why we need to allow dead_code. + #[allow(dead_code)] + pub enum StaticId { + Longhand(LonghandId), + Shorthand(ShorthandId), + LonghandAlias(LonghandId, AliasId), + ShorthandAlias(ShorthandId, AliasId), + CountedUnknown(CountedUnknownProperty), + } ascii_case_insensitive_phf_map! { - property_id -> PropertyId = { + static_id -> StaticId = { % for (kind, properties) in [("Longhand", data.longhands), ("Shorthand", data.shorthands)]: % for property in properties: - "${property.name}" => PropertyId::${kind}(${kind}Id::${property.camel_case}), + "${property.name}" => StaticId::${kind}(${kind}Id::${property.camel_case}), % for alias in property.alias: "${alias.name}" => { - PropertyId::${kind}Alias( + StaticId::${kind}Alias( ${kind}Id::${property.camel_case}, AliasId::${alias.camel_case}, ) @@ -1818,11 +1875,31 @@ impl PropertyId { % endfor % endfor % endfor + % for property in data.counted_unknown_properties: + "${property.name}" => { + StaticId::CountedUnknown(CountedUnknownProperty::${property.camel_case}) + }, + % endfor } } - if let Some(id) = property_id(property_name) { - return Ok(id.clone()) + if let Some(id) = static_id(property_name) { + return Ok(match *id { + StaticId::Longhand(id) => PropertyId::Longhand(id), + StaticId::Shorthand(id) => PropertyId::Shorthand(id), + StaticId::LonghandAlias(id, alias) => PropertyId::LonghandAlias(id, alias), + StaticId::ShorthandAlias(id, alias) => PropertyId::ShorthandAlias(id, alias), + StaticId::CountedUnknown(unknown_prop) => { + if is_counted_unknown_use_counters_enabled() { + if let Some(counters) = use_counters { + counters.counted_unknown_properties.record(unknown_prop); + } + } + + // Always return Err(()) because these aren't valid custom property names. + return Err(()); + } + }); } let name = crate::custom_properties::parse_name(property_name)?; @@ -1833,7 +1910,7 @@ impl PropertyId { /// enabled for all content. #[inline] pub fn parse_enabled_for_all_content(name: &str) -> Result<Self, ()> { - let id = Self::parse_unchecked(name)?; + let id = Self::parse_unchecked(name, None)?; if !id.enabled_for_all_content() { return Err(()); @@ -1847,7 +1924,7 @@ impl PropertyId { /// allowed in this context. #[inline] pub fn parse(name: &str, context: &ParserContext) -> Result<Self, ()> { - let id = Self::parse_unchecked(name)?; + let id = Self::parse_unchecked(name, context.use_counters)?; if !id.allowed_in(context) { return Err(()); @@ -1865,7 +1942,7 @@ impl PropertyId { name: &str, context: &ParserContext, ) -> Result<Self, ()> { - let id = Self::parse_unchecked(name)?; + let id = Self::parse_unchecked(name, None)?; if !id.allowed_in_ignoring_rule_type(context) { return Err(()); diff --git a/components/style/properties/shorthands/list.mako.rs b/components/style/properties/shorthands/list.mako.rs index f2e8e28b19d..8e842cd153e 100644 --- a/components/style/properties/shorthands/list.mako.rs +++ b/components/style/properties/shorthands/list.mako.rs @@ -61,31 +61,23 @@ let position = unwrap_or_initial!(list_style_position, position); - fn list_style_type_none() -> list_style_type::SpecifiedValue { - % if engine == "gecko": - use crate::values::generics::CounterStyleOrNone; - list_style_type::SpecifiedValue::CounterStyle(CounterStyleOrNone::None) - % else: - list_style_type::SpecifiedValue::None - % endif - } - // If there are two `none`s, then we can't have a type or image; if there is one `none`, // then we can't have both a type *and* an image; if there is no `none` then we're fine as // long as we parsed something. + use self::list_style_type::SpecifiedValue as ListStyleType; match (any, nones, list_style_type, image) { (true, 2, None, None) => { Ok(expanded! { list_style_position: position, list_style_image: ImageUrlOrNone::none(), - list_style_type: list_style_type_none(), + list_style_type: ListStyleType::None, }) } (true, 1, None, Some(image)) => { Ok(expanded! { list_style_position: position, list_style_image: image, - list_style_type: list_style_type_none(), + list_style_type: ListStyleType::None, }) } (true, 1, Some(list_style_type), None) => { @@ -99,7 +91,7 @@ Ok(expanded! { list_style_position: position, list_style_image: ImageUrlOrNone::none(), - list_style_type: list_style_type_none(), + list_style_type: ListStyleType::None, }) } (true, 0, list_style_type, image) => { diff --git a/components/style/properties/shorthands/text.mako.rs b/components/style/properties/shorthands/text.mako.rs index 33b4a074892..79f7f33d850 100644 --- a/components/style/properties/shorthands/text.mako.rs +++ b/components/style/properties/shorthands/text.mako.rs @@ -73,26 +73,51 @@ } impl<'a> ToCss for LonghandsToSerialize<'a> { + #[allow(unused)] fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where W: fmt::Write { - self.text_decoration_line.to_css(dest)?; + use crate::values::specified::TextDecorationLine; + let (is_solid_style, is_current_color, is_auto_thickness) = + ( % if engine == "gecko": - if *self.text_decoration_style != text_decoration_style::SpecifiedValue::Solid { + *self.text_decoration_style == text_decoration_style::SpecifiedValue::Solid, + *self.text_decoration_color == specified::Color::CurrentColor, + self.text_decoration_thickness.map_or(true, |t| t.is_auto()) + % else: + true, true, true + % endif + ); + + let mut has_value = false; + let is_none = *self.text_decoration_line == TextDecorationLine::none(); + if (is_solid_style && is_current_color && is_auto_thickness) || !is_none { + self.text_decoration_line.to_css(dest)?; + has_value = true; + } + + % if engine == "gecko": + if !is_solid_style { + if has_value { dest.write_str(" ")?; - self.text_decoration_style.to_css(dest)?; } + self.text_decoration_style.to_css(dest)?; + has_value = true; + } - if *self.text_decoration_color != specified::Color::CurrentColor { + if !is_current_color { + if has_value { dest.write_str(" ")?; - self.text_decoration_color.to_css(dest)?; } + self.text_decoration_color.to_css(dest)?; + has_value = true; + } - if let Some(text_decoration_thickness) = self.text_decoration_thickness { - if !text_decoration_thickness.is_auto() { - dest.write_str(" ")?; - self.text_decoration_thickness.to_css(dest)?; - } + if !is_auto_thickness { + if has_value { + dest.write_str(" ")?; } + self.text_decoration_thickness.to_css(dest)?; + } % endif Ok(()) diff --git a/components/style/scoped_tls.rs b/components/style/scoped_tls.rs index b4eed7509c9..e1e5209a058 100644 --- a/components/style/scoped_tls.rs +++ b/components/style/scoped_tls.rs @@ -15,6 +15,9 @@ use std::ops::DerefMut; /// /// We use this on Servo to construct thread-local contexts, but clear them once /// we're done with restyling. +/// +/// Note that the cleanup is done on the thread that owns the scoped TLS, thus +/// the Send bound. pub struct ScopedTLS<'scope, T: Send> { pool: &'scope rayon::ThreadPool, slots: Box<[RefCell<Option<T>>]>, diff --git a/components/style/sharing/mod.rs b/components/style/sharing/mod.rs index 44fd51362d2..38fd6283436 100644 --- a/components/style/sharing/mod.rs +++ b/components/style/sharing/mod.rs @@ -82,7 +82,7 @@ use servo_arc::Arc; use smallbitvec::SmallBitVec; use smallvec::SmallVec; use std::marker::PhantomData; -use std::mem; +use std::mem::{self, ManuallyDrop}; use std::ops::Deref; use std::ptr::NonNull; use uluru::{Entry, LRUCache}; @@ -477,10 +477,9 @@ type TypelessSharingCache = SharingCacheBase<FakeCandidate>; type StoredSharingCache = Arc<AtomicRefCell<TypelessSharingCache>>; thread_local! { - // TODO(emilio): Looks like a few of these should just be Rc<RefCell<>> or - // something. No need for atomics in the thread-local code. - static SHARING_CACHE_KEY: StoredSharingCache = - Arc::new_leaked(AtomicRefCell::new(TypelessSharingCache::default())); + // See the comment on bloom.rs about why do we leak this. + static SHARING_CACHE_KEY: ManuallyDrop<StoredSharingCache> = + ManuallyDrop::new(Arc::new_leaked(Default::default())); } /// An LRU cache of the last few nodes seen, so that we can aggressively try to @@ -533,7 +532,7 @@ impl<E: TElement> StyleSharingCache<E> { mem::align_of::<SharingCache<E>>(), mem::align_of::<TypelessSharingCache>() ); - let cache_arc = SHARING_CACHE_KEY.with(|c| c.clone()); + let cache_arc = SHARING_CACHE_KEY.with(|c| Arc::clone(&*c)); let cache = OwningHandle::new_with_fn(cache_arc, |x| unsafe { x.as_ref() }.unwrap().borrow_mut()); debug_assert!(cache.is_empty()); diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 577aa1a0267..9f274917b08 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -283,6 +283,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { fn adjust_for_text_combine_upright(&mut self) { use crate::computed_values::text_combine_upright::T as TextCombineUpright; use crate::computed_values::writing_mode::T as WritingMode; + use crate::logical_geometry; let writing_mode = self.style.get_inherited_box().clone_writing_mode(); let text_combine_upright = self.style.get_inherited_text().clone_text_combine_upright(); @@ -294,6 +295,8 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { self.style .mutate_inherited_box() .set_writing_mode(WritingMode::HorizontalTb); + self.style.writing_mode = + logical_geometry::WritingMode::new(self.style.get_inherited_box()); } } diff --git a/components/style/use_counters/mod.rs b/components/style/use_counters/mod.rs index c9a4b449ea0..bb8e92594a6 100644 --- a/components/style/use_counters/mod.rs +++ b/components/style/use_counters/mod.rs @@ -6,6 +6,7 @@ #[cfg(feature = "gecko")] use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI}; +use crate::properties::{CountedUnknownProperty, COUNTED_UNKNOWN_PROPERTY_COUNT}; use crate::properties::{NonCustomPropertyId, NON_CUSTOM_PROPERTY_ID_COUNT}; use std::cell::Cell; @@ -17,44 +18,60 @@ const BITS_PER_ENTRY: usize = 32; /// One bit per each non-custom CSS property. #[derive(Default)] +pub struct CountedUnknownPropertyUseCounters { + storage: [Cell<usize>; (COUNTED_UNKNOWN_PROPERTY_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY], +} + +/// One bit per each non-custom CSS property. +#[derive(Default)] pub struct NonCustomPropertyUseCounters { storage: [Cell<usize>; (NON_CUSTOM_PROPERTY_ID_COUNT - 1 + BITS_PER_ENTRY) / BITS_PER_ENTRY], } -impl NonCustomPropertyUseCounters { - /// Returns the bucket a given property belongs in, and the bitmask for that - /// property. - #[inline(always)] - fn bucket_and_pattern(id: NonCustomPropertyId) -> (usize, usize) { - let bit = id.bit(); - let bucket = bit / BITS_PER_ENTRY; - let bit_in_bucket = bit % BITS_PER_ENTRY; - (bucket, 1 << bit_in_bucket) - } +macro_rules! property_use_counters_methods { + ($id: ident) => { + /// Returns the bucket a given property belongs in, and the bitmask for that + /// property. + #[inline(always)] + fn bucket_and_pattern(id: $id) -> (usize, usize) { + let bit = id.bit(); + let bucket = bit / BITS_PER_ENTRY; + let bit_in_bucket = bit % BITS_PER_ENTRY; + (bucket, 1 << bit_in_bucket) + } - /// Record that a given non-custom property ID has been parsed. - #[inline] - pub fn record(&self, id: NonCustomPropertyId) { - let (bucket, pattern) = Self::bucket_and_pattern(id); - let bucket = &self.storage[bucket]; - bucket.set(bucket.get() | pattern) - } + /// Record that a given property ID has been parsed. + #[inline] + pub fn record(&self, id: $id) { + let (bucket, pattern) = Self::bucket_and_pattern(id); + let bucket = &self.storage[bucket]; + bucket.set(bucket.get() | pattern) + } - /// Returns whether a given non-custom property ID has been recorded - /// earlier. - #[inline] - pub fn recorded(&self, id: NonCustomPropertyId) -> bool { - let (bucket, pattern) = Self::bucket_and_pattern(id); - self.storage[bucket].get() & pattern != 0 - } + /// Returns whether a given property ID has been recorded + /// earlier. + #[inline] + pub fn recorded(&self, id: $id) -> bool { + let (bucket, pattern) = Self::bucket_and_pattern(id); + self.storage[bucket].get() & pattern != 0 + } - /// Merge `other` into `self`. - #[inline] - fn merge(&self, other: &Self) { - for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) { - bucket.set(bucket.get() | other_bucket.get()) + /// Merge `other` into `self`. + #[inline] + fn merge(&self, other: &Self) { + for (bucket, other_bucket) in self.storage.iter().zip(other.storage.iter()) { + bucket.set(bucket.get() | other_bucket.get()) + } } - } + }; +} + +impl CountedUnknownPropertyUseCounters { + property_use_counters_methods!(CountedUnknownProperty); +} + +impl NonCustomPropertyUseCounters { + property_use_counters_methods!(NonCustomPropertyId); } /// The use-counter data related to a given document we want to store. @@ -63,6 +80,8 @@ pub struct UseCounters { /// The counters for non-custom properties that have been parsed in the /// document's stylesheets. pub non_custom_properties: NonCustomPropertyUseCounters, + /// The counters for css properties which we haven't implemented yet. + pub counted_unknown_properties: CountedUnknownPropertyUseCounters, } impl UseCounters { @@ -72,7 +91,9 @@ impl UseCounters { #[inline] pub fn merge(&self, other: &Self) { self.non_custom_properties - .merge(&other.non_custom_properties) + .merge(&other.non_custom_properties); + self.counted_unknown_properties + .merge(&other.counted_unknown_properties); } } diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 407a547013f..a4fa6013277 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -9,11 +9,15 @@ use crate::gecko_bindings::sugar::refptr::RefPtr; #[cfg(feature = "gecko")] use crate::gecko_bindings::{bindings, structs}; use crate::values::animated::{ToAnimatedValue, ToAnimatedZero}; -use crate::values::computed::{Angle, Context, Integer, NonNegativeLength, NonNegativePercentage}; +use crate::values::computed::{ + Angle, Context, Integer, Length, NonNegativeLength, NonNegativePercentage, +}; use crate::values::computed::{Number, Percentage, ToComputedValue}; -use crate::values::generics::font as generics; use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue}; -use crate::values::specified::font::{self as specified, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT}; +use crate::values::generics::{font as generics, NonNegative}; +use crate::values::specified::font::{ + self as specified, KeywordInfo, MAX_FONT_WEIGHT, MIN_FONT_WEIGHT, +}; use crate::values::specified::length::{FontBaseSize, NoCalcLength}; use crate::values::CSSFloat; use crate::Atom; @@ -88,9 +92,6 @@ pub struct FontSize { pub keyword_info: Option<KeywordInfo>, } -/// Additional information for computed keyword-derived font sizes. -pub type KeywordInfo = generics::KeywordInfo<NonNegativeLength>; - impl FontWeight { /// Value for normal pub fn normal() -> Self { @@ -162,17 +163,17 @@ impl FontSize { } impl ToAnimatedValue for FontSize { - type AnimatedValue = NonNegativeLength; + type AnimatedValue = Length; #[inline] fn to_animated_value(self) -> Self::AnimatedValue { - self.size + self.size.0 } #[inline] fn from_animated_value(animated: Self::AnimatedValue) -> Self { FontSize { - size: animated.clamp(), + size: NonNegative(animated.clamp_to_non_negative()), keyword_info: None, } } @@ -647,10 +648,10 @@ impl ToAnimatedValue for FontSizeAdjust { pub type FontVariantAlternates = specified::VariantAlternatesList; impl FontVariantAlternates { - #[inline] /// Get initial value with VariantAlternatesList + #[inline] pub fn get_initial_value() -> Self { - specified::VariantAlternatesList(vec![].into_boxed_slice()) + Self::default() } } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 80b16dcecc9..88eb8f3955a 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -297,7 +297,7 @@ impl specified::CalcLengthPercentage { ) -> LengthPercentage { self.to_computed_value_with_zoom( context, - |abs| context.maybe_zoom_text(abs.into()).0, + |abs| context.maybe_zoom_text(abs.into()), base_size, ) } @@ -360,8 +360,8 @@ impl LengthPercentage { self.unclamped_length().px() == 0.0 && self.percentage.0 == 0.0 } - // CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we still use Au as the - // hash key. + // CSSFloat doesn't implement Hash, so does CSSPixelLength. Therefore, we + // still use Au as the hash key. #[allow(missing_docs)] pub fn to_hash_key(&self) -> (Au, NotNan<f32>) { ( @@ -840,14 +840,6 @@ impl NonNegativeLength { self } } - - /// Scale this NonNegativeLength. - /// We scale NonNegativeLength by zero if the factor is negative because it doesn't - /// make sense to scale a negative factor on a non-negative length. - #[inline] - pub fn scale_by(&self, factor: f32) -> Self { - Self::new(self.0.px() * factor.max(0.)) - } } impl From<Length> for NonNegativeLength { diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index bd78d376b35..aafb42b284a 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -75,7 +75,6 @@ pub use self::resolution::Resolution; 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, LineBreak, LineHeight}; pub use self::text::{OverflowWrap, TextOverflow, WordBreak, WordSpacing}; pub use self::text::{TextAlign, TextEmphasisPosition, TextEmphasisStyle}; @@ -116,7 +115,6 @@ pub mod position; pub mod rect; pub mod resolution; pub mod svg; -pub mod table; pub mod text; pub mod time; pub mod transform; @@ -230,7 +228,7 @@ impl<'a> Context<'a> { /// Apply text-zoom if enabled. #[cfg(feature = "gecko")] - pub fn maybe_zoom_text(&self, size: NonNegativeLength) -> NonNegativeLength { + pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength { // We disable zoom for <svg:text> by unsetting the // -x-text-zoom property, which leads to a false value // in mAllowZoom @@ -243,7 +241,7 @@ impl<'a> Context<'a> { /// (Servo doesn't do text-zoom) #[cfg(feature = "servo")] - pub fn maybe_zoom_text(&self, size: NonNegativeLength) -> NonNegativeLength { + pub fn maybe_zoom_text(&self, size: CSSPixelLength) -> CSSPixelLength { size } } @@ -685,11 +683,11 @@ impl From<CSSInteger> for PositiveInteger { /// A computed positive `<integer>` value or `none`. pub type PositiveIntegerOrNone = Either<PositiveInteger, None_>; -/// rect(...) -pub type ClipRect = generics::ClipRect<LengthOrAuto>; +/// rect(...) | auto +pub type ClipRect = generics::GenericClipRect<LengthOrAuto>; /// rect(...) | auto -pub type ClipRectOrAuto = Either<ClipRect, Auto>; +pub type ClipRectOrAuto = generics::GenericClipRectOrAuto<ClipRect>; /// The computed value of a grid `<track-breadth>` pub type TrackBreadth = GenericTrackBreadth<LengthPercentage>; @@ -709,18 +707,3 @@ pub type GridLine = GenericGridLine<Integer>; /// `<grid-template-rows> | <grid-template-columns>` pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>; - -impl ClipRectOrAuto { - /// Return an auto (default for clip-rect and image-region) value - pub fn auto() -> Self { - Either::Second(Auto) - } - - /// Check if it is auto - pub fn is_auto(&self) -> bool { - match *self { - Either::Second(_) => true, - _ => false, - } - } -} diff --git a/components/style/values/computed/table.rs b/components/style/values/computed/table.rs deleted file mode 100644 index 22d09447ba9..00000000000 --- a/components/style/values/computed/table.rs +++ /dev/null @@ -1,7 +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 table properties. - -pub use crate::values::specified::table::XSpan; diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index bdb2ac507bc..4cccd248d1c 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -198,8 +198,6 @@ impl TextDecorationsInEffect { } /// Computed value for the text-emphasis-style property -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue)] #[allow(missing_docs)] #[repr(C, u8)] diff --git a/components/style/values/generics/counters.rs b/components/style/values/generics/counters.rs index fbb6927b9f1..69893c75561 100644 --- a/components/style/values/generics/counters.rs +++ b/components/style/values/generics/counters.rs @@ -7,7 +7,7 @@ #[cfg(feature = "servo")] use crate::computed_values::list_style_type::T as ListStyleType; #[cfg(feature = "gecko")] -use crate::values::generics::CounterStyleOrNone; +use crate::values::generics::CounterStyle; #[cfg(feature = "gecko")] use crate::values::specified::Attr; use crate::values::CustomIdent; @@ -25,12 +25,14 @@ use std::ops::Deref; ToResolvedValue, ToShmem, )] -pub struct CounterPair<Integer> { +#[repr(C)] +pub struct GenericCounterPair<Integer> { /// The name of the counter. pub name: CustomIdent, /// The value of the counter / increment / etc. pub value: Integer, } +pub use self::GenericCounterPair as CounterPair; /// A generic value for the `counter-increment` property. #[derive( @@ -45,13 +47,15 @@ pub struct CounterPair<Integer> { ToResolvedValue, ToShmem, )] -pub struct CounterIncrement<I>(pub Counters<I>); +#[repr(transparent)] +pub struct GenericCounterIncrement<I>(pub GenericCounters<I>); +pub use self::GenericCounterIncrement as CounterIncrement; impl<I> CounterIncrement<I> { /// Returns a new value for `counter-increment`. #[inline] pub fn new(counters: Vec<CounterPair<I>>) -> Self { - CounterIncrement(Counters(counters.into_boxed_slice())) + CounterIncrement(Counters(counters.into())) } } @@ -77,13 +81,15 @@ impl<I> Deref for CounterIncrement<I> { ToResolvedValue, ToShmem, )] -pub struct CounterSetOrReset<I>(pub Counters<I>); +#[repr(transparent)] +pub struct GenericCounterSetOrReset<I>(pub GenericCounters<I>); +pub use self::GenericCounterSetOrReset as CounterSetOrReset; impl<I> CounterSetOrReset<I> { /// Returns a new value for `counter-set` / `counter-reset`. #[inline] pub fn new(counters: Vec<CounterPair<I>>) -> Self { - CounterSetOrReset(Counters(counters.into_boxed_slice())) + CounterSetOrReset(Counters(counters.into())) } } @@ -111,23 +117,17 @@ impl<I> Deref for CounterSetOrReset<I> { ToResolvedValue, ToShmem, )] -pub struct Counters<I>(#[css(iterable, if_empty = "none")] Box<[CounterPair<I>]>); - -impl<I> Counters<I> { - /// Move out the Box into a vector. This could just return the Box<>, but - /// Vec<> is a bit more convenient because Box<[T]> doesn't implement - /// IntoIter: https://github.com/rust-lang/rust/issues/59878 - #[inline] - pub fn into_vec(self) -> Vec<CounterPair<I>> { - self.0.into_vec() - } -} +#[repr(transparent)] +pub struct GenericCounters<I>( + #[css(iterable, if_empty = "none")] crate::OwnedSlice<GenericCounterPair<I>>, +); +pub use self::GenericCounters as Counters; #[cfg(feature = "servo")] type CounterStyleType = ListStyleType; #[cfg(feature = "gecko")] -type CounterStyleType = CounterStyleOrNone; +type CounterStyleType = CounterStyle; #[cfg(feature = "servo")] #[inline] @@ -138,7 +138,7 @@ fn is_decimal(counter_type: &CounterStyleType) -> bool { #[cfg(feature = "gecko")] #[inline] fn is_decimal(counter_type: &CounterStyleType) -> bool { - *counter_type == CounterStyleOrNone::decimal() + *counter_type == CounterStyle::decimal() } /// The specified value for the `content` property. diff --git a/components/style/values/generics/effects.rs b/components/style/values/generics/effects.rs index 724f484f283..dd9da8759be 100644 --- a/components/style/values/generics/effects.rs +++ b/components/style/values/generics/effects.rs @@ -34,8 +34,6 @@ pub struct GenericBoxShadow<Color, SizeLength, BlurShapeLength, ShapeLength> { pub use self::GenericBoxShadow as BoxShadow; /// A generic value for a single `filter`. -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[animation(no_bound(U))] #[derive( diff --git a/components/style/values/generics/font.rs b/components/style/values/generics/font.rs index eb8eac191f0..2b29104ff81 100644 --- a/components/style/values/generics/font.rs +++ b/components/style/values/generics/font.rs @@ -5,14 +5,13 @@ //! Generic types for font stuff. use crate::parser::{Parse, ParserContext}; -use app_units::Au; use byteorder::{BigEndian, ReadBytesExt}; use cssparser::Parser; use num_traits::One; use std::fmt::{self, Write}; use std::io::Cursor; -use style_traits::{CssWriter, KeywordsCollectFn, ParseError}; -use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss}; +use style_traits::{CssWriter, ParseError}; +use style_traits::{StyleParseErrorKind, ToCss}; /// https://drafts.csswg.org/css-fonts-4/#feature-tag-value #[derive( @@ -172,105 +171,6 @@ impl Parse for FontTag { } } -#[derive( - Animate, - Clone, - ComputeSquaredDistance, - Copy, - Debug, - MallocSizeOf, - PartialEq, - ToAnimatedValue, - ToAnimatedZero, - ToCss, - ToShmem, -)] -/// Additional information for keyword-derived font sizes. -pub struct KeywordInfo<Length> { - /// The keyword used - pub kw: KeywordSize, - /// A factor to be multiplied by the computed size of the keyword - #[css(skip)] - pub factor: f32, - /// An additional Au offset to add to the kw*factor in the case of calcs - #[css(skip)] - pub offset: Length, -} - -impl<L> KeywordInfo<L> -where - Au: Into<L>, -{ - /// KeywordInfo value for font-size: medium - pub fn medium() -> Self { - KeywordSize::Medium.into() - } -} - -impl<L> From<KeywordSize> for KeywordInfo<L> -where - Au: Into<L>, -{ - fn from(x: KeywordSize) -> Self { - KeywordInfo { - kw: x, - factor: 1., - offset: Au(0).into(), - } - } -} - -impl<L> SpecifiedValueInfo for KeywordInfo<L> { - fn collect_completion_keywords(f: KeywordsCollectFn) { - <KeywordSize as SpecifiedValueInfo>::collect_completion_keywords(f); - } -} - -/// CSS font keywords -#[derive( - Animate, - Clone, - ComputeSquaredDistance, - Copy, - Debug, - MallocSizeOf, - Parse, - PartialEq, - SpecifiedValueInfo, - ToAnimatedValue, - ToAnimatedZero, - ToCss, - ToShmem, -)] -#[allow(missing_docs)] -pub enum KeywordSize { - #[css(keyword = "xx-small")] - XXSmall, - XSmall, - Small, - Medium, - Large, - XLarge, - #[css(keyword = "xx-large")] - XXLarge, - #[css(keyword = "xxx-large")] - XXXLarge, -} - -impl KeywordSize { - /// Convert to an HTML <font size> value - #[inline] - pub fn html_size(self) -> u8 { - self as u8 - } -} - -impl Default for KeywordSize { - fn default() -> Self { - KeywordSize::Medium - } -} - /// A generic value for the `font-style` property. /// /// https://drafts.csswg.org/css-fonts-4/#font-style-prop diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index b9e173ea50f..29f634d10fe 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -185,8 +185,6 @@ impl Parse for GridLine<specified::Integer> { /// avoid re-implementing it for the computed type. /// /// <https://drafts.csswg.org/css-grid/#typedef-track-breadth> -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, @@ -230,8 +228,6 @@ impl<L> TrackBreadth<L> { /// generic only to avoid code bloat. It only takes `<length-percentage>` /// /// <https://drafts.csswg.org/css-grid/#typedef-track-size> -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Clone, Debug, @@ -494,8 +490,6 @@ impl<L: ToCss, I: ToCss> ToCss for TrackRepeat<L, I> { } /// Track list values. Can be <track-size> or <track-repeat> -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, @@ -729,8 +723,6 @@ impl ToCss for LineNameList { } /// Variants for `<grid-template-rows> | <grid-template-columns>` -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 343aad87694..04de85cbcf2 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -92,13 +92,10 @@ impl SymbolsType { /// <https://drafts.csswg.org/css-counter-styles/#typedef-counter-style> /// -/// Since wherever <counter-style> is used, 'none' is a valid value as -/// well, we combine them into one type to make code simpler. +/// Note that 'none' is not a valid name. #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToCss, ToResolvedValue, ToShmem)] -pub enum CounterStyleOrNone { - /// `none` - None, +pub enum CounterStyle { /// `<counter-style-name>` Name(CustomIdent), /// `symbols()` @@ -111,28 +108,25 @@ fn is_symbolic(symbols_type: &SymbolsType) -> bool { *symbols_type == SymbolsType::Symbolic } -impl CounterStyleOrNone { +impl CounterStyle { /// disc value pub fn disc() -> Self { - CounterStyleOrNone::Name(CustomIdent(atom!("disc"))) + CounterStyle::Name(CustomIdent(atom!("disc"))) } /// decimal value pub fn decimal() -> Self { - CounterStyleOrNone::Name(CustomIdent(atom!("decimal"))) + CounterStyle::Name(CustomIdent(atom!("decimal"))) } } -impl Parse for CounterStyleOrNone { +impl Parse for CounterStyle { fn parse<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { if let Ok(name) = input.try(|i| parse_counter_style_name(i)) { - return Ok(CounterStyleOrNone::Name(name)); - } - if input.try(|i| i.expect_ident_matching("none")).is_ok() { - return Ok(CounterStyleOrNone::None); + return Ok(CounterStyle::Name(name)); } input.expect_function_matching("symbols")?; input.parse_nested_block(|input| { @@ -151,12 +145,12 @@ impl Parse for CounterStyleOrNone { if symbols.0.iter().any(|sym| !sym.is_allowed_in_symbols()) { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } - Ok(CounterStyleOrNone::Symbols(symbols_type, symbols)) + Ok(CounterStyle::Symbols(symbols_type, symbols)) }) } } -impl SpecifiedValueInfo for CounterStyleOrNone { +impl SpecifiedValueInfo for CounterStyle { fn collect_completion_keywords(f: KeywordsCollectFn) { // XXX The best approach for implementing this is probably // having a CounterStyleName type wrapping CustomIdent, and @@ -165,7 +159,7 @@ impl SpecifiedValueInfo for CounterStyleOrNone { // approach here. macro_rules! predefined { ($($name:expr,)+) => { - f(&["none", "symbols", $($name,)+]); + f(&["symbols", $($name,)+]); } } include!("../../counter_style/predefined.rs"); @@ -272,9 +266,53 @@ pub struct ZeroToOne<T>(pub T); ToShmem, )] #[css(function = "rect", comma)] -pub struct ClipRect<LengthOrAuto> { +#[repr(C)] +pub struct GenericClipRect<LengthOrAuto> { pub top: LengthOrAuto, pub right: LengthOrAuto, pub bottom: LengthOrAuto, pub left: LengthOrAuto, } + +pub use self::GenericClipRect as ClipRect; + +/// Either a clip-rect or `auto`. +#[allow(missing_docs)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(C, u8)] +pub enum GenericClipRectOrAuto<R> { + Auto, + Rect(R), +} + +pub use self::GenericClipRectOrAuto as ClipRectOrAuto; + +impl<L> ClipRectOrAuto<L> { + /// Returns the `auto` value. + #[inline] + pub fn auto() -> Self { + ClipRectOrAuto::Auto + } + + /// Returns whether this value is the `auto` value. + #[inline] + pub fn is_auto(&self) -> bool { + matches!(*self, ClipRectOrAuto::Auto) + } +} diff --git a/components/style/values/generics/svg.rs b/components/style/values/generics/svg.rs index 4a1fc42551d..82183c30564 100644 --- a/components/style/values/generics/svg.rs +++ b/components/style/values/generics/svg.rs @@ -9,7 +9,6 @@ use cssparser::Parser; use style_traits::ParseError; /// The fallback of an SVG paint server value. -/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, @@ -43,8 +42,6 @@ pub use self::GenericSVGPaintFallback as SVGPaintFallback; /// An SVG paint value /// /// <https://www.w3.org/TR/SVG2/painting.html#SpecifyingPaint> -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[animation(no_bound(Url))] #[derive( Animate, @@ -84,8 +81,6 @@ impl<C, U> Default for SVGPaint<C, U> { /// /// Whereas the spec only allows PaintServer to have a fallback, Gecko lets the /// context properties have a fallback as well. -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[animation(no_bound(U))] #[derive( Animate, diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 8dbbdfcd168..4a8dc7f63fa 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -151,7 +151,6 @@ fn is_same<N: PartialEq>(x: &N, y: &N) -> bool { )] #[repr(C, u8)] /// A single operation in the list of a `transform` value -/// cbindgen:derive-tagged-enum-copy-constructor=true pub enum GenericTransformOperation<Angle, Number, Length, Integer, LengthPercentage> where Angle: Zero, diff --git a/components/style/values/generics/url.rs b/components/style/values/generics/url.rs index 1f271033036..46ed453e82d 100644 --- a/components/style/values/generics/url.rs +++ b/components/style/values/generics/url.rs @@ -5,8 +5,6 @@ //! Generic types for url properties. /// An image url or none, used for example in list-style-image -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Animate, Clone, diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index 7030a669397..3e18a23d964 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -105,16 +105,12 @@ pub enum DisplayInside { #[cfg(feature = "gecko")] MozGrid, #[cfg(feature = "gecko")] - MozInlineGrid, - #[cfg(feature = "gecko")] MozGridGroup, #[cfg(feature = "gecko")] MozGridLine, #[cfg(feature = "gecko")] MozStack, #[cfg(feature = "gecko")] - MozInlineStack, - #[cfg(feature = "gecko")] MozDeck, #[cfg(feature = "gecko")] MozGroupbox, @@ -243,16 +239,12 @@ impl Display { #[cfg(feature = "gecko")] pub const MozGrid: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGrid); #[cfg(feature = "gecko")] - pub const MozInlineGrid: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozInlineGrid); - #[cfg(feature = "gecko")] pub const MozGridGroup: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridGroup); #[cfg(feature = "gecko")] pub const MozGridLine: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGridLine); #[cfg(feature = "gecko")] pub const MozStack: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozStack); #[cfg(feature = "gecko")] - pub const MozInlineStack: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozInlineStack); - #[cfg(feature = "gecko")] pub const MozDeck: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozDeck); #[cfg(feature = "gecko")] pub const MozGroupbox: Self = Self::new(DisplayOutside::XUL, DisplayInside::MozGroupbox); @@ -422,7 +414,6 @@ impl Display { #[cfg(feature = "gecko")] DisplayOutside::XUL => match self.inside() { DisplayInside::MozBox => Display::MozInlineBox, - DisplayInside::MozStack => Display::MozInlineStack, _ => *self, }, _ => *self, @@ -469,10 +460,6 @@ impl ToCss for Display { Display::WebkitInlineBox => dest.write_str("-webkit-inline-box"), #[cfg(feature = "gecko")] Display::MozInlineBox => dest.write_str("-moz-inline-box"), - #[cfg(feature = "gecko")] - Display::MozInlineGrid => dest.write_str("-moz-inline-grid"), - #[cfg(feature = "gecko")] - Display::MozInlineStack => dest.write_str("-moz-inline-stack"), #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))] Display::TableCaption => dest.write_str("table-caption"), _ => match (outside, inside) { @@ -662,16 +649,12 @@ impl Parse for Display { #[cfg(feature = "gecko")] "-moz-grid" if moz_display_values_enabled(context) => Display::MozGrid, #[cfg(feature = "gecko")] - "-moz-inline-grid" if moz_display_values_enabled(context) => Display::MozInlineGrid, - #[cfg(feature = "gecko")] "-moz-grid-group" if moz_display_values_enabled(context) => Display::MozGridGroup, #[cfg(feature = "gecko")] "-moz-grid-line" if moz_display_values_enabled(context) => Display::MozGridLine, #[cfg(feature = "gecko")] "-moz-stack" if moz_display_values_enabled(context) => Display::MozStack, #[cfg(feature = "gecko")] - "-moz-inline-stack" if moz_display_values_enabled(context) => Display::MozInlineStack, - #[cfg(feature = "gecko")] "-moz-deck" if moz_display_values_enabled(context) => Display::MozDeck, #[cfg(feature = "gecko")] "-moz-groupbox" if moz_display_values_enabled(context) => Display::MozGroupbox, @@ -688,6 +671,7 @@ impl SpecifiedValueInfo for Display { "contents", "flex", "flow-root", + "flow-root list-item", "grid", "inline", "inline-block", diff --git a/components/style/values/specified/counters.rs b/components/style/values/specified/counters.rs index 262e7765a4a..54690b53105 100644 --- a/components/style/values/specified/counters.rs +++ b/components/style/values/specified/counters.rs @@ -8,11 +8,11 @@ use crate::computed_values::list_style_type::T as ListStyleType; use crate::parser::{Parse, ParserContext}; use crate::values::generics::counters as generics; -use crate::values::generics::counters::CounterIncrement as GenericCounterIncrement; use crate::values::generics::counters::CounterPair; -use crate::values::generics::counters::CounterSetOrReset as GenericCounterSetOrReset; +use crate::values::generics::counters::GenericCounterIncrement; +use crate::values::generics::counters::GenericCounterSetOrReset; #[cfg(feature = "gecko")] -use crate::values::generics::CounterStyleOrNone; +use crate::values::generics::CounterStyle; use crate::values::specified::url::SpecifiedImageUrl; #[cfg(feature = "gecko")] use crate::values::specified::Attr; @@ -98,13 +98,13 @@ impl Content { } #[cfg(feature = "gecko")] - fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyleOrNone { + fn parse_counter_style(context: &ParserContext, input: &mut Parser) -> CounterStyle { input .try(|input| { input.expect_comma()?; - CounterStyleOrNone::parse(context, input) + CounterStyle::parse(context, input) }) - .unwrap_or(CounterStyleOrNone::decimal()) + .unwrap_or(CounterStyle::decimal()) } } diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 127b1bfc2fb..90426f80770 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -11,9 +11,9 @@ use crate::properties::longhands::system_font::SystemFont; use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily}; use crate::values::computed::{font as computed, Length, NonNegativeLength}; use crate::values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage}; -use crate::values::computed::{Context, ToComputedValue}; +use crate::values::computed::{CSSPixelLength, Context, ToComputedValue}; +use crate::values::generics::font::VariationValue; use crate::values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag}; -use crate::values::generics::font::{KeywordSize, VariationValue}; use crate::values::generics::NonNegative; use crate::values::specified::length::{FontBaseSize, AU_PER_PT, AU_PER_PX}; use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage}; @@ -481,6 +481,115 @@ impl ToComputedValue for FontStretch { } } +/// CSS font keywords +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + Parse, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToCss, + ToShmem, +)] +#[allow(missing_docs)] +pub enum KeywordSize { + #[css(keyword = "xx-small")] + XXSmall, + XSmall, + Small, + Medium, + Large, + XLarge, + #[css(keyword = "xx-large")] + XXLarge, + #[css(keyword = "xxx-large")] + XXXLarge, +} + +impl KeywordSize { + /// Convert to an HTML <font size> value + #[inline] + pub fn html_size(self) -> u8 { + self as u8 + } +} + +impl Default for KeywordSize { + fn default() -> Self { + KeywordSize::Medium + } +} + +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + MallocSizeOf, + PartialEq, + ToAnimatedValue, + ToAnimatedZero, + ToCss, + ToShmem, +)] +/// Additional information for keyword-derived font sizes. +pub struct KeywordInfo { + /// The keyword used + pub kw: KeywordSize, + /// A factor to be multiplied by the computed size of the keyword + #[css(skip)] + pub factor: f32, + /// An additional fixed offset to add to the kw * factor in the case of + /// `calc()`. + #[css(skip)] + pub offset: CSSPixelLength, +} + +impl KeywordInfo { + /// KeywordInfo value for font-size: medium + pub fn medium() -> Self { + Self::new(KeywordSize::Medium) + } + + fn new(kw: KeywordSize) -> Self { + KeywordInfo { + kw, + factor: 1., + offset: CSSPixelLength::new(0.), + } + } + + /// Computes the final size for this font-size keyword, accounting for + /// text-zoom. + fn to_computed_value(&self, context: &Context) -> CSSPixelLength { + let base = context.maybe_zoom_text(self.kw.to_computed_value(context).0); + base * self.factor + context.maybe_zoom_text(self.offset) + } + + /// Given a parent keyword info (self), apply an additional factor/offset to + /// it. + pub fn compose(self, factor: f32, offset: CSSPixelLength) -> Self { + KeywordInfo { + kw: self.kw, + factor: self.factor * factor, + offset: self.offset * factor + offset, + } + } +} + +impl SpecifiedValueInfo for KeywordInfo { + fn collect_completion_keywords(f: KeywordsCollectFn) { + <KeywordSize as SpecifiedValueInfo>::collect_completion_keywords(f); + } +} + #[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] /// A specified font-size value pub enum FontSize { @@ -652,27 +761,6 @@ impl ToComputedValue for FontSizeAdjust { } } -/// Additional information for specified keyword-derived font sizes. -pub type KeywordInfo = generics::KeywordInfo<NonNegativeLength>; - -impl KeywordInfo { - /// Computes the final size for this font-size keyword, accounting for - /// text-zoom. - pub fn to_computed_value(&self, context: &Context) -> NonNegativeLength { - let base = context.maybe_zoom_text(self.kw.to_computed_value(context)); - base.scale_by(self.factor) + context.maybe_zoom_text(self.offset) - } - - /// Given a parent keyword info (self), apply an additional factor/offset to it - pub fn compose(self, factor: f32, offset: NonNegativeLength) -> Self { - KeywordInfo { - kw: self.kw, - factor: self.factor * factor, - offset: self.offset.scale_by(factor) + offset, - } - } -} - /// This is the ratio applied for font-size: larger /// and smaller by both Firefox and Chrome const LARGER_FONT_SIZE_RATIO: f32 = 1.2; @@ -789,20 +877,17 @@ impl ToComputedValue for KeywordSize { impl FontSize { /// <https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size> pub fn from_html_size(size: u8) -> Self { - FontSize::Keyword( - match size { - // If value is less than 1, let it be 1. - 0 | 1 => KeywordSize::XSmall, - 2 => KeywordSize::Small, - 3 => KeywordSize::Medium, - 4 => KeywordSize::Large, - 5 => KeywordSize::XLarge, - 6 => KeywordSize::XXLarge, - // If value is greater than 7, let it be 7. - _ => KeywordSize::XXXLarge, - } - .into(), - ) + FontSize::Keyword(KeywordInfo::new(match size { + // If value is less than 1, let it be 1. + 0 | 1 => KeywordSize::XSmall, + 2 => KeywordSize::Small, + 3 => KeywordSize::Medium, + 4 => KeywordSize::Large, + 5 => KeywordSize::XLarge, + 6 => KeywordSize::XXLarge, + // If value is greater than 7, let it be 7. + _ => KeywordSize::XXXLarge, + })) } /// Compute it against a given base font size @@ -819,7 +904,7 @@ impl FontSize { .get_parent_font() .clone_font_size() .keyword_info - .map(|i| i.compose(factor, Au(0).into())) + .map(|i| i.compose(factor, CSSPixelLength::new(0.))) }; let mut info = None; let size = match *self { @@ -829,17 +914,15 @@ impl FontSize { // Tack the em unit onto the factor info = compose_keyword(em); } - value.to_computed_value(context, base_size).into() + value.to_computed_value(context, base_size) }, FontSize::Length(LengthPercentage::Length(NoCalcLength::ServoCharacterWidth( value, - ))) => value.to_computed_value(base_size.resolve(context)).into(), + ))) => value.to_computed_value(base_size.resolve(context)), FontSize::Length(LengthPercentage::Length(NoCalcLength::Absolute(ref l))) => { - context.maybe_zoom_text(l.to_computed_value(context).into()) - }, - FontSize::Length(LengthPercentage::Length(ref l)) => { - l.to_computed_value(context).into() + context.maybe_zoom_text(l.to_computed_value(context)) }, + FontSize::Length(LengthPercentage::Length(ref l)) => l.to_computed_value(context), FontSize::Length(LengthPercentage::Percentage(pc)) => { // If the parent font was keyword-derived, this is too. // Tack the % onto the factor @@ -871,29 +954,32 @@ impl FontSize { context, FontBaseSize::InheritedStyleButStripEmUnits, ) - .length_component(); + .unclamped_length(); - info = parent.keyword_info.map(|i| i.compose(ratio, abs.into())); + info = parent.keyword_info.map(|i| i.compose(ratio, abs)); } let calc = calc.to_computed_value_zoomed(context, base_size); - calc.to_used_value(base_size.resolve(context)).into() + // FIXME(emilio): we _could_ use clamp_to_non_negative() + // everywhere, without affecting behavior in theory, since the + // others should reject negatives during parsing. But SMIL + // allows parsing negatives, and relies on us _not_ doing that + // clamping. That's so bonkers :( + CSSPixelLength::from(calc.to_used_value(base_size.resolve(context))) + .clamp_to_non_negative() }, FontSize::Keyword(i) => { // As a specified keyword, this is keyword derived info = Some(i); - i.to_computed_value(context) + i.to_computed_value(context).clamp_to_non_negative() }, FontSize::Smaller => { info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO); FontRelativeLength::Em(1. / LARGER_FONT_SIZE_RATIO) .to_computed_value(context, base_size) - .into() }, FontSize::Larger => { info = compose_keyword(LARGER_FONT_SIZE_RATIO); - FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO) - .to_computed_value(context, base_size) - .into() + FontRelativeLength::Em(LARGER_FONT_SIZE_RATIO).to_computed_value(context, base_size) }, FontSize::System(_) => { @@ -903,12 +989,18 @@ impl FontSize { } #[cfg(feature = "gecko")] { - context.cached_system_font.as_ref().unwrap().font_size.size + context + .cached_system_font + .as_ref() + .unwrap() + .font_size + .size + .0 } }, }; computed::FontSize { - size: size, + size: NonNegative(size), keyword_info: info, } } @@ -952,7 +1044,7 @@ impl FontSize { } if let Ok(kw) = input.try(KeywordSize::parse) { - return Ok(FontSize::Keyword(kw.into())); + return Ok(FontSize::Keyword(KeywordInfo::new(kw))); } try_match_ident_ignore_ascii_case! { input, @@ -998,6 +1090,7 @@ bitflags! { #[derive( Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToResolvedValue, ToShmem, )] +#[repr(C, u8)] /// Set of variant alternates pub enum VariantAlternates { /// Enables display of stylistic alternates @@ -1005,10 +1098,10 @@ pub enum VariantAlternates { Stylistic(CustomIdent), /// Enables display with stylistic sets #[css(comma, function)] - Styleset(#[css(iterable)] Box<[CustomIdent]>), + Styleset(#[css(iterable)] crate::OwnedSlice<CustomIdent>), /// Enables display of specific character variants #[css(comma, function)] - CharacterVariant(#[css(iterable)] Box<[CustomIdent]>), + CharacterVariant(#[css(iterable)] crate::OwnedSlice<CustomIdent>), /// Enables display of swash glyphs #[css(function)] Swash(CustomIdent), @@ -1023,11 +1116,20 @@ pub enum VariantAlternates { } #[derive( - Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToResolvedValue, ToShmem, + Clone, + Debug, + Default, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToCss, + ToResolvedValue, + ToShmem, )] +#[repr(transparent)] /// List of Variant Alternates pub struct VariantAlternatesList( - #[css(if_empty = "normal", iterable)] pub Box<[VariantAlternates]>, + #[css(if_empty = "normal", iterable)] crate::OwnedSlice<VariantAlternates>, ); impl VariantAlternatesList { @@ -1059,7 +1161,7 @@ impl FontVariantAlternates { #[inline] /// Get initial specified value with VariantAlternatesList pub fn get_initial_specified_value() -> Self { - FontVariantAlternates::Value(VariantAlternatesList(vec![].into_boxed_slice())) + FontVariantAlternates::Value(Default::default()) } system_font_methods!(FontVariantAlternates, font_variant_alternates); @@ -1093,16 +1195,14 @@ impl Parse for FontVariantAlternates { _: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<FontVariantAlternates, ParseError<'i>> { - let mut alternates = Vec::new(); if input .try(|input| input.expect_ident_matching("normal")) .is_ok() { - return Ok(FontVariantAlternates::Value(VariantAlternatesList( - alternates.into_boxed_slice(), - ))); + return Ok(FontVariantAlternates::Value(Default::default())); } + let mut alternates = Vec::new(); let mut parsed_alternates = VariantAlternatesParsingFlags::empty(); macro_rules! check_if_parsed( ($input:expr, $flag:path) => ( @@ -1156,7 +1256,7 @@ impl Parse for FontVariantAlternates { let location = i.current_source_location(); CustomIdent::from_ident(location, i.expect_ident()?, &[]) })?; - alternates.push(VariantAlternates::Styleset(idents.into_boxed_slice())); + alternates.push(VariantAlternates::Styleset(idents.into())); Ok(()) }, "character-variant" => { @@ -1165,7 +1265,7 @@ impl Parse for FontVariantAlternates { let location = i.current_source_location(); CustomIdent::from_ident(location, i.expect_ident()?, &[]) })?; - alternates.push(VariantAlternates::CharacterVariant(idents.into_boxed_slice())); + alternates.push(VariantAlternates::CharacterVariant(idents.into())); Ok(()) }, _ => return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)), @@ -1179,7 +1279,7 @@ impl Parse for FontVariantAlternates { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } Ok(FontVariantAlternates::Value(VariantAlternatesList( - alternates.into_boxed_slice(), + alternates.into(), ))) } } diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs index 3946d78652e..1c93f8e8a58 100644 --- a/components/style/values/specified/list.rs +++ b/components/style/values/specified/list.rs @@ -6,7 +6,7 @@ use crate::parser::{Parse, ParserContext}; #[cfg(feature = "gecko")] -use crate::values::generics::CounterStyleOrNone; +use crate::values::generics::CounterStyle; #[cfg(feature = "gecko")] use crate::values::CustomIdent; use cssparser::{Parser, Token}; @@ -27,8 +27,10 @@ use style_traits::{ParseError, StyleParseErrorKind}; ToShmem, )] pub enum ListStyleType { - /// <counter-style> | none - CounterStyle(CounterStyleOrNone), + /// `none` + None, + /// <counter-style> + CounterStyle(CounterStyle), /// <string> String(String), } @@ -38,7 +40,7 @@ impl ListStyleType { /// Initial specified value for `list-style-type`. #[inline] pub fn disc() -> Self { - ListStyleType::CounterStyle(CounterStyleOrNone::disc()) + ListStyleType::CounterStyle(CounterStyle::disc()) } /// Convert from gecko keyword to list-style-type. @@ -50,10 +52,10 @@ impl ListStyleType { use crate::gecko_bindings::structs; if value == structs::NS_STYLE_LIST_STYLE_NONE { - return ListStyleType::CounterStyle(CounterStyleOrNone::None); + return ListStyleType::None; } - ListStyleType::CounterStyle(CounterStyleOrNone::Name(CustomIdent(match value { + ListStyleType::CounterStyle(CounterStyle::Name(CustomIdent(match value { structs::NS_STYLE_LIST_STYLE_DISC => atom!("disc"), structs::NS_STYLE_LIST_STYLE_CIRCLE => atom!("circle"), structs::NS_STYLE_LIST_STYLE_SQUARE => atom!("square"), @@ -73,10 +75,12 @@ impl Parse for ListStyleType { context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result<Self, ParseError<'i>> { - if let Ok(style) = input.try(|i| CounterStyleOrNone::parse(context, i)) { + if let Ok(style) = input.try(|i| CounterStyle::parse(context, i)) { return Ok(ListStyleType::CounterStyle(style)); } - + if input.try(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(ListStyleType::None); + } Ok(ListStyleType::String( input.expect_string()?.as_ref().to_owned(), )) @@ -126,8 +130,6 @@ pub struct QuoteList( /// Specified and computed `quotes` property: `auto`, `none`, or a list /// of characters. -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[derive( Clone, Debug, diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 16897043da9..5daecf353bf 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -13,7 +13,7 @@ use super::generics::grid::{GridLine as GenericGridLine, TrackBreadth as Generic use super::generics::grid::{TrackList as GenericTrackList, TrackSize as GenericTrackSize}; use super::generics::transform::IsParallelTo; use super::generics::{self, GreaterThanOrEqualToOne, NonNegative}; -use super::{Auto, CSSFloat, CSSInteger, Either, None_}; +use super::{CSSFloat, CSSInteger, Either, None_}; use crate::context::QuirksMode; use crate::parser::{Parse, ParserContext}; use crate::values::serialize_atom_identifier; @@ -78,7 +78,6 @@ pub use self::svg::MozContextProperties; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::svg_path::SVGPathData; -pub use self::table::XSpan; 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}; @@ -122,7 +121,6 @@ pub mod resolution; pub mod source_size_list; pub mod svg; pub mod svg_path; -pub mod table; pub mod text; pub mod time; pub mod transform; @@ -641,7 +639,7 @@ pub type GridLine = GenericGridLine<Integer>; pub type GridTemplateComponent = GenericGridTemplateComponent<LengthPercentage, Integer>; /// rect(...) -pub type ClipRect = generics::ClipRect<LengthOrAuto>; +pub type ClipRect = generics::GenericClipRect<LengthOrAuto>; impl Parse for ClipRect { fn parse<'i, 't>( @@ -654,7 +652,7 @@ impl Parse for ClipRect { impl ClipRect { /// Parses a rect(<top>, <left>, <bottom>, <right>), allowing quirks. - pub fn parse_quirky<'i, 't>( + fn parse_quirky<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, allow_quirks: AllowQuirks, @@ -698,7 +696,7 @@ impl ClipRect { } /// rect(...) | auto -pub type ClipRectOrAuto = Either<ClipRect, Auto>; +pub type ClipRectOrAuto = generics::GenericClipRectOrAuto<ClipRect>; impl ClipRectOrAuto { /// Parses a ClipRect or Auto, allowing quirks. @@ -708,10 +706,10 @@ impl ClipRectOrAuto { allow_quirks: AllowQuirks, ) -> Result<Self, ParseError<'i>> { if let Ok(v) = input.try(|i| ClipRect::parse_quirky(context, i, allow_quirks)) { - Ok(Either::First(v)) - } else { - Auto::parse(context, input).map(Either::Second) + return Ok(generics::GenericClipRectOrAuto::Rect(v)); } + input.expect_ident_matching("auto")?; + Ok(generics::GenericClipRectOrAuto::Auto) } } diff --git a/components/style/values/specified/motion.rs b/components/style/values/specified/motion.rs index 97609ea20b0..8d6f7809fdb 100644 --- a/components/style/values/specified/motion.rs +++ b/components/style/values/specified/motion.rs @@ -15,7 +15,6 @@ 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, diff --git a/components/style/values/specified/position.rs b/components/style/values/specified/position.rs index ce3bab1047b..d3476bb9f65 100644 --- a/components/style/values/specified/position.rs +++ b/components/style/values/specified/position.rs @@ -707,8 +707,6 @@ fn is_name_code_point(c: char) -> bool { /// The syntax of this property also provides a visualization of the structure /// of the grid, making the overall layout of the grid container easier to /// understand. -/// -/// cbindgen:derive-tagged-enum-copy-constructor=true #[repr(C, u8)] #[derive( Clone, diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index 4858fbaec6b..6ae1eac2d4a 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -106,13 +106,13 @@ pub enum PaintOrder { } /// Number of non-normal components -const PAINT_ORDER_COUNT: u8 = 3; +pub const PAINT_ORDER_COUNT: u8 = 3; /// Number of bits for each component -const PAINT_ORDER_SHIFT: u8 = 2; +pub const PAINT_ORDER_SHIFT: u8 = 2; /// Mask with above bits set -const PAINT_ORDER_MASK: u8 = 0b11; +pub const PAINT_ORDER_MASK: u8 = 0b11; /// The specified value is tree `PaintOrder` values packed into the /// bitfields below, as a six-bit field, of 3 two-bit pairs @@ -135,6 +135,7 @@ const PAINT_ORDER_MASK: u8 = 0b11; ToResolvedValue, ToShmem, )] +#[repr(transparent)] pub struct SVGPaintOrder(pub u8); impl SVGPaintOrder { @@ -146,7 +147,7 @@ impl SVGPaintOrder { /// Get variant of `paint-order` pub fn order_at(&self, pos: u8) -> PaintOrder { // Safe because PaintOrder covers all possible patterns. - unsafe { ::std::mem::transmute((self.0 >> pos * PAINT_ORDER_SHIFT) & PAINT_ORDER_MASK) } + unsafe { std::mem::transmute((self.0 >> pos * PAINT_ORDER_SHIFT) & PAINT_ORDER_MASK) } } } diff --git a/components/style/values/specified/table.rs b/components/style/values/specified/table.rs deleted file mode 100644 index 2caace07eb3..00000000000 --- a/components/style/values/specified/table.rs +++ /dev/null @@ -1,34 +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/. */ - -//! Specified types for table properties. - -use crate::parser::{Parse, ParserContext}; -use cssparser::Parser; -use style_traits::{ParseError, StyleParseErrorKind}; - -#[derive( - Clone, - Copy, - Debug, - MallocSizeOf, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, -)] -/// span. for `<col span>` pres attr -pub struct XSpan(#[css(skip)] pub i32); - -impl Parse for XSpan { - // never parse it, only set via presentation attribute - fn parse<'i, 't>( - _: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result<XSpan, ParseError<'i>> { - Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) - } -} diff --git a/components/style/values/specified/text.rs b/components/style/values/specified/text.rs index 1686b9f424d..abe44aa8f03 100644 --- a/components/style/values/specified/text.rs +++ b/components/style/values/specified/text.rs @@ -89,9 +89,7 @@ impl ToComputedValue for LineHeight { GenericLineHeight::Length(ref non_negative_lp) => { let result = match non_negative_lp.0 { LengthPercentage::Length(NoCalcLength::Absolute(ref abs)) => { - context - .maybe_zoom_text(abs.to_computed_value(context).into()) - .0 + context.maybe_zoom_text(abs.to_computed_value(context)) }, LengthPercentage::Length(ref length) => length.to_computed_value(context), LengthPercentage::Percentage(ref p) => FontRelativeLength::Em(p.0) @@ -133,7 +131,6 @@ 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 { |