mirror of
https://github.com/servo/servo.git
synced 2025-10-03 18:19:14 +01:00
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
215 lines
7.2 KiB
Rust
215 lines
7.2 KiB
Rust
/* 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(())
|
|
}
|
|
}
|