From 3cf8c1931378cb1cbd7a0aeebb63af411e0fb04b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:25:19 +0200 Subject: [PATCH 01/80] style: Support -webkit-image-set as a parse-time alias to image-set() The webkit syntax is an strict subset of the modern one, so this should be doable, and is the simplest. If my reading of the WebKit code is correct it should also be the way WebKit deals with this (except they restrict -webkit-image-set() syntax artificially). * https://github.com/w3c/csswg-drafts/issues/6285 * https://github.com/whatwg/compat/issues/144 Differential Revision: https://phabricator.services.mozilla.com/D114912 --- components/style/values/specified/image.rs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 85c178e064d..dae7fe286d0 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -365,7 +365,14 @@ impl ImageSet { cors_mode: CorsMode, only_url: bool, ) -> Result> { - input.expect_function_matching("image-set")?; + let function = input.expect_function()?; + match_ignore_ascii_case! { &function, + "-webkit-image-set" | "image-set" => {}, + _ => { + let func = function.clone(); + return Err(input.new_custom_error(StyleParseErrorKind::UnexpectedFunction(func))); + } + } let items = input.parse_nested_block(|input| { input.parse_comma_separated(|input| ImageSetItem::parse(context, input, cors_mode, only_url)) })?; From 6d6ea6cfe4ae764695517247886dcd584a46bd99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:26:58 +0200 Subject: [PATCH 02/80] style: Remove support for unused gtk infobar widget and colors Presumably they were for notifications and now we use native notifications? Differential Revision: https://phabricator.services.mozilla.com/D114874 --- components/style/values/specified/box.rs | 2 -- components/style/values/specified/color.rs | 2 -- 2 files changed, 4 deletions(-) diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index 32f4f9bacae..ef465b496bc 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -1838,8 +1838,6 @@ pub enum Appearance { #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] MozWindowTitlebarMaximized, - #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] - MozGtkInfoBar, #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] MozMacActiveSourceListSelection, #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 773a93366b8..0126801638e 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -369,8 +369,6 @@ pub enum SystemColor { MozComboboxtext, MozCombobox, - MozGtkInfoBarText, - /// Color of tree column headers #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] MozColheadertext, From 87a3f2598a53ea94a3fafc4aea2f708e57c47919 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:27:43 +0200 Subject: [PATCH 03/80] style: Properly hide -moz-control-character-visibility from content Differential Revision: https://phabricator.services.mozilla.com/D114481 --- components/style/properties/longhands/inherited_text.mako.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index 246e7ff36a6..fc0e5d8fdea 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -336,6 +336,9 @@ ${helpers.predefined_type( "text::MozControlCharacterVisibility", "Default::default()", engines="gecko", + enabled_in="chrome", + gecko_pref="layout.css.moz-control-character-visibility.enabled", + has_effect_on_gecko_scrollbars=False, animation_value_type="none", spec="Nonstandard" )} From 55f20759b2cce1bb195616dcd8c168f6fbb536e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:28:36 +0200 Subject: [PATCH 04/80] style: Properly hide -moz-context-properties from content Depends on D114481 Differential Revision: https://phabricator.services.mozilla.com/D114482 --- components/style/properties/longhands/inherited_svg.mako.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/style/properties/longhands/inherited_svg.mako.rs b/components/style/properties/longhands/inherited_svg.mako.rs index 820b2d25d04..b9d55c01b20 100644 --- a/components/style/properties/longhands/inherited_svg.mako.rs +++ b/components/style/properties/longhands/inherited_svg.mako.rs @@ -209,6 +209,9 @@ ${helpers.predefined_type( "MozContextProperties", "computed::MozContextProperties::default()", engines="gecko", + enabled_in="chrome", + gecko_pref="svg.context-properties.content.enabled", + has_effect_on_gecko_scrollbars=False, animation_value_type="none", spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-context-properties)", )} From dd28d22ceefad04e15fe6f4257cc4b084627d507 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:29:24 +0200 Subject: [PATCH 05/80] style: Use titlebar colors when using CSD rather than -moz-menubartext As the titlebar may be different when active / inactive, and have other colors than a menubar. Differential Revision: https://phabricator.services.mozilla.com/D114875 --- components/style/values/specified/color.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 0126801638e..6f8d6de9fde 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -375,6 +375,14 @@ pub enum SystemColor { #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] MozColheaderhovertext, + /// Color of text in the (active) titlebar. + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] + MozGtkTitlebarText, + + /// Color of text in the (inactive) titlebar. + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] + MozGtkTitlebarInactiveText, + #[css(skip)] End, // Just for array-indexing purposes. } From 4bcf4573db348ca2a2b34a385b258e12005082ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:30:15 +0200 Subject: [PATCH 06/80] style: Avoid trying to serialize 'all' with stuff that isn't variable references or CSS wide keywords All is special, and that'd cause an error later on. Differential Revision: https://phabricator.services.mozilla.com/D115132 --- components/style/properties/properties.mako.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 99d283da46c..71bf6f1e78a 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1537,6 +1537,11 @@ impl ShorthandId { return None; } + if self == ShorthandId::All { + // 'all' only supports variables and CSS wide keywords. + return None; + } + // Check whether all declarations can be serialized as part of shorthand. if declarations3.all(|d| d.may_serialize_as_part_of_shorthand()) { return Some(AppendableValue::DeclarationsForShorthand(self, declarations)); From 9c32836913ac6cec88559fefd57dcc6b41b8a4af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:31:15 +0200 Subject: [PATCH 07/80] style: Avoid returning fmt::Errors for things that are not formatting errors They are not. The serialization code already checks if the result is empty, which can happen for other reasons. This makes the code a bit more resilient to misuse. Differential Revision: https://phabricator.services.mozilla.com/D115133 --- components/style/properties/properties.mako.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 71bf6f1e78a..b8a9255db48 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1486,13 +1486,13 @@ impl ShorthandId { // shorthand, since it only accepts CSS-wide keywords (and // variable references), which will be handled in // get_shorthand_appendable_value. - Err(fmt::Error) + Ok(()) } % for property in data.shorthands_except_all(): ShorthandId::${property.camel_case} => { match shorthands::${property.ident}::LonghandsToSerialize::from_iter(declarations) { Ok(longhands) => longhands.to_css(dest), - Err(_) => Err(fmt::Error) + Err(_) => Ok(()) } }, % endfor From 1ddd3b09c28ba248482c800de6d8c96c3bae3492 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:32:19 +0200 Subject: [PATCH 08/80] style: Refactor the author sheet cache to keep alive the relevant StylesheetContents This prevents incorrectly reusing cached results when the contents go away and new contents are allocated with the same address. Note that these keep alive transitively everything else under them, so all other medialist keys don't need this. By making this a proper hashmap it should also improve cache lookup times if the cache grows too big. Differential Revision: https://phabricator.services.mozilla.com/D115202 --- components/servo_arc/lib.rs | 8 ++ components/style/stylesheets/stylesheet.rs | 25 ++-- components/style/stylist.rs | 148 ++++++++++++++------- 3 files changed, 126 insertions(+), 55 deletions(-) diff --git a/components/servo_arc/lib.rs b/components/servo_arc/lib.rs index cff93a5d524..fccbde99c6e 100644 --- a/components/servo_arc/lib.rs +++ b/components/servo_arc/lib.rs @@ -248,6 +248,14 @@ impl Arc { } } + /// Like from_raw, but returns an addrefed arc instead. + #[inline] + pub unsafe fn from_raw_addrefed(ptr: *const T) -> Self { + let arc = Self::from_raw(ptr); + mem::forget(arc.clone()); + arc + } + /// Create a new static Arc (one that won't reference count the object) /// and place it in the allocation provided by the specified `alloc` /// function. diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs index 2f7706a6979..b8e7f246c19 100644 --- a/components/style/stylesheets/stylesheet.rs +++ b/components/style/stylesheets/stylesheet.rs @@ -65,6 +65,10 @@ pub struct StylesheetContents { pub source_map_url: RwLock>, /// This stylesheet's source URL. pub source_url: RwLock>, + + /// We don't want to allow construction outside of this file, to guarantee + /// that all contents are created with Arc<>. + _forbid_construction: (), } impl StylesheetContents { @@ -82,7 +86,7 @@ impl StylesheetContents { use_counters: Option<&UseCounters>, allow_import_rules: AllowImportRules, sanitization_data: Option<&mut SanitizationData>, - ) -> Self { + ) -> Arc { let namespaces = RwLock::new(Namespaces::default()); let (rules, source_map_url, source_url) = Stylesheet::parse_rules( css, @@ -99,7 +103,7 @@ impl StylesheetContents { sanitization_data, ); - Self { + Arc::new(Self { rules: CssRules::new(rules, &shared_lock), origin, url_data: RwLock::new(url_data), @@ -107,7 +111,8 @@ impl StylesheetContents { quirks_mode, source_map_url: RwLock::new(source_map_url), source_url: RwLock::new(source_url), - } + _forbid_construction: (), + }) } /// Creates a new StylesheetContents with the specified pre-parsed rules, @@ -126,9 +131,9 @@ impl StylesheetContents { origin: Origin, url_data: UrlExtraData, quirks_mode: QuirksMode, - ) -> Self { + ) -> Arc { debug_assert!(rules.is_static()); - Self { + Arc::new(Self { rules, origin, url_data: RwLock::new(url_data), @@ -136,7 +141,8 @@ impl StylesheetContents { quirks_mode, source_map_url: RwLock::new(None), source_url: RwLock::new(None), - } + _forbid_construction: (), + }) } /// Returns a reference to the list of rules. @@ -178,6 +184,7 @@ impl DeepCloneWithLock for StylesheetContents { namespaces: RwLock::new((*self.namespaces.read()).clone()), source_map_url: RwLock::new((*self.source_map_url.read()).clone()), source_url: RwLock::new((*self.source_url.read()).clone()), + _forbid_construction: (), } } } @@ -186,7 +193,7 @@ impl DeepCloneWithLock for StylesheetContents { #[derive(Debug)] pub struct Stylesheet { /// The contents of this stylesheet. - pub contents: StylesheetContents, + pub contents: Arc, /// The lock used for objects inside this stylesheet pub shared_lock: SharedRwLock, /// List of media associated with the Stylesheet. @@ -587,9 +594,9 @@ impl Clone for Stylesheet { // Make a deep clone of the media, using the new lock. let media = self.media.read_with(&guard).clone(); let media = Arc::new(lock.wrap(media)); - let contents = self + let contents = Arc::new(self .contents - .deep_clone_with_lock(&lock, &guard, &DeepCloneParams); + .deep_clone_with_lock(&lock, &guard, &DeepCloneParams)); Stylesheet { contents, diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 74704e707df..fb7334d3600 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -11,7 +11,7 @@ use crate::element_state::{DocumentState, ElementState}; #[cfg(feature = "gecko")] use crate::gecko_bindings::structs::{ServoStyleSetSizes, StyleRuleInclusion}; use crate::invalidation::element::invalidation_map::InvalidationMap; -use crate::invalidation::media_queries::EffectiveMediaQueryResults; +use crate::invalidation::media_queries::{EffectiveMediaQueryResults, MediaListKey, ToMediaListKey}; use crate::invalidation::stylesheets::RuleChangeKind; use crate::media_queries::Device; use crate::properties::{self, CascadeMode, ComputedValues}; @@ -26,8 +26,7 @@ use crate::stylesheet_set::{DataValidity, DocumentStylesheetSet, SheetRebuildKin use crate::stylesheet_set::{DocumentStylesheetFlusher, SheetCollectionFlusher}; use crate::stylesheets::keyframes_rule::KeyframesAnimation; use crate::stylesheets::viewport_rule::{self, MaybeNew, ViewportRule}; -use crate::stylesheets::StyleRule; -use crate::stylesheets::StylesheetInDocument; +use crate::stylesheets::{StyleRule, StylesheetInDocument, StylesheetContents}; #[cfg(feature = "gecko")] use crate::stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule, PageRule}; use crate::stylesheets::{CssRule, Origin, OriginSet, PerOrigin, PerOriginIter}; @@ -50,7 +49,9 @@ use smallbitvec::SmallBitVec; use smallvec::SmallVec; use std::sync::Mutex; use std::{mem, ops}; +use std::hash::{Hash, Hasher}; use style_traits::viewport::ViewportConstraints; +use fxhash::FxHashMap; /// The type of the stylesheets that the stylist contains. #[cfg(feature = "servo")] @@ -60,6 +61,37 @@ pub type StylistSheet = crate::stylesheets::DocumentStyleSheet; #[cfg(feature = "gecko")] pub type StylistSheet = crate::gecko::data::GeckoStyleSheet; +#[derive(Debug, Clone)] +struct StylesheetContentsPtr(Arc); + +impl PartialEq for StylesheetContentsPtr { + #[inline] + fn eq(&self, other: &Self) -> bool { + Arc::ptr_eq(&self.0, &other.0) + } +} + +impl Eq for StylesheetContentsPtr {} + +impl Hash for StylesheetContentsPtr { + fn hash(&self, state: &mut H) { + let contents: &StylesheetContents = &*self.0; + (contents as *const StylesheetContents).hash(state) + } +} + +type StyleSheetContentList = Vec; + +/// A key in the cascade data cache. +#[derive(Debug, Hash, Default, PartialEq, Eq)] +struct CascadeDataCacheKey { + media_query_results: Vec, + contents: StyleSheetContentList, +} + +unsafe impl Send for CascadeDataCacheKey {} +unsafe impl Sync for CascadeDataCacheKey {} + trait CascadeDataCacheEntry : Sized { /// Returns a reference to the cascade data. fn cascade_data(&self) -> &CascadeData; @@ -80,7 +112,7 @@ trait CascadeDataCacheEntry : Sized { } struct CascadeDataCache { - entries: Vec>, + entries: FxHashMap>, } impl CascadeDataCache @@ -88,7 +120,7 @@ where Entry: CascadeDataCacheEntry, { fn new() -> Self { - Self { entries: vec![] } + Self { entries: Default::default() } } fn len(&self) -> usize { @@ -110,51 +142,66 @@ where where S: StylesheetInDocument + PartialEq + 'static, { + use std::collections::hash_map::Entry as HashMapEntry; debug!("StyleSheetCache::lookup({})", self.len()); if !collection.dirty() { return Ok(None); } - let mut key = EffectiveMediaQueryResults::new(); + let mut key = CascadeDataCacheKey::default(); for sheet in collection.sheets() { - CascadeData::collect_applicable_media_query_results_into(device, sheet, guard, &mut key) + CascadeData::collect_applicable_media_query_results_into( + device, + sheet, + guard, + &mut key.media_query_results, + &mut key.contents, + ) } - for entry in &self.entries { - if std::ptr::eq(&**entry, old_entry) { + let new_entry; + match self.entries.entry(key) { + HashMapEntry::Vacant(e) => { + debug!("> Picking the slow path (not in the cache)"); + new_entry = Entry::rebuild( + device, + quirks_mode, + collection, + guard, + old_entry, + )?; + e.insert(new_entry.clone()); + } + HashMapEntry::Occupied(mut e) => { // Avoid reusing our old entry (this can happen if we get // invalidated due to CSSOM mutations and our old stylesheet - // contents were already unique, for example). This old entry - // will be pruned from the cache with take_unused() afterwards. - continue; - } - if entry.cascade_data().effective_media_query_results != key { - continue; - } - if log_enabled!(log::Level::Debug) { - debug!("cache hit for:"); - for sheet in collection.sheets() { - debug!(" > {:?}", sheet); + // contents were already unique, for example). + if !std::ptr::eq(&**e.get(), old_entry) { + if log_enabled!(log::Level::Debug) { + debug!("cache hit for:"); + for sheet in collection.sheets() { + debug!(" > {:?}", sheet); + } + } + // The line below ensures the "committed" bit is updated + // properly. + collection.each(|_, _| true); + return Ok(Some(e.get().clone())); } + + debug!("> Picking the slow path due to same entry as old"); + new_entry = Entry::rebuild( + device, + quirks_mode, + collection, + guard, + old_entry, + )?; + e.insert(new_entry.clone()); } - // The line below ensures the "committed" bit is updated properly - // below. - collection.each(|_, _| true); - return Ok(Some(entry.clone())); } - debug!("> Picking the slow path"); - - let new_entry = Entry::rebuild( - device, - quirks_mode, - collection, - guard, - old_entry, - )?; - - self.entries.push(new_entry.clone()); Ok(Some(new_entry)) } @@ -167,25 +214,27 @@ where /// cache to not deadlock. fn take_unused(&mut self) -> SmallVec<[Arc; 3]> { let mut unused = SmallVec::new(); - for i in (0..self.entries.len()).rev() { + self.entries.retain(|_key, value| { // is_unique() returns false for static references, but we never // have static references to UserAgentCascadeDatas. If we did, it // may not make sense to put them in the cache in the first place. - if self.entries[i].is_unique() { - unused.push(self.entries.remove(i)); + if !value.is_unique() { + return true; } - } + unused.push(value.clone()); + false + }); unused } - fn take_all(&mut self) -> Vec> { - mem::replace(&mut self.entries, Vec::new()) + fn take_all(&mut self) -> FxHashMap> { + mem::take(&mut self.entries) } #[cfg(feature = "gecko")] fn add_size_of(&self, ops: &mut MallocSizeOfOps, sizes: &mut ServoStyleSetSizes) { sizes.mOther += self.entries.shallow_size_of(ops); - for arc in self.entries.iter() { + for (_key, arc) in self.entries.iter() { // These are primary Arc references that can be measured // unconditionally. sizes.mOther += arc.unconditional_shallow_size_of(ops); @@ -2033,7 +2082,8 @@ impl CascadeData { device: &Device, stylesheet: &S, guard: &SharedRwLockReadGuard, - results: &mut EffectiveMediaQueryResults, + results: &mut Vec, + contents_list: &mut StyleSheetContentList, ) where S: StylesheetInDocument + 'static, { @@ -2042,19 +2092,25 @@ impl CascadeData { } debug!(" + {:?}", stylesheet); - results.saw_effective(stylesheet.contents()); + let contents = stylesheet.contents(); + results.push(contents.to_media_list_key()); + + // Safety: StyleSheetContents are reference-counted with Arc. + contents_list.push(StylesheetContentsPtr(unsafe { + Arc::from_raw_addrefed(contents) + })); for rule in stylesheet.effective_rules(device, guard) { match *rule { CssRule::Import(ref lock) => { let import_rule = lock.read_with(guard); debug!(" + {:?}", import_rule.stylesheet.media(guard)); - results.saw_effective(import_rule); + results.push(import_rule.to_media_list_key()); }, CssRule::Media(ref lock) => { let media_rule = lock.read_with(guard); debug!(" + {:?}", media_rule.media_queries.read_with(guard)); - results.saw_effective(media_rule); + results.push(media_rule.to_media_list_key()); }, _ => {}, } From 4df282dab7b0a5b973c9663215922cb4ee92d714 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Fri, 12 May 2023 21:12:16 +0200 Subject: [PATCH 09/80] Further changes required by Servo --- components/script/dom/htmlmetaelement.rs | 16 ++++++---------- components/script/stylesheet_loader.rs | 20 +++++++------------- 2 files changed, 13 insertions(+), 23 deletions(-) diff --git a/components/script/dom/htmlmetaelement.rs b/components/script/dom/htmlmetaelement.rs index f91e4339f1d..168c29cdb0b 100644 --- a/components/script/dom/htmlmetaelement.rs +++ b/components/script/dom/htmlmetaelement.rs @@ -21,7 +21,6 @@ use crate::dom::node::{ use crate::dom::virtualmethods::VirtualMethods; use dom_struct::dom_struct; use html5ever::{LocalName, Prefix}; -use parking_lot::RwLock; use servo_arc::Arc; use servo_config::pref; use std::sync::atomic::AtomicBool; @@ -112,15 +111,12 @@ impl HTMLMetaElement { let shared_lock = document.style_shared_lock(); let rule = CssRule::Viewport(Arc::new(shared_lock.wrap(translated_rule))); let sheet = Arc::new(Stylesheet { - contents: StylesheetContents { - rules: CssRules::new(vec![rule], shared_lock), - origin: Origin::Author, - namespaces: Default::default(), - quirks_mode: document.quirks_mode(), - url_data: RwLock::new(window_from_node(self).get_url()), - source_map_url: RwLock::new(None), - source_url: RwLock::new(None), - }, + contents: StylesheetContents::from_shared_data( + CssRules::new(vec![rule], shared_lock), + Origin::Author, + window_from_node(self).get_url(), + document.quirks_mode(), + ), media: Arc::new(shared_lock.wrap(MediaList::empty())), shared_lock: shared_lock.clone(), disabled: AtomicBool::new(false), diff --git a/components/script/stylesheet_loader.rs b/components/script/stylesheet_loader.rs index 20fa6872e49..48e3016458e 100644 --- a/components/script/stylesheet_loader.rs +++ b/components/script/stylesheet_loader.rs @@ -29,7 +29,6 @@ use net_traits::{ FetchMetadata, FetchResponseListener, FilteredMetadata, Metadata, NetworkError, ReferrerPolicy, }; use net_traits::{ResourceFetchTiming, ResourceTimingType}; -use parking_lot::RwLock; use servo_arc::Arc; use servo_url::ImmutableOrigin; use servo_url::ServoUrl; @@ -41,9 +40,7 @@ use style::parser::ParserContext; use style::shared_lock::{Locked, SharedRwLock}; use style::stylesheets::import_rule::ImportSheet; use style::stylesheets::StylesheetLoader as StyleStylesheetLoader; -use style::stylesheets::{ - CssRules, ImportRule, Namespaces, Origin, Stylesheet, StylesheetContents, -}; +use style::stylesheets::{CssRules, ImportRule, Origin, Stylesheet, StylesheetContents}; use style::values::CssUrl; pub trait StylesheetOwner { @@ -363,15 +360,12 @@ impl<'a> StyleStylesheetLoader for StylesheetLoader<'a> { media: Arc>, ) -> Arc> { let sheet = Arc::new(Stylesheet { - contents: StylesheetContents { - rules: CssRules::new(Vec::new(), lock), - origin: context.stylesheet_origin, - url_data: RwLock::new(context.url_data.clone()), - quirks_mode: context.quirks_mode, - namespaces: RwLock::new(Namespaces::default()), - source_map_url: RwLock::new(None), - source_url: RwLock::new(None), - }, + contents: StylesheetContents::from_shared_data( + CssRules::new(Vec::new(), lock), + context.stylesheet_origin, + context.url_data.clone(), + context.quirks_mode, + ), media: media, shared_lock: lock.clone(), disabled: AtomicBool::new(false), From 204cb7a9c0355cef2d28003d7474578ad5814205 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 21:59:12 +0200 Subject: [PATCH 10/80] style: Look at the right element for exportparts in each_applicable_non_document_style_rule_data Otherwise we might not find those rules for invalidation. Differential Revision: https://phabricator.services.mozilla.com/D115130 --- components/style/dom.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/style/dom.rs b/components/style/dom.rs index 3d088956289..c70a8fd26be 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -881,7 +881,7 @@ pub trait TElement: } } // TODO: Could be more granular. - if !shadow.host().exports_any_part() { + if !inner_shadow_host.exports_any_part() { break; } inner_shadow = shadow; From 908c952ab01e9cd7e99d26732cb7b37314aff241 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 22:00:09 +0200 Subject: [PATCH 11/80] style: Don't simplify percentages that resolve to lengths in min/max/clamp Those can't be ordered at specified / computed value time, since the percentage basis could be negative. Needs tests of course, running through try atm. Differential Revision: https://phabricator.services.mozilla.com/D115591 --- .../style/values/computed/length_percentage.rs | 17 +++-------------- components/style/values/specified/calc.rs | 6 +++++- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/components/style/values/computed/length_percentage.rs b/components/style/values/computed/length_percentage.rs index 098b1abfafc..cea2466ce6f 100644 --- a/components/style/values/computed/length_percentage.rs +++ b/components/style/values/computed/length_percentage.rs @@ -607,22 +607,11 @@ impl CalcLengthPercentageLeaf { impl PartialOrd for CalcLengthPercentageLeaf { fn partial_cmp(&self, other: &Self) -> Option { use self::CalcLengthPercentageLeaf::*; - - if std::mem::discriminant(self) != std::mem::discriminant(other) { - return None; - } - + // NOTE: Percentages can't be compared reasonably here because the + // percentage basis might be negative, see bug 1709018. match (self, other) { (&Length(ref one), &Length(ref other)) => one.partial_cmp(other), - (&Percentage(ref one), &Percentage(ref other)) => one.partial_cmp(other), - _ => { - match *self { - Length(..) | Percentage(..) => {}, - } - unsafe { - debug_unreachable!("Forgot a branch?"); - } - }, + _ => None, } } } diff --git a/components/style/values/specified/calc.rs b/components/style/values/specified/calc.rs index d5733a6ce4a..a22d6fd5f18 100644 --- a/components/style/values/specified/calc.rs +++ b/components/style/values/specified/calc.rs @@ -107,8 +107,12 @@ impl PartialOrd for Leaf { } match (self, other) { + // NOTE: Percentages can't be compared reasonably here because the + // percentage basis might be negative, see bug 1709018. + // Conveniently, we only use this for (for raw + // percentages, we go through resolve()). + (&Percentage(..), &Percentage(..)) => None, (&Length(ref one), &Length(ref other)) => one.partial_cmp(other), - (&Percentage(ref one), &Percentage(ref other)) => one.partial_cmp(other), (&Angle(ref one), &Angle(ref other)) => one.degrees().partial_cmp(&other.degrees()), (&Time(ref one), &Time(ref other)) => one.seconds().partial_cmp(&other.seconds()), (&Number(ref one), &Number(ref other)) => one.partial_cmp(other), From 44b94f66f92e08b797ec4ecf07180f9f4f9f7042 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 22:01:03 +0200 Subject: [PATCH 12/80] style: Use a nicer media query for proton context menus Differential Revision: https://phabricator.services.mozilla.com/D116736 --- components/style/gecko/media_features.rs | 25 ++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs index 4c23620dd15..0c748e09fc2 100644 --- a/components/style/gecko/media_features.rs +++ b/components/style/gecko/media_features.rs @@ -590,6 +590,23 @@ fn eval_moz_os_version( query_value.as_ptr() == os_version } +fn eval_moz_windows_non_native_menus( + device: &Device, + query_value: Option, + _: Option, +) -> bool { + let use_non_native_menus = match static_prefs::pref!("browser.display.windows.non_native_menus") { + 0 => false, + 1 => true, + _ => { + eval_moz_os_version(device, Some(atom!("windows-win10")), None) && + get_lnf_int_as_bool(bindings::LookAndFeel_IntID::WindowsDefaultTheme as i32) + }, + }; + + query_value.map_or(use_non_native_menus, |v| v == use_non_native_menus) +} + fn get_lnf_int(int_id: i32) -> i32 { unsafe { bindings::Gecko_GetLookAndFeelInt(int_id) } } @@ -879,6 +896,12 @@ pub static MEDIA_FEATURES: [MediaFeatureDescription; 62] = [ keyword_evaluator!(eval_toolbar_prefers_color_scheme, ToolbarPrefersColorScheme), ParsingRequirements::CHROME_AND_UA_ONLY, ), + feature!( + atom!("-moz-windows-non-native-menus"), + AllowsRanges::No, + Evaluator::BoolInteger(eval_moz_windows_non_native_menus), + ParsingRequirements::CHROME_AND_UA_ONLY, + ), lnf_int_feature!(atom!("-moz-scrollbar-start-backward"), ScrollArrowStyle, get_scrollbar_start_backward), lnf_int_feature!(atom!("-moz-scrollbar-start-forward"), ScrollArrowStyle, get_scrollbar_start_forward), @@ -903,10 +926,8 @@ pub static MEDIA_FEATURES: [MediaFeatureDescription; 62] = [ lnf_int_feature!(atom!("-moz-gtk-csd-close-button"), GTKCSDCloseButton), lnf_int_feature!(atom!("-moz-gtk-csd-reversed-placement"), GTKCSDReversedPlacement), lnf_int_feature!(atom!("-moz-system-dark-theme"), SystemUsesDarkTheme), - bool_pref_feature!(atom!("-moz-proton"), "browser.proton.enabled"), bool_pref_feature!(atom!("-moz-proton-modals"), "browser.proton.modals.enabled"), - bool_pref_feature!(atom!("-moz-proton-contextmenus"), "browser.proton.contextmenus.enabled"), bool_pref_feature!(atom!("-moz-proton-doorhangers"), "browser.proton.doorhangers.enabled"), bool_pref_feature!(atom!("-moz-proton-places-tooltip"), "browser.proton.places-tooltip.enabled"), ]; From 832807f15f14e750172875b24bbc2a47896cc17d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 22:01:52 +0200 Subject: [PATCH 13/80] style: Reserve -- as a custom property name I think this should be fairly low risk, let's try to get it done sooner rather than later. Differential Revision: https://phabricator.services.mozilla.com/D116456 --- components/style/custom_properties.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index b5461e1cbae..c031a0e3d87 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -88,7 +88,7 @@ pub type Name = Atom; /// /// pub fn parse_name(s: &str) -> Result<&str, ()> { - if s.starts_with("--") { + if s.starts_with("--") && s.len() > 2 { Ok(&s[2..]) } else { Err(()) From b4546993b4f3f674f9776d5eb4f1e3698c9ac637 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 22:07:08 +0200 Subject: [PATCH 14/80] style: Fix whitespace handling inside CSS variables As per w3c/csswg-drafts#881 and w3c/csswg-drafts#774. Differential Revision: https://phabricator.services.mozilla.com/D116459 --- components/style/custom_properties.rs | 16 ++----- .../style/properties/declaration_block.rs | 48 ++++--------------- .../style/properties/properties.mako.rs | 17 +++---- 3 files changed, 20 insertions(+), 61 deletions(-) diff --git a/components/style/custom_properties.rs b/components/style/custom_properties.rs index c031a0e3d87..df3f9660dd4 100644 --- a/components/style/custom_properties.rs +++ b/components/style/custom_properties.rs @@ -318,11 +318,6 @@ fn parse_declaration_value<'i, 't>( missing_closing_characters: &mut String, ) -> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> { input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| { - // Need at least one token - let start = input.state(); - input.next_including_whitespace()?; - input.reset(&start); - parse_declaration_value_block(input, references, missing_closing_characters) }) } @@ -334,6 +329,7 @@ fn parse_declaration_value_block<'i, 't>( mut references: Option<&mut VarOrEnvReferences>, missing_closing_characters: &mut String, ) -> Result<(TokenSerializationType, TokenSerializationType), ParseError<'i>> { + input.skip_whitespace(); let mut token_start = input.position(); let mut token = match input.next_including_whitespace_and_comments() { Ok(token) => token, @@ -477,10 +473,8 @@ fn parse_fallback<'i, 't>(input: &mut Parser<'i, 't>) -> Result<(), ParseError<' // Exclude `!` and `;` at the top level // https://drafts.csswg.org/css-syntax/#typedef-declaration-value input.parse_until_before(Delimiter::Bang | Delimiter::Semicolon, |input| { - // At least one non-comment token. - input.next_including_whitespace()?; // Skip until the end. - while let Ok(_) = input.next_including_whitespace_and_comments() {} + while input.next_including_whitespace_and_comments().is_ok() {} Ok(()) }) } @@ -996,12 +990,12 @@ fn substitute_block<'i>( while input.next().is_ok() {} } else { input.expect_comma()?; + input.skip_whitespace(); let after_comma = input.state(); let first_token_type = input .next_including_whitespace_and_comments() - // parse_var_function() ensures that .unwrap() will not fail. - .unwrap() - .serialization_type(); + .ok() + .map_or_else(TokenSerializationType::nothing, |t| t.serialization_type()); input.reset(&after_comma); let mut position = (after_comma.position(), first_token_type); last_token_type = substitute_block( diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 3639ae24f6e..6b05d7ab885 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -1076,15 +1076,9 @@ impl PropertyDeclarationBlock { // AppendableValue::Css. let mut v = CssString::new(); let value = match appendable_value { - AppendableValue::Css { - css, - with_variables, - } => { + AppendableValue::Css(css) => { debug_assert!(!css.is_empty()); - AppendableValue::Css { - css, - with_variables, - } + appendable_value }, other => { append_declaration_value(&mut v, other)?; @@ -1096,14 +1090,13 @@ impl PropertyDeclarationBlock { continue; } - AppendableValue::Css { + AppendableValue::Css({ // Safety: serialization only generates valid utf-8. #[cfg(feature = "gecko")] - css: unsafe { v.as_str_unchecked() }, + unsafe { v.as_str_unchecked() } #[cfg(feature = "servo")] - css: &v, - with_variables: false, - } + &v + }) }, }; @@ -1185,12 +1178,7 @@ where DeclarationsForShorthand(ShorthandId, I), /// A raw CSS string, coming for example from a property with CSS variables, /// or when storing a serialized shorthand value before appending directly. - Css { - /// The raw CSS string. - css: &'a str, - /// Whether the original serialization contained variables or not. - with_variables: bool, - }, + Css(&'a str), } /// Potentially appends whitespace after the first (property: value;) pair. @@ -1215,7 +1203,7 @@ where I: Iterator, { match appendable_value { - AppendableValue::Css { css, .. } => dest.write_str(css), + AppendableValue::Css(css) => dest.write_str(css), AppendableValue::Declaration(decl) => decl.to_css(dest), AppendableValue::DeclarationsForShorthand(shorthand, decls) => { shorthand.longhands_to_css(decls, &mut CssWriter::new(dest)) @@ -1238,25 +1226,7 @@ where handle_first_serialization(dest, is_first_serialization)?; property_name.to_css(&mut CssWriter::new(dest))?; - dest.write_char(':')?; - - // for normal parsed values, add a space between key: and value - match appendable_value { - AppendableValue::Declaration(decl) => { - if !decl.value_is_unparsed() { - // For normal parsed values, add a space between key: and value. - dest.write_str(" ")? - } - }, - AppendableValue::Css { with_variables, .. } => { - if !with_variables { - dest.write_str(" ")? - } - }, - // Currently append_serialization is only called with a Css or - // a Declaration AppendableValue. - AppendableValue::DeclarationsForShorthand(..) => unreachable!(), - } + dest.write_str(": ")?; append_declaration_value(dest, appendable_value)?; diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index b8a9255db48..dc48eed7608 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1521,7 +1521,7 @@ impl ShorthandId { // https://drafts.csswg.org/css-variables/#variables-in-shorthands if let Some(css) = first_declaration.with_variables_from_shorthand(self) { if declarations2.all(|d| d.with_variables_from_shorthand(self) == Some(css)) { - return Some(AppendableValue::Css { css, with_variables: true }); + return Some(AppendableValue::Css(css)); } return None; } @@ -1529,10 +1529,7 @@ impl ShorthandId { // Check whether they are all the same CSS-wide keyword. if let Some(keyword) = first_declaration.get_css_wide_keyword() { if declarations2.all(|d| d.get_css_wide_keyword() == Some(keyword)) { - return Some(AppendableValue::Css { - css: keyword.to_str(), - with_variables: false, - }); + return Some(AppendableValue::Css(keyword.to_str())) } return None; } @@ -1725,7 +1722,8 @@ impl UnparsedValue { let mut input = ParserInput::new(&css); let mut input = Parser::new(&mut input); - input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. + input.skip_whitespace(); + if let Ok(keyword) = input.try_parse(CSSWideKeyword::parse) { return Cow::Owned(PropertyDeclaration::css_wide_keyword(longhand_id, keyword)); } @@ -2441,12 +2439,11 @@ impl PropertyDeclaration { debug_assert!(id.allowed_in(context), "{:?}", id); let non_custom_id = id.non_custom_id(); + input.skip_whitespace(); + let start = input.state(); match id { PropertyId::Custom(property_name) => { - // FIXME: fully implement https://github.com/w3c/csswg-drafts/issues/774 - // before adding skip_whitespace here. - // This probably affects some test results. let value = match input.try_parse(CSSWideKeyword::parse) { Ok(keyword) => CustomDeclarationValue::CSSWideKeyword(keyword), Err(()) => CustomDeclarationValue::Value( @@ -2461,7 +2458,6 @@ impl PropertyDeclaration { } PropertyId::LonghandAlias(id, _) | PropertyId::Longhand(id) => { - input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. input.try_parse(CSSWideKeyword::parse).map(|keyword| { PropertyDeclaration::css_wide_keyword(id, keyword) }).or_else(|()| { @@ -2491,7 +2487,6 @@ impl PropertyDeclaration { } PropertyId::ShorthandAlias(id, _) | PropertyId::Shorthand(id) => { - input.skip_whitespace(); // Unnecessary for correctness, but may help try() rewind less. if let Ok(keyword) = input.try_parse(CSSWideKeyword::parse) { if id == ShorthandId::All { declarations.all_shorthand = AllShorthand::CSSWideKeyword(keyword) From 4934b747ef8bae81ee27d7ef43c7c47c895bceb0 Mon Sep 17 00:00:00 2001 From: Xidorn Quan Date: Sun, 21 May 2023 22:25:13 +0200 Subject: [PATCH 15/80] style: Make predefined symbolic counter styles not overridable Differential Revision: https://phabricator.services.mozilla.com/D116938 --- components/style/counter_style/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/components/style/counter_style/mod.rs b/components/style/counter_style/mod.rs index 1688189d3e0..e470e53ae1f 100644 --- a/components/style/counter_style/mod.rs +++ b/components/style/counter_style/mod.rs @@ -55,7 +55,12 @@ pub fn parse_counter_style_name<'i, 't>( } fn is_valid_name_definition(ident: &CustomIdent) -> bool { - ident.0 != atom!("decimal") && ident.0 != atom!("disc") + ident.0 != atom!("decimal") + && ident.0 != atom!("disc") + && ident.0 != atom!("circle") + && ident.0 != atom!("square") + && ident.0 != atom!("disclosure-closed") + && ident.0 != atom!("disclosure-open") } /// Parse the prelude of an @counter-style rule From 77cab0edc3b98f801558f8020bcfc7b90f860971 Mon Sep 17 00:00:00 2001 From: Michelle Goossens Date: Sun, 21 May 2023 22:26:03 +0200 Subject: [PATCH 16/80] style: Remove browser.proton.doorhangers.enabled pref Differential Revision: https://phabricator.services.mozilla.com/D117091 --- components/style/gecko/media_features.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs index 0c748e09fc2..683b51294c0 100644 --- a/components/style/gecko/media_features.rs +++ b/components/style/gecko/media_features.rs @@ -680,7 +680,7 @@ macro_rules! bool_pref_feature { /// to support new types in these entries and (2) ensuring that either /// nsPresContext::MediaFeatureValuesChanged is called when the value that /// would be returned by the evaluator function could change. -pub static MEDIA_FEATURES: [MediaFeatureDescription; 62] = [ +pub static MEDIA_FEATURES: [MediaFeatureDescription; 61] = [ feature!( atom!("width"), AllowsRanges::Yes, @@ -928,6 +928,5 @@ pub static MEDIA_FEATURES: [MediaFeatureDescription; 62] = [ lnf_int_feature!(atom!("-moz-system-dark-theme"), SystemUsesDarkTheme), bool_pref_feature!(atom!("-moz-proton"), "browser.proton.enabled"), bool_pref_feature!(atom!("-moz-proton-modals"), "browser.proton.modals.enabled"), - bool_pref_feature!(atom!("-moz-proton-doorhangers"), "browser.proton.doorhangers.enabled"), bool_pref_feature!(atom!("-moz-proton-places-tooltip"), "browser.proton.places-tooltip.enabled"), ]; From d103785c4b08db5a67f6827c783cd35b37ac100c Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Sun, 21 May 2023 22:29:27 +0200 Subject: [PATCH 17/80] style: Part 2: Support fit-content() in style Support fit-content for preferred size, min size, and max size. This patch only implement the style system. For layout part, we will do that in the following patches. Differential Revision: https://phabricator.services.mozilla.com/D107161 --- components/style/values/computed/length.rs | 3 ++- components/style/values/generics/length.rs | 6 +++++ components/style/values/specified/length.rs | 26 +++++++++++++++++++++ 3 files changed, 34 insertions(+), 1 deletion(-) diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index bcba3eb9bce..3f8c04abaab 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -188,7 +188,8 @@ impl Size { GenericSize::MinContent | GenericSize::MaxContent | GenericSize::MozFitContent | - GenericSize::MozAvailable => false + GenericSize::MozAvailable | + GenericSize::FitContentFunction(_) => false } } } diff --git a/components/style/values/generics/length.rs b/components/style/values/generics/length.rs index f3e025f80b7..97e9712eabc 100644 --- a/components/style/values/generics/length.rs +++ b/components/style/values/generics/length.rs @@ -161,6 +161,9 @@ pub enum GenericSize { #[cfg(feature = "gecko")] #[animation(error)] MozAvailable, + #[animation(error)] + #[css(function = "fit-content")] + FitContentFunction(LengthPercent) } pub use self::GenericSize as Size; @@ -215,6 +218,9 @@ pub enum GenericMaxSize { #[cfg(feature = "gecko")] #[animation(error)] MozAvailable, + #[animation(error)] + #[css(function = "fit-content")] + FitContentFunction(LengthPercent), } pub use self::GenericMaxSize as MaxSize; diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index aaad895dbce..03189e28caf 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -1247,6 +1247,30 @@ macro_rules! parse_size_non_length { }}; } +#[cfg(feature = "gecko")] +fn is_fit_content_function_enabled() -> bool { + static_prefs::pref!("layout.css.fit-content-function.enabled") +} +#[cfg(feature = "servo")] +fn is_fit_content_function_enabled() -> bool { + false +} + +macro_rules! parse_fit_content_function { + ($size:ident, $input:expr, $context:expr, $allow_quirks:expr) => { + if is_fit_content_function_enabled() { + if let Ok(length) = $input.try_parse(|input| { + input.expect_function_matching("fit-content")?; + input.parse_nested_block(|i| { + NonNegativeLengthPercentage::parse_quirky($context, i, $allow_quirks) + }) + }) { + return Ok($size::FitContentFunction(length)); + } + } + }; +} + impl Size { /// Parses, with quirks. pub fn parse_quirky<'i, 't>( @@ -1255,6 +1279,7 @@ impl Size { allow_quirks: AllowQuirks, ) -> Result> { parse_size_non_length!(Size, input, "auto" => Auto); + parse_fit_content_function!(Size, input, context, allow_quirks); let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?; Ok(GenericSize::LengthPercentage(length)) @@ -1287,6 +1312,7 @@ impl MaxSize { allow_quirks: AllowQuirks, ) -> Result> { parse_size_non_length!(MaxSize, input, "none" => None); + parse_fit_content_function!(MaxSize, input, context, allow_quirks); let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?; Ok(GenericMaxSize::LengthPercentage(length)) From 9273921fd3e6905f71120ed9d1bb6e3073ac401c Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Sun, 21 May 2023 22:42:17 +0200 Subject: [PATCH 18/80] Further changes required by Servo --- components/style/values/generics/length.rs | 2 ++ components/style/values/specified/length.rs | 7 +++---- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/components/style/values/generics/length.rs b/components/style/values/generics/length.rs index 97e9712eabc..3885220efa5 100644 --- a/components/style/values/generics/length.rs +++ b/components/style/values/generics/length.rs @@ -161,6 +161,7 @@ pub enum GenericSize { #[cfg(feature = "gecko")] #[animation(error)] MozAvailable, + #[cfg(feature = "gecko")] #[animation(error)] #[css(function = "fit-content")] FitContentFunction(LengthPercent) @@ -218,6 +219,7 @@ pub enum GenericMaxSize { #[cfg(feature = "gecko")] #[animation(error)] MozAvailable, + #[cfg(feature = "gecko")] #[animation(error)] #[css(function = "fit-content")] FitContentFunction(LengthPercent), diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 03189e28caf..e73a9ddfde0 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -1251,11 +1251,8 @@ macro_rules! parse_size_non_length { fn is_fit_content_function_enabled() -> bool { static_prefs::pref!("layout.css.fit-content-function.enabled") } -#[cfg(feature = "servo")] -fn is_fit_content_function_enabled() -> bool { - false -} +#[cfg(feature = "gecko")] macro_rules! parse_fit_content_function { ($size:ident, $input:expr, $context:expr, $allow_quirks:expr) => { if is_fit_content_function_enabled() { @@ -1279,6 +1276,7 @@ impl Size { allow_quirks: AllowQuirks, ) -> Result> { parse_size_non_length!(Size, input, "auto" => Auto); + #[cfg(feature = "gecko")] parse_fit_content_function!(Size, input, context, allow_quirks); let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?; @@ -1312,6 +1310,7 @@ impl MaxSize { allow_quirks: AllowQuirks, ) -> Result> { parse_size_non_length!(MaxSize, input, "none" => None); + #[cfg(feature = "gecko")] parse_fit_content_function!(MaxSize, input, context, allow_quirks); let length = NonNegativeLengthPercentage::parse_quirky(context, input, allow_quirks)?; From 8ca41ccf9e4231db71357142648c2b441d2b791f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Sun, 21 May 2023 22:46:40 +0200 Subject: [PATCH 19/80] style: Replace the old profiler thread registration FFIs with the new API in servo Differential Revision: https://phabricator.services.mozilla.com/D116517 --- components/style/Cargo.toml | 1 + components/style/global_style_data.rs | 9 +++------ 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 70219416452..782e677ea58 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -79,6 +79,7 @@ uluru = "2" unicode-bidi = "0.3" unicode-segmentation = "1.0" void = "1.0.2" +gecko-profiler = { path = "../../../tools/profiler/rust-api" } [build-dependencies] bindgen = { version = "0.62", optional = true, default-features = false } diff --git a/components/style/global_style_data.rs b/components/style/global_style_data.rs index 4e3d11b94b7..e08baa83b1d 100644 --- a/components/style/global_style_data.rs +++ b/components/style/global_style_data.rs @@ -10,6 +10,7 @@ use crate::gecko_bindings::bindings; use crate::parallel::STYLE_THREAD_STACK_SIZE_KB; use crate::shared_lock::SharedRwLock; use crate::thread_state; +use gecko_profiler; use parking_lot::{RwLock, RwLockReadGuard}; use rayon; use std::env; @@ -49,20 +50,16 @@ fn thread_startup(_index: usize) { thread_state::initialize_layout_worker_thread(); #[cfg(feature = "gecko")] unsafe { - use std::ffi::CString; - bindings::Gecko_SetJemallocThreadLocalArena(true); let name = thread_name(_index); - let name = CString::new(name).unwrap(); - // Gecko_RegisterProfilerThread copies the passed name here. - bindings::Gecko_RegisterProfilerThread(name.as_ptr()); + gecko_profiler::register_thread(&name); } } fn thread_shutdown(_: usize) { #[cfg(feature = "gecko")] unsafe { - bindings::Gecko_UnregisterProfilerThread(); + gecko_profiler::unregister_thread(); bindings::Gecko_SetJemallocThreadLocalArena(false); } ALIVE_WORKER_THREADS.fetch_sub(1, Ordering::Relaxed); From 4c7ddd63b3ca6193817267f8c476f06734a40759 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Sun, 21 May 2023 23:29:52 +0200 Subject: [PATCH 20/80] Further changes required by Servo --- components/style/Cargo.toml | 1 - components/style/global_style_data.rs | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 782e677ea58..70219416452 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -79,7 +79,6 @@ uluru = "2" unicode-bidi = "0.3" unicode-segmentation = "1.0" void = "1.0.2" -gecko-profiler = { path = "../../../tools/profiler/rust-api" } [build-dependencies] bindgen = { version = "0.62", optional = true, default-features = false } diff --git a/components/style/global_style_data.rs b/components/style/global_style_data.rs index e08baa83b1d..6a22c5a11e9 100644 --- a/components/style/global_style_data.rs +++ b/components/style/global_style_data.rs @@ -10,6 +10,7 @@ use crate::gecko_bindings::bindings; use crate::parallel::STYLE_THREAD_STACK_SIZE_KB; use crate::shared_lock::SharedRwLock; use crate::thread_state; +#[cfg(feature = "gecko")] use gecko_profiler; use parking_lot::{RwLock, RwLockReadGuard}; use rayon; From fa6ab91acd4a0d2c27b6dc927c16b5f03058bd62 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Sun, 21 May 2023 23:31:35 +0200 Subject: [PATCH 21/80] style: Part 1: Add SVG d property in CSS Add d property for style system. d property only supports path() for now and it has the functional notation without fill rule. https://github.com/w3c/svgwg/issues/320#issuecomment-414462645 Differential Revision: https://phabricator.services.mozilla.com/D81237 --- .../properties/counted_unknown_properties.py | 1 - .../style/properties/longhands/svg.mako.rs | 10 ++++ components/style/values/computed/mod.rs | 2 +- components/style/values/computed/svg.rs | 2 +- components/style/values/specified/mod.rs | 2 +- components/style/values/specified/svg.rs | 55 +++++++++++++++++++ 6 files changed, 68 insertions(+), 4 deletions(-) diff --git a/components/style/properties/counted_unknown_properties.py b/components/style/properties/counted_unknown_properties.py index 577547d099d..56d647cb57d 100644 --- a/components/style/properties/counted_unknown_properties.py +++ b/components/style/properties/counted_unknown_properties.py @@ -63,7 +63,6 @@ COUNTED_UNKNOWN_PROPERTIES = [ "-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", diff --git a/components/style/properties/longhands/svg.mako.rs b/components/style/properties/longhands/svg.mako.rs index f6128693582..3d711462ff3 100644 --- a/components/style/properties/longhands/svg.mako.rs +++ b/components/style/properties/longhands/svg.mako.rs @@ -246,3 +246,13 @@ ${helpers.predefined_type( animation_value_type="LengthPercentage", spec="https://svgwg.org/svg2-draft/geometry.html#R", )} + +${helpers.predefined_type( + "d", + "DProperty", + "specified::DProperty::none()", + engines="gecko", + animation_value_type="ComputedValue", + gecko_pref="layout.css.d-property.enabled", + spec="https://svgwg.org/svg2-draft/paths.html#TheDProperty", +)} diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 826bb2a2448..1098bae1209 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -82,7 +82,7 @@ pub use self::position::{ pub use self::ratio::Ratio; pub use self::rect::NonNegativeLengthOrNumberRect; pub use self::resolution::Resolution; -pub use self::svg::MozContextProperties; +pub use self::svg::{DProperty, MozContextProperties}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint, SVGPaintKind}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::text::TextUnderlinePosition; diff --git a/components/style/values/computed/svg.rs b/components/style/values/computed/svg.rs index a348d071ab9..344f1d83518 100644 --- a/components/style/values/computed/svg.rs +++ b/components/style/values/computed/svg.rs @@ -11,7 +11,7 @@ use crate::values::generics::svg as generic; use crate::values::RGBA; use crate::Zero; -pub use crate::values::specified::{MozContextProperties, SVGPaintOrder}; +pub use crate::values::specified::{DProperty, MozContextProperties, SVGPaintOrder}; /// Computed SVG Paint value pub type SVGPaint = generic::GenericSVGPaint; diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 8a9cb73f4da..11498337a7f 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -80,7 +80,7 @@ pub use self::position::{PositionComponent, ZIndex}; pub use self::ratio::Ratio; pub use self::rect::NonNegativeLengthOrNumberRect; pub use self::resolution::Resolution; -pub use self::svg::MozContextProperties; +pub use self::svg::{DProperty, MozContextProperties}; pub use self::svg::{SVGLength, SVGOpacity, SVGPaint}; pub use self::svg::{SVGPaintOrder, SVGStrokeDashArray, SVGWidth}; pub use self::svg_path::SVGPathData; diff --git a/components/style/values/specified/svg.rs b/components/style/values/specified/svg.rs index abc6587239c..f06fc43c46d 100644 --- a/components/style/values/specified/svg.rs +++ b/components/style/values/specified/svg.rs @@ -10,6 +10,7 @@ use crate::values::specified::color::Color; use crate::values::specified::url::SpecifiedUrl; use crate::values::specified::AllowQuirks; use crate::values::specified::LengthPercentage; +use crate::values::specified::SVGPathData; use crate::values::specified::{NonNegativeLengthPercentage, Opacity}; use crate::values::CustomIdent; use cssparser::{Parser, Token}; @@ -334,3 +335,57 @@ impl Parse for MozContextProperties { }) } } + +/// The svg d property type. +/// +/// https://svgwg.org/svg2-draft/paths.html#TheDProperty +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + Deserialize, + MallocSizeOf, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToAnimatedZero, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(C, u8)] +pub enum DProperty { + /// Path value for path() or just a . + #[css(function)] + Path(SVGPathData), + /// None value. + #[animation(error)] + None, +} + +impl DProperty { + /// return none. + #[inline] + pub fn none() -> Self { + DProperty::None + } +} + +impl Parse for DProperty { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + // Parse none. + if input.try_parse(|i| i.expect_ident_matching("none")).is_ok() { + return Ok(DProperty::none()); + } + + // Parse possible functions. + input.expect_function_matching("path")?; + let path_data = input.parse_nested_block(|i| SVGPathData::parse(context, i))?; + Ok(DProperty::Path(path_data)) + } +} From 11cadd8c4202a0bbacf1ad030cd234713adfdc35 Mon Sep 17 00:00:00 2001 From: Boris Chiou Date: Sun, 21 May 2023 23:35:30 +0200 Subject: [PATCH 22/80] style: Part 7: Notify style system when SMIL animation changes d attribute So we update d property in the style system as well. This makes sure we have the correct computed style and the correct rendering result. Differential Revision: https://phabricator.services.mozilla.com/D115570 --- components/style/values/specified/svg_path.rs | 115 ++++++++++++++++++ 1 file changed, 115 insertions(+) diff --git a/components/style/values/specified/svg_path.rs b/components/style/values/specified/svg_path.rs index 9f1c5c5e32c..5e3edc2d68d 100644 --- a/components/style/values/specified/svg_path.rs +++ b/components/style/values/specified/svg_path.rs @@ -60,6 +60,111 @@ impl SVGPathData { SVGPathData(crate::ArcSlice::from_iter(result.into_iter())) } + + // FIXME: Bug 1714238, we may drop this once we use the same data structure for both SVG and + // CSS. + /// Decode the svg path raw data from Gecko. + #[cfg(feature = "gecko")] + pub fn decode_from_f32_array(path: &[f32]) -> Result { + use crate::gecko_bindings::structs::dom::SVGPathSeg_Binding::*; + + let mut result: Vec = Vec::new(); + let mut i: usize = 0; + while i < path.len() { + // See EncodeType() and DecodeType() in SVGPathSegUtils.h. + // We are using reinterpret_cast<> to encode and decode between u32 and f32, so here we + // use to_bits() to decode the type. + let seg_type = path[i].to_bits() as u16; + i = i + 1; + match seg_type { + PATHSEG_CLOSEPATH => result.push(PathCommand::ClosePath), + PATHSEG_MOVETO_ABS | PATHSEG_MOVETO_REL => { + debug_assert!(i + 1 < path.len()); + result.push(PathCommand::MoveTo { + point: CoordPair::new(path[i], path[i + 1]), + absolute: IsAbsolute::new(seg_type == PATHSEG_MOVETO_ABS), + }); + i = i + 2; + } + PATHSEG_LINETO_ABS | PATHSEG_LINETO_REL => { + debug_assert!(i + 1 < path.len()); + result.push(PathCommand::LineTo { + point: CoordPair::new(path[i], path[i + 1]), + absolute: IsAbsolute::new(seg_type == PATHSEG_LINETO_ABS), + }); + i = i + 2; + } + PATHSEG_CURVETO_CUBIC_ABS | PATHSEG_CURVETO_CUBIC_REL => { + debug_assert!(i + 5 < path.len()); + result.push(PathCommand::CurveTo { + control1: CoordPair::new(path[i], path[i + 1]), + control2: CoordPair::new(path[i + 2], path[i + 3]), + point: CoordPair::new(path[i + 4], path[i + 5]), + absolute: IsAbsolute::new(seg_type == PATHSEG_CURVETO_CUBIC_ABS), + }); + i = i + 6; + } + PATHSEG_CURVETO_QUADRATIC_ABS | PATHSEG_CURVETO_QUADRATIC_REL => { + debug_assert!(i + 3 < path.len()); + result.push(PathCommand::QuadBezierCurveTo { + control1: CoordPair::new(path[i], path[i + 1]), + point: CoordPair::new(path[i + 2], path[i + 3]), + absolute: IsAbsolute::new(seg_type == PATHSEG_CURVETO_QUADRATIC_ABS), + }); + i = i + 4; + } + PATHSEG_ARC_ABS | PATHSEG_ARC_REL => { + debug_assert!(i + 6 < path.len()); + result.push(PathCommand::EllipticalArc { + rx: path[i], + ry: path[i + 1], + angle: path[i + 2], + large_arc_flag: ArcFlag(path[i + 3] != 0.0f32), + sweep_flag: ArcFlag(path[i + 4] != 0.0f32), + point: CoordPair::new(path[i + 5], path[i + 6]), + absolute: IsAbsolute::new(seg_type == PATHSEG_ARC_ABS), + }); + i = i + 7; + } + PATHSEG_LINETO_HORIZONTAL_ABS | PATHSEG_LINETO_HORIZONTAL_REL => { + debug_assert!(i < path.len()); + result.push(PathCommand::HorizontalLineTo { + x: path[i], + absolute: IsAbsolute::new(seg_type == PATHSEG_LINETO_HORIZONTAL_ABS), + }); + i = i + 1; + } + PATHSEG_LINETO_VERTICAL_ABS | PATHSEG_LINETO_VERTICAL_REL => { + debug_assert!(i < path.len()); + result.push(PathCommand::VerticalLineTo { + y: path[i], + absolute: IsAbsolute::new(seg_type == PATHSEG_LINETO_VERTICAL_ABS), + }); + i = i + 1; + } + PATHSEG_CURVETO_CUBIC_SMOOTH_ABS | PATHSEG_CURVETO_CUBIC_SMOOTH_REL => { + debug_assert!(i + 3 < path.len()); + result.push(PathCommand::SmoothCurveTo { + control2: CoordPair::new(path[i], path[i + 1]), + point: CoordPair::new(path[i + 2], path[i + 3]), + absolute: IsAbsolute::new(seg_type == PATHSEG_CURVETO_CUBIC_SMOOTH_ABS), + }); + i = i + 4; + } + PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS | PATHSEG_CURVETO_QUADRATIC_SMOOTH_REL => { + debug_assert!(i + 1 < path.len()); + result.push(PathCommand::SmoothQuadBezierCurveTo { + point: CoordPair::new(path[i], path[i + 1]), + absolute: IsAbsolute::new(seg_type == PATHSEG_CURVETO_QUADRATIC_SMOOTH_ABS), + }); + i = i + 2; + } + PATHSEG_UNKNOWN | _ => return Err(()), + } + } + + Ok(SVGPathData(crate::ArcSlice::from_iter(result.into_iter()))) + } } impl ToCss for SVGPathData { @@ -506,6 +611,16 @@ impl IsAbsolute { pub fn is_yes(&self) -> bool { *self == IsAbsolute::Yes } + + /// Return Yes if value is true. Otherwise, return No. + #[inline] + fn new(value: bool) -> Self { + if value { + IsAbsolute::Yes + } else { + IsAbsolute::No + } + } } /// The path coord type. From 4353d31cb07032d9e71456c3295ccbf9259c2da5 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 00:09:14 +0200 Subject: [PATCH 23/80] Further changes required by Servo --- components/style/values/specified/svg_path.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/components/style/values/specified/svg_path.rs b/components/style/values/specified/svg_path.rs index 5e3edc2d68d..a443a443326 100644 --- a/components/style/values/specified/svg_path.rs +++ b/components/style/values/specified/svg_path.rs @@ -614,6 +614,7 @@ impl IsAbsolute { /// Return Yes if value is true. Otherwise, return No. #[inline] + #[cfg(feature = "gecko")] fn new(value: bool) -> Self { if value { IsAbsolute::Yes From f0a178b56a7bccba103c0b96e95e687eb2188b5d Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Sun, 21 May 2023 23:36:30 +0200 Subject: [PATCH 24/80] style: Un-prefix -moz-tab-size (keeping the prefixed version as an alias for now) This results in lots of new WPT test passes. There were also a couple of WPT tests that turned out to be broken; tab-size-inline-001 and -002 had errors in their reference files such that they'd never pass anywhere. So those are fixed here. Depends on D117331 Differential Revision: https://phabricator.services.mozilla.com/D117332 --- components/style/properties/counted_unknown_properties.py | 1 - components/style/properties/data.py | 2 +- components/style/properties/longhands/inherited_text.mako.rs | 3 ++- components/style/values/generics/length.rs | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/components/style/properties/counted_unknown_properties.py b/components/style/properties/counted_unknown_properties.py index 56d647cb57d..2548e591060 100644 --- a/components/style/properties/counted_unknown_properties.py +++ b/components/style/properties/counted_unknown_properties.py @@ -25,7 +25,6 @@ COUNTED_UNKNOWN_PROPERTIES = [ "-webkit-user-modify", "-webkit-margin-before", "-webkit-margin-after", - "tab-size", "-webkit-margin-start", "-webkit-column-break-inside", "-webkit-padding-start", diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 8a523ccb66f..8f3c7d35269 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -759,7 +759,7 @@ def _add_logical_props(data, props): # These are probably Gecko bugs and should be supported per spec. def _remove_common_first_line_and_first_letter_properties(props, engine): if engine == "gecko": - props.remove("-moz-tab-size") + props.remove("tab-size") props.remove("hyphens") props.remove("line-break") props.remove("text-align-last") diff --git a/components/style/properties/longhands/inherited_text.mako.rs b/components/style/properties/longhands/inherited_text.mako.rs index fc0e5d8fdea..3a66eee9a3f 100644 --- a/components/style/properties/longhands/inherited_text.mako.rs +++ b/components/style/properties/longhands/inherited_text.mako.rs @@ -238,12 +238,13 @@ ${helpers.predefined_type( )} ${helpers.predefined_type( - "-moz-tab-size", + "tab-size", "NonNegativeLengthOrNumber", "generics::length::LengthOrNumber::Number(From::from(8.0))", engines="gecko", animation_value_type="LengthOrNumber", spec="https://drafts.csswg.org/css-text-3/#tab-size-property", + aliases="-moz-tab-size", )} ${helpers.predefined_type( diff --git a/components/style/values/generics/length.rs b/components/style/values/generics/length.rs index 3885220efa5..dfb3504e3cf 100644 --- a/components/style/values/generics/length.rs +++ b/components/style/values/generics/length.rs @@ -235,7 +235,7 @@ impl MaxSize { } } -/// A generic `` | `` value for the `-moz-tab-size` property. +/// A generic `` | `` value for the `tab-size` property. #[derive( Animate, Clone, From 6d9580fef0a6b14b0955af061647f9b9f8da2329 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 21 May 2023 23:37:16 +0200 Subject: [PATCH 25/80] style: Specify has_no_effect_on_gecko_scrollbars on inherited internal properties Otherwise we assert due to the styles being different from the cached ones, but it doesn't matter as these don't influence Gecko scrollbars. Differential Revision: https://phabricator.services.mozilla.com/D117147 --- components/style/properties/data.py | 5 +++-- components/style/properties/longhands/font.mako.rs | 5 +++++ 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/components/style/properties/data.py b/components/style/properties/data.py index 8f3c7d35269..b2ab520ad3d 100644 --- a/components/style/properties/data.py +++ b/components/style/properties/data.py @@ -340,13 +340,14 @@ class Longhand(Property): assert ( has_effect_on_gecko_scrollbars in [None, False, True] and not style_struct.inherited - or (gecko_pref is None) == (has_effect_on_gecko_scrollbars is None) + or (gecko_pref is None and enabled_in != "") + == (has_effect_on_gecko_scrollbars is None) ), ( "Property " + name + ": has_effect_on_gecko_scrollbars must be " + "specified, and must have a value of True or False, iff a " - + "property is inherited and is behind a Gecko pref" + + "property is inherited and is behind a Gecko pref or internal" ) self.need_index = need_index self.gecko_ffi_name = gecko_ffi_name or "m" + self.camel_case diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs index e84a5574d1a..f5304355e03 100644 --- a/components/style/properties/longhands/font.mako.rs +++ b/components/style/properties/longhands/font.mako.rs @@ -213,6 +213,7 @@ ${helpers.predefined_type( initial_value="computed::XLang::get_initial_value()", animation_value_type="none", enabled_in="", + has_effect_on_gecko_scrollbars=False, spec="Internal (not web-exposed)", )} @@ -224,6 +225,7 @@ ${helpers.predefined_type( animation_value_type="none", gecko_ffi_name="mScriptSizeMultiplier", enabled_in="", + has_effect_on_gecko_scrollbars=False, spec="Internal (not web-exposed)", )} @@ -263,6 +265,7 @@ ${helpers.single_keyword( spec="Internal (not web-exposed)", animation_value_type="none", enabled_in="", + has_effect_on_gecko_scrollbars=False, needs_conversion=True, )} @@ -273,6 +276,7 @@ ${helpers.predefined_type( engines="gecko", animation_value_type="none", enabled_in="", + has_effect_on_gecko_scrollbars=False, gecko_ffi_name="mScriptMinSize", spec="Internal (not web-exposed)", )} @@ -284,6 +288,7 @@ ${helpers.predefined_type( engines="gecko", animation_value_type="none", enabled_in="", + has_effect_on_gecko_scrollbars=False, spec="Internal (not web-exposed)", )} From d2a7ebf789359c06ea1891a5773e4354e74757be Mon Sep 17 00:00:00 2001 From: Michelle Goossens Date: Sun, 21 May 2023 23:38:22 +0200 Subject: [PATCH 26/80] style: Remove browser.proton.modals.enabled pref Differential Revision: https://phabricator.services.mozilla.com/D116903 --- components/style/gecko/media_features.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/components/style/gecko/media_features.rs b/components/style/gecko/media_features.rs index 683b51294c0..664a12f4108 100644 --- a/components/style/gecko/media_features.rs +++ b/components/style/gecko/media_features.rs @@ -680,7 +680,7 @@ macro_rules! bool_pref_feature { /// to support new types in these entries and (2) ensuring that either /// nsPresContext::MediaFeatureValuesChanged is called when the value that /// would be returned by the evaluator function could change. -pub static MEDIA_FEATURES: [MediaFeatureDescription; 61] = [ +pub static MEDIA_FEATURES: [MediaFeatureDescription; 60] = [ feature!( atom!("width"), AllowsRanges::Yes, @@ -927,6 +927,5 @@ pub static MEDIA_FEATURES: [MediaFeatureDescription; 61] = [ lnf_int_feature!(atom!("-moz-gtk-csd-reversed-placement"), GTKCSDReversedPlacement), lnf_int_feature!(atom!("-moz-system-dark-theme"), SystemUsesDarkTheme), bool_pref_feature!(atom!("-moz-proton"), "browser.proton.enabled"), - bool_pref_feature!(atom!("-moz-proton-modals"), "browser.proton.modals.enabled"), bool_pref_feature!(atom!("-moz-proton-places-tooltip"), "browser.proton.places-tooltip.enabled"), ]; From d7e00ba03d0ed8d7382ff7b04103bec8c04c2e5a Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Sun, 21 May 2023 23:39:34 +0200 Subject: [PATCH 27/80] style: Add some style quirks for legacy ::markers created from list-style-type/list-style-image Specifically: For "bullets", i.e. 'list-style-type:disc|circle|square| disclosure-closed|disclosure-open', we use a built-in font (-moz-bullet-font, which has glyphs for those symbols + space) to retain mostly backwards compatible rendering for those. Authors may override that with an explicit 'font-family' ::marker style though. We also use this font for 'list-style-image' in case it would fallback to one of the above when the image fails to load (so that we get the same width space). When the -moz-bullet-font is used we also set 'font-synthesis' to avoid synthesizing italic/bold for this font. Authors may override this with an explicit ::marker declaration. We also set 'letter-spacing' and 'word-spacing' to the initial value for bullets for web-compat reasons. Again, authors may override this with an explicit ::marker declaration. (This breaks backwards- compat slightly but makes us compatible with Chrome. We used to ignore these for list-style-type: too.) Differential Revision: https://phabricator.services.mozilla.com/D111693 --- components/style/properties/cascade.rs | 28 +++++++++++ .../style/properties/computed_value_flags.rs | 14 +++++- components/style/style_adjuster.rs | 47 +++++++++++++++++++ components/style/values/computed/text.rs | 8 ++++ components/style/values/generics/mod.rs | 15 ++++++ components/style/values/specified/font.rs | 8 ++++ components/style/values/specified/list.rs | 9 ++++ 7 files changed, 128 insertions(+), 1 deletion(-) diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 9c3e6ebd85e..1368cf9c8e7 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -786,6 +786,34 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_PADDING); } + if self + .author_specified + .contains(LonghandId::FontFamily) + { + builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY); + } + + if self + .author_specified + .contains(LonghandId::LetterSpacing) + { + builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_LETTER_SPACING); + } + + if self + .author_specified + .contains(LonghandId::WordSpacing) + { + builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_WORD_SPACING); + } + + if self + .author_specified + .contains(LonghandId::FontSynthesis) + { + builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS); + } + #[cfg(feature = "servo")] { if let Some(font) = builder.get_font_if_mutated() { diff --git a/components/style/properties/computed_value_flags.rs b/components/style/properties/computed_value_flags.rs index cc7d9c94fb9..b3e5fe4f7f9 100644 --- a/components/style/properties/computed_value_flags.rs +++ b/components/style/properties/computed_value_flags.rs @@ -12,7 +12,7 @@ bitflags! { /// If we ever want to add some flags that shouldn't inherit for them, /// we might want to add a function to handle this. #[repr(C)] - pub struct ComputedValueFlags: u16 { + pub struct ComputedValueFlags: u32 { /// Whether the style or any of the ancestors has a text-decoration-line /// property that should get propagated to descendants. /// @@ -89,6 +89,18 @@ bitflags! { /// FIXME(emilio): Try to merge this with BORDER_BACKGROUND, see /// https://github.com/w3c/csswg-drafts/issues/4777 const HAS_AUTHOR_SPECIFIED_PADDING = 1 << 15; + + /// Whether there are author-specified rules for `font-family`. + const HAS_AUTHOR_SPECIFIED_FONT_FAMILY = 1 << 16; + + /// Whether there are author-specified rules for `font-synthesis`. + const HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS = 1 << 17; + + /// Whether there are author-specified rules for `letter-spacing`. + const HAS_AUTHOR_SPECIFIED_LETTER_SPACING = 1 << 18; + + /// Whether there are author-specified rules for `word-spacing`. + const HAS_AUTHOR_SPECIFIED_WORD_SPACING = 1 << 19; } } diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 158be6d5dfb..bfd43da6088 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -818,6 +818,52 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { } } + /// A legacy ::marker (i.e. no 'content') without an author-specified 'font-family' + /// and 'list-style-type:disc|circle|square|disclosure-closed|disclosure-open' + /// is assigned 'font-family:-moz-bullet-font'. (This is for
  • etc.) + /// We don't want synthesized italic/bold for this font, so turn that off too. + /// Likewise for 'letter/word-spacing' -- unless the author specified it then reset + /// them to their initial value because traditionally we never added such spacing + /// between a legacy bullet and the list item's content, so we keep that behavior + /// for web-compat reasons. + /// We intentionally don't check 'list-style-image' below since we want it to use + /// the same font as its fallback ('list-style-type') in case it fails to load. + #[cfg(feature = "gecko")] + fn adjust_for_marker_pseudo(&mut self) { + use crate::values::computed::font::{FamilyName, FontFamily, FontFamilyList, FontFamilyNameSyntax, FontSynthesis, SingleFontFamily}; + use crate::values::computed::text::{LetterSpacing, WordSpacing}; + + let is_legacy_marker = self.style.pseudo.map_or(false, |p| p.is_marker()) && + self.style.get_counters().ineffective_content_property() && + self.style.get_list().clone_list_style_type().is_bullet(); + if !is_legacy_marker { + return; + } + if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY) { + let moz_bullet_font_family = FontFamily { + families: FontFamilyList::new(Box::new([SingleFontFamily::FamilyName(FamilyName { + name: atom!("-moz-bullet-font"), + syntax: FontFamilyNameSyntax::Identifiers, + })])), + is_system_font: false, + }; + self.style.mutate_font().set_font_family(moz_bullet_font_family); + + // FIXME(mats): We can remove this if support for font-synthesis is added to @font-face rules. + // Then we can add it to the @font-face rule in html.css instead. + // https://github.com/w3c/csswg-drafts/issues/6081 + if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_SYNTHESIS) { + self.style.mutate_font().set_font_synthesis(FontSynthesis::none()); + } + } + if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_LETTER_SPACING) { + self.style.mutate_inherited_text().set_letter_spacing(LetterSpacing::normal()); + } + if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_WORD_SPACING) { + self.style.mutate_inherited_text().set_word_spacing(WordSpacing::normal()); + } + } + /// Adjusts the style to account for various fixups that don't fit naturally /// into the cascade. /// @@ -883,6 +929,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { { self.adjust_for_appearance(element); self.adjust_for_inert(); + self.adjust_for_marker_pseudo(); } self.set_bits(); } diff --git a/components/style/values/computed/text.rs b/components/style/values/computed/text.rs index b42dfb488a3..629626b06b3 100644 --- a/components/style/values/computed/text.rs +++ b/components/style/values/computed/text.rs @@ -110,6 +110,14 @@ impl ToComputedValue for specified::WordSpacing { /// A computed value for the `line-height` property. pub type LineHeight = GenericLineHeight; +impl WordSpacing { + /// Return the `normal` computed value, which is just zero. + #[inline] + pub fn normal() -> Self { + LengthPercentage::zero() + } +} + #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToResolvedValue)] #[repr(C)] /// text-overflow. diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 39c898efed7..c0cdf04b71d 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -95,6 +95,21 @@ impl CounterStyle { pub fn decimal() -> Self { CounterStyle::Name(CustomIdent(atom!("decimal"))) } + + /// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`) + #[inline] + pub fn is_bullet(&self) -> bool { + match self { + CounterStyle::Name(CustomIdent(ref name)) => { + name == &atom!("disc") || + name == &atom!("circle") || + name == &atom!("square") || + name == &atom!("disclosure-closed") || + name == &atom!("disclosure-open") + } + _ => false, + } + } } impl Parse for CounterStyle { diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 329dedd31ca..b007bc3f5a4 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -2005,6 +2005,14 @@ impl FontSynthesis { style: true, } } + #[inline] + /// Get the 'none' value of font-synthesis + pub fn none() -> Self { + FontSynthesis { + weight: false, + style: false, + } + } } impl Parse for FontSynthesis { diff --git a/components/style/values/specified/list.rs b/components/style/values/specified/list.rs index 5d31c0b34d2..14004e65cc8 100644 --- a/components/style/values/specified/list.rs +++ b/components/style/values/specified/list.rs @@ -67,6 +67,15 @@ impl ListStyleType { _ => unreachable!("Unknown counter style keyword value"), }))) } + + /// Is this a bullet? (i.e. `list-style-type: disc|circle|square|disclosure-closed|disclosure-open`) + #[inline] + pub fn is_bullet(&self) -> bool { + match self { + ListStyleType::CounterStyle(ref style) => style.is_bullet(), + _ => false, + } + } } #[cfg(feature = "gecko")] From d1936e6a4acc7184f26215b8560778ab075e53af Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 00:28:26 +0200 Subject: [PATCH 28/80] Further changes required by Servo --- components/style/properties/cascade.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 1368cf9c8e7..91d6c6c99dd 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -807,6 +807,7 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { builder.add_flags(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_WORD_SPACING); } + #[cfg(feature = "gecko")] if self .author_specified .contains(LonghandId::FontSynthesis) From 16168fe4e7438bf594f24f796a2f3cbc21ba5d81 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Sun, 21 May 2023 23:43:02 +0200 Subject: [PATCH 29/80] style: Implement CSS support for the optional adjustment-basis metric keywords for the font-size-adjust property (enabled on Nightly only for now) Differential Revision: https://phabricator.services.mozilla.com/D115596 --- components/style/properties/gecko.mako.rs | 21 +----- .../style/properties/longhands/font.mako.rs | 3 +- components/style/values/computed/font.rs | 57 +--------------- components/style/values/generics/font.rs | 53 +++++++++++++++ components/style/values/specified/font.rs | 65 ++++++++++++------- 5 files changed, 99 insertions(+), 100 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 7a864c06d27..a88aec3b684 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1008,26 +1008,7 @@ fn static_assert() { ${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 { - T::None => self.gecko.mFont.sizeAdjust = -1.0 as f32, - T::Number(n) => self.gecko.mFont.sizeAdjust = n, - } - } - - pub fn copy_font_size_adjust_from(&mut self, other: &Self) { - self.gecko.mFont.sizeAdjust = other.gecko.mFont.sizeAdjust; - } - - pub fn reset_font_size_adjust(&mut self, other: &Self) { - self.copy_font_size_adjust_from(other) - } - - pub fn clone_font_size_adjust(&self) -> longhands::font_size_adjust::computed_value::T { - use crate::properties::longhands::font_size_adjust::computed_value::T; - T::from_gecko_adjust(self.gecko.mFont.sizeAdjust) - } + ${impl_simple("font_size_adjust", "mFont.sizeAdjust")} #[allow(non_snake_case)] pub fn set__x_lang(&mut self, v: longhands::_x_lang::computed_value::T) { diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs index f5304355e03..cf75bb59123 100644 --- a/components/style/properties/longhands/font.mako.rs +++ b/components/style/properties/longhands/font.mako.rs @@ -388,8 +388,7 @@ pub mod system_font { font_weight, font_stretch, font_style, - font_size_adjust: longhands::font_size_adjust::computed_value - ::T::from_gecko_adjust(system.sizeAdjust), + font_size_adjust: system.sizeAdjust, % for kwprop in kw_font_props: ${kwprop}: longhands::${kwprop}::computed_value::T::from_gecko_keyword( system.${to_camel_case_lower(kwprop.replace('font_', ''))} diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 0bd177bcc85..d5906d0e89f 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -8,9 +8,9 @@ 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::animated::ToAnimatedValue; use crate::values::computed::{ - Angle, Context, Integer, Length, NonNegativeLength, NonNegativePercentage, + Angle, Context, Integer, Length, NonNegativeLength, NonNegativeNumber, NonNegativePercentage, }; use crate::values::computed::{Number, Percentage, ToComputedValue}; use crate::values::generics::font::{FeatureTagValue, FontSettings, VariationValue}; @@ -623,24 +623,7 @@ impl<'a> Iterator for FontFamilyNameIter<'a> { } /// Preserve the readability of text when font fallback occurs -#[derive( - Animate, - Clone, - ComputeSquaredDistance, - Copy, - Debug, - MallocSizeOf, - PartialEq, - ToCss, - ToResolvedValue, -)] -pub enum FontSizeAdjust { - #[animation(error)] - /// None variant - None, - /// Number variant - Number(CSSFloat), -} +pub type FontSizeAdjust = generics::GenericFontSizeAdjust; impl FontSizeAdjust { #[inline] @@ -648,40 +631,6 @@ impl FontSizeAdjust { pub fn none() -> Self { FontSizeAdjust::None } - - /// Get font-size-adjust with float number - pub fn from_gecko_adjust(gecko: f32) -> Self { - if gecko == -1.0 { - FontSizeAdjust::None - } else { - FontSizeAdjust::Number(gecko) - } - } -} - -impl ToAnimatedZero for FontSizeAdjust { - #[inline] - // FIXME(emilio): why? - fn to_animated_zero(&self) -> Result { - Err(()) - } -} - -impl ToAnimatedValue for FontSizeAdjust { - type AnimatedValue = Self; - - #[inline] - fn to_animated_value(self) -> Self { - self - } - - #[inline] - fn from_animated_value(animated: Self::AnimatedValue) -> Self { - match animated { - FontSizeAdjust::Number(number) => FontSizeAdjust::Number(number.max(0.)), - _ => animated, - } - } } /// Use VariantAlternatesList as computed type of FontVariantAlternates diff --git a/components/style/values/generics/font.rs b/components/style/values/generics/font.rs index 226613d4545..02f91068d38 100644 --- a/components/style/values/generics/font.rs +++ b/components/style/values/generics/font.rs @@ -202,3 +202,56 @@ pub enum FontStyle { #[value_info(starts_with_keyword)] Oblique(Angle), } + +/// A generic value for the `font-size-adjust` property. +/// +/// https://www.w3.org/TR/css-fonts-4/#font-size-adjust-prop +/// https://github.com/w3c/csswg-drafts/issues/6160 +#[allow(missing_docs)] +#[repr(u8)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +pub enum GenericFontSizeAdjust { + #[animation(error)] + None, + // 'ex' is the implied basis, so the keyword can be omitted + Ex(Number), + #[value_info(starts_with_keyword)] + Cap(Number), + #[value_info(starts_with_keyword)] + Ch(Number), + #[value_info(starts_with_keyword)] + Ic(Number), +} + +impl ToCss for GenericFontSizeAdjust { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + let (prefix, value) = match self { + Self::None => return dest.write_str("none"), + Self::Ex(v) => ("", v), + Self::Cap(v) => ("cap ", v), + Self::Ch(v) => ("ch ", v), + Self::Ic(v) => ("ic ", v), + }; + + dest.write_str(prefix)?; + value.to_css(dest) + } +} diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index b007bc3f5a4..52e0585b3b2 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -13,8 +13,9 @@ use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, use crate::values::computed::{font as computed, Length, NonNegativeLength}; use crate::values::computed::{Angle as ComputedAngle, Percentage as ComputedPercentage}; use crate::values::computed::{CSSPixelLength, Context, ToComputedValue}; +use crate::values::computed::FontSizeAdjust as ComputedFontSizeAdjust; use crate::values::generics::font::VariationValue; -use crate::values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag}; +use crate::values::generics::font::{self as generics, FeatureTagValue, FontSettings, FontTag, GenericFontSizeAdjust}; use crate::values::generics::NonNegative; use crate::values::specified::length::{FontBaseSize, PX_PER_PT}; use crate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage}; @@ -761,16 +762,13 @@ impl Parse for FamilyName { } } -#[derive( - Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, -)] /// Preserve the readability of text when font fallback occurs +#[derive( + Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, +)] +#[allow(missing_docs)] pub enum FontSizeAdjust { - /// None variant - None, - /// Number variant - Number(NonNegativeNumber), - /// system font + Value(GenericFontSizeAdjust), #[css(skip)] System(SystemFont), } @@ -779,34 +777,53 @@ impl FontSizeAdjust { #[inline] /// Default value of font-size-adjust pub fn none() -> Self { - FontSizeAdjust::None + FontSizeAdjust::Value(GenericFontSizeAdjust::None) } system_font_methods!(FontSizeAdjust, font_size_adjust); } +impl Parse for FontSizeAdjust { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let location = input.current_source_location(); + if let Ok(ident) = input.try_parse(|i| i.expect_ident_cloned()) { + let basis_enabled = static_prefs::pref!("layout.css.font-size-adjust.basis.enabled"); + let basis = match_ignore_ascii_case! { &ident, + "none" => return Ok(FontSizeAdjust::none()), + // Check for size adjustment basis keywords if enabled. + "ex" if basis_enabled => GenericFontSizeAdjust::Ex, + "cap" if basis_enabled => GenericFontSizeAdjust::Cap, + "ch" if basis_enabled => GenericFontSizeAdjust::Ch, + "ic" if basis_enabled => GenericFontSizeAdjust::Ic, + // Unknown (or disabled) keyword. + _ => return Err(location.new_custom_error( + ::selectors::parser::SelectorParseErrorKind::UnexpectedIdent(ident) + )), + }; + let value = NonNegativeNumber::parse(context, input)?; + return Ok(FontSizeAdjust::Value(basis(value))); + } + // Without a basis keyword, the number refers to the 'ex' metric. + let value = NonNegativeNumber::parse(context, input)?; + Ok(FontSizeAdjust::Value(GenericFontSizeAdjust::Ex(value))) + } +} + impl ToComputedValue for FontSizeAdjust { - type ComputedValue = computed::FontSizeAdjust; + type ComputedValue = ComputedFontSizeAdjust; fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { match *self { - FontSizeAdjust::None => computed::FontSizeAdjust::None, - FontSizeAdjust::Number(ref n) => { - // The computed version handles clamping of animated values - // itself. - computed::FontSizeAdjust::Number(n.to_computed_value(context).0) - }, + FontSizeAdjust::Value(v) => v.to_computed_value(context), FontSizeAdjust::System(_) => self.compute_system(context), } } - fn from_computed_value(computed: &computed::FontSizeAdjust) -> Self { - match *computed { - computed::FontSizeAdjust::None => FontSizeAdjust::None, - computed::FontSizeAdjust::Number(v) => { - FontSizeAdjust::Number(NonNegativeNumber::from_computed_value(&v.into())) - }, - } + fn from_computed_value(computed: &ComputedFontSizeAdjust) -> Self { + Self::Value(ToComputedValue::from_computed_value(computed)) } } From 0ebad03ab5c1512b68742e17a9fdbb761850d1ae Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 00:37:47 +0200 Subject: [PATCH 30/80] Further changes required by Servo --- components/style/values/specified/font.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 52e0585b3b2..102c55420ab 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -790,7 +790,10 @@ impl Parse for FontSizeAdjust { ) -> Result> { let location = input.current_source_location(); if let Ok(ident) = input.try_parse(|i| i.expect_ident_cloned()) { + #[cfg(feature = "gecko")] let basis_enabled = static_prefs::pref!("layout.css.font-size-adjust.basis.enabled"); + #[cfg(feature = "servo")] + let basis_enabled = false; let basis = match_ignore_ascii_case! { &ident, "none" => return Ok(FontSizeAdjust::none()), // Check for size adjustment basis keywords if enabled. From 9eb244fc0cceb9b028bc730fe768c8c65a294a65 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 00:50:14 +0200 Subject: [PATCH 31/80] style: Add an internal -moz-system-color() function to expose both light and dark system colors Differential Revision: https://phabricator.services.mozilla.com/D117416 --- components/style/values/specified/color.rs | 59 +++++++++++++++++++--- 1 file changed, 52 insertions(+), 7 deletions(-) diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 6f8d6de9fde..3500c3aa73d 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -131,6 +131,20 @@ impl ToCss for ColorMix { } } +/// The color scheme for a specific system color. +#[cfg(feature = "gecko")] +#[derive(Clone, Copy, Debug, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)] +#[repr(u8)] +pub enum SystemColorScheme { + /// The default color-scheme for the document. + #[css(skip)] + Default, + /// A light color scheme. + Light, + /// A dark color scheme. + Dark, +} + /// Specified color value #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] pub enum Color { @@ -145,9 +159,10 @@ pub enum Color { }, /// A complex color value from computed value Complex(ComputedColor), - /// A system color + /// Either a system color, or a `-moz-system-color(, light|dark)` + /// function which allows chrome code to choose between color schemes. #[cfg(feature = "gecko")] - System(SystemColor), + System(SystemColor, SystemColorScheme), /// A color mix. ColorMix(Box), /// Quirksmode-only rule for inheriting color from the body @@ -390,7 +405,7 @@ pub enum SystemColor { #[cfg(feature = "gecko")] impl SystemColor { #[inline] - fn compute(&self, cx: &Context) -> ComputedColor { + fn compute(&self, cx: &Context, scheme: SystemColorScheme) -> ComputedColor { use crate::gecko_bindings::bindings; let prefs = cx.device().pref_sheet_prefs(); @@ -403,7 +418,7 @@ impl SystemColor { SystemColor::Visitedtext => prefs.mVisitedLinkColor, _ => unsafe { - bindings::Gecko_GetLookAndFeelSystemColor(*self as i32, cx.device().document()) + bindings::Gecko_GetLookAndFeelSystemColor(*self as i32, cx.device().document(), scheme) }, }) } @@ -479,6 +494,20 @@ impl<'a, 'b: 'a, 'i: 'a> ::cssparser::ColorComponentParser<'i> for ColorComponen } } +fn parse_moz_system_color<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, +) -> Result<(SystemColor, SystemColorScheme), ParseError<'i>> { + debug_assert!(context.chrome_rules_enabled()); + input.expect_function_matching("-moz-system-color")?; + input.parse_nested_block(|input| { + let color = SystemColor::parse(context, input)?; + input.expect_comma()?; + let scheme = SystemColorScheme::parse(input)?; + Ok((color, scheme)) + }) +} + impl Parse for Color { fn parse<'i, 't>( context: &ParserContext, @@ -504,7 +533,13 @@ impl Parse for Color { #[cfg(feature = "gecko")] { if let Ok(system) = input.try_parse(|i| SystemColor::parse(context, i)) { - return Ok(Color::System(system)); + return Ok(Color::System(system, SystemColorScheme::Default)); + } + + if context.chrome_rules_enabled() { + if let Ok((color, scheme)) = input.try_parse(|i| parse_moz_system_color(context, i)) { + return Ok(Color::System(color, scheme)); + } } } @@ -543,7 +578,17 @@ impl ToCss for Color { Color::Complex(_) => Ok(()), Color::ColorMix(ref mix) => mix.to_css(dest), #[cfg(feature = "gecko")] - Color::System(system) => system.to_css(dest), + Color::System(system, scheme) => { + if scheme == SystemColorScheme::Default { + system.to_css(dest) + } else { + dest.write_str("-moz-system-color(")?; + system.to_css(dest)?; + dest.write_str(", ")?; + scheme.to_css(dest)?; + dest.write_char(')') + } + } #[cfg(feature = "gecko")] Color::InheritFromBodyQuirk => Ok(()), } @@ -709,7 +754,7 @@ impl Color { )) }, #[cfg(feature = "gecko")] - Color::System(system) => system.compute(context?), + Color::System(system, scheme) => system.compute(context?, scheme), #[cfg(feature = "gecko")] Color::InheritFromBodyQuirk => ComputedColor::rgba(context?.device().body_text_color()), }) From 2bf074e4340c87aa67ba7f0dd5197367c84fb10b Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 01:12:10 +0200 Subject: [PATCH 32/80] Further changes required by Servo --- components/style/values/specified/color.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 3500c3aa73d..85d8d613290 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -494,6 +494,7 @@ impl<'a, 'b: 'a, 'i: 'a> ::cssparser::ColorComponentParser<'i> for ColorComponen } } +#[cfg(feature = "gecko")] fn parse_moz_system_color<'i, 't>( context: &ParserContext, input: &mut Parser<'i, 't>, From ed806afe525ea2fec86a90b107f2cb45c2a81533 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 00:51:12 +0200 Subject: [PATCH 33/80] style: Expose text selection foreground / background colors to chrome code Differential Revision: https://phabricator.services.mozilla.com/D117417 --- components/style/values/specified/color.rs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 85d8d613290..4016cd1d81e 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -196,13 +196,13 @@ pub enum SystemColor { TextBackground, #[css(skip)] TextForeground, - #[css(skip)] + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] TextSelectBackground, - #[css(skip)] + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] TextSelectForeground, - #[css(skip)] + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] TextSelectBackgroundDisabled, - #[css(skip)] + #[parse(condition = "ParserContext::in_ua_or_chrome_sheet")] TextSelectBackgroundAttention, #[css(skip)] TextHighlightBackground, @@ -417,9 +417,15 @@ impl SystemColor { SystemColor::Activetext => prefs.mActiveLinkColor, SystemColor::Visitedtext => prefs.mVisitedLinkColor, - _ => unsafe { - bindings::Gecko_GetLookAndFeelSystemColor(*self as i32, cx.device().document(), scheme) - }, + _ => { + let color = unsafe { + bindings::Gecko_GetLookAndFeelSystemColor(*self as i32, cx.device().document(), scheme) + }; + if color == bindings::NS_SAME_AS_FOREGROUND_COLOR { + return ComputedColor::currentcolor(); + } + color + } }) } } From 837e41c8eb65f9bdcd33ff8fdd4657b078c4cdeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 00:51:45 +0200 Subject: [PATCH 34/80] style: Remove -moz-outline-radius It does nothing since 88 and we unshipped it in 89. Differential Revision: https://phabricator.services.mozilla.com/D117532 --- components/style/properties/gecko.mako.rs | 11 +---- .../properties/longhands/outline.mako.rs | 14 ------ .../properties/shorthands/outline.mako.rs | 47 ------------------- components/style/values/generics/border.rs | 2 +- 4 files changed, 2 insertions(+), 72 deletions(-) diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index a88aec3b684..0e9b178944c 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -799,11 +799,8 @@ fn static_assert() { ${impl_simple_type_with_conversion("masonry_auto_flow", "mMasonryAutoFlow")} -<% skip_outline_longhands = " ".join("outline-style outline-width".split() + - ["-moz-outline-radius-{0}".format(x.replace("_", "")) - for x in CORNERS]) %> <%self:impl_trait style_struct_name="Outline" - skip_longhands="${skip_outline_longhands}"> + skip_longhands="outline-style outline-width"> pub fn set_outline_style(&mut self, v: longhands::outline_style::computed_value::T) { self.gecko.mOutlineStyle = v; @@ -831,12 +828,6 @@ fn static_assert() { inherit_from="mOutlineWidth", round_to_pixels=True) %> - % for corner in CORNERS: - <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.replace("_", ""), - "mOutlineRadius", - corner) %> - % endfor - pub fn outline_has_nonzero_width(&self) -> bool { self.gecko.mActualOutlineWidth != 0 } diff --git a/components/style/properties/longhands/outline.mako.rs b/components/style/properties/longhands/outline.mako.rs index e5cd09fbe82..c744f5f523f 100644 --- a/components/style/properties/longhands/outline.mako.rs +++ b/components/style/properties/longhands/outline.mako.rs @@ -42,20 +42,6 @@ ${helpers.predefined_type( spec="https://drafts.csswg.org/css-ui/#propdef-outline-width", )} -// The -moz-outline-radius-* properties are non-standard and not on a standards track. -% for corner in ["topleft", "topright", "bottomright", "bottomleft"]: - ${helpers.predefined_type( - "-moz-outline-radius-" + corner, - "BorderCornerRadius", - "computed::BorderCornerRadius::zero()", - engines="gecko", - boxed=True, - animation_value_type="BorderCornerRadius", - gecko_pref="layout.css.moz-outline-radius.enabled", - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)", - )} -% endfor - ${helpers.predefined_type( "outline-offset", "Length", diff --git a/components/style/properties/shorthands/outline.mako.rs b/components/style/properties/shorthands/outline.mako.rs index db397498919..b90f8d966f3 100644 --- a/components/style/properties/shorthands/outline.mako.rs +++ b/components/style/properties/shorthands/outline.mako.rs @@ -78,50 +78,3 @@ } } - -// The -moz-outline-radius shorthand is non-standard and not on a standards track. -<%helpers:shorthand - name="-moz-outline-radius" - engines="gecko" - gecko_pref="layout.css.moz-outline-radius.enabled" - sub_properties="${' '.join( - '-moz-outline-radius-%s' % corner - for corner in ['topleft', 'topright', 'bottomright', 'bottomleft'] - )}" - spec="Nonstandard (https://developer.mozilla.org/en-US/docs/Web/CSS/-moz-outline-radius)" -> - use crate::values::generics::rect::Rect; - use crate::values::specified::border::BorderRadius; - use crate::parser::Parse; - - pub fn parse_value<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - let radii = BorderRadius::parse(context, input)?; - Ok(expanded! { - _moz_outline_radius_topleft: radii.top_left, - _moz_outline_radius_topright: radii.top_right, - _moz_outline_radius_bottomright: radii.bottom_right, - _moz_outline_radius_bottomleft: radii.bottom_left, - }) - } - - impl<'a> ToCss for LonghandsToSerialize<'a> { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { - use crate::values::generics::border::BorderCornerRadius; - - let LonghandsToSerialize { - _moz_outline_radius_topleft: &BorderCornerRadius(ref tl), - _moz_outline_radius_topright: &BorderCornerRadius(ref tr), - _moz_outline_radius_bottomright: &BorderCornerRadius(ref br), - _moz_outline_radius_bottomleft: &BorderCornerRadius(ref bl), - } = *self; - - let widths = Rect::new(tl.width(), tr.width(), br.width(), bl.width()); - let heights = Rect::new(tl.height(), tr.height(), br.height(), bl.height()); - - BorderRadius::serialize_rects(widths, heights, dest) - } - } - diff --git a/components/style/values/generics/border.rs b/components/style/values/generics/border.rs index 37d91464b01..e4e78e31222 100644 --- a/components/style/values/generics/border.rs +++ b/components/style/values/generics/border.rs @@ -147,7 +147,7 @@ impl BorderSpacing { } } -/// A generic value for `border-radius`, `outline-radius` and `inset()`. +/// A generic value for `border-radius` and `inset()`. /// /// #[derive( From 67f9b97735e8e83789c88ae3c4657f40fdc056c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 01:07:30 +0200 Subject: [PATCH 35/80] style: Unify font-family storage This changes font-family storage to reuse the rust types, removing a bunch of code while at it. This allows us to, for example, use a single static font family for -moz-bullet and clone it, rather than creating a lot of expensive copies. Differential Revision: https://phabricator.services.mozilla.com/D118011 --- .../style/gecko_bindings/sugar/refptr.rs | 5 - components/style/properties/cascade.rs | 23 +- components/style/properties/gecko.mako.rs | 49 +-- .../style/properties/longhands/font.mako.rs | 12 +- components/style/style_adjuster.rs | 11 +- components/style/values/computed/font.rs | 327 +++++++----------- components/style/values/specified/font.rs | 29 +- components/style_traits/arc_slice.rs | 18 + 8 files changed, 180 insertions(+), 294 deletions(-) diff --git a/components/style/gecko_bindings/sugar/refptr.rs b/components/style/gecko_bindings/sugar/refptr.rs index a141aef4e8b..d8c0cea0f2b 100644 --- a/components/style/gecko_bindings/sugar/refptr.rs +++ b/components/style/gecko_bindings/sugar/refptr.rs @@ -308,11 +308,6 @@ impl_threadsafe_refcount!( bindings::Gecko_AddRefnsIURIArbitraryThread, bindings::Gecko_ReleasensIURIArbitraryThread ); -impl_threadsafe_refcount!( - structs::SharedFontList, - bindings::Gecko_AddRefSharedFontListArbitraryThread, - bindings::Gecko_ReleaseSharedFontListArbitraryThread -); impl_threadsafe_refcount!( structs::SheetLoadDataHolder, bindings::Gecko_AddRefSheetLoadDataHolderArbitraryThread, diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 91d6c6c99dd..822a7c52053 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -878,18 +878,19 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { // System fonts are all right, and should have the default font type // set to none already, so bail out early. - if font.mFont.systemFont { + if font.mFont.family.is_system_font { debug_assert_eq!( - font.mFont.fontlist.mDefaultFontType, + font.mFont.family.families.fallback, GenericFontFamily::None ); return; } + let generic = font.mFont.family.families.single_generic().unwrap_or(GenericFontFamily::None); let default_font_type = unsafe { bindings::Gecko_nsStyleFont_ComputeDefaultFontType( builder.device.document(), - font.mGenericID, + generic, font.mLanguage.mRawPtr, ) }; @@ -899,15 +900,15 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { // cursive or fantasy, since they're ignored, see bug 789788), and // we have a generic family to actually replace it with. let prioritize_user_fonts = !use_document_fonts && + default_font_type != GenericFontFamily::None && matches!( - font.mGenericID, + generic, GenericFontFamily::None | - GenericFontFamily::Fantasy | - GenericFontFamily::Cursive - ) && - default_font_type != GenericFontFamily::None; + GenericFontFamily::Fantasy | + GenericFontFamily::Cursive + ); - if !prioritize_user_fonts && default_font_type == font.mFont.fontlist.mDefaultFontType { + if !prioritize_user_fonts && default_font_type == font.mFont.family.families.fallback { // Nothing to do. return; } @@ -915,9 +916,9 @@ impl<'a, 'b: 'a> Cascade<'a, 'b> { }; let font = builder.mutate_font().gecko_mut(); - font.mFont.fontlist.mDefaultFontType = default_font_type; + font.mFont.family.families.fallback = default_font_type; if prioritize_user_fonts { - unsafe { bindings::Gecko_nsStyleFont_PrioritizeUserFonts(font, default_font_type) } + font.mFont.family.families.prioritize_first_generic_or_prepend(default_font_type); } } diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index 0e9b178944c..86cdeefa982 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -22,7 +22,6 @@ use crate::gecko_bindings::bindings::Gecko_CopyConstruct_${style_struct.gecko_ff use crate::gecko_bindings::bindings::Gecko_Destroy_${style_struct.gecko_ffi_name}; % endfor use crate::gecko_bindings::bindings::Gecko_CopyCounterStyle; -use crate::gecko_bindings::bindings::Gecko_CopyFontFamilyFrom; use crate::gecko_bindings::bindings::Gecko_EnsureImageLayersLength; use crate::gecko_bindings::bindings::Gecko_nsStyleFont_SetLang; use crate::gecko_bindings::bindings::Gecko_nsStyleFont_CopyLangFrom; @@ -848,52 +847,6 @@ fn static_assert() { <% impl_font_settings("font_feature_settings", "gfxFontFeature", "FeatureTagValue", "i32", "u32") %> <% impl_font_settings("font_variation_settings", "gfxFontVariation", "VariationValue", "f32", "f32") %> - pub fn set_font_family(&mut self, v: longhands::font_family::computed_value::T) { - use crate::values::computed::font::GenericFontFamily; - - let is_system_font = v.is_system_font; - self.gecko.mFont.systemFont = is_system_font; - self.gecko.mGenericID = if is_system_font { - GenericFontFamily::None - } else { - v.families.single_generic().unwrap_or(GenericFontFamily::None) - }; - self.gecko.mFont.fontlist.mFontlist.mBasePtr.set_move( - v.families.shared_font_list().clone() - ); - // Fixed-up if needed in Cascade::fixup_font_stuff. - self.gecko.mFont.fontlist.mDefaultFontType = GenericFontFamily::None; - } - - pub fn copy_font_family_from(&mut self, other: &Self) { - unsafe { Gecko_CopyFontFamilyFrom(&mut self.gecko.mFont, &other.gecko.mFont); } - self.gecko.mGenericID = other.gecko.mGenericID; - self.gecko.mFont.systemFont = other.gecko.mFont.systemFont; - } - - pub fn reset_font_family(&mut self, other: &Self) { - self.copy_font_family_from(other) - } - - pub fn clone_font_family(&self) -> longhands::font_family::computed_value::T { - use crate::values::computed::font::{FontFamily, SingleFontFamily, FontFamilyList}; - - let fontlist = &self.gecko.mFont.fontlist; - let shared_fontlist = unsafe { fontlist.mFontlist.mBasePtr.to_safe() }; - - let families = if shared_fontlist.mNames.is_empty() { - let default = SingleFontFamily::Generic(fontlist.mDefaultFontType); - FontFamilyList::new(Box::new([default])) - } else { - FontFamilyList::SharedFontList(shared_fontlist) - }; - - FontFamily { - families, - is_system_font: self.gecko.mFont.systemFont, - } - } - pub fn unzoom_fonts(&mut self, device: &Device) { use crate::values::generics::NonNegative; self.gecko.mSize = NonNegative(device.unzoom_text(self.gecko.mSize.0)); @@ -1001,6 +954,8 @@ fn static_assert() { ${impl_simple("font_size_adjust", "mFont.sizeAdjust")} + ${impl_simple("font_family", "mFont.family")} + #[allow(non_snake_case)] pub fn set__x_lang(&mut self, v: longhands::_x_lang::computed_value::T) { let ptr = v.0.as_ptr(); diff --git a/components/style/properties/longhands/font.mako.rs b/components/style/properties/longhands/font.mako.rs index cf75bb59123..12191509622 100644 --- a/components/style/properties/longhands/font.mako.rs +++ b/components/style/properties/longhands/font.mako.rs @@ -314,7 +314,6 @@ pub mod system_font { //! variable reference. We may want to improve this behavior at some //! point. See also https://github.com/w3c/csswg-drafts/issues/1586. - use crate::values::computed::font::GenericFontFamily; use crate::properties::longhands; use std::hash::{Hash, Hasher}; use crate::values::computed::{ToComputedValue, Context}; @@ -356,7 +355,7 @@ pub mod system_font { use std::mem; use crate::values::computed::Percentage; use crate::values::specified::font::KeywordInfo; - use crate::values::computed::font::{FontFamily, FontSize, FontStretch, FontStyle, FontFamilyList}; + use crate::values::computed::font::{FontSize, FontStretch, FontStyle}; use crate::values::generics::NonNegative; let mut system = mem::MaybeUninit::::uninit(); @@ -375,12 +374,7 @@ pub mod system_font { }))); let font_style = FontStyle::from_gecko(system.style); let ret = ComputedSystemFont { - font_family: FontFamily { - families: FontFamilyList::SharedFontList( - unsafe { system.fontlist.mFontlist.mBasePtr.to_safe() } - ), - is_system_font: true, - }, + font_family: system.family.clone(), font_size: FontSize { size: NonNegative(cx.maybe_zoom_text(system.size.0)), keyword_info: KeywordInfo::none() @@ -403,7 +397,6 @@ pub mod system_font { font_variation_settings: longhands::font_variation_settings::get_initial_value(), font_variant_alternates: longhands::font_variant_alternates::get_initial_value(), system_font: *self, - default_font_type: system.fontlist.mDefaultFontType, }; unsafe { bindings::Gecko_nsFont_Destroy(system); } ret @@ -435,7 +428,6 @@ pub mod system_font { pub ${name}: longhands::${name}::computed_value::T, % endfor pub system_font: SystemFont, - pub default_font_type: GenericFontFamily, } } diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index bfd43da6088..5fe28e5bc72 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -830,7 +830,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { /// the same font as its fallback ('list-style-type') in case it fails to load. #[cfg(feature = "gecko")] fn adjust_for_marker_pseudo(&mut self) { - use crate::values::computed::font::{FamilyName, FontFamily, FontFamilyList, FontFamilyNameSyntax, FontSynthesis, SingleFontFamily}; + use crate::values::computed::font::{FontFamily, FontSynthesis}; use crate::values::computed::text::{LetterSpacing, WordSpacing}; let is_legacy_marker = self.style.pseudo.map_or(false, |p| p.is_marker()) && @@ -840,14 +840,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { return; } if !self.style.flags.get().contains(ComputedValueFlags::HAS_AUTHOR_SPECIFIED_FONT_FAMILY) { - let moz_bullet_font_family = FontFamily { - families: FontFamilyList::new(Box::new([SingleFontFamily::FamilyName(FamilyName { - name: atom!("-moz-bullet-font"), - syntax: FontFamilyNameSyntax::Identifiers, - })])), - is_system_font: false, - }; - self.style.mutate_font().set_font_family(moz_bullet_font_family); + self.style.mutate_font().set_font_family(FontFamily::moz_bullet().clone()); // FIXME(mats): We can remove this if support for font-synthesis is added to @font-face rules. // Then we can add it to the @font-face rule in html.css instead. diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index d5906d0e89f..af1dd87e797 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -4,8 +4,6 @@ //! Computed values for font properties -#[cfg(feature = "gecko")] -use crate::gecko_bindings::sugar::refptr::RefPtr; #[cfg(feature = "gecko")] use crate::gecko_bindings::{bindings, structs}; use crate::values::animated::ToAnimatedValue; @@ -26,13 +24,7 @@ use cssparser::{serialize_identifier, CssStringWriter, Parser}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use std::fmt::{self, Write}; use std::hash::{Hash, Hasher}; -#[cfg(feature = "gecko")] -use std::mem::{self, ManuallyDrop}; -#[cfg(feature = "servo")] -use std::slice; use style_traits::{CssWriter, ParseError, ToCss}; -#[cfg(feature = "gecko")] -use to_shmem::{self, SharedMemoryBuilder, ToShmem}; pub use crate::values::computed::Length as MozScriptMinSize; pub use crate::values::specified::font::{FontSynthesis, MozScriptSizeMultiplier}; @@ -183,6 +175,7 @@ impl ToAnimatedValue for FontSize { #[derive(Clone, Debug, Eq, PartialEq, ToComputedValue, ToResolvedValue)] #[cfg_attr(feature = "servo", derive(Hash, MallocSizeOf, Serialize, Deserialize))] /// Specifies a prioritized list of font family names or generic family names. +#[repr(C)] pub struct FontFamily { /// The actual list of family names. pub families: FontFamilyList, @@ -190,27 +183,95 @@ pub struct FontFamily { pub is_system_font: bool, } +macro_rules! static_font_family { + ($ident:ident, $family:expr) => { + lazy_static! { + static ref $ident: FontFamily = FontFamily { + families: FontFamilyList { + list: crate::ArcSlice::from_iter_leaked(std::iter::once($family)), + fallback: GenericFontFamily::None, + }, + is_system_font: false, + }; + } + }; +} + + impl FontFamily { #[inline] /// Get default font family as `serif` which is a generic font-family pub fn serif() -> Self { - FontFamily { - families: FontFamilyList::new(Box::new([SingleFontFamily::Generic( - GenericFontFamily::Serif, - )])), - is_system_font: false, + Self::generic(GenericFontFamily::Serif).clone() + } + + /// Returns the font family for `-moz-bullet-font`. + pub(crate) fn moz_bullet() -> &'static Self { + static_font_family!(MOZ_BULLET, SingleFontFamily::FamilyName(FamilyName { + name: atom!("-moz-bullet-font"), + syntax: FontFamilyNameSyntax::Identifiers, + })); + + &*MOZ_BULLET + } + + /// Returns a font family for a single system font. + pub fn for_system_font(name: &str) -> Self { + Self { + families: FontFamilyList { + list: crate::ArcSlice::from_iter(std::iter::once(SingleFontFamily::FamilyName(FamilyName { + name: Atom::from(name), + syntax: FontFamilyNameSyntax::Identifiers, + }))), + fallback: GenericFontFamily::None, + }, + is_system_font: true, + } + } + + /// Returns a generic font family. + pub fn generic(generic: GenericFontFamily) -> &'static Self { + macro_rules! generic_font_family { + ($ident:ident, $family:ident) => { + static_font_family!($ident, SingleFontFamily::Generic(GenericFontFamily::$family)) + } + } + + generic_font_family!(SERIF, Serif); + generic_font_family!(SANS_SERIF, SansSerif); + generic_font_family!(MONOSPACE, Monospace); + generic_font_family!(CURSIVE, Cursive); + generic_font_family!(FANTASY, Fantasy); + generic_font_family!(MOZ_EMOJI, MozEmoji); + + match generic { + GenericFontFamily::None => { + debug_assert!(false, "Bogus caller!"); + &*SERIF + } + GenericFontFamily::Serif => &*SERIF, + GenericFontFamily::SansSerif => &*SANS_SERIF, + GenericFontFamily::Monospace => &*MONOSPACE, + GenericFontFamily::Cursive => &*CURSIVE, + GenericFontFamily::Fantasy => &*FANTASY, + GenericFontFamily::MozEmoji => &*MOZ_EMOJI, } } } #[cfg(feature = "gecko")] impl MallocSizeOf for FontFamily { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { - // SharedFontList objects are generally shared from the pointer - // stored in the specified value. So only count this if the - // SharedFontList is unshared. - let shared_font_list = self.families.shared_font_list().get(); - unsafe { bindings::Gecko_SharedFontList_SizeOfIncludingThisIfUnshared(shared_font_list) } + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + use malloc_size_of::MallocUnconditionalSizeOf; + // SharedFontList objects are generally measured from the pointer stored + // in the specified value. So only count this if the SharedFontList is + // unshared. + let shared_font_list = &self.families.list; + if shared_font_list.is_unique() { + shared_font_list.unconditional_size_of(ops) + } else { + 0 + } } } @@ -220,7 +281,10 @@ impl ToCss for FontFamily { W: fmt::Write, { let mut iter = self.families.iter(); - iter.next().unwrap().to_css(dest)?; + match iter.next() { + Some(f) => f.to_css(dest)?, + None => return self.families.fallback.to_css(dest), + } for family in iter { dest.write_str(", ")?; family.to_css(dest)?; @@ -229,15 +293,16 @@ impl ToCss for FontFamily { } } +/// The name of a font family of choice. #[derive( Clone, Debug, Eq, Hash, MallocSizeOf, PartialEq, ToComputedValue, ToResolvedValue, ToShmem, )] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -/// The name of a font family of choice +#[repr(C)] pub struct FamilyName { - /// Name of the font family + /// Name of the font family. pub name: Atom, - /// Syntax of the font family + /// Syntax of the font family. pub syntax: FontFamilyNameSyntax, } @@ -291,11 +356,13 @@ pub enum FontFamilyNameSyntax { Identifiers, } +/// A set of faces that vary in weight, width or slope. +/// cbindgen:derive-mut-casts=true #[derive( Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToComputedValue, ToResolvedValue, ToShmem, )] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize, Hash))] -/// A set of faces that vary in weight, width or slope. +#[repr(u8)] pub enum SingleFontFamily { /// The name of a font family of choice. FamilyName(FamilyName), @@ -429,145 +496,57 @@ impl SingleFontFamily { syntax: FontFamilyNameSyntax::Quoted, }) } - - #[cfg(feature = "gecko")] - /// Get the corresponding font-family with family name - fn from_font_family_name(family: &structs::FontFamilyName) -> SingleFontFamily { - if family.mName.mRawPtr.is_null() { - debug_assert_ne!(family.mGeneric, GenericFontFamily::None); - return SingleFontFamily::Generic(family.mGeneric); - } - let name = unsafe { Atom::from_raw(family.mName.mRawPtr) }; - SingleFontFamily::FamilyName(FamilyName { - name, - syntax: family.mSyntax, - }) - } } -#[cfg(feature = "servo")] -#[derive( - Clone, - Debug, - Deserialize, - Eq, - Hash, - MallocSizeOf, - PartialEq, - Serialize, - ToComputedValue, - ToResolvedValue, - ToShmem, -)] -/// A list of SingleFontFamily -pub struct FontFamilyList(Box<[SingleFontFamily]>); - -#[cfg(feature = "gecko")] -#[derive(Clone, Debug, ToComputedValue, ToResolvedValue)] -/// A list of SingleFontFamily -pub enum FontFamilyList { - /// A strong reference to a Gecko SharedFontList object. - SharedFontList( - #[compute(no_field_bound)] - #[resolve(no_field_bound)] - RefPtr, - ), - /// A font-family generic ID. - Generic(GenericFontFamily), +/// A list of font families. +#[derive(Clone, Debug, ToComputedValue, ToResolvedValue, ToShmem, PartialEq, Eq)] +#[repr(C)] +pub struct FontFamilyList { + /// The actual list of font families specified. + pub list: crate::ArcSlice, + /// A fallback font type (none, serif, or sans-serif, generally). + pub fallback: GenericFontFamily, } -#[cfg(feature = "gecko")] -impl ToShmem for FontFamilyList { - fn to_shmem(&self, _builder: &mut SharedMemoryBuilder) -> to_shmem::Result { - // In practice, the only SharedFontList objects we create from shared - // style sheets are ones with a single generic entry. - Ok(ManuallyDrop::new(match *self { - FontFamilyList::SharedFontList(ref r) => { - if !(r.mNames.len() == 1 && r.mNames[0].mName.mRawPtr.is_null()) { - return Err(String::from( - "ToShmem failed for FontFamilyList: cannot handle non-generic families", - )); - } - FontFamilyList::Generic(r.mNames[0].mGeneric) - }, - FontFamilyList::Generic(t) => FontFamilyList::Generic(t), - })) - } -} - -#[cfg(feature = "gecko")] -impl PartialEq for FontFamilyList { - fn eq(&self, other: &FontFamilyList) -> bool { - let self_list = self.shared_font_list(); - let other_list = other.shared_font_list(); - - if self_list.mNames.len() != other_list.mNames.len() { - return false; - } - for (a, b) in self_list.mNames.iter().zip(other_list.mNames.iter()) { - if a.mSyntax != b.mSyntax || - a.mName.mRawPtr != b.mName.mRawPtr || - a.mGeneric != b.mGeneric - { - return false; - } - } - true - } -} - -#[cfg(feature = "gecko")] -impl Eq for FontFamilyList {} - impl FontFamilyList { - /// Return FontFamilyList with a vector of SingleFontFamily - #[cfg(feature = "servo")] - pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList { - FontFamilyList(families) + /// Return iterator of SingleFontFamily + pub fn iter(&self) -> impl Iterator { + self.list.iter() } - /// Return FontFamilyList with a vector of SingleFontFamily - #[cfg(feature = "gecko")] - pub fn new(families: Box<[SingleFontFamily]>) -> FontFamilyList { - let fontlist; - let names; - unsafe { - fontlist = bindings::Gecko_SharedFontList_Create(); - names = &mut (*fontlist).mNames; - names.ensure_capacity(families.len()); + /// Puts the fallback in the list if needed. + pub fn normalize(&mut self) { + if self.fallback == GenericFontFamily::None { + return; + } + let mut new_list = self.list.iter().cloned().collect::>(); + new_list.push(SingleFontFamily::Generic(self.fallback)); + self.list = crate::ArcSlice::from_iter(new_list.into_iter()); + } + + /// If there's a generic font family on the list (which isn't cursive or + /// fantasy), then move it to the front of the list. Otherwise, prepend the + /// default generic. + pub (crate) fn prioritize_first_generic_or_prepend(&mut self, generic: GenericFontFamily) { + let index_of_first_generic = self.iter().position(|f| { + match *f { + SingleFontFamily::Generic(f) => f != GenericFontFamily::Cursive && f != GenericFontFamily::Fantasy, + _ => false, + } + }); + + if let Some(0) = index_of_first_generic { + return; // Already first + } + + let mut new_list = self.list.iter().cloned().collect::>(); + let element_to_prepend = match index_of_first_generic { + Some(i) => new_list.remove(i), + None => SingleFontFamily::Generic(generic), }; - for family in families.iter() { - match *family { - SingleFontFamily::FamilyName(ref f) => unsafe { - bindings::Gecko_nsTArray_FontFamilyName_AppendNamed( - names, - f.name.as_ptr(), - f.syntax, - ); - }, - SingleFontFamily::Generic(family) => unsafe { - bindings::Gecko_nsTArray_FontFamilyName_AppendGeneric(names, family); - }, - } - } - - FontFamilyList::SharedFontList(unsafe { RefPtr::from_addrefed(fontlist) }) - } - - /// Return iterator of SingleFontFamily - #[cfg(feature = "servo")] - pub fn iter(&self) -> slice::Iter { - self.0.iter() - } - - /// Return iterator of SingleFontFamily - #[cfg(feature = "gecko")] - pub fn iter(&self) -> FontFamilyNameIter { - FontFamilyNameIter { - names: &self.shared_font_list().mNames, - cur: 0, - } + new_list.insert(0, element_to_prepend); + self.list = crate::ArcSlice::from_iter(new_list.into_iter()); } /// Return the generic ID if it is a single generic font @@ -580,46 +559,6 @@ impl FontFamilyList { } None } - - /// Return a reference to the Gecko SharedFontList. - #[cfg(feature = "gecko")] - pub fn shared_font_list(&self) -> &RefPtr { - match *self { - FontFamilyList::SharedFontList(ref r) => r, - FontFamilyList::Generic(t) => { - unsafe { - // TODO(heycam): Should really add StaticRefPtr sugar. - let index = t as usize; - mem::transmute::< - &structs::StaticRefPtr, - &RefPtr, - >(&structs::SharedFontList_sSingleGenerics[index]) - } - }, - } - } -} - -/// Iterator of FontFamily -#[cfg(feature = "gecko")] -pub struct FontFamilyNameIter<'a> { - names: &'a structs::nsTArray, - cur: usize, -} - -#[cfg(feature = "gecko")] -impl<'a> Iterator for FontFamilyNameIter<'a> { - type Item = SingleFontFamily; - - fn next(&mut self) -> Option { - if self.cur < self.names.len() { - let item = SingleFontFamily::from_font_family_name(&self.names[self.cur]); - self.cur += 1; - Some(item) - } else { - None - } - } } /// Preserve the readability of text when font fallback occurs diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 102c55420ab..7f3731375a3 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -6,8 +6,6 @@ #[cfg(feature = "gecko")] use crate::context::QuirksMode; -#[cfg(feature = "gecko")] -use crate::gecko_bindings::bindings; use crate::parser::{Parse, ParserContext}; use crate::values::computed::font::{FamilyName, FontFamilyList, FontStyleAngle, SingleFontFamily}; use crate::values::computed::{font as computed, Length, NonNegativeLength}; @@ -24,7 +22,7 @@ use crate::values::CustomIdent; use crate::Atom; use cssparser::{Parser, Token}; #[cfg(feature = "gecko")] -use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf}; use std::fmt::{self, Write}; use style_traits::values::SequenceWriter; use style_traits::{CssWriter, KeywordsCollectFn, ParseError}; @@ -687,9 +685,10 @@ impl FontFamily { /// Parse a specified font-family value pub fn parse_specified<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { let values = input.parse_comma_separated(SingleFontFamily::parse)?; - Ok(FontFamily::Values(FontFamilyList::new( - values.into_boxed_slice(), - ))) + Ok(FontFamily::Values(FontFamilyList { + list: crate::ArcSlice::from_iter(values.into_iter()), + fallback: computed::GenericFontFamily::None, + })) } } @@ -698,8 +697,8 @@ impl ToComputedValue for FontFamily { fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { match *self { - FontFamily::Values(ref v) => computed::FontFamily { - families: v.clone(), + FontFamily::Values(ref list) => computed::FontFamily { + families: list.clone(), is_system_font: false, }, FontFamily::System(_) => self.compute_system(context), @@ -713,18 +712,12 @@ impl ToComputedValue for FontFamily { #[cfg(feature = "gecko")] impl MallocSizeOf for FontFamily { - fn size_of(&self, _ops: &mut MallocSizeOfOps) -> usize { + fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { match *self { FontFamily::Values(ref v) => { - // Although a SharedFontList object is refcounted, we always - // attribute its size to the specified value, as long as it's - // not a value in SharedFontList::sSingleGenerics. - if matches!(v, FontFamilyList::SharedFontList(_)) { - let ptr = v.shared_font_list().get(); - unsafe { bindings::Gecko_SharedFontList_SizeOfIncludingThis(ptr) } - } else { - 0 - } + // Although the family list is refcounted, we always attribute + // its size to the specified value. + v.list.unconditional_size_of(ops) }, FontFamily::System(_) => 0, } diff --git a/components/style_traits/arc_slice.rs b/components/style_traits/arc_slice.rs index 95afe6b3aad..e55861d183b 100644 --- a/components/style_traits/arc_slice.rs +++ b/components/style_traits/arc_slice.rs @@ -13,6 +13,8 @@ use std::ptr::NonNull; use std::{iter, mem}; use to_shmem_derive::ToShmem; +use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf}; + /// A canary that we stash in ArcSlices. /// /// Given we cannot use a zero-sized-type for the header, since well, C++ @@ -137,6 +139,22 @@ impl ArcSlice { std::mem::forget(empty); ptr as *mut _ } + + /// Returns whether there's only one reference to this ArcSlice. + pub fn is_unique(&self) -> bool { + self.0.with_arc(|arc| arc.is_unique()) + } +} + +impl MallocUnconditionalSizeOf for ArcSlice { + #[allow(unsafe_code)] + fn unconditional_size_of(&self, ops: &mut MallocSizeOfOps) -> usize { + let mut size = unsafe { ops.malloc_size_of(self.0.heap_ptr()) }; + for el in self.iter() { + size += el.size_of(ops); + } + size + } } /// The inner pointer of an ArcSlice, to be sent via FFI. From 4f0e0c888c49a908e95406d20258fa7f0fd4d2a2 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 08:30:46 +0200 Subject: [PATCH 36/80] Further changes required by Servo --- components/gfx/tests/font_context.rs | 4 ++- components/script/dom/element.rs | 6 ++-- components/style/values/computed/font.rs | 38 ++++++++++++++++++++++- components/style/values/specified/font.rs | 4 +++ 4 files changed, 47 insertions(+), 5 deletions(-) diff --git a/components/gfx/tests/font_context.rs b/components/gfx/tests/font_context.rs index 4752a5fb3b3..0cda196f12d 100644 --- a/components/gfx/tests/font_context.rs +++ b/components/gfx/tests/font_context.rs @@ -120,7 +120,9 @@ fn font_family(names: Vec<&str>) -> FontFamily { .collect(); FontFamily { - families: FontFamilyList::new(names.into_boxed_slice()), + families: FontFamilyList { + list: names.into_boxed_slice(), + }, is_system_font: false, } } diff --git a/components/script/dom/element.rs b/components/script/dom/element.rs index d8b80df754a..1ceec50281d 100644 --- a/components/script/dom/element.rs +++ b/components/script/dom/element.rs @@ -733,9 +733,9 @@ impl<'dom> LayoutElementHelpers<'dom> for LayoutDom<'dom, Element> { hints.push(from_declaration( shared_lock, PropertyDeclaration::FontFamily(font_family::SpecifiedValue::Values( - computed::font::FontFamilyList::new(Box::new([ - computed::font::SingleFontFamily::from_atom(font_family), - ])), + computed::font::FontFamilyList { + list: Box::new([computed::font::SingleFontFamily::from_atom(font_family)]), + }, )), )); } diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index af1dd87e797..b944640d8e7 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -188,7 +188,11 @@ macro_rules! static_font_family { lazy_static! { static ref $ident: FontFamily = FontFamily { families: FontFamilyList { + #[cfg(feature = "gecko")] list: crate::ArcSlice::from_iter_leaked(std::iter::once($family)), + #[cfg(feature = "servo")] + list: Box::new([$family]), + #[cfg(feature = "gecko")] fallback: GenericFontFamily::None, }, is_system_font: false, @@ -206,6 +210,7 @@ impl FontFamily { } /// Returns the font family for `-moz-bullet-font`. + #[cfg(feature = "gecko")] pub(crate) fn moz_bullet() -> &'static Self { static_font_family!(MOZ_BULLET, SingleFontFamily::FamilyName(FamilyName { name: atom!("-moz-bullet-font"), @@ -216,6 +221,7 @@ impl FontFamily { } /// Returns a font family for a single system font. + #[cfg(feature = "gecko")] pub fn for_system_font(name: &str) -> Self { Self { families: FontFamilyList { @@ -242,6 +248,7 @@ impl FontFamily { generic_font_family!(MONOSPACE, Monospace); generic_font_family!(CURSIVE, Cursive); generic_font_family!(FANTASY, Fantasy); + #[cfg(feature = "gecko")] generic_font_family!(MOZ_EMOJI, MozEmoji); match generic { @@ -254,6 +261,7 @@ impl FontFamily { GenericFontFamily::Monospace => &*MONOSPACE, GenericFontFamily::Cursive => &*CURSIVE, GenericFontFamily::Fantasy => &*FANTASY, + #[cfg(feature = "gecko")] GenericFontFamily::MozEmoji => &*MOZ_EMOJI, } } @@ -283,7 +291,12 @@ impl ToCss for FontFamily { let mut iter = self.families.iter(); match iter.next() { Some(f) => f.to_css(dest)?, - None => return self.families.fallback.to_css(dest), + None => { + #[cfg(feature = "gecko")] + return self.families.fallback.to_css(dest); + #[cfg(feature = "servo")] + unreachable!(); + }, } for family in iter { dest.write_str(", ")?; @@ -499,6 +512,7 @@ impl SingleFontFamily { } /// A list of font families. +#[cfg(feature = "gecko")] #[derive(Clone, Debug, ToComputedValue, ToResolvedValue, ToShmem, PartialEq, Eq)] #[repr(C)] pub struct FontFamilyList { @@ -508,6 +522,26 @@ pub struct FontFamilyList { pub fallback: GenericFontFamily, } +/// A list of font families. +#[cfg(feature = "servo")] +#[derive( + Clone, + Debug, + Deserialize, + Eq, + Hash, + MallocSizeOf, + PartialEq, + Serialize, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +pub struct FontFamilyList { + /// The actual list of font families specified. + pub list: Box<[SingleFontFamily]>, +} + impl FontFamilyList { /// Return iterator of SingleFontFamily pub fn iter(&self) -> impl Iterator { @@ -515,6 +549,7 @@ impl FontFamilyList { } /// Puts the fallback in the list if needed. + #[cfg(feature = "gecko")] pub fn normalize(&mut self) { if self.fallback == GenericFontFamily::None { return; @@ -527,6 +562,7 @@ impl FontFamilyList { /// If there's a generic font family on the list (which isn't cursive or /// fantasy), then move it to the front of the list. Otherwise, prepend the /// default generic. + #[cfg(feature = "gecko")] pub (crate) fn prioritize_first_generic_or_prepend(&mut self, generic: GenericFontFamily) { let index_of_first_generic = self.iter().position(|f| { match *f { diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 7f3731375a3..385ed8da53c 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -686,7 +686,11 @@ impl FontFamily { pub fn parse_specified<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { let values = input.parse_comma_separated(SingleFontFamily::parse)?; Ok(FontFamily::Values(FontFamilyList { + #[cfg(feature = "gecko")] list: crate::ArcSlice::from_iter(values.into_iter()), + #[cfg(feature = "servo")] + list: values.into_boxed_slice(), + #[cfg(feature = "gecko")] fallback: computed::GenericFontFamily::None, })) } From c9d4f812e56c62035e3736b44489bf62f2c78914 Mon Sep 17 00:00:00 2001 From: Emily McDonough Date: Mon, 22 May 2023 09:50:52 +0200 Subject: [PATCH 37/80] style: Use a computed type for page-size which converts paper sizes to a Size2D Differential Revision: https://phabricator.services.mozilla.com/D115842 --- components/style/values/computed/page.rs | 63 +++++++++++++++++++++++- components/style/values/generics/page.rs | 63 ++++++++++++++---------- 2 files changed, 100 insertions(+), 26 deletions(-) diff --git a/components/style/values/computed/page.rs b/components/style/values/computed/page.rs index d8ef03c1f6d..524f6ba468e 100644 --- a/components/style/values/computed/page.rs +++ b/components/style/values/computed/page.rs @@ -5,10 +5,71 @@ //! Computed @page at-rule properties use crate::values::computed::length::NonNegativeLength; +use crate::values::computed::{Context, ToComputedValue}; use crate::values::generics; use crate::values::generics::size::Size2D; +use crate::values::specified::page as specified; +pub use generics::page::GenericPageSize; pub use generics::page::Orientation; pub use generics::page::PaperSize; + /// Computed value of the @page size descriptor -pub type PageSize = generics::page::GenericPageSize>; +/// +/// The spec says that the computed value should be the same as the specified +/// value but with all absolute units, but it's not currently possibly observe +/// the computed value of page-size. +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss, ToResolvedValue, ToShmem)] +#[repr(C, u8)] +pub enum PageSize { + /// Specified size, paper size, or paper size and orientation. + Size(Size2D), + /// `landscape` or `portrait` value, no specified size. + Orientation(Orientation), + /// `auto` value + Auto, +} + +impl ToComputedValue for specified::PageSize { + type ComputedValue = PageSize; + + fn to_computed_value(&self, ctx: &Context) -> Self::ComputedValue { + match &*self { + Self::Size(s) => PageSize::Size(s.to_computed_value(ctx)), + Self::PaperSizeAndOrientation(p, Orientation::Landscape) => PageSize::Size(Size2D { + width: p.long_edge().to_computed_value(ctx), + height: p.short_edge().to_computed_value(ctx), + }), + Self::PaperSizeAndOrientation(p, Orientation::Portrait) | Self::PaperSize(p) => { + PageSize::Size(Size2D { + width: p.short_edge().to_computed_value(ctx), + height: p.long_edge().to_computed_value(ctx), + }) + }, + Self::Orientation(o) => PageSize::Orientation(*o), + Self::Auto => PageSize::Auto, + } + } + + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + match *computed { + PageSize::Size(s) => Self::Size(ToComputedValue::from_computed_value(&s)), + PageSize::Orientation(o) => Self::Orientation(o), + PageSize::Auto => Self::Auto, + } + } +} + +impl PageSize { + /// `auto` value. + #[inline] + pub fn auto() -> Self { + PageSize::Auto + } + + /// Whether this is the `auto` value. + #[inline] + pub fn is_auto(&self) -> bool { + matches!(*self, PageSize::Auto) + } +} diff --git a/components/style/values/generics/page.rs b/components/style/values/generics/page.rs index 35ffee7b97e..6f561710491 100644 --- a/components/style/values/generics/page.rs +++ b/components/style/values/generics/page.rs @@ -4,22 +4,14 @@ //! @page at-rule properties +use crate::values::generics::NonNegative; +use crate::values::specified::length::AbsoluteLength; + /// Page size names. /// /// https://drafts.csswg.org/css-page-3/#typedef-page-size-page-size #[derive( - Clone, - Copy, - Debug, - Eq, - MallocSizeOf, - Parse, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, + Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, )] #[repr(u8)] pub enum PaperSize { @@ -45,6 +37,39 @@ pub enum PaperSize { Ledger, } +impl PaperSize { + /// Gets the long edge length of the paper size + pub fn long_edge(&self) -> NonNegative { + NonNegative(match *self { + PaperSize::A5 => AbsoluteLength::Mm(210.0), + PaperSize::A4 => AbsoluteLength::Mm(297.0), + PaperSize::A3 => AbsoluteLength::Mm(420.0), + PaperSize::B5 => AbsoluteLength::Mm(250.0), + PaperSize::B4 => AbsoluteLength::Mm(353.0), + PaperSize::JisB5 => AbsoluteLength::Mm(257.0), + PaperSize::JisB4 => AbsoluteLength::Mm(364.0), + PaperSize::Letter => AbsoluteLength::In(11.0), + PaperSize::Legal => AbsoluteLength::In(14.0), + PaperSize::Ledger => AbsoluteLength::In(17.0), + }) + } + /// Gets the short edge length of the paper size + pub fn short_edge(&self) -> NonNegative { + NonNegative(match *self { + PaperSize::A5 => AbsoluteLength::Mm(148.0), + PaperSize::A4 => AbsoluteLength::Mm(210.0), + PaperSize::A3 => AbsoluteLength::Mm(297.0), + PaperSize::B5 => AbsoluteLength::Mm(176.0), + PaperSize::B4 => AbsoluteLength::Mm(250.0), + PaperSize::JisB5 => AbsoluteLength::Mm(182.0), + PaperSize::JisB4 => AbsoluteLength::Mm(257.0), + PaperSize::Letter => AbsoluteLength::In(8.5), + PaperSize::Legal => AbsoluteLength::In(8.5), + PaperSize::Ledger => AbsoluteLength::In(11.0), + }) + } +} + /// Paper orientation /// /// https://drafts.csswg.org/css-page-3/#page-size-prop @@ -57,7 +82,6 @@ pub enum PaperSize { Parse, PartialEq, SpecifiedValueInfo, - ToComputedValue, ToCss, ToResolvedValue, ToShmem, @@ -73,18 +97,7 @@ pub enum Orientation { /// Page size property /// /// https://drafts.csswg.org/css-page-3/#page-size-prop -#[derive( - Clone, - Copy, - Debug, - MallocSizeOf, - PartialEq, - SpecifiedValueInfo, - ToComputedValue, - ToCss, - ToResolvedValue, - ToShmem, -)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] #[repr(C, u8)] pub enum GenericPageSize { /// Page dimensions. From 183ec78be5b927702744352659d7648ce54f6cfb Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Mon, 22 May 2023 09:51:42 +0200 Subject: [PATCH 38/80] style: Implement 'content: none' for ::marker Differential Revision: https://phabricator.services.mozilla.com/D111707 --- components/style/style_adjuster.rs | 5 +++-- components/style/values/resolved/counters.rs | 13 +++++++------ 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index 5fe28e5bc72..a0f1980d31c 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -832,10 +832,11 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { fn adjust_for_marker_pseudo(&mut self) { use crate::values::computed::font::{FontFamily, FontSynthesis}; use crate::values::computed::text::{LetterSpacing, WordSpacing}; + use crate::values::computed::counters::{Content}; let is_legacy_marker = self.style.pseudo.map_or(false, |p| p.is_marker()) && - self.style.get_counters().ineffective_content_property() && - self.style.get_list().clone_list_style_type().is_bullet(); + self.style.get_list().clone_list_style_type().is_bullet() && + self.style.get_counters().clone_content() == Content::Normal; if !is_legacy_marker { return; } diff --git a/components/style/values/resolved/counters.rs b/components/style/values/resolved/counters.rs index bf6490f7401..3bb439a104d 100644 --- a/components/style/values/resolved/counters.rs +++ b/components/style/values/resolved/counters.rs @@ -27,15 +27,16 @@ impl ToResolvedValue for computed::Content { .style .pseudo() .map_or(false, |p| p.is_before_or_after()); + let is_marker = context + .style + .pseudo() + .map_or(false, |p| p.is_marker()); match self { Self::Normal if is_before_or_after => Self::None, - // For now, make `content: none` compute to `normal` on other - // elements, as we don't respect it. - // - // FIXME(emilio, bug 1605473): for marker this should be preserved - // and respected, probably. - Self::None if !is_before_or_after => Self::Normal, + // For now, make `content: none` compute to `normal` for elements + // other than ::before, ::after and ::marker, as we don't respect it. + Self::None if !is_before_or_after && !is_marker => Self::Normal, other => other, } } From d92f66246e5c78b684ff0e640942331e552c94a6 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Mon, 22 May 2023 09:55:31 +0200 Subject: [PATCH 39/80] style: [css-content] Implement 'content: none' for elements Differential Revision: https://phabricator.services.mozilla.com/D114130 --- components/style/values/resolved/counters.rs | 21 ++++++++++---------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/components/style/values/resolved/counters.rs b/components/style/values/resolved/counters.rs index 3bb439a104d..c00e63fda22 100644 --- a/components/style/values/resolved/counters.rs +++ b/components/style/values/resolved/counters.rs @@ -23,20 +23,19 @@ impl ToResolvedValue for computed::Content { #[inline] fn to_resolved_value(self, context: &Context) -> Self { - let is_before_or_after = context - .style - .pseudo() - .map_or(false, |p| p.is_before_or_after()); - let is_marker = context - .style - .pseudo() - .map_or(false, |p| p.is_marker()); - + let (is_pseudo, is_before_or_after, is_marker) = + match context.style.pseudo() { + Some(ref pseudo) => (true, pseudo.is_before_or_after(), pseudo.is_marker()), + None => (false, false, false) + }; match self { Self::Normal if is_before_or_after => Self::None, - // For now, make `content: none` compute to `normal` for elements + // For now, make `content: none` compute to `normal` for pseudos // other than ::before, ::after and ::marker, as we don't respect it. - Self::None if !is_before_or_after && !is_marker => Self::Normal, + // https://github.com/w3c/csswg-drafts/issues/6124 + // Ditto for non-pseudo elements if the pref is disabled. + Self::None if (is_pseudo && !is_before_or_after && !is_marker) || + (!is_pseudo && !static_prefs::pref!("layout.css.element-content-none.enabled")) => Self::Normal, other => other, } } From 2c5aa34bb0cd01e88891985eee08edc40118dada Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 10:46:14 +0200 Subject: [PATCH 40/80] Further changes required by Servo --- components/style/values/resolved/counters.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/components/style/values/resolved/counters.rs b/components/style/values/resolved/counters.rs index c00e63fda22..cdaebcdea3e 100644 --- a/components/style/values/resolved/counters.rs +++ b/components/style/values/resolved/counters.rs @@ -7,6 +7,14 @@ use super::{Context, ToResolvedValue}; use crate::values::computed; +#[inline] +fn allow_element_content_none() -> bool { + #[cfg(feature = "gecko")] + return static_prefs::pref!("layout.css.element-content-none.enabled"); + #[cfg(feature = "servo")] + return false; +} + /// https://drafts.csswg.org/css-content/#content-property /// /// We implement this at resolved value time because otherwise it causes us to @@ -35,7 +43,7 @@ impl ToResolvedValue for computed::Content { // https://github.com/w3c/csswg-drafts/issues/6124 // Ditto for non-pseudo elements if the pref is disabled. Self::None if (is_pseudo && !is_before_or_after && !is_marker) || - (!is_pseudo && !static_prefs::pref!("layout.css.element-content-none.enabled")) => Self::Normal, + (!is_pseudo && !allow_element_content_none()) => Self::Normal, other => other, } } From f81ffda69d550e041a0bb549a1e81b4c4b76507e Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 22 May 2023 09:56:09 +0200 Subject: [PATCH 41/80] style: Clamp perspective() values to a minimum of 1px Differential Revision: https://phabricator.services.mozilla.com/D118250 --- components/style/values/animated/transform.rs | 4 ++-- components/style/values/generics/transform.rs | 11 ++--------- 2 files changed, 4 insertions(+), 11 deletions(-) diff --git a/components/style/values/animated/transform.rs b/components/style/values/animated/transform.rs index 621ae60084d..a204ec2be2e 100644 --- a/components/style/values/animated/transform.rs +++ b/components/style/values/animated/transform.rs @@ -1204,8 +1204,8 @@ impl ComputeSquaredDistance for ComputedTransformOperation { // FIXME(emilio): Is this right? Why interpolating this with // Perspective but not with anything else? let mut p_matrix = Matrix3D::identity(); - if p.px() > 0. { - p_matrix.m34 = -1. / p.px(); + if p.px() >= 0. { + p_matrix.m34 = -1. / p.px().max(1.); } p_matrix.compute_squared_distance(&m) }, diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 4d1df3d58ea..9669d44f1a2 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -583,17 +583,10 @@ impl Transform { /// Return the transform matrix from a perspective length. #[inline] pub fn create_perspective_matrix(d: CSSFloat) -> Transform3D { - // TODO(gw): The transforms spec says that perspective length must - // be positive. However, there is some confusion between the spec - // and browser implementations as to handling the case of 0 for the - // perspective value. Until the spec bug is resolved, at least ensure - // that a provided perspective value of <= 0.0 doesn't cause panics - // and behaves as it does in other browsers. - // See https://lists.w3.org/Archives/Public/www-style/2016Jan/0020.html for more details. - if d <= 0.0 { + if d < 0.0 { Transform3D::identity() } else { - Transform3D::perspective(d) + Transform3D::perspective(d.max(1.)) } } From 58e9ee4d1e5cc1de64ae6e4879568244f6205345 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 09:59:34 +0200 Subject: [PATCH 42/80] style: Make get_shorthand_appendable_value less generic This will allow to save some codesize from longhands_to_css. Differential Revision: https://phabricator.services.mozilla.com/D118834 --- .../style/properties/declaration_block.rs | 36 +++++++------------ .../style/properties/properties.mako.rs | 33 +++++++---------- 2 files changed, 26 insertions(+), 43 deletions(-) diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 6b05d7ab885..3d10db6c7da 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -385,7 +385,7 @@ impl PropertyDeclarationBlock { // Step 1.2.3 // 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()) { + match shorthand.get_shorthand_appendable_value(&list) { Some(appendable_value) => append_declaration_value(dest, appendable_value), None => return Ok(()), } @@ -911,9 +911,6 @@ impl PropertyDeclarationBlock { /// /// https://drafts.csswg.org/cssom/#serialize-a-css-declaration-block pub fn to_css(&self, dest: &mut CssStringWriter) -> fmt::Result { - use std::iter::Cloned; - use std::slice; - let mut is_first_serialization = true; // trailing serializations should have a prepended space // Step 1 -> dest = result list @@ -938,7 +935,7 @@ impl PropertyDeclarationBlock { // properties in a declaration block, and that custom // properties can't be part of a shorthand, we can just care // about them here. - append_serialization::>, _>( + append_serialization( dest, &property, AppendableValue::Declaration(declaration), @@ -992,7 +989,7 @@ impl PropertyDeclarationBlock { // Step 3.4.3: // Let current longhands be an empty array. - let mut current_longhands = SmallVec::<[_; 10]>::new(); + let mut current_longhands = SmallVec::<[&_; 10]>::new(); let mut logical_groups = LogicalGroupSet::new(); let mut saw_one = false; let mut logical_mismatch = false; @@ -1066,7 +1063,7 @@ impl PropertyDeclarationBlock { // 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()) + .get_shorthand_appendable_value(¤t_longhands) { None => continue, Some(appendable_value) => appendable_value, @@ -1109,7 +1106,7 @@ impl PropertyDeclarationBlock { // // 3.4.10: // Append serialized declaration to list. - append_serialization::>, _>( + append_serialization( dest, &shorthand, value, @@ -1145,7 +1142,7 @@ impl PropertyDeclarationBlock { // its important flag set. // // Append serialized declaration to list. - append_serialization::>, _>( + append_serialization( dest, &property, AppendableValue::Declaration(declaration), @@ -1165,17 +1162,14 @@ 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, -{ +pub enum AppendableValue<'a, 'b: 'a> { /// A given declaration, of which we'll serialize just the value. Declaration(&'a PropertyDeclaration), /// A set of declarations for a given shorthand. /// /// FIXME: This needs more docs, where are the shorthands expanded? We print /// the property name before-hand, don't we? - DeclarationsForShorthand(ShorthandId, I), + DeclarationsForShorthand(ShorthandId, &'a [&'b PropertyDeclaration]), /// A raw CSS string, coming for example from a property with CSS variables, /// or when storing a serialized shorthand value before appending directly. Css(&'a str), @@ -1195,13 +1189,10 @@ where } /// Append a given kind of appendable value to a serialization. -pub fn append_declaration_value<'a, I>( +pub fn append_declaration_value<'a, 'b: 'a>( dest: &mut CssStringWriter, - appendable_value: AppendableValue<'a, I>, -) -> fmt::Result -where - I: Iterator, -{ + appendable_value: AppendableValue<'a, 'b>, +) -> fmt::Result { match appendable_value { AppendableValue::Css(css) => dest.write_str(css), AppendableValue::Declaration(decl) => decl.to_css(dest), @@ -1212,15 +1203,14 @@ where } /// Append a given property and value pair to a serialization. -pub fn append_serialization<'a, I, N>( +pub fn append_serialization<'a, 'b: 'a, N>( dest: &mut CssStringWriter, property_name: &N, - appendable_value: AppendableValue<'a, I>, + appendable_value: AppendableValue<'a, 'b>, importance: Importance, is_first_serialization: &mut bool, ) -> fmt::Result where - I: Iterator, N: ToCss, { handle_first_serialization(dest, is_first_serialization)?; diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index dc48eed7608..474b3339170 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1471,15 +1471,17 @@ impl ShorthandId { /// /// Returns an error if writing to the stream fails, or if the declarations /// do not map to a shorthand. - pub fn longhands_to_css<'a, W, I>( + pub fn longhands_to_css( &self, - declarations: I, + declarations: &[&PropertyDeclaration], dest: &mut CssWriter, ) -> fmt::Result where W: Write, - I: Iterator, { + // TODO(emilio): Save codesize here by using a lookup table on + // ShorthandId instead. + let declarations = declarations.iter().cloned(); match *self { ShorthandId::All => { // No need to try to serialize the declarations as the 'all' @@ -1502,25 +1504,16 @@ impl ShorthandId { /// Finds and returns an appendable value for the given declarations. /// /// Returns the optional appendable value. - pub fn get_shorthand_appendable_value<'a, I>( + pub fn get_shorthand_appendable_value<'a, 'b: 'a>( self, - declarations: I, - ) -> Option> - where - I: IntoIterator, - I::IntoIter: Clone, - { - let declarations = declarations.into_iter(); - - // Only cloning iterators (a few pointers each) not declarations. - let mut declarations2 = declarations.clone(); - let mut declarations3 = declarations.clone(); - - let first_declaration = declarations2.next()?; + declarations: &'a [&'b PropertyDeclaration], + ) -> Option> { + let first_declaration = declarations.get(0)?; + let rest = || declarations.iter().skip(1); // https://drafts.csswg.org/css-variables/#variables-in-shorthands if let Some(css) = first_declaration.with_variables_from_shorthand(self) { - if declarations2.all(|d| d.with_variables_from_shorthand(self) == Some(css)) { + if rest().all(|d| d.with_variables_from_shorthand(self) == Some(css)) { return Some(AppendableValue::Css(css)); } return None; @@ -1528,7 +1521,7 @@ impl ShorthandId { // Check whether they are all the same CSS-wide keyword. if let Some(keyword) = first_declaration.get_css_wide_keyword() { - if declarations2.all(|d| d.get_css_wide_keyword() == Some(keyword)) { + if rest().all(|d| d.get_css_wide_keyword() == Some(keyword)) { return Some(AppendableValue::Css(keyword.to_str())) } return None; @@ -1540,7 +1533,7 @@ impl ShorthandId { } // Check whether all declarations can be serialized as part of shorthand. - if declarations3.all(|d| d.may_serialize_as_part_of_shorthand()) { + if declarations.iter().all(|d| d.may_serialize_as_part_of_shorthand()) { return Some(AppendableValue::DeclarationsForShorthand(self, declarations)); } From 85b7a60a6994818d742881811e9e08d200e5fa42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 10:00:33 +0200 Subject: [PATCH 43/80] style: Reduce code size of shorthand serialization Differential Revision: https://phabricator.services.mozilla.com/D118835 --- .../style/properties/declaration_block.rs | 2 +- components/style/properties/helpers.mako.rs | 17 ++++-- .../style/properties/properties.mako.rs | 60 +++++++++---------- 3 files changed, 39 insertions(+), 40 deletions(-) diff --git a/components/style/properties/declaration_block.rs b/components/style/properties/declaration_block.rs index 3d10db6c7da..980d3de11ff 100644 --- a/components/style/properties/declaration_block.rs +++ b/components/style/properties/declaration_block.rs @@ -1197,7 +1197,7 @@ pub fn append_declaration_value<'a, 'b: 'a>( AppendableValue::Css(css) => dest.write_str(css), AppendableValue::Declaration(decl) => decl.to_css(dest), AppendableValue::DeclarationsForShorthand(shorthand, decls) => { - shorthand.longhands_to_css(decls, &mut CssWriter::new(dest)) + shorthand.longhands_to_css(decls, dest) }, } } diff --git a/components/style/properties/helpers.mako.rs b/components/style/properties/helpers.mako.rs index ecd714cebfc..e46024feba1 100644 --- a/components/style/properties/helpers.mako.rs +++ b/components/style/properties/helpers.mako.rs @@ -845,10 +845,7 @@ impl<'a> LonghandsToSerialize<'a> { /// Tries to get a serializable set of longhands given a set of /// property declarations. - pub fn from_iter(iter: I) -> Result - where - I: Iterator, - { + pub fn from_iter(iter: impl Iterator) -> Result { // Define all of the expected variables that correspond to the shorthand % for sub_property in shorthand.sub_properties: let mut ${sub_property.ident} = @@ -856,8 +853,8 @@ % endfor // Attempt to assign the incoming declarations to the expected variables - for longhand in iter { - match *longhand { + for declaration in iter { + match *declaration { % for sub_property in shorthand.sub_properties: PropertyDeclaration::${sub_property.camel_case}(ref value) => { ${sub_property.ident} = Some(value) @@ -918,6 +915,14 @@ }) } + /// Try to serialize a given shorthand to a string. + pub fn to_css(declarations: &[&PropertyDeclaration], dest: &mut crate::str::CssStringWriter) -> fmt::Result { + match LonghandsToSerialize::from_iter(declarations.iter().cloned()) { + Ok(longhands) => longhands.to_css(&mut CssWriter::new(dest)), + Err(_) => Ok(()) + } + } + ${caller.body()} } % endif diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 474b3339170..7b69f23db9e 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1471,34 +1471,31 @@ impl ShorthandId { /// /// Returns an error if writing to the stream fails, or if the declarations /// do not map to a shorthand. - pub fn longhands_to_css( + pub fn longhands_to_css( &self, declarations: &[&PropertyDeclaration], - dest: &mut CssWriter, - ) -> fmt::Result - where - W: Write, - { - // TODO(emilio): Save codesize here by using a lookup table on - // ShorthandId instead. - let declarations = declarations.iter().cloned(); - match *self { - ShorthandId::All => { - // No need to try to serialize the declarations as the 'all' - // shorthand, since it only accepts CSS-wide keywords (and - // variable references), which will be handled in - // get_shorthand_appendable_value. - Ok(()) - } - % for property in data.shorthands_except_all(): - ShorthandId::${property.camel_case} => { - match shorthands::${property.ident}::LonghandsToSerialize::from_iter(declarations) { - Ok(longhands) => longhands.to_css(dest), - Err(_) => Ok(()) - } - }, - % endfor + dest: &mut CssStringWriter, + ) -> fmt::Result { + type LonghandsToCssFn = for<'a, 'b> fn(&'a [&'b PropertyDeclaration], &mut CssStringWriter) -> fmt::Result; + fn all_to_css(_: &[&PropertyDeclaration], _: &mut CssStringWriter) -> fmt::Result { + // No need to try to serialize the declarations as the 'all' + // shorthand, since it only accepts CSS-wide keywords (and variable + // references), which will be handled in + // get_shorthand_appendable_value. + Ok(()) } + + static LONGHANDS_TO_CSS: [LonghandsToCssFn; ${len(data.shorthands)}] = [ + % for shorthand in data.shorthands: + % if shorthand.ident == "all": + all_to_css, + % else: + shorthands::${shorthand.ident}::to_css, + % endif + % endfor + ]; + + LONGHANDS_TO_CSS[*self as usize](declarations, dest) } /// Finds and returns an appendable value for the given declarations. @@ -1591,23 +1588,20 @@ impl ShorthandId { input: &mut Parser<'i, 't>, ) -> Result<(), ParseError<'i>>; - fn unreachable<'i, 't>( + fn parse_all<'i, 't>( _: &mut SourcePropertyDeclaration, _: &ParserContext, - _: &mut Parser<'i, 't> + input: &mut Parser<'i, 't> ) -> Result<(), ParseError<'i>> { - unreachable!() + // 'all' accepts no value other than CSS-wide keywords + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } - // 'all' accepts no value other than CSS-wide keywords - if *self == ShorthandId::All { - return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } static PARSE_INTO: [ParseIntoFn; ${len(data.shorthands)}] = [ % for shorthand in data.shorthands: % if shorthand.ident == "all": - unreachable, + parse_all, % else: shorthands::${shorthand.ident}::parse_into, % endif From 25edb3c21bda1a98bca34942d8128b951f6476aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 10:01:09 +0200 Subject: [PATCH 44/80] style: More fine-grained viewport units invalidation This should speed up window resize significantly. Differential Revision: https://phabricator.services.mozilla.com/D118878 --- components/style/data.rs | 19 +++++++ .../invalidation/element/restyle_hints.rs | 7 ++- components/style/invalidation/mod.rs | 1 + .../style/invalidation/viewport_units.rs | 57 +++++++++++++++++++ .../style/properties/computed_value_flags.rs | 3 + components/style/values/computed/length.rs | 2 + 6 files changed, 88 insertions(+), 1 deletion(-) create mode 100644 components/style/invalidation/viewport_units.rs diff --git a/components/style/data.rs b/components/style/data.rs index 76d64956f19..f486b24dc58 100644 --- a/components/style/data.rs +++ b/components/style/data.rs @@ -175,6 +175,25 @@ impl ElementStyles { self.primary().get_box().clone_display().is_none() } + /// Whether this element uses viewport units. + pub fn uses_viewport_units(&self) -> bool { + use crate::computed_value_flags::ComputedValueFlags; + + if self.primary().flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) { + return true; + } + + for pseudo_style in self.pseudos.as_array() { + if let Some(ref pseudo_style) = pseudo_style { + if pseudo_style.flags.intersects(ComputedValueFlags::USES_VIEWPORT_UNITS) { + return true; + } + } + } + + false + } + #[cfg(feature = "gecko")] fn size_of_excluding_cvs(&self, _ops: &mut MallocSizeOfOps) -> usize { // As the method name suggests, we don't measures the ComputedValues diff --git a/components/style/invalidation/element/restyle_hints.rs b/components/style/invalidation/element/restyle_hints.rs index c0bf2424d52..c423d853905 100644 --- a/components/style/invalidation/element/restyle_hints.rs +++ b/components/style/invalidation/element/restyle_hints.rs @@ -60,7 +60,12 @@ impl RestyleHint { /// Returns whether this hint invalidates the element and all its /// descendants. pub fn contains_subtree(&self) -> bool { - self.contains(RestyleHint::RESTYLE_SELF | RestyleHint::RESTYLE_DESCENDANTS) + self.contains(Self::restyle_subtree()) + } + + /// Returns whether we'll recascade all of the descendants. + pub fn will_recascade_subtree(&self) -> bool { + self.contains_subtree() || self.contains(Self::recascade_subtree()) } /// Returns whether we need to restyle this element. diff --git a/components/style/invalidation/mod.rs b/components/style/invalidation/mod.rs index a59d9474b0a..12b0d06853b 100644 --- a/components/style/invalidation/mod.rs +++ b/components/style/invalidation/mod.rs @@ -7,3 +7,4 @@ pub mod element; pub mod media_queries; pub mod stylesheets; +pub mod viewport_units; diff --git a/components/style/invalidation/viewport_units.rs b/components/style/invalidation/viewport_units.rs new file mode 100644 index 00000000000..acf8b095f9f --- /dev/null +++ b/components/style/invalidation/viewport_units.rs @@ -0,0 +1,57 @@ +/* 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/. */ + +//! Invalidates style of all elements that depend on viewport units. + +use crate::dom::{TElement, TNode}; +use crate::invalidation::element::restyle_hints::RestyleHint; + +/// Invalidates style of all elements that depend on viewport units. +/// +/// Returns whether any element was invalidated. +pub fn invalidate(root: E) -> bool +where + E: TElement, +{ + debug!("invalidation::viewport_units::invalidate({:?})", root); + invalidate_recursively(root) +} + +fn invalidate_recursively(element: E) -> bool +where + E: TElement, +{ + let mut data = match element.mutate_data() { + Some(data) => data, + None => return false, + }; + + if data.hint.will_recascade_subtree() { + debug!("invalidate_recursively: {:?} was already invalid", element); + return false; + } + + let uses_viewport_units = data.styles.uses_viewport_units(); + if uses_viewport_units { + debug!("invalidate_recursively: {:?} uses viewport units", element); + data.hint.insert(RestyleHint::RECASCADE_SELF); + } + + let mut any_children_invalid = false; + for child in element.traversal_children() { + if let Some(child) = child.as_element() { + any_children_invalid |= invalidate_recursively(child); + } + } + + if any_children_invalid { + debug!( + "invalidate_recursively: Children of {:?} changed, setting dirty descendants", + element + ); + unsafe { element.set_dirty_descendants() } + } + + uses_viewport_units || any_children_invalid +} diff --git a/components/style/properties/computed_value_flags.rs b/components/style/properties/computed_value_flags.rs index b3e5fe4f7f9..0942bbd0d13 100644 --- a/components/style/properties/computed_value_flags.rs +++ b/components/style/properties/computed_value_flags.rs @@ -101,6 +101,9 @@ bitflags! { /// Whether there are author-specified rules for `word-spacing`. const HAS_AUTHOR_SPECIFIED_WORD_SPACING = 1 << 19; + + /// Whether the style depends on viewport units. + const USES_VIEWPORT_UNITS = 1 << 20; } } diff --git a/components/style/values/computed/length.rs b/components/style/values/computed/length.rs index 3f8c04abaab..3c4f7a2dbdc 100644 --- a/components/style/values/computed/length.rs +++ b/components/style/values/computed/length.rs @@ -5,6 +5,7 @@ //! `` computed values, and related ones. use super::{Context, Number, ToComputedValue}; +use crate::computed_value_flags::ComputedValueFlags; use crate::values::animated::ToAnimatedValue; use crate::values::computed::NonNegativeNumber; use crate::values::generics::length as generics; @@ -36,6 +37,7 @@ impl ToComputedValue for specified::NoCalcLength { length.to_computed_value(context, FontBaseSize::CurrentStyle) }, specified::NoCalcLength::ViewportPercentage(length) => { + context.builder.add_flags(ComputedValueFlags::USES_VIEWPORT_UNITS); length.to_computed_value(context.viewport_size_for_viewport_unit_resolution()) }, specified::NoCalcLength::ServoCharacterWidth(length) => { From 695ff236c81e7fc7c4f73db35ce12b3dcce40fb6 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Mon, 22 May 2023 10:01:51 +0200 Subject: [PATCH 45/80] style: Update font-size-adjust keywords to match CSSWG resolution in csswg-drafts/#6288 Differential Revision: https://phabricator.services.mozilla.com/D118198 --- components/style/values/generics/font.rs | 22 +++++++++++++--------- components/style/values/specified/font.rs | 13 +++++++------ 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/components/style/values/generics/font.rs b/components/style/values/generics/font.rs index 02f91068d38..a88df7be173 100644 --- a/components/style/values/generics/font.rs +++ b/components/style/values/generics/font.rs @@ -207,6 +207,7 @@ pub enum FontStyle { /// /// https://www.w3.org/TR/css-fonts-4/#font-size-adjust-prop /// https://github.com/w3c/csswg-drafts/issues/6160 +/// https://github.com/w3c/csswg-drafts/issues/6288 #[allow(missing_docs)] #[repr(u8)] #[derive( @@ -228,14 +229,16 @@ pub enum FontStyle { pub enum GenericFontSizeAdjust { #[animation(error)] None, - // 'ex' is the implied basis, so the keyword can be omitted - Ex(Number), + // 'ex-height' is the implied basis, so the keyword can be omitted + ExHeight(Number), #[value_info(starts_with_keyword)] - Cap(Number), + CapHeight(Number), #[value_info(starts_with_keyword)] - Ch(Number), + ChWidth(Number), #[value_info(starts_with_keyword)] - Ic(Number), + IcWidth(Number), + #[value_info(starts_with_keyword)] + IcHeight(Number), } impl ToCss for GenericFontSizeAdjust { @@ -245,10 +248,11 @@ impl ToCss for GenericFontSizeAdjust { { let (prefix, value) = match self { Self::None => return dest.write_str("none"), - Self::Ex(v) => ("", v), - Self::Cap(v) => ("cap ", v), - Self::Ch(v) => ("ch ", v), - Self::Ic(v) => ("ic ", v), + Self::ExHeight(v) => ("", v), + Self::CapHeight(v) => ("cap-height ", v), + Self::ChWidth(v) => ("ch-width ", v), + Self::IcWidth(v) => ("ic-width ", v), + Self::IcHeight(v) => ("ic-height ", v), }; dest.write_str(prefix)?; diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 385ed8da53c..9b417a410c6 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -794,10 +794,11 @@ impl Parse for FontSizeAdjust { let basis = match_ignore_ascii_case! { &ident, "none" => return Ok(FontSizeAdjust::none()), // Check for size adjustment basis keywords if enabled. - "ex" if basis_enabled => GenericFontSizeAdjust::Ex, - "cap" if basis_enabled => GenericFontSizeAdjust::Cap, - "ch" if basis_enabled => GenericFontSizeAdjust::Ch, - "ic" if basis_enabled => GenericFontSizeAdjust::Ic, + "ex-height" if basis_enabled => GenericFontSizeAdjust::ExHeight, + "cap-height" if basis_enabled => GenericFontSizeAdjust::CapHeight, + "ch-width" if basis_enabled => GenericFontSizeAdjust::ChWidth, + "ic-width" if basis_enabled => GenericFontSizeAdjust::IcWidth, + "ic-height" if basis_enabled => GenericFontSizeAdjust::IcHeight, // Unknown (or disabled) keyword. _ => return Err(location.new_custom_error( ::selectors::parser::SelectorParseErrorKind::UnexpectedIdent(ident) @@ -806,9 +807,9 @@ impl Parse for FontSizeAdjust { let value = NonNegativeNumber::parse(context, input)?; return Ok(FontSizeAdjust::Value(basis(value))); } - // Without a basis keyword, the number refers to the 'ex' metric. + // Without a basis keyword, the number refers to the 'ex-height' metric. let value = NonNegativeNumber::parse(context, input)?; - Ok(FontSizeAdjust::Value(GenericFontSizeAdjust::Ex(value))) + Ok(FontSizeAdjust::Value(GenericFontSizeAdjust::ExHeight(value))) } } From 1918c1c2034ca0ac75744bfa08c53ddfc8fb1caf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 10:03:20 +0200 Subject: [PATCH 46/80] style: Inline GeckoNode::prev_sibling It's very hot when matching some kind of selectors like the ones in bug 1717267, and the two function calls show up in the profiles. Differential Revision: https://phabricator.services.mozilla.com/D119505 --- components/style/dom.rs | 2 +- components/style/gecko/wrapper.rs | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/components/style/dom.rs b/components/style/dom.rs index c70a8fd26be..c85ff1edaff 100644 --- a/components/style/dom.rs +++ b/components/style/dom.rs @@ -151,7 +151,7 @@ pub trait TNode: Sized + Copy + Clone + Debug + NodeInfo + PartialEq { /// Get this node's first child. fn first_child(&self) -> Option; - /// Get this node's first child. + /// Get this node's last child. fn last_child(&self) -> Option; /// Get this node's previous sibling. diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs index 3f23981a823..476e710795d 100644 --- a/components/style/gecko/wrapper.rs +++ b/components/style/gecko/wrapper.rs @@ -409,9 +409,11 @@ impl<'ln> TNode for GeckoNode<'ln> { #[inline] fn prev_sibling(&self) -> Option { unsafe { - bindings::Gecko_GetPreviousSibling(self.0) - .as_ref() - .map(GeckoNode) + let prev_or_last = GeckoNode::from_content(self.0.mPreviousOrLastSibling.as_ref()?); + if prev_or_last.0.mNextSibling.raw::().is_null() { + return None; + } + Some(prev_or_last) } } From d7d407a9ae253e8014f824dc6d07e4e168b351de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 10:04:21 +0200 Subject: [PATCH 47/80] style: Fix mixed indentation in style_adjuster.rs Differential Revision: https://phabricator.services.mozilla.com/D119579 --- components/style/style_adjuster.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index a0f1980d31c..e9c82f60d0e 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -836,7 +836,7 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { let is_legacy_marker = self.style.pseudo.map_or(false, |p| p.is_marker()) && self.style.get_list().clone_list_style_type().is_bullet() && - self.style.get_counters().clone_content() == Content::Normal; + self.style.get_counters().clone_content() == Content::Normal; if !is_legacy_marker { return; } From 2634ad10de643e9c6ff93bbec4e8941d10b0ce75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 10:05:08 +0200 Subject: [PATCH 48/80] style: Blockify outside markers at used value time rather than at computed value time Trusting the display value in style_adjuster is wrong, as some elements force a given kind of frame (like
    ). Differential Revision: https://phabricator.services.mozilla.com/D119609 --- components/style/style_adjuster.rs | 13 ------------- 1 file changed, 13 deletions(-) diff --git a/components/style/style_adjuster.rs b/components/style/style_adjuster.rs index e9c82f60d0e..5e66e91e894 100644 --- a/components/style/style_adjuster.rs +++ b/components/style/style_adjuster.rs @@ -232,9 +232,6 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { where E: TElement, { - #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))] - use crate::computed_values::list_style_position::T as ListStylePosition; - let mut blockify = false; macro_rules! blockify_if { ($if_what:expr) => { @@ -254,16 +251,6 @@ impl<'a, 'b: 'a> StyleAdjuster<'a, 'b> { blockify_if!(self.style.is_floating()); blockify_if!(self.style.is_absolutely_positioned()); - #[cfg(any(feature = "servo-layout-2013", feature = "gecko"))] - blockify_if!( - self.style.pseudo.map_or(false, |p| p.is_marker()) && - self.style.get_parent_list().clone_list_style_position() == - ListStylePosition::Outside && - !layout_parent_style - .get_box() - .clone_display() - .is_inline_flow() - ); if !blockify { return; From c0a2b99c4f55d086c294e0d54eff0e41a438f22c Mon Sep 17 00:00:00 2001 From: Sonia Singla Date: Mon, 22 May 2023 10:06:31 +0200 Subject: [PATCH 49/80] style: Remove layout.css.prefixes.columns Differential Revision: https://phabricator.services.mozilla.com/D120057 --- components/style/properties/longhands/column.mako.rs | 7 ------- components/style/properties/longhands/position.mako.rs | 1 - components/style/properties/shorthands/column.mako.rs | 2 -- 3 files changed, 10 deletions(-) diff --git a/components/style/properties/longhands/column.mako.rs b/components/style/properties/longhands/column.mako.rs index 2d9a116d30b..747a1c2db0a 100644 --- a/components/style/properties/longhands/column.mako.rs +++ b/components/style/properties/longhands/column.mako.rs @@ -13,7 +13,6 @@ ${helpers.predefined_type( engines="gecko servo-2013 servo-2020", servo_2020_pref="layout.2020.unimplemented", initial_specified_value="specified::length::NonNegativeLengthOrAuto::auto()", - extra_prefixes="moz:layout.css.prefixes.columns", animation_value_type="NonNegativeLengthOrAuto", servo_2013_pref="layout.columns.enabled", spec="https://drafts.csswg.org/css-multicol/#propdef-column-width", @@ -29,7 +28,6 @@ ${helpers.predefined_type( initial_specified_value="specified::ColumnCount::auto()", servo_2013_pref="layout.columns.enabled", animation_value_type="AnimatedColumnCount", - extra_prefixes="moz:layout.css.prefixes.columns", spec="https://drafts.csswg.org/css-multicol/#propdef-column-count", servo_restyle_damage="rebuild_and_reflow", )} @@ -38,7 +36,6 @@ ${helpers.single_keyword( "column-fill", "balance auto", engines="gecko", - extra_prefixes="moz:layout.css.prefixes.columns", animation_value_type="discrete", gecko_enum_prefix="StyleColumnFill", spec="https://drafts.csswg.org/css-multicol/#propdef-column-fill", @@ -53,7 +50,6 @@ ${helpers.predefined_type( computed_type="crate::values::computed::NonNegativeLength", spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-width", animation_value_type="NonNegativeLength", - extra_prefixes="moz:layout.css.prefixes.columns", )} // https://drafts.csswg.org/css-multicol-1/#crc @@ -64,7 +60,6 @@ ${helpers.predefined_type( engines="gecko", initial_specified_value="specified::Color::currentcolor()", animation_value_type="AnimatedColor", - extra_prefixes="moz:layout.css.prefixes.columns", ignored_when_colors_disabled=True, spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-color", )} @@ -76,7 +71,6 @@ ${helpers.single_keyword( animation_value_type="discrete", gecko_enum_prefix="StyleColumnSpan", spec="https://drafts.csswg.org/css-multicol/#propdef-column-span", - extra_prefixes="moz:layout.css.prefixes.columns", )} ${helpers.predefined_type( @@ -85,7 +79,6 @@ ${helpers.predefined_type( "computed::BorderStyle::None", engines="gecko", initial_specified_value="specified::BorderStyle::None", - extra_prefixes="moz:layout.css.prefixes.columns", animation_value_type="discrete", spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule-style", )} diff --git a/components/style/properties/longhands/position.mako.rs b/components/style/properties/longhands/position.mako.rs index 1795bde7e5f..7ca7772b9c7 100644 --- a/components/style/properties/longhands/position.mako.rs +++ b/components/style/properties/longhands/position.mako.rs @@ -434,7 +434,6 @@ ${helpers.predefined_type( "computed::length::NonNegativeLengthPercentageOrNormal::normal()", engines="gecko servo-2013", aliases="grid-column-gap" if engine == "gecko" else "", - extra_prefixes="moz:layout.css.prefixes.columns", servo_2013_pref="layout.columns.enabled", spec="https://drafts.csswg.org/css-align-3/#propdef-column-gap", animation_value_type="NonNegativeLengthPercentageOrNormal", diff --git a/components/style/properties/shorthands/column.mako.rs b/components/style/properties/shorthands/column.mako.rs index e7c775dff04..2fc8b72fae9 100644 --- a/components/style/properties/shorthands/column.mako.rs +++ b/components/style/properties/shorthands/column.mako.rs @@ -9,7 +9,6 @@ sub_properties="column-width column-count" servo_2013_pref="layout.columns.enabled", derive_serialize="True" - extra_prefixes="moz:layout.css.prefixes.columns" spec="https://drafts.csswg.org/css-multicol/#propdef-columns"> use crate::properties::longhands::{column_count, column_width}; @@ -60,7 +59,6 @@ <%helpers:shorthand name="column-rule" engines="gecko" - extra_prefixes="moz:layout.css.prefixes.columns" sub_properties="column-rule-width column-rule-style column-rule-color" derive_serialize="True" spec="https://drafts.csswg.org/css-multicol/#propdef-column-rule" From 8f4d78295272ad59d9fa90c294e5f3d6fdc93c83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 10:07:21 +0200 Subject: [PATCH 50/80] style: Don't EnsureUniqueInner from the cssRules getter Instead, fix up the various content data structures when the stylesheet is mutated. This makes reading a stylesheet not disable style sharing. Differential Revision: https://phabricator.services.mozilla.com/D115203 --- components/style/gecko/data.rs | 9 ++++++++- components/style/stylesheets/import_rule.rs | 8 +++++++- 2 files changed, 15 insertions(+), 2 deletions(-) diff --git a/components/style/gecko/data.rs b/components/style/gecko/data.rs index 0689aa6c0c4..39f7d7cc8d8 100644 --- a/components/style/gecko/data.rs +++ b/components/style/gecko/data.rs @@ -56,10 +56,17 @@ impl GeckoStyleSheet { /// already holds a strong reference. #[inline] pub unsafe fn from_addrefed(s: *const DomStyleSheet) -> Self { - debug_assert!(!s.is_null()); + assert!(!s.is_null()); GeckoStyleSheet(s) } + /// HACK(emilio): This is so that we can avoid crashing release due to + /// bug 1719963 and can hopefully get a useful report from fuzzers. + #[inline] + pub fn hack_is_null(&self) -> bool { + self.0.is_null() + } + /// Get the raw `StyleSheet` that we're wrapping. pub fn raw(&self) -> &DomStyleSheet { unsafe { &*self.0 } diff --git a/components/style/stylesheets/import_rule.rs b/components/style/stylesheets/import_rule.rs index 396be242024..8f518f29bac 100644 --- a/components/style/stylesheets/import_rule.rs +++ b/components/style/stylesheets/import_rule.rs @@ -56,7 +56,13 @@ impl ImportSheet { /// exists. pub fn as_sheet(&self) -> Option<&crate::gecko::data::GeckoStyleSheet> { match *self { - ImportSheet::Sheet(ref s) => Some(s), + ImportSheet::Sheet(ref s) => { + debug_assert!(!s.hack_is_null()); + if s.hack_is_null() { + return None; + } + Some(s) + }, ImportSheet::Pending(_) => None, } } From 45d6e64d51dda49f7d6ba55558d15cb8a9bdba08 Mon Sep 17 00:00:00 2001 From: Sonia Singla Date: Mon, 22 May 2023 10:08:05 +0200 Subject: [PATCH 51/80] style: Remove layout.css.clip-path-path.enabled Differential Revision: https://phabricator.services.mozilla.com/D120235 --- components/style/values/specified/basic_shape.rs | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/components/style/values/specified/basic_shape.rs b/components/style/values/specified/basic_shape.rs index 37aaae2ec2a..3c571ff8e84 100644 --- a/components/style/values/specified/basic_shape.rs +++ b/components/style/values/specified/basic_shape.rs @@ -55,15 +55,6 @@ pub type ShapeRadius = generic::ShapeRadius; /// The specified value of `Polygon` pub type Polygon = generic::GenericPolygon; -#[cfg(feature = "gecko")] -fn is_clip_path_path_enabled(context: &ParserContext) -> bool { - context.chrome_rules_enabled() || static_prefs::pref!("layout.css.clip-path-path.enabled") -} -#[cfg(feature = "servo")] -fn is_clip_path_path_enabled(_: &ParserContext) -> bool { - false -} - /// A helper for both clip-path and shape-outside parsing of shapes. fn parse_shape_or_box<'i, 't, R, ReferenceBox>( context: &ParserContext, @@ -116,10 +107,8 @@ impl Parse for ClipPath { return Ok(ClipPath::None); } - if is_clip_path_path_enabled(context) { - if let Ok(p) = input.try_parse(|i| Path::parse(context, i)) { - return Ok(ClipPath::Path(p)); - } + if let Ok(p) = input.try_parse(|i| Path::parse(context, i)) { + return Ok(ClipPath::Path(p)); } if let Ok(url) = input.try_parse(|i| SpecifiedUrl::parse(context, i)) { From c2a50c92faea6011c4384c3b025750a3dd9e02e7 Mon Sep 17 00:00:00 2001 From: Emily McDonough Date: Mon, 22 May 2023 10:09:22 +0200 Subject: [PATCH 52/80] style: Remove the paper size variant of GenericPageSize and add an implied default to the paper size and orientation variant Differential Revision: https://phabricator.services.mozilla.com/D119915 --- components/style/values/computed/page.rs | 12 +++++------- components/style/values/generics/page.rs | 19 +++++++++++-------- components/style/values/specified/page.rs | 10 +++++----- 3 files changed, 21 insertions(+), 20 deletions(-) diff --git a/components/style/values/computed/page.rs b/components/style/values/computed/page.rs index 524f6ba468e..27b16d0af15 100644 --- a/components/style/values/computed/page.rs +++ b/components/style/values/computed/page.rs @@ -36,16 +36,14 @@ impl ToComputedValue for specified::PageSize { fn to_computed_value(&self, ctx: &Context) -> Self::ComputedValue { match &*self { Self::Size(s) => PageSize::Size(s.to_computed_value(ctx)), - Self::PaperSizeAndOrientation(p, Orientation::Landscape) => PageSize::Size(Size2D { + Self::PaperSize(p, Orientation::Landscape) => PageSize::Size(Size2D { width: p.long_edge().to_computed_value(ctx), height: p.short_edge().to_computed_value(ctx), }), - Self::PaperSizeAndOrientation(p, Orientation::Portrait) | Self::PaperSize(p) => { - PageSize::Size(Size2D { - width: p.short_edge().to_computed_value(ctx), - height: p.long_edge().to_computed_value(ctx), - }) - }, + Self::PaperSize(p, Orientation::Portrait) => PageSize::Size(Size2D { + width: p.short_edge().to_computed_value(ctx), + height: p.long_edge().to_computed_value(ctx), + }), Self::Orientation(o) => PageSize::Orientation(*o), Self::Auto => PageSize::Auto, } diff --git a/components/style/values/generics/page.rs b/components/style/values/generics/page.rs index 6f561710491..1de1a8e912c 100644 --- a/components/style/values/generics/page.rs +++ b/components/style/values/generics/page.rs @@ -94,22 +94,25 @@ pub enum Orientation { Landscape, } +#[inline] +fn is_portrait(orientation: &Orientation) -> bool { + *orientation == Orientation::Portrait +} + /// Page size property /// /// https://drafts.csswg.org/css-page-3/#page-size-prop #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] #[repr(C, u8)] pub enum GenericPageSize { - /// Page dimensions. - Size(S), - /// Paper size with no orientation. - PaperSize(PaperSize), - /// An orientation with no size. - Orientation(Orientation), - /// Paper size by name, with an orientation. - PaperSizeAndOrientation(PaperSize, Orientation), /// `auto` value. Auto, + /// Page dimensions. + Size(S), + /// An orientation with no size. + Orientation(Orientation), + /// Paper size by name + PaperSize(PaperSize, #[css(skip_if = "is_portrait")] Orientation), } pub use self::GenericPageSize as PageSize; diff --git a/components/style/values/specified/page.rs b/components/style/values/specified/page.rs index 81684e114a3..4d96b532689 100644 --- a/components/style/values/specified/page.rs +++ b/components/style/values/specified/page.rs @@ -23,15 +23,15 @@ impl Parse for PageSize { ) -> Result> { // Try to parse as [ ] if let Ok(paper_size) = input.try_parse(PaperSize::parse) { - if let Ok(orientation) = input.try_parse(Orientation::parse) { - return Ok(PageSize::PaperSizeAndOrientation(paper_size, orientation)); - } - return Ok(PageSize::PaperSize(paper_size)); + let orientation = input + .try_parse(Orientation::parse) + .unwrap_or(Orientation::Portrait); + return Ok(PageSize::PaperSize(paper_size, orientation)); } // Try to parse as [ ] if let Ok(orientation) = input.try_parse(Orientation::parse) { if let Ok(paper_size) = input.try_parse(PaperSize::parse) { - return Ok(PageSize::PaperSizeAndOrientation(paper_size, orientation)); + return Ok(PageSize::PaperSize(paper_size, orientation)); } return Ok(PageSize::Orientation(orientation)); } From eca66dba72731b373afca2b8698969b227507e74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 10:11:48 +0200 Subject: [PATCH 53/80] style: Factor PreferenceSheet colors to its own struct This will come handy in the next patch. Depends on D120678 Differential Revision: https://phabricator.services.mozilla.com/D120679 --- components/style/gecko/media_queries.rs | 6 +++--- components/style/values/specified/color.rs | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 5d960a8e9e1..2f5a9673d4c 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -93,7 +93,7 @@ impl Device { document, default_values: ComputedValues::default_values(doc), root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()), - body_text_color: AtomicUsize::new(prefs.mDefaultColor as usize), + body_text_color: AtomicUsize::new(prefs.mColors.mDefault as usize), used_root_font_size: AtomicBool::new(false), used_font_metrics: AtomicBool::new(false), used_viewport_size: AtomicBool::new(false), @@ -387,12 +387,12 @@ impl Device { /// Returns the default background color. pub fn default_background_color(&self) -> RGBA { - convert_nscolor_to_rgba(self.pref_sheet_prefs().mDefaultBackgroundColor) + convert_nscolor_to_rgba(self.pref_sheet_prefs().mColors.mDefaultBackground) } /// Returns the default foreground color. pub fn default_color(&self) -> RGBA { - convert_nscolor_to_rgba(self.pref_sheet_prefs().mDefaultColor) + convert_nscolor_to_rgba(self.pref_sheet_prefs().mColors.mDefault) } /// Returns the current effective text zoom. diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 4016cd1d81e..408dfc99e9a 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -408,14 +408,14 @@ impl SystemColor { fn compute(&self, cx: &Context, scheme: SystemColorScheme) -> ComputedColor { use crate::gecko_bindings::bindings; - let prefs = cx.device().pref_sheet_prefs(); + let colors = &cx.device().pref_sheet_prefs().mColors; convert_nscolor_to_computedcolor(match *self { - SystemColor::Canvastext => prefs.mDefaultColor, - SystemColor::Canvas => prefs.mDefaultBackgroundColor, - SystemColor::Linktext => prefs.mLinkColor, - SystemColor::Activetext => prefs.mActiveLinkColor, - SystemColor::Visitedtext => prefs.mVisitedLinkColor, + SystemColor::Canvastext => colors.mDefault, + SystemColor::Canvas => colors.mDefaultBackground, + SystemColor::Linktext => colors.mLink, + SystemColor::Activetext => colors.mActiveLink, + SystemColor::Visitedtext => colors.mVisitedLink, _ => { let color = unsafe { From 7d1823563e62267a1462e1c1aa4102be2ee5f5ef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 10:13:05 +0200 Subject: [PATCH 54/80] style: Remove layout.css.image-set.enabled We shipped this in 88. Differential Revision: https://phabricator.services.mozilla.com/D120899 --- components/style/values/specified/image.rs | 20 +++----------------- 1 file changed, 3 insertions(+), 17 deletions(-) diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index dae7fe286d0..0e55d18d079 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -81,16 +81,6 @@ fn cross_fade_enabled() -> bool { false } -#[cfg(feature = "gecko")] -fn image_set_enabled() -> bool { - static_prefs::pref!("layout.css.image-set.enabled") -} - -#[cfg(feature = "servo")] -fn image_set_enabled() -> bool { - false -} - impl SpecifiedValueInfo for Gradient { const SUPPORTED_TYPES: u8 = CssType::GRADIENT; @@ -132,9 +122,7 @@ impl SpecifiedValueInfo for generic::ImageSet Date: Mon, 22 May 2023 20:41:42 +0200 Subject: [PATCH 55/80] Further changes required by Servo --- components/style/values/specified/image.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/components/style/values/specified/image.rs b/components/style/values/specified/image.rs index 0e55d18d079..f2167e52800 100644 --- a/components/style/values/specified/image.rs +++ b/components/style/values/specified/image.rs @@ -81,6 +81,16 @@ fn cross_fade_enabled() -> bool { false } +#[cfg(feature = "gecko")] +fn image_set_enabled() -> bool { + true +} + +#[cfg(feature = "servo")] +fn image_set_enabled() -> bool { + false +} + impl SpecifiedValueInfo for Gradient { const SUPPORTED_TYPES: u8 = CssType::GRADIENT; @@ -122,7 +132,9 @@ impl SpecifiedValueInfo for generic::ImageSet Date: Mon, 22 May 2023 10:26:26 +0200 Subject: [PATCH 56/80] style: Add system-ui boilerplate Alias -apple-system to it, and put it behind a pref for now. This is pretty boring (read: uncontroversial hopefully) code. The follow-up work is modifying StaticPresData to look up the fonts using system APIs, probably. Maybe a bit more work if on macOS they can't be named. Differential Revision: https://phabricator.services.mozilla.com/D119984 --- .../style/properties/shorthands/font.mako.rs | 2 +- components/style/values/computed/font.rs | 21 +++++++++--- components/style/values/specified/font.rs | 33 ++++++++----------- 3 files changed, 31 insertions(+), 25 deletions(-) diff --git a/components/style/properties/shorthands/font.mako.rs b/components/style/properties/shorthands/font.mako.rs index 26205c2ea9c..b24711b4aed 100644 --- a/components/style/properties/shorthands/font.mako.rs +++ b/components/style/properties/shorthands/font.mako.rs @@ -137,7 +137,7 @@ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } - let family = FontFamily::parse_specified(input)?; + let family = FontFamily::parse(context, input)?; Ok(expanded! { % for name in "style weight stretch variant_caps".split(): font_${name}: unwrap_or_initial!(font_${name}, ${name}), diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index b944640d8e7..9d7ba40c0bd 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -6,6 +6,7 @@ #[cfg(feature = "gecko")] use crate::gecko_bindings::{bindings, structs}; +use crate::parser::{Parse, ParserContext}; use crate::values::animated::ToAnimatedValue; use crate::values::computed::{ Angle, Context, Integer, Length, NonNegativeLength, NonNegativeNumber, NonNegativePercentage, @@ -250,6 +251,7 @@ impl FontFamily { generic_font_family!(FANTASY, Fantasy); #[cfg(feature = "gecko")] generic_font_family!(MOZ_EMOJI, MozEmoji); + generic_font_family!(SYSTEM_UI, SystemUi); match generic { GenericFontFamily::None => { @@ -263,6 +265,7 @@ impl FontFamily { GenericFontFamily::Fantasy => &*FANTASY, #[cfg(feature = "gecko")] GenericFontFamily::MozEmoji => &*MOZ_EMOJI, + GenericFontFamily::SystemUi => &*SYSTEM_UI, } } } @@ -383,6 +386,10 @@ pub enum SingleFontFamily { Generic(GenericFontFamily), } +fn system_ui_enabled(_: &ParserContext) -> bool { + static_prefs::pref!("layout.css.system-ui.enabled") +} + /// A generic font-family name. /// /// The order here is important, if you change it make sure that @@ -417,15 +424,17 @@ pub enum GenericFontFamily { Monospace, Cursive, Fantasy, + #[parse(aliases = "-apple-system", condition = "system_ui_enabled")] + SystemUi, /// An internal value for emoji font selection. #[css(skip)] #[cfg(feature = "gecko")] MozEmoji, } -impl SingleFontFamily { +impl Parse for SingleFontFamily { /// Parse a font-family value. - pub fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { if let Ok(value) = input.try_parse(|i| i.expect_string_cloned()) { return Ok(SingleFontFamily::FamilyName(FamilyName { name: Atom::from(&*value), @@ -433,11 +442,11 @@ impl SingleFontFamily { })); } - let first_ident = input.expect_ident_cloned()?; - if let Ok(generic) = GenericFontFamily::from_ident(&first_ident) { + if let Ok(generic) = input.try_parse(|i| GenericFontFamily::parse(context, i)) { return Ok(SingleFontFamily::Generic(generic)); } + let first_ident = input.expect_ident_cloned()?; let reserved = match_ignore_ascii_case! { &first_ident, // https://drafts.csswg.org/css-fonts/#propdef-font-family // "Font family names that happen to be the same as a keyword value @@ -480,8 +489,10 @@ impl SingleFontFamily { syntax, })) } +} - #[cfg(feature = "servo")] +#[cfg(feature = "servo")] +impl SingleFontFamily { /// Get the corresponding font-family with Atom pub fn from_atom(input: Atom) -> SingleFontFamily { match input { diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 9b417a410c6..22859d1af1b 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -681,19 +681,6 @@ pub enum FontFamily { impl FontFamily { system_font_methods!(FontFamily, font_family); - - /// Parse a specified font-family value - pub fn parse_specified<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - let values = input.parse_comma_separated(SingleFontFamily::parse)?; - Ok(FontFamily::Values(FontFamilyList { - #[cfg(feature = "gecko")] - list: crate::ArcSlice::from_iter(values.into_iter()), - #[cfg(feature = "servo")] - list: values.into_boxed_slice(), - #[cfg(feature = "gecko")] - fallback: computed::GenericFontFamily::None, - })) - } } impl ToComputedValue for FontFamily { @@ -733,23 +720,31 @@ impl Parse for FontFamily { /// = | [ + ] /// TODO: fn parse<'i, 't>( - _: &ParserContext, + context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - FontFamily::parse_specified(input) + let values = input.parse_comma_separated(|input| SingleFontFamily::parse(context, input))?; + Ok(FontFamily::Values(FontFamilyList { + #[cfg(feature = "gecko")] + list: crate::ArcSlice::from_iter(values.into_iter()), + #[cfg(feature = "servo")] + list: values.into_boxed_slice(), + #[cfg(feature = "gecko")] + fallback: computed::GenericFontFamily::None, + })) } } impl SpecifiedValueInfo for FontFamily {} -/// `FamilyName::parse` is based on `SingleFontFamily::parse` and not the other way around -/// because we want the former to exclude generic family keywords. +/// `FamilyName::parse` is based on `SingleFontFamily::parse` and not the other +/// way around because we want the former to exclude generic family keywords. impl Parse for FamilyName { fn parse<'i, 't>( - _: &ParserContext, + context: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - match SingleFontFamily::parse(input) { + match SingleFontFamily::parse(context, input) { Ok(SingleFontFamily::FamilyName(name)) => Ok(name), Ok(SingleFontFamily::Generic(_)) => { Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) From fd41056ca5f78ebf379c1975c88f508223062760 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 11:03:30 +0200 Subject: [PATCH 57/80] Further changes required by Servo --- components/atoms/static_atoms.txt | 1 + components/canvas/canvas_data.rs | 2 ++ components/gfx/font.rs | 1 + components/style/values/computed/font.rs | 7 ++++++- 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/components/atoms/static_atoms.txt b/components/atoms/static_atoms.txt index bdb16e30e78..8409639055f 100644 --- a/components/atoms/static_atoms.txt +++ b/components/atoms/static_atoms.txt @@ -127,6 +127,7 @@ stroke-opacity storage submit suspend +system-ui tel text time diff --git a/components/canvas/canvas_data.rs b/components/canvas/canvas_data.rs index 31c74f1e7a4..ac00083d44e 100644 --- a/components/canvas/canvas_data.rs +++ b/components/canvas/canvas_data.rs @@ -1387,6 +1387,8 @@ fn to_font_kit_family(font_family: &font::SingleFontFamily) -> FamilyName { font::GenericFontFamily::Monospace => FamilyName::Monospace, font::GenericFontFamily::Fantasy => FamilyName::Fantasy, font::GenericFontFamily::Cursive => FamilyName::Cursive, + // TODO: There is no FontFamily::SystemUi. + font::GenericFontFamily::SystemUi => unreachable!("system-ui should be disabled"), font::GenericFontFamily::None => unreachable!("Shouldn't appear in computed values"), }, } diff --git a/components/gfx/font.rs b/components/gfx/font.rs index d53f6761b66..05ffb897a4e 100644 --- a/components/gfx/font.rs +++ b/components/gfx/font.rs @@ -569,6 +569,7 @@ impl<'a> From<&'a SingleFontFamily> for FontFamilyName { GenericFontFamily::Monospace => atom!("monospace"), GenericFontFamily::Cursive => atom!("cursive"), GenericFontFamily::Fantasy => atom!("fantasy"), + GenericFontFamily::SystemUi => atom!("system-ui"), }), } } diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 9d7ba40c0bd..d4818fb0e97 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -387,7 +387,10 @@ pub enum SingleFontFamily { } fn system_ui_enabled(_: &ParserContext) -> bool { - static_prefs::pref!("layout.css.system-ui.enabled") + #[cfg(feature = "gecko")] + return static_prefs::pref!("layout.css.system-ui.enabled"); + #[cfg(feature = "servo")] + return false; } /// A generic font-family name. @@ -501,6 +504,7 @@ impl SingleFontFamily { atom!("cursive") => return SingleFontFamily::Generic(GenericFontFamily::Cursive), atom!("fantasy") => return SingleFontFamily::Generic(GenericFontFamily::Fantasy), atom!("monospace") => return SingleFontFamily::Generic(GenericFontFamily::Monospace), + atom!("system-ui") => return SingleFontFamily::Generic(GenericFontFamily::SystemUi), _ => {}, } @@ -510,6 +514,7 @@ impl SingleFontFamily { "cursive" => return SingleFontFamily::Generic(GenericFontFamily::Cursive), "fantasy" => return SingleFontFamily::Generic(GenericFontFamily::Fantasy), "monospace" => return SingleFontFamily::Generic(GenericFontFamily::Monospace), + "system-ui" => return SingleFontFamily::Generic(GenericFontFamily::SystemUi), _ => {} } From 028f2f95d2499e4ddbb8ce1e1200d19f73fb5850 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 11:56:02 +0200 Subject: [PATCH 58/80] style: Initial support for the color-scheme CSS property Add initial support for the color-scheme CSS property, allowing pages to choose between light and dark system colors per-element, and such. Things that are left to do so that this can be enabled by default: * Dark system colors on Windows / Android / Standins. * Dark Canvas/CanvasText/Link visited colors (which right now are set via PreferenceSheet). * Dark form controls in nsNativeBasicTheme. * Processing the color-scheme meta tag to fill-in Document::mColorSchemeBits. But this seems like enough progress to be landable on its own. Differential Revision: https://phabricator.services.mozilla.com/D120843 --- .../properties/longhands/inherited_ui.mako.rs | 11 ++ .../style/properties/properties.mako.rs | 3 + components/style/values/computed/color.rs | 2 + components/style/values/computed/mod.rs | 2 +- components/style/values/specified/color.rs | 126 +++++++++++++++++- components/style/values/specified/mod.rs | 2 +- 6 files changed, 143 insertions(+), 3 deletions(-) diff --git a/components/style/properties/longhands/inherited_ui.mako.rs b/components/style/properties/longhands/inherited_ui.mako.rs index f08abbc6235..badcc3f2012 100644 --- a/components/style/properties/longhands/inherited_ui.mako.rs +++ b/components/style/properties/longhands/inherited_ui.mako.rs @@ -95,6 +95,17 @@ ${helpers.predefined_type( has_effect_on_gecko_scrollbars=False, )} +${helpers.predefined_type( + "color-scheme", + "ColorScheme", + "specified::color::ColorScheme::normal()", + engines="gecko", + spec="https://drafts.csswg.org/css-color-adjust/#color-scheme-prop", + gecko_pref="layout.css.color-scheme.enabled", + animation_value_type="discrete", + has_effect_on_gecko_scrollbars=False, +)} + ${helpers.predefined_type( "scrollbar-color", "ui::ScrollbarColor", diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 7b69f23db9e..ae5e4b6afb1 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1376,6 +1376,9 @@ impl LonghandId { LonghandId::FontStyle | LonghandId::FontFamily | + // color-scheme affects how system colors resolve. + LonghandId::ColorScheme | + // Needed to properly compute the writing mode, to resolve logical // properties, and similar stuff. LonghandId::WritingMode | diff --git a/components/style/values/computed/color.rs b/components/style/values/computed/color.rs index 664fed95886..36cd1db4a42 100644 --- a/components/style/values/computed/color.rs +++ b/components/style/values/computed/color.rs @@ -11,6 +11,8 @@ use cssparser::{Color as CSSParserColor, RGBA}; use std::fmt; use style_traits::{CssWriter, ToCss}; +pub use crate::values::specified::color::ColorScheme; + /// The computed value of the `color` property. pub type ColorPropertyValue = RGBA; diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 1098bae1209..c87142ac1b5 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -50,7 +50,7 @@ pub use self::box_::{Display, Overflow, OverflowAnchor, TransitionProperty}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize}; pub use self::box_::{ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStrictness, ScrollSnapType}; pub use self::box_::{TouchAction, VerticalAlign, WillChange}; -pub use self::color::{Color, ColorOrAuto, ColorPropertyValue}; +pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, ColorScheme}; pub use self::column::ColumnCount; pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset}; pub use self::easing::TimingFunction; diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 408dfc99e9a..e4b73f6c0da 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -12,6 +12,7 @@ use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue}; use crate::values::generics::color::{GenericColorOrAuto, GenericCaretColor}; use crate::values::specified::calc::CalcNode; use crate::values::specified::Percentage; +use crate::values::CustomIdent; use cssparser::{AngleOrNumber, Color as CSSParserColor, Parser, Token, RGBA}; use cssparser::{BasicParseErrorKind, NumberOrPercentage, ParseErrorKind}; use itoa; @@ -409,7 +410,10 @@ impl SystemColor { use crate::gecko_bindings::bindings; let colors = &cx.device().pref_sheet_prefs().mColors; + let style_color_scheme = cx.style().get_inherited_ui().clone_color_scheme(); + // TODO: At least Canvas / CanvasText should be color-scheme aware + // (probably the link colors too). convert_nscolor_to_computedcolor(match *self { SystemColor::Canvastext => colors.mDefault, SystemColor::Canvas => colors.mDefaultBackground, @@ -419,7 +423,7 @@ impl SystemColor { _ => { let color = unsafe { - bindings::Gecko_GetLookAndFeelSystemColor(*self as i32, cx.device().document(), scheme) + bindings::Gecko_GetLookAndFeelSystemColor(*self as i32, cx.device().document(), scheme, &style_color_scheme) }; if color == bindings::NS_SAME_AS_FOREGROUND_COLOR { return ComputedColor::currentcolor(); @@ -876,3 +880,123 @@ impl Parse for CaretColor { ColorOrAuto::parse(context, input).map(GenericCaretColor) } } + +bitflags! { + /// Various flags to represent the color-scheme property in an efficient + /// way. + #[derive(Default, MallocSizeOf, SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem)] + #[repr(C)] + #[value_info(other_values = "light,dark,only")] + pub struct ColorSchemeFlags: u8 { + /// Whether the author specified `light`. + const LIGHT = 1 << 0; + /// Whether the author specified `dark`. + const DARK = 1 << 1; + /// Whether the author specified `only`. + const ONLY = 1 << 2; + } +} + +/// +#[derive( + Clone, + Debug, + Default, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +#[repr(C)] +#[value_info(other_values = "normal")] +pub struct ColorScheme { + #[ignore_malloc_size_of = "Arc"] + idents: crate::ArcSlice, + bits: ColorSchemeFlags, +} + +impl ColorScheme { + /// Returns the `normal` value. + pub fn normal() -> Self { + Self { + idents: Default::default(), + bits: ColorSchemeFlags::empty(), + } + } +} + +impl Parse for ColorScheme { + fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + let mut idents = vec![]; + let mut bits = ColorSchemeFlags::empty(); + + let mut location = input.current_source_location(); + while let Ok(ident) = input.try_parse(|i| i.expect_ident_cloned()) { + let mut is_only = false; + match_ignore_ascii_case! { &ident, + "normal" => { + if idents.is_empty() && bits.is_empty() { + return Ok(Self::normal()); + } + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + }, + "light" => bits.insert(ColorSchemeFlags::LIGHT), + "dark" => bits.insert(ColorSchemeFlags::DARK), + "only" => { + if bits.intersects(ColorSchemeFlags::ONLY) { + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + bits.insert(ColorSchemeFlags::ONLY); + is_only = true; + }, + _ => {}, + }; + + if is_only { + if !idents.is_empty() { + // Only is allowed either at the beginning or at the end, + // but not in the middle. + break; + } + } else { + idents.push(CustomIdent::from_ident(location, &ident, &[])?); + } + location = input.current_source_location(); + } + + if idents.is_empty() { + return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + + Ok(Self { + idents: crate::ArcSlice::from_iter(idents.into_iter()), + bits, + }) + } +} + +impl ToCss for ColorScheme { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + if self.idents.is_empty() { + debug_assert!(self.bits.is_empty()); + return dest.write_str("normal"); + } + let mut first = true; + for ident in self.idents.iter() { + if !first { + dest.write_char(' ')?; + } + first = false; + ident.to_css(dest)?; + } + if self.bits.intersects(ColorSchemeFlags::ONLY) { + dest.write_str(" only")?; + } + Ok(()) + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 11498337a7f..6cd952cd82f 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -42,7 +42,7 @@ pub use self::box_::{Clear, Float, Overflow, OverflowAnchor}; pub use self::box_::{OverflowClipBox, OverscrollBehavior, Perspective, Resize}; pub use self::box_::{ScrollSnapAlign, ScrollSnapAxis, ScrollSnapStrictness, ScrollSnapType}; pub use self::box_::{TouchAction, TransitionProperty, VerticalAlign, WillChange}; -pub use self::color::{Color, ColorOrAuto, ColorPropertyValue}; +pub use self::color::{Color, ColorOrAuto, ColorPropertyValue, ColorScheme}; pub use self::column::ColumnCount; pub use self::counters::{Content, ContentItem, CounterIncrement, CounterSetOrReset}; pub use self::easing::TimingFunction; From e617ece91ee5482232f89d270af7cded6d77c3f6 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 11:59:07 +0200 Subject: [PATCH 59/80] Further changes required by Servo --- components/style/properties/properties.mako.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index ae5e4b6afb1..fff28e4bfab 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -1366,6 +1366,9 @@ impl LonghandId { // font-size depends on math-depth's computed value. LonghandId::MathDepth | + + // color-scheme affects how system colors resolve. + LonghandId::ColorScheme | % endif // Needed to compute the first available font, in order to @@ -1376,9 +1379,6 @@ impl LonghandId { LonghandId::FontStyle | LonghandId::FontFamily | - // color-scheme affects how system colors resolve. - LonghandId::ColorScheme | - // Needed to properly compute the writing mode, to resolve logical // properties, and similar stuff. LonghandId::WritingMode | From 9b070745c9df123ccf4289a452e67fff05954a1d Mon Sep 17 00:00:00 2001 From: Morgan Reschenberg Date: Mon, 22 May 2023 12:02:05 +0200 Subject: [PATCH 60/80] style: Add MozNativevisitedhyperlinktext color, use it to style visited links Differential Revision: https://phabricator.services.mozilla.com/D120657 --- components/style/values/specified/color.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index e4b73f6c0da..1aafe592305 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -374,6 +374,10 @@ pub enum SystemColor { /// colors. MozNativehyperlinktext, + /// As above, but visited link color. + #[css(skip)] + MozNativevisitedhyperlinktext, + #[parse(aliases = "-moz-hyperlinktext")] Linktext, #[parse(aliases = "-moz-activehyperlinktext")] From 9e33a154fd4800aac135639fc9396340a40b892d Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Mon, 22 May 2023 13:07:32 +0200 Subject: [PATCH 61/80] style: Setup bindgen flags for servo similarly to cranelift and neqo While the use of toml allows the flags to be separated, the split is done via some shell shenanigans anyways, and servo's build.rs can handle the same just fine. Differential Revision: https://phabricator.services.mozilla.com/D121042 --- components/style/build_gecko.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/components/style/build_gecko.rs b/components/style/build_gecko.rs index 094b44a7087..ddf4a8b71ef 100644 --- a/components/style/build_gecko.rs +++ b/components/style/build_gecko.rs @@ -46,11 +46,15 @@ lazy_static! { .join("layout/style/ServoBindings.toml"); read_config(&path) }; - static ref BUILD_CONFIG: Table = { + static ref BINDGEN_FLAGS: Vec = { // Load build-specific config overrides. let path = PathBuf::from(env::var_os("MOZ_TOPOBJDIR").unwrap()) - .join("layout/style/bindgen.toml"); - read_config(&path) + .join("layout/style/extra-bindgen-flags"); + println!("cargo:rerun-if-changed={}", path.to_str().unwrap()); + fs::read_to_string(path).expect("Failed to read extra-bindgen-flags file") + .split_whitespace() + .map(std::borrow::ToOwned::to_owned) + .collect() }; static ref INCLUDE_RE: Regex = Regex::new(r#"#include\s*"(.+?)""#).unwrap(); static ref DISTDIR_PATH: PathBuf = { @@ -159,12 +163,8 @@ impl BuilderExt for Builder { builder = builder.clang_arg("-DDEBUG=1").clang_arg("-DJS_DEBUG=1"); } - let build_config = BUILD_CONFIG["build"] - .as_table() - .expect("Malformed config file"); - let extra_bindgen_flags = build_config["args"].as_array().unwrap().as_slice(); - for item in extra_bindgen_flags.iter() { - builder = builder.clang_arg(item.as_str().expect("Expect string in list")); + for item in &*BINDGEN_FLAGS { + builder = builder.clang_arg(item); } builder From 5a9fae3fb5c95de011904dccaada49d6c7e477b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 22 May 2023 13:08:55 +0200 Subject: [PATCH 62/80] style: Remove the old profiler label frames code in the servo codebase and replace it with the new API Differential Revision: https://phabricator.services.mozilla.com/D120795 --- components/style/driver.rs | 2 +- components/style/gecko/mod.rs | 2 - components/style/gecko/profiler.rs | 75 ------------------------------ components/style/lib.rs | 2 + components/style/macros.rs | 29 ------------ components/style/parallel.rs | 4 +- 6 files changed, 5 insertions(+), 109 deletions(-) delete mode 100644 components/style/gecko/profiler.rs diff --git a/components/style/driver.rs b/components/style/driver.rs index 475d04269c5..41833c9c320 100644 --- a/components/style/driver.rs +++ b/components/style/driver.rs @@ -140,7 +140,7 @@ where // ensures that we process all the elements at a given depth before // proceeding to the next depth, which is important for style sharing. rayon::scope_fifo(|scope| { - profiler_label!(Style); + gecko_profiler_label!(Layout, StyleComputation); parallel::traverse_nodes( drain, DispatchMode::TailCall, diff --git a/components/style/gecko/mod.rs b/components/style/gecko/mod.rs index 3ff2cfcf140..7b19810fcf2 100644 --- a/components/style/gecko/mod.rs +++ b/components/style/gecko/mod.rs @@ -13,8 +13,6 @@ pub mod conversions; pub mod data; pub mod media_features; pub mod media_queries; -#[cfg(feature = "gecko_profiler")] -pub mod profiler; pub mod pseudo_element; pub mod restyle_damage; pub mod selector_parser; diff --git a/components/style/gecko/profiler.rs b/components/style/gecko/profiler.rs deleted file mode 100644 index db269b497d1..00000000000 --- a/components/style/gecko/profiler.rs +++ /dev/null @@ -1,75 +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/. */ - -//! Gecko profiler support. -//! -//! Use the `profiler_label!` macro from macros.rs. - -use crate::gecko_bindings::structs; - -/// A label describing a category of work that style threads can perform. -pub enum ProfilerLabel { - /// Style computation. - Style, - /// Style sheet parsing. - Parse, -} - -/// RAII object that constructs and destroys a C++ AutoProfilerLabel object -/// pointed to be the specified reference. -#[cfg(feature = "gecko_profiler")] -pub struct AutoProfilerLabel<'a>(&'a mut structs::AutoProfilerLabel); - -#[cfg(feature = "gecko_profiler")] -impl<'a> AutoProfilerLabel<'a> { - /// Creates a new AutoProfilerLabel with the specified label type. - /// - /// unsafe since the caller must ensure that `label` is allocated on the - /// stack. - #[inline] - pub unsafe fn new( - label: &mut std::mem::MaybeUninit, - label_type: ProfilerLabel, - ) -> AutoProfilerLabel { - let category_pair = match label_type { - ProfilerLabel::Style => structs::JS::ProfilingCategoryPair_LAYOUT_StyleComputation, - ProfilerLabel::Parse => structs::JS::ProfilingCategoryPair_LAYOUT_CSSParsing, - }; - structs::Gecko_Construct_AutoProfilerLabel(label.as_mut_ptr(), category_pair); - AutoProfilerLabel(&mut *label.as_mut_ptr()) - } -} - -#[cfg(feature = "gecko_profiler")] -impl<'a> Drop for AutoProfilerLabel<'a> { - #[inline] - fn drop(&mut self) { - unsafe { - structs::Gecko_Destroy_AutoProfilerLabel(self.0); - } - } -} - -/// Whether the Gecko profiler is currently active. -/// -/// This implementation must be kept in sync with -/// `mozilla::profiler::detail::RacyFeatures::IsActive`. -#[cfg(feature = "gecko_profiler")] -#[inline] -pub fn profiler_is_active() -> bool { - use self::structs::profiler::detail; - use std::mem; - use std::sync::atomic::{AtomicU32, Ordering}; - - let active_and_features: &AtomicU32 = - unsafe { mem::transmute(&detail::RacyFeatures_sActiveAndFeatures) }; - (active_and_features.load(Ordering::Relaxed) & detail::RacyFeatures_Active) != 0 -} - -/// Always false when the Gecko profiler is disabled. -#[cfg(not(feature = "gecko_profiler"))] -#[inline] -pub fn profiler_is_active() -> bool { - false -} diff --git a/components/style/lib.rs b/components/style/lib.rs index a9853e4c823..ddfbd5d5995 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -33,6 +33,8 @@ extern crate cssparser; extern crate debug_unreachable; #[macro_use] extern crate derive_more; +#[macro_use] +extern crate gecko_profiler; #[cfg(feature = "gecko")] #[macro_use] pub mod gecko_string_cache; diff --git a/components/style/macros.rs b/components/style/macros.rs index f5937d8b469..e27a554acf4 100644 --- a/components/style/macros.rs +++ b/components/style/macros.rs @@ -105,35 +105,6 @@ macro_rules! define_keyword_type { }; } -/// Place a Gecko profiler label on the stack. -/// -/// The `label_type` argument must be the name of a variant of `ProfilerLabel`. -#[cfg(feature = "gecko_profiler")] -#[macro_export] -macro_rules! profiler_label { - ($label_type:ident) => { - let mut _profiler_label = - ::std::mem::MaybeUninit::<$crate::gecko_bindings::structs::AutoProfilerLabel>::uninit(); - let _profiler_label = if $crate::gecko::profiler::profiler_is_active() { - unsafe { - Some($crate::gecko::profiler::AutoProfilerLabel::new( - &mut _profiler_label, - $crate::gecko::profiler::ProfilerLabel::$label_type, - )) - } - } else { - None - }; - }; -} - -/// No-op when the Gecko profiler is not available. -#[cfg(not(feature = "gecko_profiler"))] -#[macro_export] -macro_rules! profiler_label { - ($label_type:ident) => {}; -} - #[cfg(feature = "servo")] macro_rules! local_name { ($s:tt) => { diff --git a/components/style/parallel.rs b/components/style/parallel.rs index f03bf64fe61..fea031115a7 100644 --- a/components/style/parallel.rs +++ b/components/style/parallel.rs @@ -274,7 +274,7 @@ pub fn traverse_nodes<'a, 'scope, E, D, I>( top_down_dom(&work, root, traversal_data, scope, pool, traversal, tls); } else { scope.spawn_fifo(move |scope| { - profiler_label!(Style); + gecko_profiler_label!(Layout, StyleComputation); let work = work; top_down_dom(&work, root, traversal_data, scope, pool, traversal, tls); }); @@ -284,7 +284,7 @@ pub fn traverse_nodes<'a, 'scope, E, D, I>( let nodes: WorkUnit = chunk.collect(); let traversal_data_copy = traversal_data.clone(); scope.spawn_fifo(move |scope| { - profiler_label!(Style); + gecko_profiler_label!(Layout, StyleComputation); let n = nodes; top_down_dom(&*n, root, traversal_data_copy, scope, pool, traversal, tls) }); From 237674727355f507f4bb04564069b8761165471b Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 13:13:12 +0200 Subject: [PATCH 63/80] Further changes required by Servo --- components/style/driver.rs | 1 + components/style/lib.rs | 1 + components/style/parallel.rs | 2 ++ 3 files changed, 4 insertions(+) diff --git a/components/style/driver.rs b/components/style/driver.rs index 41833c9c320..82ed2a66386 100644 --- a/components/style/driver.rs +++ b/components/style/driver.rs @@ -140,6 +140,7 @@ where // ensures that we process all the elements at a given depth before // proceeding to the next depth, which is important for style sharing. rayon::scope_fifo(|scope| { + #[cfg(feature = "gecko")] gecko_profiler_label!(Layout, StyleComputation); parallel::traverse_nodes( drain, diff --git a/components/style/lib.rs b/components/style/lib.rs index ddfbd5d5995..b721ea0d952 100644 --- a/components/style/lib.rs +++ b/components/style/lib.rs @@ -34,6 +34,7 @@ extern crate debug_unreachable; #[macro_use] extern crate derive_more; #[macro_use] +#[cfg(feature = "gecko")] extern crate gecko_profiler; #[cfg(feature = "gecko")] #[macro_use] diff --git a/components/style/parallel.rs b/components/style/parallel.rs index fea031115a7..82f003cff71 100644 --- a/components/style/parallel.rs +++ b/components/style/parallel.rs @@ -274,6 +274,7 @@ pub fn traverse_nodes<'a, 'scope, E, D, I>( top_down_dom(&work, root, traversal_data, scope, pool, traversal, tls); } else { scope.spawn_fifo(move |scope| { + #[cfg(feature = "gecko")] gecko_profiler_label!(Layout, StyleComputation); let work = work; top_down_dom(&work, root, traversal_data, scope, pool, traversal, tls); @@ -284,6 +285,7 @@ pub fn traverse_nodes<'a, 'scope, E, D, I>( let nodes: WorkUnit = chunk.collect(); let traversal_data_copy = traversal_data.clone(); scope.spawn_fifo(move |scope| { + #[cfg(feature = "gecko")] gecko_profiler_label!(Layout, StyleComputation); let n = nodes; top_down_dom(&*n, root, traversal_data_copy, scope, pool, traversal, tls) From d9719a3946c57972ce393cfb096cf2b9c104c9a0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Naz=C4=B1m=20Can=20Alt=C4=B1nova?= Date: Mon, 22 May 2023 13:16:59 +0200 Subject: [PATCH 64/80] style: Remove the unused "gecko_profiler" feature from servo This was being used when we had special code for gecko profiler in the servo codebase but we just removed the last one. This is safe to remove now. The "enabled" feature in the gecko-profiler crate is being controlled by gkrust-shared directly now. Differential Revision: https://phabricator.services.mozilla.com/D120796 --- components/style/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/components/style/Cargo.toml b/components/style/Cargo.toml index 70219416452..b4eb6dc55c5 100644 --- a/components/style/Cargo.toml +++ b/components/style/Cargo.toml @@ -27,7 +27,6 @@ servo-layout-2013 = [] servo-layout-2020 = [] gecko_debug = [] gecko_refcount_logging = [] -gecko_profiler = [] [dependencies] app_units = "0.7" From cf44eb3e779b91d213b6135ae4d4acccda7f2de8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 13:19:38 +0200 Subject: [PATCH 65/80] style: Don't alias -apple-system to system-ui for now, to keep /css/css-fonts/animations/system-fonts.html happy We probably want to do this when they do something different, but for now behavior should be the same and it causes some subtests to fail because `getComputedStyle(..).fontFamily` for system fonts seems to return -apple-system, but `.style.fontFamily = "-apple-system"` returns `system-ui`. MANUAL PUSH: Orange fix on a CLOSED TREE --- components/style/values/computed/font.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index d4818fb0e97..a477af5e68b 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -427,7 +427,7 @@ pub enum GenericFontFamily { Monospace, Cursive, Fantasy, - #[parse(aliases = "-apple-system", condition = "system_ui_enabled")] + #[parse(condition = "system_ui_enabled")] SystemUi, /// An internal value for emoji font selection. #[css(skip)] From 5530f7e90cbcc2116e43b3de9c1181179308b08f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 13:21:38 +0200 Subject: [PATCH 66/80] style: Support break-inside: avoid-{page,column} break-before/after: page|column seem harder because you need to deal with nested breaks, I think, but this should be straight-forward. Differential Revision: https://phabricator.services.mozilla.com/D121206 --- .../style/properties/longhands/box.mako.rs | 1 - .../style/properties/shorthands/box.mako.rs | 36 ++++++++++--- components/style/values/specified/box.rs | 50 +++++++++++++------ 3 files changed, 66 insertions(+), 21 deletions(-) diff --git a/components/style/properties/longhands/box.mako.rs b/components/style/properties/longhands/box.mako.rs index f2d0234a918..c8942fdc6ff 100644 --- a/components/style/properties/longhands/box.mako.rs +++ b/components/style/properties/longhands/box.mako.rs @@ -503,7 +503,6 @@ ${helpers.predefined_type( "BreakWithin", "computed::BreakWithin::Auto", engines="gecko", - aliases="page-break-inside", spec="https://drafts.csswg.org/css-break/#propdef-break-inside", animation_value_type="discrete", )} diff --git a/components/style/properties/shorthands/box.mako.rs b/components/style/properties/shorthands/box.mako.rs index 851232545c9..4beef9a0d95 100644 --- a/components/style/properties/shorthands/box.mako.rs +++ b/components/style/properties/shorthands/box.mako.rs @@ -316,15 +316,15 @@ ${helpers.two_properties_shorthand( name="page-break-before" flags="SHORTHAND_IN_GETCS IS_LEGACY_SHORTHAND" sub_properties="break-before" - spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-before" + spec="https://drafts.csswg.org/css-break-3/#page-break-properties" > pub fn parse_value<'i>( - _: &ParserContext, + context: &ParserContext, input: &mut Parser<'i, '_>, ) -> Result> { use crate::values::specified::box_::BreakBetween; Ok(expanded! { - break_before: BreakBetween::parse_legacy(input)?, + break_before: BreakBetween::parse_legacy(context, input)?, }) } @@ -340,15 +340,15 @@ ${helpers.two_properties_shorthand( name="page-break-after" flags="SHORTHAND_IN_GETCS IS_LEGACY_SHORTHAND" sub_properties="break-after" - spec="https://drafts.csswg.org/css2/page.html#propdef-page-break-after" + spec="https://drafts.csswg.org/css-break-3/#page-break-properties" > pub fn parse_value<'i>( - _: &ParserContext, + context: &ParserContext, input: &mut Parser<'i, '_>, ) -> Result> { use crate::values::specified::box_::BreakBetween; Ok(expanded! { - break_after: BreakBetween::parse_legacy(input)?, + break_after: BreakBetween::parse_legacy(context, input)?, }) } @@ -359,6 +359,30 @@ ${helpers.two_properties_shorthand( } +<%helpers:shorthand + engines="gecko" + name="page-break-inside" + flags="SHORTHAND_IN_GETCS IS_LEGACY_SHORTHAND" + sub_properties="break-inside" + spec="https://drafts.csswg.org/css-break-3/#page-break-properties" +> + pub fn parse_value<'i>( + context: &ParserContext, + input: &mut Parser<'i, '_>, + ) -> Result> { + use crate::values::specified::box_::BreakWithin; + Ok(expanded! { + break_inside: BreakWithin::parse_legacy(context, input)?, + }) + } + + impl<'a> ToCss for LonghandsToSerialize<'a> { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result where W: fmt::Write { + self.break_inside.to_css_legacy(dest) + } + } + + <%helpers:shorthand name="offset" engines="gecko" sub_properties="offset-path offset-distance offset-rotate offset-anchor" diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index ef465b496bc..c2224fdd231 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -1894,28 +1894,19 @@ pub enum BreakBetween { } impl BreakBetween { - /// Parse a legacy break-between value for `page-break-*`. + /// Parse a legacy break-between value for `page-break-{before,after}`. /// /// See https://drafts.csswg.org/css-break/#page-break-properties. #[inline] - pub fn parse_legacy<'i>(input: &mut Parser<'i, '_>) -> Result> { - let location = input.current_source_location(); - let ident = input.expect_ident()?; - let break_value = match BreakBetween::from_ident(ident) { - Ok(v) => v, - Err(()) => { - return Err(location - .new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))); - }, - }; + pub(crate) fn parse_legacy<'i>(_: &ParserContext, input: &mut Parser<'i, '_>) -> Result> { + let break_value = BreakBetween::parse(input)?; match break_value { BreakBetween::Always => Ok(BreakBetween::Page), BreakBetween::Auto | BreakBetween::Avoid | BreakBetween::Left | BreakBetween::Right => { Ok(break_value) }, BreakBetween::Page => { - Err(location - .new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))) + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) }, } } @@ -1923,7 +1914,7 @@ impl BreakBetween { /// Serialize a legacy break-between value for `page-break-*`. /// /// See https://drafts.csswg.org/css-break/#page-break-properties. - pub fn to_css_legacy(&self, dest: &mut CssWriter) -> fmt::Result + pub(crate) fn to_css_legacy(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, { @@ -1960,6 +1951,37 @@ impl BreakBetween { pub enum BreakWithin { Auto, Avoid, + AvoidPage, + AvoidColumn, +} + +impl BreakWithin { + /// Parse a legacy break-between value for `page-break-inside`. + /// + /// See https://drafts.csswg.org/css-break/#page-break-properties. + #[inline] + pub(crate) fn parse_legacy<'i>(_: &ParserContext, input: &mut Parser<'i, '_>) -> Result> { + let break_value = BreakWithin::parse(input)?; + match break_value { + BreakWithin::Auto | BreakWithin::Avoid => Ok(break_value), + BreakWithin::AvoidPage | BreakWithin::AvoidColumn => { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + }, + } + } + + /// Serialize a legacy break-between value for `page-break-inside`. + /// + /// See https://drafts.csswg.org/css-break/#page-break-properties. + pub(crate) fn to_css_legacy(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + match *self { + BreakWithin::Auto | BreakWithin::Avoid => self.to_css(dest), + BreakWithin::AvoidPage | BreakWithin::AvoidColumn => Ok(()), + } + } } /// The value for the `overflow-x` / `overflow-y` properties. From d564f200aab0d9457253460324ff388bded9bce6 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 14:07:42 +0200 Subject: [PATCH 67/80] Further changes required by Servo --- components/style/values/specified/box.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/components/style/values/specified/box.rs b/components/style/values/specified/box.rs index c2224fdd231..76dd263e831 100644 --- a/components/style/values/specified/box.rs +++ b/components/style/values/specified/box.rs @@ -1897,6 +1897,7 @@ impl BreakBetween { /// Parse a legacy break-between value for `page-break-{before,after}`. /// /// See https://drafts.csswg.org/css-break/#page-break-properties. + #[cfg(feature = "gecko")] #[inline] pub(crate) fn parse_legacy<'i>(_: &ParserContext, input: &mut Parser<'i, '_>) -> Result> { let break_value = BreakBetween::parse(input)?; @@ -1914,6 +1915,7 @@ impl BreakBetween { /// Serialize a legacy break-between value for `page-break-*`. /// /// See https://drafts.csswg.org/css-break/#page-break-properties. + #[cfg(feature = "gecko")] pub(crate) fn to_css_legacy(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, @@ -1959,6 +1961,7 @@ impl BreakWithin { /// Parse a legacy break-between value for `page-break-inside`. /// /// See https://drafts.csswg.org/css-break/#page-break-properties. + #[cfg(feature = "gecko")] #[inline] pub(crate) fn parse_legacy<'i>(_: &ParserContext, input: &mut Parser<'i, '_>) -> Result> { let break_value = BreakWithin::parse(input)?; @@ -1973,6 +1976,7 @@ impl BreakWithin { /// Serialize a legacy break-between value for `page-break-inside`. /// /// See https://drafts.csswg.org/css-break/#page-break-properties. + #[cfg(feature = "gecko")] pub(crate) fn to_css_legacy(&self, dest: &mut CssWriter) -> fmt::Result where W: Write, From c241182d095540bb918bc51faa37572c5686e67c Mon Sep 17 00:00:00 2001 From: Barret Rennie Date: Mon, 22 May 2023 14:23:02 +0200 Subject: [PATCH 68/80] style: Support color-mix() in non-sRGB color spaces Out of gamut colours are currently clipped into sRGB. Differential Revision: https://phabricator.services.mozilla.com/D120561 --- components/style/values/animated/color.rs | 672 ++++++++++++++++++++- components/style/values/specified/color.rs | 80 ++- 2 files changed, 716 insertions(+), 36 deletions(-) diff --git a/components/style/values/animated/color.rs b/components/style/values/animated/color.rs index 773310dd9b6..f99e344a57a 100644 --- a/components/style/values/animated/color.rs +++ b/components/style/values/animated/color.rs @@ -7,6 +7,8 @@ use crate::values::animated::{Animate, Procedure, ToAnimatedZero}; use crate::values::distance::{ComputeSquaredDistance, SquaredDistance}; use crate::values::generics::color::{Color as GenericColor, ComplexColorRatios}; +use crate::values::specified::color::{ColorSpaceKind, HueAdjuster}; +use euclid::default::{Transform3D, Vector3D}; /// An animated RGBA color. /// @@ -41,6 +43,26 @@ impl RGBA { alpha, } } + + /// Returns whether or not the colour is in gamut for sRGB. + pub fn in_gamut(&self) -> bool { + 0. <= self.red && + self.red <= 1. && + 0. <= self.green && + self.green <= 1. && + 0. <= self.blue && + self.blue <= 1. + } + + /// Returns the colour with coordinates clamped to the sRGB range. + pub fn clamp(&self) -> Self { + Self { + red: self.red.max(0.).min(1.), + green: self.green.max(0.).min(1.), + blue: self.blue.max(0.).min(1.), + alpha: self.alpha, + } + } } impl Animate for RGBA { @@ -106,43 +128,69 @@ impl Color { /// Mix two colors into one. pub fn mix( + color_space: ColorSpaceKind, left_color: &Color, left_weight: f32, right_color: &Color, right_weight: f32, + hue_adjuster: HueAdjuster, ) -> Self { - let left_bg = left_color.scaled_rgba(); - let right_bg = right_color.scaled_rgba(); - let alpha = (left_bg.alpha * left_weight + - right_bg.alpha * right_weight) - .min(1.); - - let mut fg = 0.; - let mut red = 0.; - let mut green = 0.; - let mut blue = 0.; - - let colors = [ - (left_color, &left_bg, left_weight), - (right_color, &right_bg, right_weight), - ]; - - for &(color, bg, weight) in &colors { - fg += color.ratios.fg * weight; - - red += bg.red * bg.alpha * weight; - green += bg.green * bg.alpha * weight; - blue += bg.blue * bg.alpha * weight; + match color_space { + ColorSpaceKind::Srgb => Self::mix_in::( + left_color, + left_weight, + right_color, + right_weight, + hue_adjuster, + ), + ColorSpaceKind::Xyz => Self::mix_in::( + left_color, + left_weight, + right_color, + right_weight, + hue_adjuster, + ), + ColorSpaceKind::Lab => Self::mix_in::( + left_color, + left_weight, + right_color, + right_weight, + hue_adjuster, + ), + ColorSpaceKind::Lch => Self::mix_in::( + left_color, + left_weight, + right_color, + right_weight, + hue_adjuster, + ), } + } - let color = if alpha <= 0. { - RGBA::transparent() + fn mix_in( + left_color: &Color, + left_weight: f32, + right_color: &Color, + right_weight: f32, + hue_adjuster: HueAdjuster, + ) -> Self + where + S: ModelledColor, + { + let left_bg = S::from(left_color.scaled_rgba()); + let right_bg = S::from(right_color.scaled_rgba()); + + let color = S::lerp(left_bg, left_weight, right_bg, right_weight, hue_adjuster); + let rgba: RGBA = color.into(); + let rgba = if !rgba.in_gamut() { + // TODO: Better gamut mapping. + rgba.clamp() } else { - let inv = 1. / alpha; - RGBA::new(red * inv, green * inv, blue * inv, alpha) + rgba }; - Self::new(color, ComplexColorRatios { bg: 1., fg }) + let fg = left_color.ratios.fg * left_weight + right_color.ratios.fg * right_weight; + Self::new(rgba, ComplexColorRatios { bg: 1., fg }) } fn scaled_rgba(&self) -> RGBA { @@ -309,3 +357,573 @@ impl ToAnimatedZero for Color { Ok(RGBA::transparent().into()) } } + +/// A color modelled in a specific color space (such as sRGB or CIE XYZ). +/// +/// For now, colors modelled in other spaces need to be convertible to and from +/// `RGBA` because we use sRGB for displaying colors. +trait ModelledColor: Clone + Copy + From + Into { + /// Linearly interpolate between the left and right colors. + /// + /// The HueAdjuster parameter is only for color spaces where the hue is + /// represented as an angle (e.g., CIE LCH). + fn lerp( + left_bg: Self, + left_weight: f32, + right_bg: Self, + right_weight: f32, + hue_adjuster: HueAdjuster, + ) -> Self; +} + +impl ModelledColor for RGBA { + fn lerp( + left_bg: Self, + left_weight: f32, + right_bg: Self, + right_weight: f32, + _: HueAdjuster, + ) -> Self { + // Interpolation with alpha, as per + // https://drafts.csswg.org/css-color/#interpolation-alpha. + let mut red = 0.; + let mut green = 0.; + let mut blue = 0.; + + // sRGB is a rectangular othogonal color space, so all component values + // are multiplied by the alpha value. + for &(bg, weight) in &[(left_bg, left_weight), (right_bg, right_weight)] { + red += bg.red * bg.alpha * weight; + green += bg.green * bg.alpha * weight; + blue += bg.blue * bg.alpha * weight; + } + + let alpha = (left_bg.alpha * left_weight + right_bg.alpha * right_weight).min(1.); + if alpha <= 0. { + RGBA::transparent() + } else { + let inv = 1. / alpha; + RGBA::new(red * inv, green * inv, blue * inv, alpha) + } + } +} + +/// An animated XYZA colour. +#[derive(Clone, Copy, Debug)] +pub struct XYZA { + /// The x component. + pub x: f32, + /// The y component. + pub y: f32, + /// The z component. + pub z: f32, + /// The alpha component. + pub alpha: f32, +} + +impl XYZA { + /// Returns a transparent color. + #[inline] + pub fn transparent() -> Self { + Self { + x: 0., + y: 0., + z: 0., + alpha: 0., + } + } +} + +impl ModelledColor for XYZA { + fn lerp( + left_bg: Self, + left_weight: f32, + right_bg: Self, + right_weight: f32, + _: HueAdjuster, + ) -> Self { + // Interpolation with alpha, as per + // https://drafts.csswg.org/css-color/#interpolation-alpha. + let mut x = 0.; + let mut y = 0.; + let mut z = 0.; + + // CIE XYZ is a rectangular othogonal color space, so all component + // values are multiplied by the alpha value. + for &(bg, weight) in &[(left_bg, left_weight), (right_bg, right_weight)] { + x += bg.x * bg.alpha * weight; + y += bg.y * bg.alpha * weight; + z += bg.z * bg.alpha * weight; + } + + let alpha = (left_bg.alpha * left_weight + right_bg.alpha * right_weight).min(1.); + if alpha <= 0. { + Self::transparent() + } else { + let inv = 1. / alpha; + Self { + x: x * inv, + y: y * inv, + z: z * inv, + alpha, + } + } + } +} + +/// An animated LABA colour. +#[derive(Clone, Copy, Debug)] +pub struct LABA { + /// The lightness component. + pub lightness: f32, + /// The a component. + pub a: f32, + /// The b component. + pub b: f32, + /// The alpha component. + pub alpha: f32, +} + +impl LABA { + /// Returns a transparent color. + #[inline] + pub fn transparent() -> Self { + Self { + lightness: 0., + a: 0., + b: 0., + alpha: 0., + } + } +} + +impl ModelledColor for LABA { + fn lerp( + left_bg: Self, + left_weight: f32, + right_bg: Self, + right_weight: f32, + _: HueAdjuster, + ) -> Self { + // Interpolation with alpha, as per + // https://drafts.csswg.org/css-color/#interpolation-alpha. + let mut lightness = 0.; + let mut a = 0.; + let mut b = 0.; + + // CIE LAB is a rectangular othogonal color space, so all component + // values are multiplied by the alpha value. + for &(bg, weight) in &[(left_bg, left_weight), (right_bg, right_weight)] { + lightness += bg.lightness * bg.alpha * weight; + a += bg.a * bg.alpha * weight; + b += bg.b * bg.alpha * weight; + } + + let alpha = (left_bg.alpha * left_weight + right_bg.alpha * right_weight).min(1.); + if alpha <= 0. { + Self::transparent() + } else { + let inv = 1. / alpha; + Self { + lightness: lightness * inv, + a: a * inv, + b: b * inv, + alpha, + } + } + } +} + +/// An animated LCHA colour. +#[derive(Clone, Copy, Debug)] +pub struct LCHA { + /// The lightness component. + pub lightness: f32, + /// The chroma component. + pub chroma: f32, + /// The hua component. + pub hue: f32, + /// The alpha component. + pub alpha: f32, +} + +impl LCHA { + /// Returns a transparent color. + #[inline] + pub fn transparent() -> Self { + Self { + lightness: 0., + chroma: 0., + hue: 0., + alpha: 0., + } + } +} + +impl LCHA { + fn adjust(left_bg: Self, right_bg: Self, hue_adjuster: HueAdjuster) -> (Self, Self) { + use std::f32::consts::{PI, TAU}; + + let mut left_bg = left_bg; + let mut right_bg = right_bg; + + // Adjust the hue angle as per + // https://drafts.csswg.org/css-color/#hue-interpolation. + // + // If both hue angles are NAN, they should be set to 0. Otherwise, if a + // single hue angle is NAN, it should use the other hue angle. + if left_bg.hue.is_nan() || right_bg.hue.is_nan() { + if left_bg.hue.is_nan() && right_bg.hue.is_nan() { + left_bg.hue = 0.; + right_bg.hue = 0.; + } else if left_bg.hue.is_nan() { + left_bg.hue = right_bg.hue; + } else if right_bg.hue.is_nan() { + right_bg.hue = left_bg.hue; + } + } + + if hue_adjuster != HueAdjuster::Specified { + // Normalize hue into [0, 2 * PI) + while left_bg.hue < 0. { + left_bg.hue += TAU; + } + while left_bg.hue > TAU { + left_bg.hue -= TAU; + } + + while right_bg.hue < 0. { + right_bg.hue += TAU; + } + while right_bg.hue >= TAU { + right_bg.hue -= TAU; + } + } + + match hue_adjuster { + HueAdjuster::Shorter => { + let delta = right_bg.hue - left_bg.hue; + + if delta > PI { + left_bg.hue += PI; + } else if delta < -1. * PI { + right_bg.hue += PI; + } + }, + + HueAdjuster::Longer => { + let delta = right_bg.hue - left_bg.hue; + if 0. < delta && delta < PI { + left_bg.hue += TAU; + } else if -1. * PI < delta && delta < 0. { + right_bg.hue += TAU; + } + }, + + HueAdjuster::Increasing => { + if right_bg.hue < left_bg.hue { + right_bg.hue += TAU; + } + }, + + HueAdjuster::Decreasing => { + if left_bg.hue < right_bg.hue { + left_bg.hue += TAU; + } + }, + + //Angles are not adjusted. They are interpolated like any other + //component. + HueAdjuster::Specified => {}, + } + + (left_bg, right_bg) + } +} + +impl ModelledColor for LCHA { + fn lerp( + left_bg: Self, + left_weight: f32, + right_bg: Self, + right_weight: f32, + hue_adjuster: HueAdjuster, + ) -> Self { + // Interpolation with alpha, as per + // https://drafts.csswg.org/css-color/#interpolation-alpha. + let (left_bg, right_bg) = Self::adjust(left_bg, right_bg, hue_adjuster); + + let mut lightness = 0.; + let mut chroma = 0.; + let mut hue = 0.; + + // CIE LCH is a cylindical polar color space, so all component values + // are multiplied by the alpha value. + for &(bg, weight) in &[(left_bg, left_weight), (right_bg, right_weight)] { + lightness += bg.lightness * bg.alpha * weight; + chroma += bg.chroma * bg.alpha * weight; + // LCHA is a cylindrical color space so the hue coordinate is not + // pre-multipled by the alpha component when interpolating. + hue += bg.hue * weight; + } + + let alpha = (left_bg.alpha * left_weight + right_bg.alpha * right_weight).min(1.); + if alpha <= 0. { + Self::transparent() + } else { + let inv = 1. / alpha; + Self { + lightness: lightness * inv, + chroma: chroma * inv, + hue, + alpha, + } + } + } +} + +impl From for XYZA { + /// Convert an RGBA colour to XYZ as specified in [1]. + /// + /// [1]: https://drafts.csswg.org/css-color/#rgb-to-lab + fn from(rgba: RGBA) -> Self { + fn linearize(value: f32) -> f32 { + let sign = if value < 0. { -1. } else { 1. }; + let abs = value.abs(); + if abs < 0.04045 { + return value / 12.92; + } + + sign * ((abs + 0.055) / 1.055).powf(2.4) + } + + #[cfg_attr(rustfmt, rustfmt_skip)] + const SRGB_TO_XYZ: Transform3D = Transform3D::new( + 0.41239079926595934, 0.21263900587151027, 0.01933081871559182, 0., + 0.357584339383878, 0.715168678767756, 0.11919477979462598, 0., + 0.1804807884018343, 0.07219231536073371, 0.9505321522496607, 0., + 0., 0., 0., 1., + ); + + #[cfg_attr(rustfmt, rustfmt_skip)] + const BRADFORD: Transform3D = Transform3D::new( + 1.0479298208405488, 0.029627815688159344, -0.009243058152591178, 0., + 0.022946793341019088, 0.990434484573249, 0.015055144896577895, 0., + -0.05019222954313557, -0.01707382502938514, 0.7518742899580008, 0., + 0., 0., 0., 1., + ); + + // 1. Convert from sRGB to linear-light sRGB (undo gamma encoding). + let rgb = Vector3D::new( + linearize(rgba.red), + linearize(rgba.green), + linearize(rgba.blue), + ); + + // 2. Convert from linear sRGB to CIE XYZ. + // 3. Convert from a D65 whitepoint (used by sRGB) to the D50 whitepoint used in XYZ + // with the Bradford transform. + let xyz = SRGB_TO_XYZ.then(&BRADFORD).transform_vector3d(rgb); + + XYZA { + x: xyz.x, + y: xyz.y, + z: xyz.z, + alpha: rgba.alpha, + } + } +} + +impl From for LABA { + /// Convert an XYZ colour to LAB as specified in [1] and [2]. + /// + /// [1]: https://drafts.csswg.org/css-color/#rgb-to-lab + /// [2]: https://drafts.csswg.org/css-color/#color-conversion-code + fn from(xyza: XYZA) -> Self { + const WHITE: [f32; 3] = [0.96422, 1., 0.82521]; + + fn compute_f(value: f32) -> f32 { + const EPSILON: f32 = 216. / 24389.; + const KAPPA: f32 = 24389. / 27.; + + if value > EPSILON { + value.cbrt() + } else { + (KAPPA * value + 16.) / 116. + } + } + + // 4. Convert D50-adapted XYZ to Lab. + let f = [ + compute_f(xyza.x / WHITE[0]), + compute_f(xyza.y / WHITE[1]), + compute_f(xyza.z / WHITE[2]), + ]; + + let lightness = 116. * f[1] - 16.; + let a = 500. * (f[0] - f[1]); + let b = 200. * (f[1] - f[2]); + + LABA { + lightness, + a, + b, + alpha: xyza.alpha, + } + } +} + +impl From for LCHA { + /// Convert a LAB color to LCH as specified in [1]. + /// + /// [1]: https://drafts.csswg.org/css-color/#color-conversion-code + fn from(laba: LABA) -> Self { + let hue = laba.b.atan2(laba.a); + let chroma = (laba.a * laba.a + laba.b * laba.b).sqrt(); + LCHA { + lightness: laba.lightness, + chroma, + hue, + alpha: laba.alpha, + } + } +} + +impl From for LABA { + /// Convert a LCH color to LAB as specified in [1]. + /// + /// [1]: https://drafts.csswg.org/css-color/#color-conversion-code + fn from(lcha: LCHA) -> Self { + let a = lcha.chroma * lcha.hue.cos(); + let b = lcha.chroma * lcha.hue.sin(); + LABA { + lightness: lcha.lightness, + a, + b, + alpha: lcha.alpha, + } + } +} + +impl From for XYZA { + /// Convert a CIELAB color to XYZ as specified in [1] and [2]. + /// + /// [1]: https://drafts.csswg.org/css-color/#lab-to-predefined + /// [2]: https://drafts.csswg.org/css-color/#color-conversion-code + fn from(laba: LABA) -> Self { + // 1. Convert LAB to (D50-adapated) XYZ. + const KAPPA: f32 = 24389. / 27.; + const EPSILON: f32 = 216. / 24389.; + const WHITE: [f32; 3] = [0.96422, 1., 0.82521]; + + let f1 = (laba.lightness + 16f32) / 116f32; + let f0 = (laba.a / 500.) + f1; + let f2 = f1 - laba.b / 200.; + + let x = if f0.powf(3.) > EPSILON { + f0.powf(3.) + } else { + (116. * f0 - 16.) / KAPPA + }; + let y = if laba.lightness > KAPPA * EPSILON { + ((laba.lightness + 16.) / 116.).powf(3.) + } else { + laba.lightness / KAPPA + }; + let z = if f2.powf(3.) > EPSILON { + f2.powf(3.) + } else { + (116. * f2 - 16.) / KAPPA + }; + + XYZA { + x: x * WHITE[0], + y: y * WHITE[1], + z: z * WHITE[2], + alpha: laba.alpha, + } + } +} + +impl From for RGBA { + /// Convert an XYZ color to sRGB as specified in [1] and [2]. + /// + /// [1]: https://www.w3.org/TR/css-color-4/#lab-to-predefined + /// [2]: https://www.w3.org/TR/css-color-4/#color-conversion-code + fn from(xyza: XYZA) -> Self { + #[cfg_attr(rustfmt, rustfmt_skip)] + const BRADFORD_INVERSE: Transform3D = Transform3D::new( + 0.9554734527042182, -0.028369706963208136, 0.012314001688319899, 0., + -0.023098536874261423, 1.0099954580058226, -0.020507696433477912, 0., + 0.0632593086610217, 0.021041398966943008, 1.3303659366080753, 0., + 0., 0., 0., 1., + ); + + #[cfg_attr(rustfmt, rustfmt_skip)] + const XYZ_TO_SRGB: Transform3D = Transform3D::new( + 3.2409699419045226, -0.9692436362808796, 0.05563007969699366, 0., + -1.537383177570094, 1.8759675015077202, -0.20397695888897652, 0., + -0.4986107602930034, 0.04155505740717559, 1.0569715142428786, 0., + 0., 0., 0., 1., + ); + + // 2. Convert from a D50 whitepoint (used by Lab) to the D65 whitepoint + // used in sRGB, with the Bradford transform. + // 3. Convert from (D65-adapted) CIE XYZ to linear-light srgb + let xyz = Vector3D::new(xyza.x, xyza.y, xyza.z); + let linear_rgb = BRADFORD_INVERSE.then(&XYZ_TO_SRGB).transform_vector3d(xyz); + + // 4. Convert from linear-light srgb to srgb (do gamma encoding). + fn delinearize(value: f32) -> f32 { + let sign = if value < 0. { -1. } else { 1. }; + let abs = value.abs(); + + if abs > 0.0031308 { + sign * (1.055 * abs.powf(1. / 2.4) - 0.055) + } else { + 12.92 * value + } + } + + let red = delinearize(linear_rgb.x); + let green = delinearize(linear_rgb.y); + let blue = delinearize(linear_rgb.z); + + RGBA { + red, + green, + blue, + alpha: xyza.alpha, + } + } +} + +impl From for LABA { + fn from(rgba: RGBA) -> Self { + let xyza: XYZA = rgba.into(); + xyza.into() + } +} + +impl From for RGBA { + fn from(laba: LABA) -> Self { + let xyza: XYZA = laba.into(); + xyza.into() + } +} + +impl From for LCHA { + fn from(rgba: RGBA) -> Self { + let xyza: XYZA = rgba.into(); + let laba: LABA = xyza.into(); + laba.into() + } +} + +impl From for RGBA { + fn from(lcha: LCHA) -> Self { + let laba: LABA = lcha.into(); + let xyza: XYZA = laba.into(); + xyza.into() + } +} diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index 1aafe592305..c289b557835 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -9,7 +9,7 @@ use super::AllowQuirks; use crate::gecko_bindings::structs::nscolor; use crate::parser::{Parse, ParserContext}; use crate::values::computed::{Color as ComputedColor, Context, ToComputedValue}; -use crate::values::generics::color::{GenericColorOrAuto, GenericCaretColor}; +use crate::values::generics::color::{GenericCaretColor, GenericColorOrAuto}; use crate::values::specified::calc::CalcNode; use crate::values::specified::Percentage; use crate::values::CustomIdent; @@ -21,17 +21,51 @@ use std::io::Write as IoWrite; use style_traits::{CssType, CssWriter, KeywordsCollectFn, ParseError, StyleParseErrorKind}; use style_traits::{SpecifiedValueInfo, ToCss, ValueParseErrorKind}; +/// A color space as defined in [1]. +/// +/// [1]: https://drafts.csswg.org/css-color-5/#typedef-colorspace +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)] +pub enum ColorSpaceKind { + /// The sRGB color space. + Srgb, + /// The CIEXYZ color space. + Xyz, + /// The CIELAB color space. + Lab, + /// The CIELAB color space, expressed in cylindrical coordinates. + Lch, +} + +/// A hue adjuster as defined in [1]. +/// +/// [1]: https://drafts.csswg.org/css-color-5/#typedef-hue-adjuster +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)] +pub enum HueAdjuster { + /// The "shorter" angle adjustment. + Shorter, + /// The "longer" angle adjustment. + Longer, + /// The "increasing" angle adjustment. + Increasing, + /// The "decreasing" angle adjustment. + Decreasing, + /// The "specified" angle adjustment. + Specified, +} + /// A restricted version of the css `color-mix()` function, which only supports -/// percentages and sRGB color-space interpolation. +/// percentages. /// /// https://drafts.csswg.org/css-color-5/#color-mix #[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] #[allow(missing_docs)] pub struct ColorMix { + pub color_space: ColorSpaceKind, pub left: Color, pub left_percentage: Percentage, pub right: Color, pub right_percentage: Percentage, + pub hue_adjuster: HueAdjuster, } #[cfg(feature = "gecko")] @@ -62,6 +96,9 @@ impl Parse for ColorMix { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)); } + let color_spaces_enabled = context.chrome_rules_enabled() || + static_prefs::pref!("layout.css.color-mix.color-spaces.enabled"); + input.expect_function_matching("color-mix")?; // NOTE(emilio): This implements the syntax described here for now, @@ -70,12 +107,18 @@ impl Parse for ColorMix { // https://github.com/w3c/csswg-drafts/issues/6066#issuecomment-789836765 input.parse_nested_block(|input| { input.expect_ident_matching("in")?; - // TODO: support multiple interpolation spaces. - input.expect_ident_matching("srgb")?; + let color_space = if color_spaces_enabled { + ColorSpaceKind::parse(input)? + } else { + input.expect_ident_matching("srgb")?; + ColorSpaceKind::Srgb + }; input.expect_comma()?; let left = Color::parse(context, input)?; - let left_percentage = input.try_parse(|input| Percentage::parse(context, input)).ok(); + let left_percentage = input + .try_parse(|input| Percentage::parse(context, input)) + .ok(); input.expect_comma()?; @@ -88,11 +131,18 @@ impl Parse for ColorMix { let left_percentage = left_percentage.unwrap_or_else(|| Percentage::new(1.0 - right_percentage.get())); + + let hue_adjuster = input + .try_parse(|input| HueAdjuster::parse(input)) + .unwrap_or(HueAdjuster::Shorter); + Ok(ColorMix { + color_space, left, left_percentage, right, right_percentage, + hue_adjuster, }) }) } @@ -116,7 +166,9 @@ impl ToCss for ColorMix { (1.0 - percent.get() - other.get()).abs() <= f32::EPSILON } - dest.write_str("color-mix(in srgb, ")?; + dest.write_str("color-mix(in ")?; + self.color_space.to_css(dest)?; + dest.write_str(", ")?; self.left.to_css(dest)?; if !can_omit(&self.left_percentage, &self.right_percentage, true) { dest.write_str(" ")?; @@ -128,6 +180,12 @@ impl ToCss for ColorMix { dest.write_str(" ")?; self.right_percentage.to_css(dest)?; } + + if self.hue_adjuster != HueAdjuster::Shorter { + dest.write_str(" ")?; + self.hue_adjuster.to_css(dest)?; + } + dest.write_str(")") } } @@ -433,7 +491,7 @@ impl SystemColor { return ComputedColor::currentcolor(); } color - } + }, }) } } @@ -552,7 +610,9 @@ impl Parse for Color { } if context.chrome_rules_enabled() { - if let Ok((color, scheme)) = input.try_parse(|i| parse_moz_system_color(context, i)) { + if let Ok((color, scheme)) = + input.try_parse(|i| parse_moz_system_color(context, i)) + { return Ok(Color::System(color, scheme)); } } @@ -603,7 +663,7 @@ impl ToCss for Color { scheme.to_css(dest)?; dest.write_char(')') } - } + }, #[cfg(feature = "gecko")] Color::InheritFromBodyQuirk => Ok(()), } @@ -762,10 +822,12 @@ impl Color { let left = mix.left.to_computed_color(context)?.to_animated_value(); let right = mix.right.to_computed_color(context)?.to_animated_value(); ToAnimatedValue::from_animated_value(AnimatedColor::mix( + mix.color_space, &left, mix.left_percentage.get(), &right, mix.right_percentage.get(), + mix.hue_adjuster, )) }, #[cfg(feature = "gecko")] From fd3d12e2144a8290ba4c38522dfeb4254c15298b Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 14:29:04 +0200 Subject: [PATCH 69/80] Further changes required by Servo --- components/style/values/specified/color.rs | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/components/style/values/specified/color.rs b/components/style/values/specified/color.rs index c289b557835..f84883702c7 100644 --- a/components/style/values/specified/color.rs +++ b/components/style/values/specified/color.rs @@ -68,16 +68,20 @@ pub struct ColorMix { pub hue_adjuster: HueAdjuster, } -#[cfg(feature = "gecko")] #[inline] fn allow_color_mix() -> bool { - static_prefs::pref!("layout.css.color-mix.enabled") + #[cfg(feature = "gecko")] + return static_prefs::pref!("layout.css.color-mix.enabled"); + #[cfg(feature = "servo")] + return false; } -#[cfg(feature = "servo")] #[inline] -fn allow_color_mix() -> bool { - false +fn allow_color_mix_color_spaces() -> bool { + #[cfg(feature = "gecko")] + return static_prefs::pref!("layout.css.color-mix.color-spaces.enabled"); + #[cfg(feature = "servo")] + return false; } // NOTE(emilio): Syntax is still a bit in-flux, since [1] doesn't seem @@ -97,7 +101,7 @@ impl Parse for ColorMix { } let color_spaces_enabled = context.chrome_rules_enabled() || - static_prefs::pref!("layout.css.color-mix.color-spaces.enabled"); + allow_color_mix_color_spaces(); input.expect_function_matching("color-mix")?; From 0cb64672f45ac2ade8e49c2fb251b1c1f5f311c0 Mon Sep 17 00:00:00 2001 From: Mats Palmgren Date: Mon, 22 May 2023 14:34:39 +0200 Subject: [PATCH 70/80] style: [css-fonts] Implement 'font-synthesis: small-caps' Differential Revision: https://phabricator.services.mozilla.com/D114313 --- components/style/values/specified/font.rs | 100 +++++++++++++++------- 1 file changed, 68 insertions(+), 32 deletions(-) diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 22859d1af1b..9455fca9527 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -1990,23 +1990,24 @@ impl Parse for FontFeatureSettings { Debug, MallocSizeOf, PartialEq, - SpecifiedValueInfo, ToComputedValue, ToResolvedValue, ToShmem, )] /// Whether user agents are allowed to synthesize bold or oblique font faces -/// when a font family lacks bold or italic faces +/// when a font family lacks those faces, or a small-caps variant when this is +/// not supported by the face. pub struct FontSynthesis { /// If a `font-weight` is requested that the font family does not contain, /// the user agent may synthesize the requested weight from the weights /// that do exist in the font family. - #[css(represents_keyword)] pub weight: bool, /// If a font-style is requested that the font family does not contain, /// the user agent may synthesize the requested style from the normal face in the font family. - #[css(represents_keyword)] pub style: bool, + /// This bit controls whether the user agent is allowed to synthesize small caps variant + /// when a font face lacks it. + pub small_caps: bool, } impl FontSynthesis { @@ -2016,6 +2017,7 @@ impl FontSynthesis { FontSynthesis { weight: true, style: true, + small_caps: true, } } #[inline] @@ -2024,8 +2026,14 @@ impl FontSynthesis { FontSynthesis { weight: false, style: false, + small_caps: false, } } + #[inline] + /// Return true if this is the 'none' value + pub fn is_none(&self) -> bool { + *self == Self::none() + } } impl Parse for FontSynthesis { @@ -2033,26 +2041,23 @@ impl Parse for FontSynthesis { _: &ParserContext, input: &mut Parser<'i, 't>, ) -> Result> { - let mut result = FontSynthesis { - weight: false, - style: false, - }; - try_match_ident_ignore_ascii_case! { input, - "none" => Ok(result), - "weight" => { - result.weight = true; - if input.try_parse(|input| input.expect_ident_matching("style")).is_ok() { - result.style = true; - } - Ok(result) - }, - "style" => { - result.style = true; - if input.try_parse(|input| input.expect_ident_matching("weight")).is_ok() { - result.weight = true; - } - Ok(result) - }, + use crate::values::SelectorParseErrorKind; + let mut result = Self::none(); + while let Ok(ident) = input.try_parse(|i| i.expect_ident_cloned()) { + match_ignore_ascii_case! { &ident, + "none" if result.is_none() => return Ok(result), + "weight" if !result.weight => result.weight = true, + "style" if !result.style => result.style = true, + "small-caps" if !result.small_caps && + static_prefs::pref!("layout.css.font-synthesis-small-caps.enabled") + => result.small_caps = true, + _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident))), + } + } + if !result.is_none() { + Ok(result) + } else { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) } } } @@ -2062,14 +2067,41 @@ impl ToCss for FontSynthesis { where W: Write, { - if self.weight && self.style { - dest.write_str("weight style") - } else if self.style { - dest.write_str("style") - } else if self.weight { - dest.write_str("weight") - } else { - dest.write_str("none") + if self.is_none() { + return dest.write_str("none"); + } + + let mut need_space = false; + if self.weight { + dest.write_str("weight")?; + need_space = true; + } + if self.style { + if need_space { + dest.write_str(" ")?; + } + dest.write_str("style")?; + need_space = true; + } + if self.small_caps { + if need_space { + dest.write_str(" ")?; + } + dest.write_str("small-caps")?; + } + Ok(()) + } +} + +impl SpecifiedValueInfo for FontSynthesis { + fn collect_completion_keywords(f: KeywordsCollectFn) { + f(&[ + "none", + "weight", + "style", + ]); + if static_prefs::pref!("layout.css.font-synthesis-small-caps.enabled") { + f(&["small-caps"]); } } } @@ -2082,6 +2114,7 @@ impl From for FontSynthesis { FontSynthesis { weight: bits & structs::NS_FONT_SYNTHESIS_WEIGHT as u8 != 0, style: bits & structs::NS_FONT_SYNTHESIS_STYLE as u8 != 0, + small_caps: bits & structs::NS_FONT_SYNTHESIS_SMALL_CAPS as u8 != 0, } } } @@ -2098,6 +2131,9 @@ impl From for u8 { if v.style { bits |= structs::NS_FONT_SYNTHESIS_STYLE as u8; } + if v.small_caps { + bits |= structs::NS_FONT_SYNTHESIS_SMALL_CAPS as u8; + } bits } } From 6ea5fdc40edac98945569626a2bbb565afe3509c Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 15:15:53 +0200 Subject: [PATCH 71/80] Further changes required by Servo --- components/style/values/specified/font.rs | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index 9455fca9527..e78fec45d02 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -2036,6 +2036,14 @@ impl FontSynthesis { } } +#[inline] +fn allow_font_synthesis_small_caps() -> bool { + #[cfg(feature = "gecko")] + return static_prefs::pref!("layout.css.font-synthesis-small-caps.enabled"); + #[cfg(feature = "servo")] + return false; +} + impl Parse for FontSynthesis { fn parse<'i, 't>( _: &ParserContext, @@ -2048,8 +2056,7 @@ impl Parse for FontSynthesis { "none" if result.is_none() => return Ok(result), "weight" if !result.weight => result.weight = true, "style" if !result.style => result.style = true, - "small-caps" if !result.small_caps && - static_prefs::pref!("layout.css.font-synthesis-small-caps.enabled") + "small-caps" if !result.small_caps && allow_font_synthesis_small_caps() => result.small_caps = true, _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident))), } @@ -2100,7 +2107,7 @@ impl SpecifiedValueInfo for FontSynthesis { "weight", "style", ]); - if static_prefs::pref!("layout.css.font-synthesis-small-caps.enabled") { + if allow_font_synthesis_small_caps() { f(&["small-caps"]); } } From f31f541125be7779e087e8eeac23c27aee1b388f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 14:35:21 +0200 Subject: [PATCH 72/80] style: Add a use counter for content-visibility Differential Revision: https://phabricator.services.mozilla.com/D122873 --- components/style/properties/counted_unknown_properties.py | 1 + 1 file changed, 1 insertion(+) diff --git a/components/style/properties/counted_unknown_properties.py b/components/style/properties/counted_unknown_properties.py index 2548e591060..6a562a9abab 100644 --- a/components/style/properties/counted_unknown_properties.py +++ b/components/style/properties/counted_unknown_properties.py @@ -121,4 +121,5 @@ COUNTED_UNKNOWN_PROPERTIES = [ "-webkit-columns", "-webkit-column-rule-color", "-webkit-shape-margin", + "content-visibility", ] From 26c5db6a6e89cc20a5ae13447b2ad1e7afbe2fc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 14:36:08 +0200 Subject: [PATCH 73/80] style: Respect transparent and system color border colors in forced-colors mode Differential Revision: https://phabricator.services.mozilla.com/D123111 --- components/style/properties/cascade.rs | 17 +++++++++- .../style/properties/properties.mako.rs | 33 +++++++++++++++++-- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/components/style/properties/cascade.rs b/components/style/properties/cascade.rs index 822a7c52053..e3f919cc56e 100644 --- a/components/style/properties/cascade.rs +++ b/components/style/properties/cascade.rs @@ -464,7 +464,22 @@ fn tweak_when_ignoring_colors( } } }, - _ => {}, + _ => { + // We honor transparent and system colors more generally for all + // colors. + // + // NOTE(emilio): This doesn't handle caret-color and + // accent-color because those use a slightly different syntax + // ( | auto for example). That's probably fine though, as + // using a system color for caret-color doesn't make sense (using + // currentColor is fine), and we ignore accent-color in + // high-contrast-mode anyways. + if let Some(color) = declaration.color_value() { + if color.is_system() || alpha_channel(color, context) == 0 { + return; + } + } + }, } *declaration.to_mut() = diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index fff28e4bfab..67183062e2f 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -232,7 +232,7 @@ pub mod shorthands { // which don't exist in `LonghandId`. <% - extra = [ + extra_variants = [ { "name": "CSSWideKeyword", "type": "WideKeywordDeclaration", @@ -252,7 +252,7 @@ pub mod shorthands { "copy": False, }, ] - for v in extra: + for v in extra_variants: variants.append(v) groups[v["type"]] = [v] %> @@ -394,6 +394,17 @@ impl MallocSizeOf for PropertyDeclaration { impl PropertyDeclaration { + /// Returns whether this is a variant of the Longhand(Value) type, rather + /// than one of the special variants in extra_variants. + fn is_longhand_value(&self) -> bool { + match *self { + % for v in extra_variants: + PropertyDeclaration::${v["name"]}(..) => false, + % endfor + _ => true, + } + } + /// Like the method on ToCss, but without the type parameter to avoid /// accidentally monomorphizing this large function multiple times for /// different writers. @@ -409,6 +420,24 @@ impl PropertyDeclaration { % endfor } } + + /// Returns the color value of a given property, for high-contrast-mode + /// tweaks. + pub(crate) fn color_value(&self) -> Option<<&crate::values::specified::Color> { + ${static_longhand_id_set("COLOR_PROPERTIES", lambda p: p.predefined_type == "Color")} + <% + # sanity check + assert data.longhands_by_name["background-color"].predefined_type == "Color" + + color_specified_type = data.longhands_by_name["background-color"].specified_type() + %> + let id = self.id().as_longhand()?; + if !COLOR_PROPERTIES.contains(id) || !self.is_longhand_value() { + return None; + } + let repr = self as *const _ as *const PropertyDeclarationVariantRepr<${color_specified_type}>; + Some(unsafe { &(*repr).value }) + } } /// A module with all the code related to animated properties. From 79893116e7d142e449970f617707d656e2ecc23a Mon Sep 17 00:00:00 2001 From: Matt Woodrow Date: Mon, 22 May 2023 14:37:04 +0200 Subject: [PATCH 74/80] style: Return an infinite perspective in TransformOperation::Perspective::to_animated_zero Differential Revision: https://phabricator.services.mozilla.com/D122919 --- components/style/values/animated/transform.rs | 8 ++++++-- components/style/values/computed/transform.rs | 4 ++-- components/style/values/generics/transform.rs | 6 +++--- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/components/style/values/animated/transform.rs b/components/style/values/animated/transform.rs index a204ec2be2e..57d1900a0f9 100644 --- a/components/style/values/animated/transform.rs +++ b/components/style/values/animated/transform.rs @@ -1112,8 +1112,12 @@ impl Animate for ComputedTransformOperation { let decomposed = decompose_3d_matrix(interpolated)?; let perspective_z = decomposed.perspective.2; - let used_value = if perspective_z == 0. { - 0. + // Clamp results outside of the -1 to 0 range so that we get perspective + // function values between 1 and infinity. + let used_value = if perspective_z >= 0. { + std::f32::INFINITY + } else if perspective_z <= -1. { + 1. } else { -1. / perspective_z }; diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index 46c471b7e2e..431893973f5 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -516,8 +516,8 @@ impl ToAnimatedZero for TransformOperation { generic::TransformOperation::Rotate(_) => { Ok(generic::TransformOperation::Rotate(Angle::zero())) }, - generic::TransformOperation::Perspective(ref l) => Ok( - generic::TransformOperation::Perspective(l.to_animated_zero()?), + generic::TransformOperation::Perspective(_) => Ok( + generic::TransformOperation::Perspective(Length::new(std::f32::INFINITY)) ), generic::TransformOperation::AccumulateMatrix { .. } | generic::TransformOperation::InterpolateMatrix { .. } => { diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 9669d44f1a2..1733baa2d23 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -583,10 +583,10 @@ impl Transform { /// Return the transform matrix from a perspective length. #[inline] pub fn create_perspective_matrix(d: CSSFloat) -> Transform3D { - if d < 0.0 { - Transform3D::identity() - } else { + if d.is_finite() { Transform3D::perspective(d.max(1.)) + } else { + Transform3D::identity() } } From db1ada85dc6cdd268a61b521ac238a3080f5efb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 14:37:44 +0200 Subject: [PATCH 75/80] style: Workaround GCC-calling-into-LLVM ABI issue by making GenericFontFamily larger This enum being a bit larger doesn't cause many common data structures to grow, so this should be fine. Differential Revision: https://phabricator.services.mozilla.com/D123146 --- components/style/values/computed/font.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index a477af5e68b..e2b29f61d5e 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -398,6 +398,10 @@ fn system_ui_enabled(_: &ParserContext) -> bool { /// The order here is important, if you change it make sure that /// `gfxPlatformFontList.h`s ranged array and `gfxFontFamilyList`'s /// sSingleGenerics are updated as well. +/// +/// NOTE(emilio): Should be u8, but it's a u32 because of ABI issues between GCC +/// and LLVM see https://bugs.llvm.org/show_bug.cgi?id=44228 / bug 1600735 / +/// bug 1726515. #[derive( Clone, Copy, @@ -413,7 +417,7 @@ fn system_ui_enabled(_: &ParserContext) -> bool { ToShmem, )] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[repr(u8)] +#[repr(u32)] #[allow(missing_docs)] pub enum GenericFontFamily { /// No generic family specified, only for internal usage. From ce45f68d9c07b34cb017ec0fe89de542f0771744 Mon Sep 17 00:00:00 2001 From: Nicolas Silva Date: Mon, 22 May 2023 14:56:11 +0200 Subject: [PATCH 76/80] style: Update euclid in stylo Differential Revision: https://phabricator.services.mozilla.com/D85762 --- components/style/values/generics/transform.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 1733baa2d23..95f5e999b77 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -443,32 +443,31 @@ where use self::TransformOperation::*; use std::f64; - const TWO_PI: f64 = 2.0f64 * f64::consts::PI; let reference_width = reference_box.map(|v| v.size.width); let reference_height = reference_box.map(|v| v.size.height); let matrix = match *self { Rotate3D(ax, ay, az, theta) => { - let theta = TWO_PI - theta.radians64(); + let theta = theta.radians64(); let (ax, ay, az, theta) = get_normalized_vector_and_angle(ax.into(), ay.into(), az.into(), theta); Transform3D::rotation( ax as f64, ay as f64, az as f64, - -euclid::Angle::radians(theta), + euclid::Angle::radians(theta), ) }, RotateX(theta) => { - let theta = euclid::Angle::radians(TWO_PI - theta.radians64()); - Transform3D::rotation(1., 0., 0., -theta) + let theta = euclid::Angle::radians(theta.radians64()); + Transform3D::rotation(1., 0., 0., theta) }, RotateY(theta) => { - let theta = euclid::Angle::radians(TWO_PI - theta.radians64()); - Transform3D::rotation(0., 1., 0., -theta) + let theta = euclid::Angle::radians(theta.radians64()); + Transform3D::rotation(0., 1., 0., theta) }, RotateZ(theta) | Rotate(theta) => { - let theta = euclid::Angle::radians(TWO_PI - theta.radians64()); - Transform3D::rotation(0., 0., 1., -theta) + let theta = euclid::Angle::radians(theta.radians64()); + Transform3D::rotation(0., 0., 1., theta) }, Perspective(ref d) => { let m = create_perspective_matrix(d.to_pixel_length(None)?); From fa840e166636d1f4529ac8dbaef6fa326d07289b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 15:05:17 +0200 Subject: [PATCH 77/80] style: Implement transform: perspective(none) Differential Revision: https://phabricator.services.mozilla.com/D123350 --- components/style/values/animated/transform.rs | 30 +++++++----- components/style/values/computed/transform.rs | 5 +- components/style/values/generics/transform.rs | 46 +++++++++++++++++-- .../style/values/specified/transform.rs | 10 +++- 4 files changed, 72 insertions(+), 19 deletions(-) diff --git a/components/style/values/animated/transform.rs b/components/style/values/animated/transform.rs index 57d1900a0f9..598bf9b59a7 100644 --- a/components/style/values/animated/transform.rs +++ b/components/style/values/animated/transform.rs @@ -1105,8 +1105,8 @@ impl Animate for ComputedTransformOperation { // interpolated as defined in section Interpolation of // Matrices afterwards. // - let from = create_perspective_matrix(fd.px()); - let to = create_perspective_matrix(td.px()); + let from = create_perspective_matrix(fd.infinity_or(|l| l.px())); + let to = create_perspective_matrix(td.infinity_or(|l| l.px())); let interpolated = Matrix3D::from(from).animate(&Matrix3D::from(to), procedure)?; @@ -1115,15 +1115,17 @@ impl Animate for ComputedTransformOperation { // Clamp results outside of the -1 to 0 range so that we get perspective // function values between 1 and infinity. let used_value = if perspective_z >= 0. { - std::f32::INFINITY - } else if perspective_z <= -1. { - 1. + transform::PerspectiveFunction::None } else { - -1. / perspective_z + transform::PerspectiveFunction::Length(CSSPixelLength::new( + if perspective_z <= -1. { + 1. + } else { + -1. / perspective_z + } + )) }; - Ok(TransformOperation::Perspective(CSSPixelLength::new( - used_value, - ))) + Ok(TransformOperation::Perspective(used_value)) }, _ if self.is_translate() && other.is_translate() => self .to_translate_3d() @@ -1202,14 +1204,18 @@ impl ComputeSquaredDistance for ComputedTransformOperation { ( &TransformOperation::Perspective(ref fd), &TransformOperation::Perspective(ref td), - ) => fd.compute_squared_distance(td), + ) => { + fd.infinity_or(|l| l.px()) + .compute_squared_distance(&td.infinity_or(|l| l.px())) + }, (&TransformOperation::Perspective(ref p), &TransformOperation::Matrix3D(ref m)) | (&TransformOperation::Matrix3D(ref m), &TransformOperation::Perspective(ref p)) => { // FIXME(emilio): Is this right? Why interpolating this with // Perspective but not with anything else? let mut p_matrix = Matrix3D::identity(); - if p.px() >= 0. { - p_matrix.m34 = -1. / p.px().max(1.); + let p = p.infinity_or(|p| p.px()); + if p >= 0. { + p_matrix.m34 = -1. / p.max(1.); } p_matrix.compute_squared_distance(&m) }, diff --git a/components/style/values/computed/transform.rs b/components/style/values/computed/transform.rs index 431893973f5..5eafa0cd627 100644 --- a/components/style/values/computed/transform.rs +++ b/components/style/values/computed/transform.rs @@ -24,6 +24,9 @@ pub type Transform = generic::GenericTransform; pub type TransformOrigin = generic::GenericTransformOrigin; +/// The computed value of the `perspective()` transform function. +pub type PerspectiveFunction = generic::PerspectiveFunction; + /// A vector to represent the direction vector (rotate axis) for Rotate3D. pub type DirectionVector = Vector3D; @@ -517,7 +520,7 @@ impl ToAnimatedZero for TransformOperation { Ok(generic::TransformOperation::Rotate(Angle::zero())) }, generic::TransformOperation::Perspective(_) => Ok( - generic::TransformOperation::Perspective(Length::new(std::f32::INFINITY)) + generic::TransformOperation::Perspective(generic::PerspectiveFunction::None) ), generic::TransformOperation::AccumulateMatrix { .. } | generic::TransformOperation::InterpolateMatrix { .. } => { diff --git a/components/style/values/generics/transform.rs b/components/style/values/generics/transform.rs index 95f5e999b77..92987f89fe4 100644 --- a/components/style/values/generics/transform.rs +++ b/components/style/values/generics/transform.rs @@ -141,6 +141,41 @@ fn is_same(x: &N, y: &N) -> bool { x == y } +/// A value for the `perspective()` transform function, which is either a +/// non-negative `` or `none`. +#[derive( + Clone, + Debug, + Deserialize, + MallocSizeOf, + PartialEq, + Serialize, + SpecifiedValueInfo, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +#[repr(C, u8)] +pub enum GenericPerspectiveFunction { + /// `none` + None, + /// A ``. + Length(L), +} + +impl GenericPerspectiveFunction { + /// Returns `f32::INFINITY` or the result of a function on the length value. + pub fn infinity_or(&self, f: impl FnOnce(&L) -> f32) -> f32 { + match *self { + Self::None => std::f32::INFINITY, + Self::Length(ref l) => f(l), + } + } +} + +pub use self::GenericPerspectiveFunction as PerspectiveFunction; + #[derive( Clone, Debug, @@ -240,7 +275,7 @@ where /// /// The value must be greater than or equal to zero. #[css(function)] - Perspective(Length), + Perspective(GenericPerspectiveFunction), /// A intermediate type for interpolation of mismatched transform lists. #[allow(missing_docs)] #[css(comma, function = "interpolatematrix")] @@ -469,9 +504,12 @@ where let theta = euclid::Angle::radians(theta.radians64()); Transform3D::rotation(0., 0., 1., theta) }, - Perspective(ref d) => { - let m = create_perspective_matrix(d.to_pixel_length(None)?); - m.cast() + Perspective(ref p) => { + let px = match p { + PerspectiveFunction::None => std::f32::INFINITY, + PerspectiveFunction::Length(ref p) => p.to_pixel_length(None)?, + }; + create_perspective_matrix(px).cast() }, Scale3D(sx, sy, sz) => Transform3D::scale(sx.into(), sy.into(), sz.into()), Scale(sx, sy) => Transform3D::scale(sx.into(), sy.into(), 1.), diff --git a/components/style/values/specified/transform.rs b/components/style/values/specified/transform.rs index ba2be4ee8d3..c10b79a089b 100644 --- a/components/style/values/specified/transform.rs +++ b/components/style/values/specified/transform.rs @@ -238,8 +238,14 @@ impl Transform { Ok(generic::TransformOperation::SkewY(theta)) }, "perspective" => { - let d = specified::Length::parse_non_negative(context, input)?; - Ok(generic::TransformOperation::Perspective(d)) + let p = match input.try_parse(|input| specified::Length::parse_non_negative(context, input)) { + Ok(p) => generic::PerspectiveFunction::Length(p), + Err(..) => { + input.expect_ident_matching("none")?; + generic::PerspectiveFunction::None + } + }; + Ok(generic::TransformOperation::Perspective(p)) }, _ => Err(()), }; From 55d0636fe5dc1d726a6917349b01ceeaf9794ebb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Mon, 22 May 2023 15:06:59 +0200 Subject: [PATCH 78/80] style: Remove layout.css.is-and-where-better-error-recovery.enabled We shipped this in 84 Differential Revision: https://phabricator.services.mozilla.com/D123623 --- components/selectors/parser.rs | 17 ++++------------- components/style/gecko/selector_parser.rs | 11 +---------- 2 files changed, 5 insertions(+), 23 deletions(-) diff --git a/components/selectors/parser.rs b/components/selectors/parser.rs index 0b8d7d2331e..c6650102616 100644 --- a/components/selectors/parser.rs +++ b/components/selectors/parser.rs @@ -256,11 +256,6 @@ pub trait Parser<'i> { false } - /// The error recovery that selector lists inside :is() and :where() have. - fn is_and_where_error_recovery(&self) -> ParseErrorRecovery { - ParseErrorRecovery::IgnoreInvalidSelector - } - /// Whether the given function name is an alias for the `:is()` function. fn is_is_alias(&self, _name: &str) -> bool { false @@ -344,7 +339,7 @@ pub struct SelectorList( ); /// How to treat invalid selectors in a selector list. -pub enum ParseErrorRecovery { +enum ParseErrorRecovery { /// Discard the entire selector list, this is the default behavior for /// almost all of CSS. DiscardList, @@ -2277,7 +2272,7 @@ where state | SelectorParsingState::SKIP_DEFAULT_NAMESPACE | SelectorParsingState::DISALLOW_PSEUDOS, - parser.is_and_where_error_recovery(), + ParseErrorRecovery::IgnoreInvalidSelector, )?; Ok(component(inner.0.into_vec().into_boxed_slice())) } @@ -2686,10 +2681,6 @@ pub mod tests { true } - fn is_and_where_error_recovery(&self) -> ParseErrorRecovery { - ParseErrorRecovery::DiscardList - } - fn parse_part(&self) -> bool { true } @@ -3294,9 +3285,9 @@ pub mod tests { assert!(parse("::slotted(div)::before").is_ok()); assert!(parse("slot::slotted(div,foo)").is_err()); - assert!(parse("foo:where()").is_err()); + assert!(parse("foo:where()").is_ok()); assert!(parse("foo:where(div, foo, .bar baz)").is_ok()); - assert!(parse("foo:where(::before)").is_err()); + assert!(parse_expected("foo:where(::before)", Some("foo:where()")).is_ok()); } #[test] diff --git a/components/style/gecko/selector_parser.rs b/components/style/gecko/selector_parser.rs index b2fe46a9a2c..5379454daa0 100644 --- a/components/style/gecko/selector_parser.rs +++ b/components/style/gecko/selector_parser.rs @@ -14,7 +14,7 @@ use crate::string_cache::{Atom, Namespace, WeakAtom, WeakNamespace}; use crate::values::{AtomIdent, AtomString}; use cssparser::{BasicParseError, BasicParseErrorKind, Parser}; use cssparser::{CowRcStr, SourceLocation, ToCss, Token}; -use selectors::parser::{ParseErrorRecovery, SelectorParseErrorKind}; +use selectors::parser::SelectorParseErrorKind; use selectors::SelectorList; use std::fmt; use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss as ToCss_}; @@ -311,15 +311,6 @@ impl<'a, 'i> ::selectors::Parser<'i> for SelectorParser<'a> { true } - #[inline] - fn is_and_where_error_recovery(&self) -> ParseErrorRecovery { - if static_prefs::pref!("layout.css.is-and-where-better-error-recovery.enabled") { - ParseErrorRecovery::IgnoreInvalidSelector - } else { - ParseErrorRecovery::DiscardList - } - } - #[inline] fn parse_part(&self) -> bool { true From e35533196ff8aeda0a7db1626b3998c8546f4914 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 15:26:39 +0200 Subject: [PATCH 79/80] Avoid complaints from ./mach test-tidy --- servo-tidy.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/servo-tidy.toml b/servo-tidy.toml index f80b71c8cfc..9b86cf96f5a 100644 --- a/servo-tidy.toml +++ b/servo-tidy.toml @@ -81,10 +81,14 @@ packages = [ files = [ "./components/net/tests/parsable_mime/text", # These are ignored to avoid diverging from Gecko + "./components/style/counter_style/mod.rs", "./components/style/properties/helpers.mako.rs", "./components/style/stylesheets/rule_parser.rs", "./components/style/stylist.rs", + "./components/style/values/computed/font.rs", "./components/style/values/computed/image.rs", + "./components/style/values/specified/color.rs", + "./components/style/values/specified/transform.rs", # Mako does not lend itself easily to splitting long lines "./components/style/properties/helpers/animated_properties.mako.rs", "./components/style/properties/shorthands/text.mako.rs", From 05d697323d27390eaf5537ea074cd0fe25801837 Mon Sep 17 00:00:00 2001 From: Oriol Brufau Date: Mon, 22 May 2023 19:13:29 +0200 Subject: [PATCH 80/80] Update tests --- ...ckground-position-calc-minmax-001.html.ini | 2 - ...on-negative-percentage-comparison.html.ini | 2 - .../transform-interpolation-001.html.ini | 45 ------------- ...orm-interpolation-verify-reftests.html.ini | 51 --------------- .../parsing/transform-valid.html.ini | 3 - .../perspective-zero-2.html.ini | 2 - .../perspective-zero-3.html.ini | 2 - .../css-transforms/perspective-zero.html.ini | 2 - .../transform3d-perspective-005.html.ini | 2 - .../minmax-percentage-serialize.html.ini | 33 ---------- .../css-variables/variable-cssText.html.ini | 6 -- .../variable-declaration-07.html.ini | 2 - .../variable-declaration-09.html.ini | 2 - .../variable-declaration-29.html.ini | 2 - .../variable-definition.html.ini | 63 ------------------- .../variable-empty-name-reserved.html.ini | 3 - .../variable-reference-06.html.ini | 2 - .../variable-reference-11.html.ini | 2 - .../css-variables/variable-reference.html.ini | 3 - ...substitution-variable-declaration.html.ini | 21 ------- .../variable-supports-05.html.ini | 2 - .../variable-supports-07.html.ini | 2 - .../variable-supports-37.html.ini | 2 - .../variable-supports-39.html.ini | 2 - .../variable-supports-57.html.ini | 2 - .../variable-supports-58.html.ini | 2 - .../serialize-variable-reference.html.ini | 6 -- ...ckground-position-calc-minmax-001.html.ini | 2 - ...on-negative-percentage-comparison.html.ini | 2 - .../transform-interpolation-001.html.ini | 45 ------------- ...orm-interpolation-verify-reftests.html.ini | 51 --------------- .../parsing/transform-valid.html.ini | 3 - .../perspective-zero-2.html.ini | 2 - .../perspective-zero-3.html.ini | 2 - .../css-transforms/perspective-zero.html.ini | 2 - .../transform3d-perspective-005.html.ini | 3 - .../minmax-percentage-serialize.html.ini | 33 ---------- .../css-variables/variable-cssText.html.ini | 6 -- .../variable-declaration-07.html.ini | 2 - .../variable-declaration-09.html.ini | 2 - .../variable-declaration-29.html.ini | 2 - .../variable-definition.html.ini | 63 ------------------- .../variable-empty-name-reserved.html.ini | 3 - .../variable-reference-06.html.ini | 2 - .../variable-reference-11.html.ini | 2 - .../css-variables/variable-reference.html.ini | 3 - ...substitution-variable-declaration.html.ini | 21 ------- .../variable-supports-05.html.ini | 2 - .../variable-supports-07.html.ini | 2 - .../variable-supports-37.html.ini | 2 - .../variable-supports-39.html.ini | 2 - .../variable-supports-57.html.ini | 2 - .../variable-supports-58.html.ini | 2 - .../serialize-variable-reference.html.ini | 6 -- ...t_variable_serialization_computed.html.ini | 2 +- tests/wpt/mozilla/meta/MANIFEST.json | 2 +- .../test_variable_serialization_computed.html | 56 +++++++++-------- 57 files changed, 32 insertions(+), 565 deletions(-) delete mode 100644 tests/wpt/metadata-layout-2020/css/css-backgrounds/background-position-calc-minmax-001.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-backgrounds/background-position-negative-percentage-comparison.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero-2.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero-3.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-transforms/transform3d-perspective-005.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-07.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-09.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-29.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-empty-name-reserved.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-reference-06.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-reference-11.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-05.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-07.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-37.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-39.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-57.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-58.html.ini delete mode 100644 tests/wpt/metadata-layout-2020/css/cssom/serialize-variable-reference.html.ini delete mode 100644 tests/wpt/metadata/css/css-backgrounds/background-position-calc-minmax-001.html.ini delete mode 100644 tests/wpt/metadata/css/css-backgrounds/background-position-negative-percentage-comparison.html.ini delete mode 100644 tests/wpt/metadata/css/css-transforms/perspective-zero-2.html.ini delete mode 100644 tests/wpt/metadata/css/css-transforms/perspective-zero-3.html.ini delete mode 100644 tests/wpt/metadata/css/css-transforms/perspective-zero.html.ini delete mode 100644 tests/wpt/metadata/css/css-transforms/transform3d-perspective-005.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-declaration-07.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-declaration-09.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-declaration-29.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-empty-name-reserved.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-reference-06.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-reference-11.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-supports-05.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-supports-07.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-supports-37.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-supports-39.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-supports-57.html.ini delete mode 100644 tests/wpt/metadata/css/css-variables/variable-supports-58.html.ini delete mode 100644 tests/wpt/metadata/css/cssom/serialize-variable-reference.html.ini diff --git a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-position-calc-minmax-001.html.ini b/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-position-calc-minmax-001.html.ini deleted file mode 100644 index ac3423de86d..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-position-calc-minmax-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[background-position-calc-minmax-001.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-position-negative-percentage-comparison.html.ini b/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-position-negative-percentage-comparison.html.ini deleted file mode 100644 index 97f5bd10ffd..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-backgrounds/background-position-negative-percentage-comparison.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[background-position-negative-percentage-comparison.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/animation/transform-interpolation-001.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/animation/transform-interpolation-001.html.ini index c9ba291778f..4cb29198072 100644 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/animation/transform-interpolation-001.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-transforms/animation/transform-interpolation-001.html.ini @@ -926,51 +926,6 @@ [Web Animations: property from [scaleZ(2)\] to [scaleZ(2) perspective(500px)\] at (2) should be [scaleZ(2) perspective(250px)\]] expected: FAIL - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (-1) should be [perspective(none)\]] - expected: FAIL - - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (0) should be [perspective(none)\]] - expected: FAIL - - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (0.5) should be [perspective(1000px)\]] - expected: FAIL - - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (1) should be [perspective(500px)\]] - expected: FAIL - - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (2) should be [perspective(250px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (-1) should be [perspective(none)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (0) should be [perspective(none)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (0.5) should be [perspective(1000px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (1) should be [perspective(500px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (2) should be [perspective(250px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (-1) should be [perspective(none)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (0) should be [perspective(none)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (0.5) should be [perspective(1000px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (1) should be [perspective(500px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (2) should be [perspective(250px)\]] - expected: FAIL - [Web Animations: property from [perspective(none)\] to [perspective(500px)\] at (-1) should be [perspective(none)\]] expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/animation/transform-interpolation-verify-reftests.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/animation/transform-interpolation-verify-reftests.html.ini index 0f6e1f8159e..926da2b159f 100644 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/animation/transform-interpolation-verify-reftests.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-transforms/animation/transform-interpolation-verify-reftests.html.ini @@ -203,39 +203,12 @@ [Web Animations: property from [matrix(1,0,0,1,0,0) rotate(0deg)\] to [matrix(2,0,0,2,0,0) rotate(360deg)\] at (0.5) should be [matrix(1.5,0,0,1.5,0,0) rotate(180deg)\]] expected: FAIL - [CSS Transitions: property from [perspective(none) translateZ(15px)\] to [perspective(none) translateZ(15px)\] at (0.5) should be [perspective(none) translateZ(15px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none) translateZ(15px)\] to [perspective(none) translateZ(15px)\] at (0.5) should be [perspective(none) translateZ(15px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none) translateZ(15px)\] to [perspective(none) translateZ(15px)\] at (0.5) should be [perspective(none) translateZ(15px)\]] - expected: FAIL - [Web Animations: property from [perspective(none) translateZ(15px)\] to [perspective(none) translateZ(15px)\] at (0.5) should be [perspective(none) translateZ(15px)\]] expected: FAIL - [CSS Transitions: property from [perspective(100px) translateZ(50px)\] to [perspective(none) translateZ(50px)\] at (0.5) should be [perspective(200px) translateZ(50px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(100px) translateZ(50px)\] to [perspective(none) translateZ(50px)\] at (0.5) should be [perspective(200px) translateZ(50px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(100px) translateZ(50px)\] to [perspective(none) translateZ(50px)\] at (0.5) should be [perspective(200px) translateZ(50px)\]] - expected: FAIL - [Web Animations: property from [perspective(100px) translateZ(50px)\] to [perspective(none) translateZ(50px)\] at (0.5) should be [perspective(200px) translateZ(50px)\]] expected: FAIL - [CSS Transitions: property from [perspective(none) translateZ(15px)\] to [perspective(25px) translateZ(15px)\] at (0.5) should be [perspective(50px) translateZ(15px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none) translateZ(15px)\] to [perspective(25px) translateZ(15px)\] at (0.5) should be [perspective(50px) translateZ(15px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none) translateZ(15px)\] to [perspective(25px) translateZ(15px)\] at (0.5) should be [perspective(50px) translateZ(15px)\]] - expected: FAIL - [Web Animations: property from [perspective(none) translateZ(15px)\] to [perspective(25px) translateZ(15px)\] at (0.5) should be [perspective(50px) translateZ(15px)\]] expected: FAIL @@ -248,9 +221,6 @@ [CSS Transitions with transition: all: property from [perspective(0.1px) translateZ(0.25px)\] to [perspective(0.1px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] expected: FAIL - [CSS Animations: property from [perspective(0.1px) translateZ(0.25px)\] to [perspective(0.1px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] - expected: FAIL - [Web Animations: property from [perspective(0.1px) translateZ(0.25px)\] to [perspective(0.1px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] expected: FAIL @@ -260,21 +230,9 @@ [CSS Transitions with transition: all: property from [perspective(0px) translateZ(0.25px)\] to [perspective(0px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] expected: FAIL - [CSS Animations: property from [perspective(0px) translateZ(0.25px)\] to [perspective(0px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] - expected: FAIL - [Web Animations: property from [perspective(0px) translateZ(0.25px)\] to [perspective(0px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] expected: FAIL - [CSS Transitions: property from [perspective(0px) translateZ(0.5px)\] to [perspective(3px) translateZ(0.5px)\] at (0.5) should be [perspective(1.5px) translateZ(0.5px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(0px) translateZ(0.5px)\] to [perspective(3px) translateZ(0.5px)\] at (0.5) should be [perspective(1.5px) translateZ(0.5px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(0px) translateZ(0.5px)\] to [perspective(3px) translateZ(0.5px)\] at (0.5) should be [perspective(1.5px) translateZ(0.5px)\]] - expected: FAIL - [Web Animations: property from [perspective(0px) translateZ(0.5px)\] to [perspective(3px) translateZ(0.5px)\] at (0.5) should be [perspective(1.5px) translateZ(0.5px)\]] expected: FAIL @@ -290,14 +248,5 @@ [Web Animations: property from [perspective(10px) translateZ(0.5px)\] to [perspective(1px) translateZ(0.5px)\] at (-1) should be [translateZ(0.5px)\]] expected: FAIL - [CSS Transitions: property from [perspective(1px) translateZ(0.5px)\] to [perspective(10px) translateZ(0.5px)\] at (-1) should be [perspective(1px) translateZ(0.5px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(1px) translateZ(0.5px)\] to [perspective(10px) translateZ(0.5px)\] at (-1) should be [perspective(1px) translateZ(0.5px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(1px) translateZ(0.5px)\] to [perspective(10px) translateZ(0.5px)\] at (-1) should be [perspective(1px) translateZ(0.5px)\]] - expected: FAIL - [Web Animations: property from [perspective(1px) translateZ(0.5px)\] to [perspective(10px) translateZ(0.5px)\] at (-1) should be [perspective(1px) translateZ(0.5px)\]] expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/parsing/transform-valid.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/parsing/transform-valid.html.ini index 6ee0275f23d..99bacfc4422 100644 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/parsing/transform-valid.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-transforms/parsing/transform-valid.html.ini @@ -1,6 +1,3 @@ [transform-valid.html] - [e.style['transform'\] = "perspective(none)" should set the property value] - expected: FAIL - [e.style['transform'\] = "translate(1px, 0%)" should set the property value] expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero-2.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero-2.html.ini deleted file mode 100644 index c3150604a8a..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero-2.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[perspective-zero-2.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero-3.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero-3.html.ini deleted file mode 100644 index b2860a8900b..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero-3.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[perspective-zero-3.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero.html.ini deleted file mode 100644 index 66e93c50082..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/perspective-zero.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[perspective-zero.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-transforms/transform3d-perspective-005.html.ini b/tests/wpt/metadata-layout-2020/css/css-transforms/transform3d-perspective-005.html.ini deleted file mode 100644 index ae307d59949..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-transforms/transform3d-perspective-005.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[transform3d-perspective-005.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-values/minmax-percentage-serialize.html.ini b/tests/wpt/metadata-layout-2020/css/css-values/minmax-percentage-serialize.html.ini index b291291efc4..88a8612cfd8 100644 --- a/tests/wpt/metadata-layout-2020/css/css-values/minmax-percentage-serialize.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-values/minmax-percentage-serialize.html.ini @@ -1,36 +1,3 @@ [minmax-percentage-serialize.html] - ['min(1%, 2%, 3%)' as a specified value should serialize as 'min(1%, 2%, 3%)'.] - expected: FAIL - - ['min(1%, 2%, 3%)' as a computed value should serialize as 'min(1%, 2%, 3%)'.] - expected: FAIL - - ['min(3%, 2%, 1%)' as a specified value should serialize as 'min(3%, 2%, 1%)'.] - expected: FAIL - - ['min(3%, 2%, 1%)' as a computed value should serialize as 'min(3%, 2%, 1%)'.] - expected: FAIL - - ['max(1%, 2%, 3%)' as a specified value should serialize as 'max(1%, 2%, 3%)'.] - expected: FAIL - - ['max(1%, 2%, 3%)' as a computed value should serialize as 'max(1%, 2%, 3%)'.] - expected: FAIL - - ['max(3%, 2%, 1%)' as a specified value should serialize as 'max(3%, 2%, 1%)'.] - expected: FAIL - - ['max(3%, 2%, 1%)' as a computed value should serialize as 'max(3%, 2%, 1%)'.] - expected: FAIL - - ['min(1%, 2%, 3%) 0px' as a specified value should serialize as 'min(1%, 2%, 3%) 0px'.] - expected: FAIL - ['min(1%, 2%, 3%) 0px' as a computed value should serialize as 'min(1%, 2%, 3%) 0px'.] expected: FAIL - - ['calc(min(1%, 2%) + max(3%, 4%) + 10%)' as a specified value should serialize as 'calc(10% + min(1%, 2%) + max(3%, 4%))'.] - expected: FAIL - - ['calc(min(1%, 2%) + max(3%, 4%) + 10%)' as a computed value should serialize as 'calc(10% + min(1%, 2%) + max(3%, 4%))'.] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-cssText.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-cssText.html.ini index a360bf99f1b..26c397aae58 100644 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-cssText.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-variables/variable-cssText.html.ini @@ -7,9 +7,3 @@ [target6] expected: FAIL - - [target9] - expected: FAIL - - [target11] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-07.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-07.html.ini deleted file mode 100644 index 7255d7fc46e..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-07.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-declaration-07.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-09.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-09.html.ini deleted file mode 100644 index 177674de03e..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-09.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-declaration-09.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-29.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-29.html.ini deleted file mode 100644 index 815d162d51a..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-declaration-29.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-declaration-29.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-definition.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-definition.html.ini index a3daa11079d..7d3d2c0fa5e 100644 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-definition.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-variables/variable-definition.html.ini @@ -5,78 +5,15 @@ [CSSOM.setProperty with space 2] expected: FAIL - [no char variable] - expected: FAIL - - [white space value (single space)] - expected: FAIL - - [white space value (double space)] - expected: FAIL - [can't overwrite with no value] expected: FAIL - [can overwrite with space value] - expected: FAIL - - [ leading white space (single space)] - expected: FAIL - - [ leading white space (double space) 2] - expected: FAIL - - [no char variable (Computed Style)] - expected: FAIL - - [white space value (single space) (Computed Style)] - expected: FAIL - - [white space value (double space) (Computed Style)] - expected: FAIL - [can't overwrite with no value (Computed Style)] expected: FAIL - [can overwrite with space value (Computed Style)] - expected: FAIL - - [ leading white space (single space) (Computed Style)] - expected: FAIL - - [ leading white space (double space) 2 (Computed Style)] - expected: FAIL - - [no char variable (Cascading)] - expected: FAIL - - [white space value (single space) (Cascading)] - expected: FAIL - - [white space value (double space) (Cascading)] - expected: FAIL - [can't overwrite with no value (Cascading)] expected: FAIL - [can overwrite with space value (Cascading)] - expected: FAIL - - [ leading white space (single space) (Cascading)] - expected: FAIL - - [ leading white space (double space) 2 (Cascading)] - expected: FAIL - - [can overwrite with no value] - expected: FAIL - - [can overwrite with no value (Computed Style)] - expected: FAIL - - [can overwrite with no value (Cascading)] - expected: FAIL - [ trailing white space (single space)] expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-empty-name-reserved.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-empty-name-reserved.html.ini deleted file mode 100644 index 709cf140b1f..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-empty-name-reserved.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[variable-empty-name-reserved.html] - [-- is a reserved property name] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference-06.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference-06.html.ini deleted file mode 100644 index cd8687ce1d1..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference-06.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-reference-06.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference-11.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference-11.html.ini deleted file mode 100644 index d51bc156ae2..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference-11.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-reference-11.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference.html.ini index 327fe5c08c2..193b9f252c9 100644 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-variables/variable-reference.html.ini @@ -1,6 +1,3 @@ [variable-reference.html] - [width: var(--prop,);] - expected: FAIL - [Variable reference left open at end of stylesheet] expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-substitution-variable-declaration.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-substitution-variable-declaration.html.ini index 7e95ee1dde0..60c36462bdc 100644 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-substitution-variable-declaration.html.ini +++ b/tests/wpt/metadata-layout-2020/css/css-variables/variable-substitution-variable-declaration.html.ini @@ -1,24 +1,3 @@ [variable-substitution-variable-declaration.html] [target10 --varC] expected: FAIL - - [target1 --var2] - expected: FAIL - - [target2 --var1] - expected: FAIL - - [target3 --var1] - expected: FAIL - - [target3 --var2] - expected: FAIL - - [target4 --varC] - expected: FAIL - - [target8 --varB] - expected: FAIL - - [target9 --varA] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-05.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-05.html.ini deleted file mode 100644 index 4d0f1862a6c..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-05.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-05.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-07.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-07.html.ini deleted file mode 100644 index 69995c11cbe..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-07.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-07.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-37.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-37.html.ini deleted file mode 100644 index c9b4e3a1ea4..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-37.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-37.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-39.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-39.html.ini deleted file mode 100644 index 11fc7d6d05c..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-39.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-39.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-57.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-57.html.ini deleted file mode 100644 index 676c3da63fa..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-57.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-57.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-58.html.ini b/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-58.html.ini deleted file mode 100644 index ebf7e5d65d9..00000000000 --- a/tests/wpt/metadata-layout-2020/css/css-variables/variable-supports-58.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-58.html] - expected: FAIL diff --git a/tests/wpt/metadata-layout-2020/css/cssom/serialize-variable-reference.html.ini b/tests/wpt/metadata-layout-2020/css/cssom/serialize-variable-reference.html.ini deleted file mode 100644 index 0441ef458d3..00000000000 --- a/tests/wpt/metadata-layout-2020/css/cssom/serialize-variable-reference.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[serialize-variable-reference.html] - [Longhand with variable preserves original serialization but trims whitespace: without whitespace] - expected: FAIL - - [Shorthand with variable preserves original serialization but trims whitespace: without whitespace] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-backgrounds/background-position-calc-minmax-001.html.ini b/tests/wpt/metadata/css/css-backgrounds/background-position-calc-minmax-001.html.ini deleted file mode 100644 index ac3423de86d..00000000000 --- a/tests/wpt/metadata/css/css-backgrounds/background-position-calc-minmax-001.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[background-position-calc-minmax-001.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-backgrounds/background-position-negative-percentage-comparison.html.ini b/tests/wpt/metadata/css/css-backgrounds/background-position-negative-percentage-comparison.html.ini deleted file mode 100644 index 97f5bd10ffd..00000000000 --- a/tests/wpt/metadata/css/css-backgrounds/background-position-negative-percentage-comparison.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[background-position-negative-percentage-comparison.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/animation/transform-interpolation-001.html.ini b/tests/wpt/metadata/css/css-transforms/animation/transform-interpolation-001.html.ini index 4d012f732e9..0b468b702d1 100644 --- a/tests/wpt/metadata/css/css-transforms/animation/transform-interpolation-001.html.ini +++ b/tests/wpt/metadata/css/css-transforms/animation/transform-interpolation-001.html.ini @@ -929,51 +929,6 @@ [Web Animations: property from [scaleZ(2)\] to [scaleZ(2) perspective(500px)\] at (2) should be [scaleZ(2) perspective(250px)\]] expected: FAIL - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (-1) should be [perspective(none)\]] - expected: FAIL - - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (0) should be [perspective(none)\]] - expected: FAIL - - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (0.5) should be [perspective(1000px)\]] - expected: FAIL - - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (1) should be [perspective(500px)\]] - expected: FAIL - - [CSS Transitions: property from [perspective(none)\] to [perspective(500px)\] at (2) should be [perspective(250px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (-1) should be [perspective(none)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (0) should be [perspective(none)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (0.5) should be [perspective(1000px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (1) should be [perspective(500px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none)\] to [perspective(500px)\] at (2) should be [perspective(250px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (-1) should be [perspective(none)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (0) should be [perspective(none)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (0.5) should be [perspective(1000px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (1) should be [perspective(500px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none)\] to [perspective(500px)\] at (2) should be [perspective(250px)\]] - expected: FAIL - [Web Animations: property from [perspective(none)\] to [perspective(500px)\] at (-1) should be [perspective(none)\]] expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/animation/transform-interpolation-verify-reftests.html.ini b/tests/wpt/metadata/css/css-transforms/animation/transform-interpolation-verify-reftests.html.ini index 0f6e1f8159e..926da2b159f 100644 --- a/tests/wpt/metadata/css/css-transforms/animation/transform-interpolation-verify-reftests.html.ini +++ b/tests/wpt/metadata/css/css-transforms/animation/transform-interpolation-verify-reftests.html.ini @@ -203,39 +203,12 @@ [Web Animations: property from [matrix(1,0,0,1,0,0) rotate(0deg)\] to [matrix(2,0,0,2,0,0) rotate(360deg)\] at (0.5) should be [matrix(1.5,0,0,1.5,0,0) rotate(180deg)\]] expected: FAIL - [CSS Transitions: property from [perspective(none) translateZ(15px)\] to [perspective(none) translateZ(15px)\] at (0.5) should be [perspective(none) translateZ(15px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none) translateZ(15px)\] to [perspective(none) translateZ(15px)\] at (0.5) should be [perspective(none) translateZ(15px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none) translateZ(15px)\] to [perspective(none) translateZ(15px)\] at (0.5) should be [perspective(none) translateZ(15px)\]] - expected: FAIL - [Web Animations: property from [perspective(none) translateZ(15px)\] to [perspective(none) translateZ(15px)\] at (0.5) should be [perspective(none) translateZ(15px)\]] expected: FAIL - [CSS Transitions: property from [perspective(100px) translateZ(50px)\] to [perspective(none) translateZ(50px)\] at (0.5) should be [perspective(200px) translateZ(50px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(100px) translateZ(50px)\] to [perspective(none) translateZ(50px)\] at (0.5) should be [perspective(200px) translateZ(50px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(100px) translateZ(50px)\] to [perspective(none) translateZ(50px)\] at (0.5) should be [perspective(200px) translateZ(50px)\]] - expected: FAIL - [Web Animations: property from [perspective(100px) translateZ(50px)\] to [perspective(none) translateZ(50px)\] at (0.5) should be [perspective(200px) translateZ(50px)\]] expected: FAIL - [CSS Transitions: property from [perspective(none) translateZ(15px)\] to [perspective(25px) translateZ(15px)\] at (0.5) should be [perspective(50px) translateZ(15px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(none) translateZ(15px)\] to [perspective(25px) translateZ(15px)\] at (0.5) should be [perspective(50px) translateZ(15px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(none) translateZ(15px)\] to [perspective(25px) translateZ(15px)\] at (0.5) should be [perspective(50px) translateZ(15px)\]] - expected: FAIL - [Web Animations: property from [perspective(none) translateZ(15px)\] to [perspective(25px) translateZ(15px)\] at (0.5) should be [perspective(50px) translateZ(15px)\]] expected: FAIL @@ -248,9 +221,6 @@ [CSS Transitions with transition: all: property from [perspective(0.1px) translateZ(0.25px)\] to [perspective(0.1px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] expected: FAIL - [CSS Animations: property from [perspective(0.1px) translateZ(0.25px)\] to [perspective(0.1px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] - expected: FAIL - [Web Animations: property from [perspective(0.1px) translateZ(0.25px)\] to [perspective(0.1px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] expected: FAIL @@ -260,21 +230,9 @@ [CSS Transitions with transition: all: property from [perspective(0px) translateZ(0.25px)\] to [perspective(0px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] expected: FAIL - [CSS Animations: property from [perspective(0px) translateZ(0.25px)\] to [perspective(0px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] - expected: FAIL - [Web Animations: property from [perspective(0px) translateZ(0.25px)\] to [perspective(0px) translateZ(0.25px)\] at (0.5) should be [perspective(1px) translateZ(0.25px)\]] expected: FAIL - [CSS Transitions: property from [perspective(0px) translateZ(0.5px)\] to [perspective(3px) translateZ(0.5px)\] at (0.5) should be [perspective(1.5px) translateZ(0.5px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(0px) translateZ(0.5px)\] to [perspective(3px) translateZ(0.5px)\] at (0.5) should be [perspective(1.5px) translateZ(0.5px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(0px) translateZ(0.5px)\] to [perspective(3px) translateZ(0.5px)\] at (0.5) should be [perspective(1.5px) translateZ(0.5px)\]] - expected: FAIL - [Web Animations: property from [perspective(0px) translateZ(0.5px)\] to [perspective(3px) translateZ(0.5px)\] at (0.5) should be [perspective(1.5px) translateZ(0.5px)\]] expected: FAIL @@ -290,14 +248,5 @@ [Web Animations: property from [perspective(10px) translateZ(0.5px)\] to [perspective(1px) translateZ(0.5px)\] at (-1) should be [translateZ(0.5px)\]] expected: FAIL - [CSS Transitions: property from [perspective(1px) translateZ(0.5px)\] to [perspective(10px) translateZ(0.5px)\] at (-1) should be [perspective(1px) translateZ(0.5px)\]] - expected: FAIL - - [CSS Transitions with transition: all: property from [perspective(1px) translateZ(0.5px)\] to [perspective(10px) translateZ(0.5px)\] at (-1) should be [perspective(1px) translateZ(0.5px)\]] - expected: FAIL - - [CSS Animations: property from [perspective(1px) translateZ(0.5px)\] to [perspective(10px) translateZ(0.5px)\] at (-1) should be [perspective(1px) translateZ(0.5px)\]] - expected: FAIL - [Web Animations: property from [perspective(1px) translateZ(0.5px)\] to [perspective(10px) translateZ(0.5px)\] at (-1) should be [perspective(1px) translateZ(0.5px)\]] expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/parsing/transform-valid.html.ini b/tests/wpt/metadata/css/css-transforms/parsing/transform-valid.html.ini index f3a04d4e445..d79492e1f8b 100644 --- a/tests/wpt/metadata/css/css-transforms/parsing/transform-valid.html.ini +++ b/tests/wpt/metadata/css/css-transforms/parsing/transform-valid.html.ini @@ -11,8 +11,5 @@ [e.style['transform'\] = "scaleX(2e80)" should set the property value] expected: FAIL - [e.style['transform'\] = "perspective(none)" should set the property value] - expected: FAIL - [e.style['transform'\] = "translate(1px, 0%)" should set the property value] expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/perspective-zero-2.html.ini b/tests/wpt/metadata/css/css-transforms/perspective-zero-2.html.ini deleted file mode 100644 index c3150604a8a..00000000000 --- a/tests/wpt/metadata/css/css-transforms/perspective-zero-2.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[perspective-zero-2.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/perspective-zero-3.html.ini b/tests/wpt/metadata/css/css-transforms/perspective-zero-3.html.ini deleted file mode 100644 index b2860a8900b..00000000000 --- a/tests/wpt/metadata/css/css-transforms/perspective-zero-3.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[perspective-zero-3.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/perspective-zero.html.ini b/tests/wpt/metadata/css/css-transforms/perspective-zero.html.ini deleted file mode 100644 index 66e93c50082..00000000000 --- a/tests/wpt/metadata/css/css-transforms/perspective-zero.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[perspective-zero.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-transforms/transform3d-perspective-005.html.ini b/tests/wpt/metadata/css/css-transforms/transform3d-perspective-005.html.ini deleted file mode 100644 index bb87827bac7..00000000000 --- a/tests/wpt/metadata/css/css-transforms/transform3d-perspective-005.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[transform3d-perspective-005.html] - type: reftest - expected: FAIL diff --git a/tests/wpt/metadata/css/css-values/minmax-percentage-serialize.html.ini b/tests/wpt/metadata/css/css-values/minmax-percentage-serialize.html.ini index fe7a776c7c8..961fe9f21c2 100644 --- a/tests/wpt/metadata/css/css-values/minmax-percentage-serialize.html.ini +++ b/tests/wpt/metadata/css/css-values/minmax-percentage-serialize.html.ini @@ -35,38 +35,5 @@ [e.style['margin-left'\] = "min(3%, 2%, 1%)" should set the property value] expected: FAIL - ['max(1%, 2%, 3%)' as a computed value should serialize as 'max(1%, 2%, 3%)'.] - expected: FAIL - - ['min(3%, 2%, 1%)' as a specified value should serialize as 'min(3%, 2%, 1%)'.] - expected: FAIL - - ['max(3%, 2%, 1%)' as a specified value should serialize as 'max(3%, 2%, 1%)'.] - expected: FAIL - - ['min(1%, 2%, 3%)' as a computed value should serialize as 'min(1%, 2%, 3%)'.] - expected: FAIL - - ['min(1%, 2%, 3%)' as a specified value should serialize as 'min(1%, 2%, 3%)'.] - expected: FAIL - - ['max(3%, 2%, 1%)' as a computed value should serialize as 'max(3%, 2%, 1%)'.] - expected: FAIL - - ['min(3%, 2%, 1%)' as a computed value should serialize as 'min(3%, 2%, 1%)'.] - expected: FAIL - - ['max(1%, 2%, 3%)' as a specified value should serialize as 'max(1%, 2%, 3%)'.] - expected: FAIL - - ['min(1%, 2%, 3%) 0px' as a specified value should serialize as 'min(1%, 2%, 3%) 0px'.] - expected: FAIL - ['min(1%, 2%, 3%) 0px' as a computed value should serialize as 'min(1%, 2%, 3%) 0px'.] expected: FAIL - - ['calc(min(1%, 2%) + max(3%, 4%) + 10%)' as a specified value should serialize as 'calc(10% + min(1%, 2%) + max(3%, 4%))'.] - expected: FAIL - - ['calc(min(1%, 2%) + max(3%, 4%) + 10%)' as a computed value should serialize as 'calc(10% + min(1%, 2%) + max(3%, 4%))'.] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-cssText.html.ini b/tests/wpt/metadata/css/css-variables/variable-cssText.html.ini index 21cab20fc4f..3b7b425e100 100644 --- a/tests/wpt/metadata/css/css-variables/variable-cssText.html.ini +++ b/tests/wpt/metadata/css/css-variables/variable-cssText.html.ini @@ -14,14 +14,8 @@ [target6] expected: FAIL - [target9] - expected: FAIL - [target4] expected: FAIL [target5] expected: FAIL - - [target11] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-declaration-07.html.ini b/tests/wpt/metadata/css/css-variables/variable-declaration-07.html.ini deleted file mode 100644 index 7255d7fc46e..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-declaration-07.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-declaration-07.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-declaration-09.html.ini b/tests/wpt/metadata/css/css-variables/variable-declaration-09.html.ini deleted file mode 100644 index 177674de03e..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-declaration-09.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-declaration-09.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-declaration-29.html.ini b/tests/wpt/metadata/css/css-variables/variable-declaration-29.html.ini deleted file mode 100644 index 815d162d51a..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-declaration-29.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-declaration-29.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-definition.html.ini b/tests/wpt/metadata/css/css-variables/variable-definition.html.ini index a3daa11079d..7d3d2c0fa5e 100644 --- a/tests/wpt/metadata/css/css-variables/variable-definition.html.ini +++ b/tests/wpt/metadata/css/css-variables/variable-definition.html.ini @@ -5,78 +5,15 @@ [CSSOM.setProperty with space 2] expected: FAIL - [no char variable] - expected: FAIL - - [white space value (single space)] - expected: FAIL - - [white space value (double space)] - expected: FAIL - [can't overwrite with no value] expected: FAIL - [can overwrite with space value] - expected: FAIL - - [ leading white space (single space)] - expected: FAIL - - [ leading white space (double space) 2] - expected: FAIL - - [no char variable (Computed Style)] - expected: FAIL - - [white space value (single space) (Computed Style)] - expected: FAIL - - [white space value (double space) (Computed Style)] - expected: FAIL - [can't overwrite with no value (Computed Style)] expected: FAIL - [can overwrite with space value (Computed Style)] - expected: FAIL - - [ leading white space (single space) (Computed Style)] - expected: FAIL - - [ leading white space (double space) 2 (Computed Style)] - expected: FAIL - - [no char variable (Cascading)] - expected: FAIL - - [white space value (single space) (Cascading)] - expected: FAIL - - [white space value (double space) (Cascading)] - expected: FAIL - [can't overwrite with no value (Cascading)] expected: FAIL - [can overwrite with space value (Cascading)] - expected: FAIL - - [ leading white space (single space) (Cascading)] - expected: FAIL - - [ leading white space (double space) 2 (Cascading)] - expected: FAIL - - [can overwrite with no value] - expected: FAIL - - [can overwrite with no value (Computed Style)] - expected: FAIL - - [can overwrite with no value (Cascading)] - expected: FAIL - [ trailing white space (single space)] expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-empty-name-reserved.html.ini b/tests/wpt/metadata/css/css-variables/variable-empty-name-reserved.html.ini deleted file mode 100644 index 709cf140b1f..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-empty-name-reserved.html.ini +++ /dev/null @@ -1,3 +0,0 @@ -[variable-empty-name-reserved.html] - [-- is a reserved property name] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-reference-06.html.ini b/tests/wpt/metadata/css/css-variables/variable-reference-06.html.ini deleted file mode 100644 index cd8687ce1d1..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-reference-06.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-reference-06.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-reference-11.html.ini b/tests/wpt/metadata/css/css-variables/variable-reference-11.html.ini deleted file mode 100644 index d51bc156ae2..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-reference-11.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-reference-11.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-reference.html.ini b/tests/wpt/metadata/css/css-variables/variable-reference.html.ini index b7248b8df50..193b9f252c9 100644 --- a/tests/wpt/metadata/css/css-variables/variable-reference.html.ini +++ b/tests/wpt/metadata/css/css-variables/variable-reference.html.ini @@ -1,6 +1,3 @@ [variable-reference.html] [Variable reference left open at end of stylesheet] expected: FAIL - - [width: var(--prop,);] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-substitution-variable-declaration.html.ini b/tests/wpt/metadata/css/css-variables/variable-substitution-variable-declaration.html.ini index 7e95ee1dde0..60c36462bdc 100644 --- a/tests/wpt/metadata/css/css-variables/variable-substitution-variable-declaration.html.ini +++ b/tests/wpt/metadata/css/css-variables/variable-substitution-variable-declaration.html.ini @@ -1,24 +1,3 @@ [variable-substitution-variable-declaration.html] [target10 --varC] expected: FAIL - - [target1 --var2] - expected: FAIL - - [target2 --var1] - expected: FAIL - - [target3 --var1] - expected: FAIL - - [target3 --var2] - expected: FAIL - - [target4 --varC] - expected: FAIL - - [target8 --varB] - expected: FAIL - - [target9 --varA] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-supports-05.html.ini b/tests/wpt/metadata/css/css-variables/variable-supports-05.html.ini deleted file mode 100644 index 4d0f1862a6c..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-supports-05.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-05.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-supports-07.html.ini b/tests/wpt/metadata/css/css-variables/variable-supports-07.html.ini deleted file mode 100644 index 69995c11cbe..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-supports-07.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-07.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-supports-37.html.ini b/tests/wpt/metadata/css/css-variables/variable-supports-37.html.ini deleted file mode 100644 index c9b4e3a1ea4..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-supports-37.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-37.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-supports-39.html.ini b/tests/wpt/metadata/css/css-variables/variable-supports-39.html.ini deleted file mode 100644 index 11fc7d6d05c..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-supports-39.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-39.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-supports-57.html.ini b/tests/wpt/metadata/css/css-variables/variable-supports-57.html.ini deleted file mode 100644 index 676c3da63fa..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-supports-57.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-57.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/css-variables/variable-supports-58.html.ini b/tests/wpt/metadata/css/css-variables/variable-supports-58.html.ini deleted file mode 100644 index ebf7e5d65d9..00000000000 --- a/tests/wpt/metadata/css/css-variables/variable-supports-58.html.ini +++ /dev/null @@ -1,2 +0,0 @@ -[variable-supports-58.html] - expected: FAIL diff --git a/tests/wpt/metadata/css/cssom/serialize-variable-reference.html.ini b/tests/wpt/metadata/css/cssom/serialize-variable-reference.html.ini deleted file mode 100644 index 0441ef458d3..00000000000 --- a/tests/wpt/metadata/css/cssom/serialize-variable-reference.html.ini +++ /dev/null @@ -1,6 +0,0 @@ -[serialize-variable-reference.html] - [Longhand with variable preserves original serialization but trims whitespace: without whitespace] - expected: FAIL - - [Shorthand with variable preserves original serialization but trims whitespace: without whitespace] - expected: FAIL diff --git a/tests/wpt/mozilla/meta-layout-2020/css/test_variable_serialization_computed.html.ini b/tests/wpt/mozilla/meta-layout-2020/css/test_variable_serialization_computed.html.ini index 379a8dea72f..92035e18fb2 100644 --- a/tests/wpt/mozilla/meta-layout-2020/css/test_variable_serialization_computed.html.ini +++ b/tests/wpt/mozilla/meta-layout-2020/css/test_variable_serialization_computed.html.ini @@ -1,3 +1,3 @@ [test_variable_serialization_computed.html] - [subtest #23 with `counter-reset: var(--a)red; --a:orange;`] + [subtest #29 with `counter-reset: var(--a)red; --a:orange;`] expected: FAIL diff --git a/tests/wpt/mozilla/meta/MANIFEST.json b/tests/wpt/mozilla/meta/MANIFEST.json index 2b08028733d..f8593976dd6 100644 --- a/tests/wpt/mozilla/meta/MANIFEST.json +++ b/tests/wpt/mozilla/meta/MANIFEST.json @@ -12624,7 +12624,7 @@ ] ], "test_variable_serialization_computed.html": [ - "a7f0b63d1c415f2fb49badcedc780f26f6bd3058", + "4b051b2462face35b8a7f982f1826248901ca867", [ null, {} diff --git a/tests/wpt/mozilla/tests/css/test_variable_serialization_computed.html b/tests/wpt/mozilla/tests/css/test_variable_serialization_computed.html index a7f0b63d1c4..4b051b2462f 100644 --- a/tests/wpt/mozilla/tests/css/test_variable_serialization_computed.html +++ b/tests/wpt/mozilla/tests/css/test_variable_serialization_computed.html @@ -22,43 +22,47 @@ so an implementation could fail this test but still be conforming. // its expected computed value. var values = [ ["", "--z", "an-inherited-value"], - ["--a: ", "--a", " "], + ["--a: ", "--a", ""], ["--a: initial", "--a", ""], ["--z: initial", "--z", ""], ["--a: inherit", "--a", ""], ["--z: inherit", "--z", "an-inherited-value"], ["--a: unset", "--a", ""], ["--z: unset", "--z", "an-inherited-value"], - ["--a: 1px", "--a", " 1px"], + ["--a: 1px", "--a", "1px"], ["--a: var(--a)", "--a", ""], ["--a: var(--b)", "--a", ""], - ["--a: var(--b); --b: 1px", "--a", " 1px"], - ["--a: var(--b, 1px)", "--a", " 1px"], + ["--a: var(--b); --b: 1px", "--a", "1px"], + ["--a: var(--b, 1px)", "--a", "1px"], ["--a: var(--a, 1px)", "--a", ""], ["--a: something 3px url(whereever) calc(var(--a) + 1px)", "--a", ""], - ["--a: something 3px url(whereever) calc(var(--b,1em) + 1px)", "--a", " something 3px url(whereever) calc(1em + 1px)"], - ["--a: var(--b, var(--c, var(--d, Black)))", "--a", " Black"], - ["--a: a var(--b) c; --b:b", "--a", " a b c"], - ["--a: a var(--b,b var(--c) d) e; --c:c", "--a", " a b c d e"], - ["--a: var(--b)red; --b:orange;", "--a", " orange/**/red"], - ["--a: var(--b)var(--c); --b:orange; --c:red;", "--a", " orange/**/red"], - ["--a: var(--b)var(--c,red); --b:orange;", "--a", " orange/**/red"], - ["--a: var(--b,orange)var(--c); --c:red;", "--a", " orange/**/red"], + ["--a: something 3px url(whereever) calc(var(--b,1em) + 1px)", "--a", "something 3px url(whereever) calc(1em + 1px)"], + ["--a: var(--b, var(--c, var(--d, Black)))", "--a", "Black"], + ["--a: a var(--b) c; --b:b", "--a", "a b c"], + ["--a: a var(--b,b var(--c) d) e; --c:c", "--a", "a b c d e"], + ["--a: var(--b)red; --b:orange;", "--a", "orange/**/red"], + ["--a: var(--b)var(--c); --b:orange; --c:red;", "--a", "orange/**/red"], + ["--a: var(--b)var(--c,red); --b:orange;", "--a", "orange/**/red"], + ["--a: var(--b,orange)var(--c); --c:red;", "--a", "orange/**/red"], + ["--a: var(--b)-; --b:-;", "--a", "-/**/-"], + ["--a: var(--b)--; --b:-;", "--a", "-/**/--"], + ["--a: var(--b)--x; --b:-;", "--a", "-/**/--x"], + ["--a: var(--b)var(--c); --b:-; --c:-;", "--a", "-/**/-"], + ["--a: var(--b)var(--c); --b:--; --c:-;", "--a", "--/**/-"], + ["--a: var(--b)var(--c); --b:--x; --c:-;", "--a", "--x/**/-"], ["counter-reset: var(--a)red; --a:orange;", "counter-reset", "orange 0 red 0"], - ["--a: var(--b)var(--c); --c:[c]; --b:('ab", "--a", " ('ab')[c]"], - ["--a: '", "--a", " ''"], - ["--a: '\\", "--a", " ''"], - ["--a: \\", "--a", " \\\ufffd"], - ["--a: \"", "--a", " \"\""], - ["--a: \"\\", "--a", " \"\""], - ["--a: /* abc ", "--a", " /* abc */"], - ["--a: /* abc *", "--a", " /* abc */"], - ["--a: url(http://example.org/", "--a", " url(http://example.org/)"], - ["--a: url(http://example.org/\\", "--a", " url(http://example.org/\\\ufffd)"], - ["--a: url('http://example.org/", "--a", " url('http://example.org/')"], - ["--a: url('http://example.org/\\", "--a", " url('http://example.org/')"], - ["--a: url(\"http://example.org/", "--a", " url(\"http://example.org/\")"], - ["--a: url(\"http://example.org/\\", "--a", " url(\"http://example.org/\")"] + ["--a: var(--b)var(--c); --c:[c]; --b:('ab", "--a", "('ab')[c]"], + ["--a: '", "--a", "''"], + ["--a: '\\", "--a", "''"], + ["--a: \\", "--a", "\\\ufffd"], + ["--a: \"", "--a", "\"\""], + ["--a: \"\\", "--a", "\"\""], + ["--a: url(http://example.org/", "--a", "url(http://example.org/)"], + ["--a: url(http://example.org/\\", "--a", "url(http://example.org/\\\ufffd)"], + ["--a: url('http://example.org/", "--a", "url('http://example.org/')"], + ["--a: url('http://example.org/\\", "--a", "url('http://example.org/')"], + ["--a: url(\"http://example.org/", "--a", "url(\"http://example.org/\")"], + ["--a: url(\"http://example.org/\\", "--a", "url(\"http://example.org/\")"] ]; var div = document.querySelector("div");