diff options
author | Jonathan Kew <jkew@mozilla.com> | 2022-10-07 23:00:43 +0000 |
---|---|---|
committer | Martin Robinson <mrobinson@igalia.com> | 2023-11-03 08:59:49 +0100 |
commit | a4ad5e19b0ec17d7e55e468cd9370fe7996b8bc9 (patch) | |
tree | 4bd6b90d0cae03e11b2e57103a5b4ce34ff10baf /components/style | |
parent | ab4580e112ef2c4e2afb13296b73d17940b86004 (diff) | |
download | servo-a4ad5e19b0ec17d7e55e468cd9370fe7996b8bc9.tar.gz servo-a4ad5e19b0ec17d7e55e468cd9370fe7996b8bc9.zip |
style: Implement CSS parsing for the @font-palette-values rule
Not yet hooked up to any rendering functionality.
The intention is for both the @font-palette-values at-rule and the font-palette property
to be behind the same pref being introduced here.
Differential Revision: https://phabricator.services.mozilla.com/D157953
Diffstat (limited to 'components/style')
-rw-r--r-- | components/style/error_reporting.rs | 10 | ||||
-rw-r--r-- | components/style/gecko/arc_types.rs | 15 | ||||
-rw-r--r-- | components/style/invalidation/stylesheets.rs | 4 | ||||
-rw-r--r-- | components/style/stylesheets/font_feature_values_rule.rs | 19 | ||||
-rw-r--r-- | components/style/stylesheets/font_palette_values_rule.rs | 215 | ||||
-rw-r--r-- | components/style/stylesheets/mod.rs | 11 | ||||
-rw-r--r-- | components/style/stylesheets/rule_parser.rs | 29 | ||||
-rw-r--r-- | components/style/stylesheets/rules_iterator.rs | 3 | ||||
-rw-r--r-- | components/style/stylesheets/stylesheet.rs | 1 | ||||
-rw-r--r-- | components/style/stylist.rs | 26 | ||||
-rw-r--r-- | components/style/values/mod.rs | 38 | ||||
-rw-r--r-- | components/style/values/specified/mod.rs | 12 |
12 files changed, 353 insertions, 30 deletions
diff --git a/components/style/error_reporting.rs b/components/style/error_reporting.rs index 752f68b5bdc..042838f3394 100644 --- a/components/style/error_reporting.rs +++ b/components/style/error_reporting.rs @@ -26,6 +26,8 @@ pub enum ContextualParseError<'a> { UnsupportedFontFaceDescriptor(&'a str, ParseError<'a>), /// A font feature values descriptor was not recognized. UnsupportedFontFeatureValuesDescriptor(&'a str, ParseError<'a>), + /// A font palette values descriptor was not recognized. + UnsupportedFontPaletteValuesDescriptor(&'a str, ParseError<'a>), /// A keyframe rule was not valid. InvalidKeyframeRule(&'a str, ParseError<'a>), /// A font feature values rule was not valid. @@ -149,6 +151,14 @@ impl<'a> fmt::Display for ContextualParseError<'a> { )?; parse_error_to_str(err, f) }, + ContextualParseError::UnsupportedFontPaletteValuesDescriptor(decl, ref err) => { + write!( + f, + "Unsupported @font-palette-values descriptor declaration: '{}', ", + decl + )?; + parse_error_to_str(err, f) + }, ContextualParseError::InvalidKeyframeRule(rule, ref err) => { write!(f, "Invalid keyframe rule: '{}', ", rule)?; parse_error_to_str(err, f) diff --git a/components/style/gecko/arc_types.rs b/components/style/gecko/arc_types.rs index bb1d88d8a55..fc712422536 100644 --- a/components/style/gecko/arc_types.rs +++ b/components/style/gecko/arc_types.rs @@ -12,10 +12,10 @@ use crate::gecko::url::CssUrlData; use crate::gecko_bindings::structs::{ RawServoAnimationValue, RawServoContainerRule, RawServoCounterStyleRule, RawServoCssUrlData, RawServoDeclarationBlock, RawServoFontFaceRule, RawServoFontFeatureValuesRule, - RawServoImportRule, RawServoKeyframe, RawServoKeyframesRule, RawServoLayerBlockRule, - RawServoLayerStatementRule, RawServoMediaList, RawServoMediaRule, RawServoMozDocumentRule, - RawServoNamespaceRule, RawServoPageRule, RawServoStyleRule, RawServoStyleSheetContents, - RawServoSupportsRule, ServoCssRules, + RawServoFontPaletteValuesRule, RawServoImportRule, RawServoKeyframe, RawServoKeyframesRule, + RawServoLayerBlockRule, RawServoLayerStatementRule, RawServoMediaList, RawServoMediaRule, + RawServoMozDocumentRule, RawServoNamespaceRule, RawServoPageRule, RawServoStyleRule, + RawServoStyleSheetContents, RawServoSupportsRule, ServoCssRules, }; use crate::gecko_bindings::sugar::ownership::{HasArcFFI, HasFFI, Strong}; use crate::media_queries::MediaList; @@ -25,8 +25,8 @@ use crate::shared_lock::Locked; use crate::stylesheets::keyframes_rule::Keyframe; use crate::stylesheets::{ ContainerRule, CounterStyleRule, CssRules, DocumentRule, FontFaceRule, FontFeatureValuesRule, - ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule, MediaRule, NamespaceRule, - PageRule, StyleRule, StylesheetContents, SupportsRule, + FontPaletteValuesRule, ImportRule, KeyframesRule, LayerBlockRule, LayerStatementRule, + MediaRule, NamespaceRule, PageRule, StyleRule, StylesheetContents, SupportsRule, }; use servo_arc::{Arc, ArcBorrow}; use std::{mem, ptr}; @@ -104,6 +104,9 @@ impl_arc_ffi!(Locked<DocumentRule> => RawServoMozDocumentRule impl_arc_ffi!(Locked<FontFeatureValuesRule> => RawServoFontFeatureValuesRule [Servo_FontFeatureValuesRule_AddRef, Servo_FontFeatureValuesRule_Release]); +impl_arc_ffi!(Locked<FontPaletteValuesRule> => RawServoFontPaletteValuesRule + [Servo_FontPaletteValuesRule_AddRef, Servo_FontPaletteValuesRule_Release]); + impl_arc_ffi!(Locked<FontFaceRule> => RawServoFontFaceRule [Servo_FontFaceRule_AddRef, Servo_FontFaceRule_Release]); diff --git a/components/style/invalidation/stylesheets.rs b/components/style/invalidation/stylesheets.rs index b367e18daa9..f18fe7942c5 100644 --- a/components/style/invalidation/stylesheets.rs +++ b/components/style/invalidation/stylesheets.rs @@ -552,6 +552,7 @@ impl StylesheetInvalidationSet { Page(..) | Viewport(..) | FontFeatureValues(..) | + FontPaletteValues(..) | LayerStatement(..) | FontFace(..) | Keyframes(..) | @@ -632,7 +633,8 @@ impl StylesheetInvalidationSet { // existing elements. } }, - CounterStyle(..) | Page(..) | Viewport(..) | FontFeatureValues(..) => { + CounterStyle(..) | Page(..) | Viewport(..) | FontFeatureValues(..) | + FontPaletteValues(..) => { debug!( " > Found unsupported rule, marking the whole subtree \ invalid." diff --git a/components/style/stylesheets/font_feature_values_rule.rs b/components/style/stylesheets/font_feature_values_rule.rs index dc128e77fb0..784628f0dde 100644 --- a/components/style/stylesheets/font_feature_values_rule.rs +++ b/components/style/stylesheets/font_feature_values_rule.rs @@ -275,23 +275,6 @@ macro_rules! font_feature_values_blocks { rule } - /// Prints font family names. - pub fn font_family_to_css<W>( - &self, - dest: &mut CssWriter<W>, - ) -> fmt::Result - where - W: Write, - { - let mut iter = self.family_names.iter(); - iter.next().unwrap().to_css(dest)?; - for val in iter { - dest.write_str(", ")?; - val.to_css(dest)?; - } - Ok(()) - } - /// Prints inside of `@font-feature-values` block. pub fn value_to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where @@ -349,7 +332,7 @@ macro_rules! font_feature_values_blocks { impl ToCssWithGuard for FontFeatureValuesRule { fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result { dest.write_str("@font-feature-values ")?; - self.font_family_to_css(&mut CssWriter::new(dest))?; + self.family_names.to_css(&mut CssWriter::new(dest))?; dest.write_str(" {\n")?; self.value_to_css(&mut CssWriter::new(dest))?; dest.write_str("}") diff --git a/components/style/stylesheets/font_palette_values_rule.rs b/components/style/stylesheets/font_palette_values_rule.rs new file mode 100644 index 00000000000..95d62443321 --- /dev/null +++ b/components/style/stylesheets/font_palette_values_rule.rs @@ -0,0 +1,215 @@ +/* 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/. */ + +//! The [`@font-palette-values`][font-palette-values] at-rule. +//! +//! [font-palette-values]: https://drafts.csswg.org/css-fonts/#font-palette-values + +use crate::error_reporting::ContextualParseError; +use crate::parser::{Parse, ParserContext}; +use crate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; +use crate::str::CssStringWriter; +use crate::values::computed::font::FamilyName; +use crate::values::specified::Color as SpecifiedColor; +use crate::values::specified::NonNegativeInteger; +use crate::values::DashedIdent; +use cssparser::{AtRuleParser, CowRcStr}; +use cssparser::{DeclarationParser, DeclarationListParser, Parser}; +use cssparser::{QualifiedRuleParser, SourceLocation}; +use std::fmt::{self, Write}; +use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; +use style_traits::{Comma, OneOrMoreSeparated}; +use selectors::parser::SelectorParseErrorKind; +use crate::stylesheets::font_feature_values_rule::parse_family_name_list; + +#[allow(missing_docs)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)] +pub struct FontPaletteOverrideColor { + index: NonNegativeInteger, + color: SpecifiedColor, +} + +impl Parse for FontPaletteOverrideColor { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<FontPaletteOverrideColor, ParseError<'i>> { + let index = NonNegativeInteger::parse(context, input)?; + let location = input.current_source_location(); + let color = SpecifiedColor::parse(context, input)?; + // Only absolute colors are accepted here. + if let SpecifiedColor::Numeric { parsed: _, authored: _ } = color { + Ok(FontPaletteOverrideColor{ index, color }) + } else { + Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + } + } +} + +impl ToCss for FontPaletteOverrideColor { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: fmt::Write, + { + self.index.to_css(dest)?; + dest.write_str(" ")?; + self.color.to_css(dest) + } +} + +impl OneOrMoreSeparated for FontPaletteOverrideColor { + type S = Comma; +} + +impl OneOrMoreSeparated for FamilyName { + type S = Comma; +} + +#[allow(missing_docs)] +#[derive(Clone, Debug, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)] +pub enum FontPaletteBase { + Light, + Dark, + Index(NonNegativeInteger), +} + +/// The [`@font-palette-values`][font-palette-values] at-rule. +/// +/// [font-palette-values]: https://drafts.csswg.org/css-fonts/#font-palette-values +#[derive(Clone, Debug, PartialEq, ToShmem)] +pub struct FontPaletteValuesRule { + /// Palette name. + pub name: DashedIdent, + /// Font family list for @font-palette-values rule. + /// Family names cannot contain generic families. FamilyName + /// also accepts only non-generic names. + pub family_names: Vec<FamilyName>, + /// The base palette. + pub base_palette: Option<FontPaletteBase>, + /// The list of override colors. + pub override_colors: Vec<FontPaletteOverrideColor>, + /// The line and column of the rule's source code. + pub source_location: SourceLocation, +} + +impl FontPaletteValuesRule { + /// Creates an empty FontPaletteValuesRule with given location and name. + fn new(name: DashedIdent, location: SourceLocation) -> Self { + FontPaletteValuesRule { + name, + family_names: vec![], + base_palette: None, + override_colors: vec![], + source_location: location, + } + } + + /// Parses a `FontPaletteValuesRule`. + pub fn parse( + context: &ParserContext, + input: &mut Parser, + name: DashedIdent, + location: SourceLocation, + ) -> Self { + let mut rule = FontPaletteValuesRule::new(name, location); + { + let parser = FontPaletteValuesDeclarationParser { + context: context, + rule: &mut rule, + }; + let mut iter = DeclarationListParser::new(input, parser); + while let Some(declaration) = iter.next() { + if let Err((error, slice)) = declaration { + let location = error.location; + let error = ContextualParseError::UnsupportedFontPaletteValuesDescriptor(slice, error); + context.log_css_error(location, error); + } + } + } + rule + } + + /// Prints inside of `@font-palette-values` block. + fn value_to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: Write, + { + if !self.family_names.is_empty() { + dest.write_str("font-family: ")?; + self.family_names.to_css(dest)?; + dest.write_str("; ")?; + } + if let Some(base) = &self.base_palette { + dest.write_str("base-palette: ")?; + base.to_css(dest)?; + dest.write_str("; ")?; + } + if !self.override_colors.is_empty() { + dest.write_str("override-colors: ")?; + self.override_colors.to_css(dest)?; + dest.write_str("; ")?; + } + Ok(()) + } +} + +impl ToCssWithGuard for FontPaletteValuesRule { + fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result { + dest.write_str("@font-palette-values ")?; + self.name.to_css(&mut CssWriter::new(dest))?; + dest.write_str(" { ")?; + self.value_to_css(&mut CssWriter::new(dest))?; + dest.write_str("}") + } +} + +/// Parser for declarations in `FontPaletteValuesRule`. +struct FontPaletteValuesDeclarationParser<'a> { + context: &'a ParserContext<'a>, + rule: &'a mut FontPaletteValuesRule, +} + +impl<'a, 'i> AtRuleParser<'i> for FontPaletteValuesDeclarationParser<'a> { + type Prelude = (); + type AtRule = (); + type Error = StyleParseErrorKind<'i>; +} + +impl<'a, 'i> QualifiedRuleParser<'i> for FontPaletteValuesDeclarationParser<'a> { + type Prelude = (); + type QualifiedRule = (); + type Error = StyleParseErrorKind<'i>; +} + +fn parse_override_colors<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, +) -> Result<Vec<FontPaletteOverrideColor>, ParseError<'i>> { + input.parse_comma_separated(|i| FontPaletteOverrideColor::parse(context, i)) +} + +impl<'a, 'b, 'i> DeclarationParser<'i> for FontPaletteValuesDeclarationParser<'a> { + type Declaration = (); + type Error = StyleParseErrorKind<'i>; + + fn parse_value<'t>( + &mut self, + name: CowRcStr<'i>, + input: &mut Parser<'i, 't>, + ) -> Result<(), ParseError<'i>> { + match_ignore_ascii_case! { &*name, + "font-family" => { + self.rule.family_names = parse_family_name_list(self.context, input)? + }, + "base-palette" => { + self.rule.base_palette = Some(input.parse_entirely(|i| FontPaletteBase::parse(self.context, i))?) + }, + "override-colors" => { + self.rule.override_colors = parse_override_colors(self.context, input)? + }, + _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))), + } + Ok(()) + } +} diff --git a/components/style/stylesheets/mod.rs b/components/style/stylesheets/mod.rs index 9625ad62cb3..01b0c07d7a9 100644 --- a/components/style/stylesheets/mod.rs +++ b/components/style/stylesheets/mod.rs @@ -10,6 +10,7 @@ mod counter_style_rule; mod document_rule; mod font_face_rule; pub mod font_feature_values_rule; +pub mod font_palette_values_rule; pub mod import_rule; pub mod keyframes_rule; pub mod layer_rule; @@ -50,6 +51,7 @@ pub use self::counter_style_rule::CounterStyleRule; pub use self::document_rule::DocumentRule; pub use self::font_face_rule::FontFaceRule; pub use self::font_feature_values_rule::FontFeatureValuesRule; +pub use self::font_palette_values_rule::FontPaletteValuesRule; pub use self::import_rule::ImportRule; pub use self::keyframes_rule::KeyframesRule; pub use self::layer_rule::{LayerBlockRule, LayerStatementRule}; @@ -256,6 +258,7 @@ pub enum CssRule { Container(Arc<Locked<ContainerRule>>), FontFace(Arc<Locked<FontFaceRule>>), FontFeatureValues(Arc<Locked<FontFeatureValuesRule>>), + FontPaletteValues(Arc<Locked<FontPaletteValuesRule>>), CounterStyle(Arc<Locked<CounterStyleRule>>), Viewport(Arc<Locked<ViewportRule>>), Keyframes(Arc<Locked<KeyframesRule>>), @@ -293,6 +296,7 @@ impl CssRule { CssRule::FontFace(_) => 0, CssRule::FontFeatureValues(_) => 0, + CssRule::FontPaletteValues(_) => 0, CssRule::CounterStyle(_) => 0, CssRule::Viewport(_) => 0, CssRule::Keyframes(_) => 0, @@ -348,6 +352,7 @@ pub enum CssRuleType { LayerBlock = 16, LayerStatement = 17, Container = 18, + FontPaletteValues = 19, } #[allow(missing_docs)] @@ -367,6 +372,7 @@ impl CssRule { CssRule::Media(_) => CssRuleType::Media, CssRule::FontFace(_) => CssRuleType::FontFace, CssRule::FontFeatureValues(_) => CssRuleType::FontFeatureValues, + CssRule::FontPaletteValues(_) => CssRuleType::FontPaletteValues, CssRule::CounterStyle(_) => CssRuleType::CounterStyle, CssRule::Keyframes(_) => CssRuleType::Keyframes, CssRule::Namespace(_) => CssRuleType::Namespace, @@ -474,6 +480,10 @@ impl DeepCloneWithLock for CssRule { let rule = arc.read_with(guard); CssRule::FontFeatureValues(Arc::new(lock.wrap(rule.clone()))) }, + CssRule::FontPaletteValues(ref arc) => { + let rule = arc.read_with(guard); + CssRule::FontPaletteValues(Arc::new(lock.wrap(rule.clone()))) + }, CssRule::CounterStyle(ref arc) => { let rule = arc.read_with(guard); CssRule::CounterStyle(Arc::new(lock.wrap(rule.clone()))) @@ -531,6 +541,7 @@ impl ToCssWithGuard for CssRule { CssRule::Style(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::FontFace(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::FontFeatureValues(ref lock) => lock.read_with(guard).to_css(guard, dest), + CssRule::FontPaletteValues(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::CounterStyle(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::Viewport(ref lock) => lock.read_with(guard).to_css(guard, dest), CssRule::Keyframes(ref lock) => lock.read_with(guard).to_css(guard, dest), diff --git a/components/style/stylesheets/rule_parser.rs b/components/style/stylesheets/rule_parser.rs index 659b704161e..9fe2d0c87e9 100644 --- a/components/style/stylesheets/rule_parser.rs +++ b/components/style/stylesheets/rule_parser.rs @@ -23,11 +23,12 @@ use crate::stylesheets::stylesheet::Namespaces; use crate::stylesheets::supports_rule::SupportsCondition; use crate::stylesheets::{ viewport_rule, AllowImportRules, CorsMode, CssRule, CssRuleType, CssRules, DocumentRule, - FontFeatureValuesRule, KeyframesRule, MediaRule, NamespaceRule, PageRule, PageSelectors, - RulesMutateError, StyleRule, StylesheetLoader, SupportsRule, ViewportRule, + FontFeatureValuesRule, FontPaletteValuesRule, KeyframesRule, MediaRule, NamespaceRule, + PageRule, PageSelectors, RulesMutateError, StyleRule, StylesheetLoader, SupportsRule, + ViewportRule, }; use crate::values::computed::font::FamilyName; -use crate::values::{CssUrl, CustomIdent, KeyframesName}; +use crate::values::{CssUrl, CustomIdent, DashedIdent, KeyframesName}; use crate::{Namespace, Prefix}; use cssparser::{ AtRuleParser, BasicParseError, BasicParseErrorKind, CowRcStr, Parser, ParserState, @@ -184,6 +185,8 @@ pub enum AtRulePrelude { FontFace, /// A @font-feature-values rule prelude, with its FamilyName list. FontFeatureValues(Vec<FamilyName>), + /// A @font-palette-values rule prelude, with its identifier. + FontPaletteValues(DashedIdent), /// A @counter-style rule prelude, with its counter style name. CounterStyle(CustomIdent), /// A @media rule prelude, with its media queries. @@ -500,6 +503,10 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { let family_names = parse_family_name_list(self.context, input)?; AtRulePrelude::FontFeatureValues(family_names) }, + "font-palette-values" if static_prefs::pref!("layout.css.font-palette.enabled") => { + let name = DashedIdent::parse(self.context, input)?; + AtRulePrelude::FontPaletteValues(name) + }, "counter-style" if cfg!(feature = "gecko") => { let name = parse_counter_style_name_definition(input)?; AtRulePrelude::CounterStyle(name) @@ -573,6 +580,22 @@ impl<'a, 'b, 'i> AtRuleParser<'i> for NestedRuleParser<'a, 'b> { ), )))) }, + AtRulePrelude::FontPaletteValues(name) => { + let context = ParserContext::new_with_rule_type( + self.context, + CssRuleType::FontPaletteValues, + self.namespaces, + ); + + Ok(CssRule::FontPaletteValues(Arc::new(self.shared_lock.wrap( + FontPaletteValuesRule::parse( + &context, + input, + name, + start.source_location(), + ), + )))) + }, AtRulePrelude::CounterStyle(name) => { let context = ParserContext::new_with_rule_type( self.context, diff --git a/components/style/stylesheets/rules_iterator.rs b/components/style/stylesheets/rules_iterator.rs index 5c90e506714..00c095bb8b8 100644 --- a/components/style/stylesheets/rules_iterator.rs +++ b/components/style/stylesheets/rules_iterator.rs @@ -70,7 +70,8 @@ where CssRule::Keyframes(_) | CssRule::Page(_) | CssRule::LayerStatement(_) | - CssRule::FontFeatureValues(_) => None, + CssRule::FontFeatureValues(_) | + CssRule::FontPaletteValues(_) => None, CssRule::Import(ref import_rule) => { let import_rule = import_rule.read_with(guard); if !C::process_import(guard, device, quirks_mode, import_rule) { diff --git a/components/style/stylesheets/stylesheet.rs b/components/style/stylesheets/stylesheet.rs index 51a1a29ac07..a1a678ec436 100644 --- a/components/style/stylesheets/stylesheet.rs +++ b/components/style/stylesheets/stylesheet.rs @@ -381,6 +381,7 @@ impl SanitizationKind { CssRule::Keyframes(..) | CssRule::Page(..) | CssRule::FontFeatureValues(..) | + CssRule::FontPaletteValues(..) | CssRule::Viewport(..) | CssRule::CounterStyle(..) => !is_standard, } diff --git a/components/style/stylist.rs b/components/style/stylist.rs index 487f3ade5de..8dfdc91e58b 100644 --- a/components/style/stylist.rs +++ b/components/style/stylist.rs @@ -32,7 +32,9 @@ use crate::stylesheets::keyframes_rule::KeyframesAnimation; use crate::stylesheets::layer_rule::{LayerName, LayerOrder}; use crate::stylesheets::viewport_rule::{self, MaybeNew, ViewportRule}; #[cfg(feature = "gecko")] -use crate::stylesheets::{CounterStyleRule, FontFaceRule, FontFeatureValuesRule, PageRule}; +use crate::stylesheets::{ + CounterStyleRule, FontFaceRule, FontFeatureValuesRule, FontPaletteValuesRule, PageRule, +}; use crate::stylesheets::{ CssRule, EffectiveRulesIterator, Origin, OriginSet, PageRule, PerOrigin, PerOriginIter, }; @@ -1679,6 +1681,10 @@ pub struct ExtraStyleData { #[cfg(feature = "gecko")] pub font_feature_values: LayerOrderedVec<Arc<Locked<FontFeatureValuesRule>>>, + /// A list of effective font-palette-values rules. + #[cfg(feature = "gecko")] + pub font_palette_values: LayerOrderedVec<Arc<Locked<FontPaletteValuesRule>>>, + /// A map of effective counter-style rules. #[cfg(feature = "gecko")] pub counter_styles: LayerOrderedMap<Arc<Locked<CounterStyleRule>>>, @@ -1704,6 +1710,15 @@ impl ExtraStyleData { self.font_feature_values.push(rule.clone(), layer); } + /// Add the given @font-palette-values rule. + fn add_font_palette_values( + &mut self, + rule: &Arc<Locked<FontPaletteValuesRule>>, + layer: LayerId, + ) { + self.font_palette_values.push(rule.clone(), layer); + } + /// Add the given @counter-style rule. fn add_counter_style( &mut self, @@ -1745,6 +1760,7 @@ impl ExtraStyleData { fn sort_by_layer(&mut self, layers: &[CascadeLayer]) { self.font_faces.sort(layers); self.font_feature_values.sort(layers); + self.font_palette_values.sort(layers); self.counter_styles.sort(layers); self.pages.global.sort(layers); } @@ -1754,6 +1770,7 @@ impl ExtraStyleData { { self.font_faces.clear(); self.font_feature_values.clear(); + self.font_palette_values.clear(); self.counter_styles.clear(); self.pages.clear(); } @@ -1790,6 +1807,7 @@ impl MallocSizeOf for ExtraStyleData { let mut n = 0; n += self.font_faces.shallow_size_of(ops); n += self.font_feature_values.shallow_size_of(ops); + n += self.font_palette_values.shallow_size_of(ops); n += self.counter_styles.shallow_size_of(ops); n += self.pages.shallow_size_of(ops); n @@ -2638,6 +2656,11 @@ impl CascadeData { .add_font_feature_values(rule, containing_rule_state.layer_id); }, #[cfg(feature = "gecko")] + CssRule::FontPaletteValues(ref rule) => { + self.extra_data + .add_font_palette_values(rule, containing_rule_state.layer_id); + }, + #[cfg(feature = "gecko")] CssRule::CounterStyle(ref rule) => { self.extra_data.add_counter_style( guard, @@ -2888,6 +2911,7 @@ impl CascadeData { CssRule::Document(..) | CssRule::LayerBlock(..) | CssRule::LayerStatement(..) | + CssRule::FontPaletteValues(..) | CssRule::FontFeatureValues(..) => { // Not affected by device changes. continue; diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 2a0481ab684..c0ddeddd7ee 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -492,6 +492,44 @@ impl ToCss for CustomIdent { } } +/// <https://www.w3.org/TR/css-values-4/#dashed-idents> +/// This is simply an Atom, but will only parse if the identifier starts with "--". +#[repr(transparent)] +#[derive( + Clone, + Debug, + Eq, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +pub struct DashedIdent(pub Atom); + +impl Parse for DashedIdent { + fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> { + let location = input.current_source_location(); + let ident = input.expect_ident()?; + if ident.starts_with("--") { + Ok(Self(Atom::from(ident.as_ref()))) + } else { + Err(location.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone()))) + } + } +} + +impl ToCss for DashedIdent { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: Write, + { + serialize_atom_identifier(&self.0, dest) + } +} + /// The <timeline-name> or <keyframes-name>. /// The definition of these two names are the same, so we use the same type for them. /// diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index b31bc17300e..e157f59d993 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -411,6 +411,18 @@ impl NonNegativeNumber { } } +/// An Integer which is >= 0. +pub type NonNegativeInteger = NonNegative<Integer>; + +impl Parse for NonNegativeInteger { + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + Ok(NonNegative(Integer::parse_non_negative(context, input)?)) + } +} + /// A Number which is >= 1.0. pub type GreaterThanOrEqualToOneNumber = GreaterThanOrEqualToOne<Number>; |