mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
Auto merge of #19167 - CYBAI:font-variant-alternates-out-of-mako, r=emilio
style: Move font-variant-alternates outside of mako This is a sub-PR of #19015 r? emilio --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix #19166 (github issue number if applicable). - [x] These changes do not require tests <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19167) <!-- Reviewable:end -->
This commit is contained in:
commit
33fa728d6e
6 changed files with 317 additions and 205 deletions
|
@ -2402,7 +2402,7 @@ fn static_assert() {
|
|||
<% impl_simple_type_with_conversion("font_language_override", "mFont.languageOverride") %>
|
||||
|
||||
pub fn set_font_variant_alternates(&mut self,
|
||||
v: longhands::font_variant_alternates::computed_value::T,
|
||||
v: values::computed::font::FontVariantAlternates,
|
||||
device: &Device) {
|
||||
use gecko_bindings::bindings::{Gecko_ClearAlternateValues, Gecko_AppendAlternateValues};
|
||||
use gecko_bindings::bindings::Gecko_nsFont_ResetFontFeatureValuesLookup;
|
||||
|
@ -2410,7 +2410,7 @@ fn static_assert() {
|
|||
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
|
||||
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
|
||||
% endfor
|
||||
use self::longhands::font_variant_alternates::VariantAlternates;
|
||||
use values::specified::font::VariantAlternates;
|
||||
|
||||
unsafe {
|
||||
Gecko_ClearAlternateValues(&mut self.gecko.mFont, v.len());
|
||||
|
@ -2471,13 +2471,13 @@ fn static_assert() {
|
|||
self.copy_font_variant_alternates_from(other)
|
||||
}
|
||||
|
||||
pub fn clone_font_variant_alternates(&self) -> longhands::font_variant_alternates::computed_value::T {
|
||||
pub fn clone_font_variant_alternates(&self) -> values::computed::font::FontVariantAlternates {
|
||||
use Atom;
|
||||
% for value in "normal swash stylistic ornaments annotation styleset character_variant historical".split():
|
||||
use gecko_bindings::structs::NS_FONT_VARIANT_ALTERNATES_${value.upper()};
|
||||
% endfor
|
||||
use properties::longhands::font_variant_alternates::VariantAlternates;
|
||||
use properties::longhands::font_variant_alternates::VariantAlternatesList;
|
||||
use values::specified::font::VariantAlternates;
|
||||
use values::specified::font::VariantAlternatesList;
|
||||
use values::CustomIdent;
|
||||
|
||||
if self.gecko.mFont.variantAlternates == NS_FONT_VARIANT_ALTERNATES_NORMAL as u16 {
|
||||
|
|
|
@ -670,204 +670,14 @@ ${helpers.single_keyword_system("font-kerning",
|
|||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
animation_value_type="discrete")}
|
||||
|
||||
<%helpers:longhand name="font-variant-alternates" products="gecko" animation_value_type="discrete"
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER"
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates">
|
||||
use properties::longhands::system_font::SystemFont;
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::CustomIdent;
|
||||
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
||||
pub enum VariantAlternates {
|
||||
Stylistic(CustomIdent),
|
||||
Styleset(Box<[CustomIdent]>),
|
||||
CharacterVariant(Box<[CustomIdent]>),
|
||||
Swash(CustomIdent),
|
||||
Ornaments(CustomIdent),
|
||||
Annotation(CustomIdent),
|
||||
HistoricalForms,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
||||
pub struct VariantAlternatesList(pub Box<[VariantAlternates]>);
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||
pub enum SpecifiedValue {
|
||||
Value(VariantAlternatesList),
|
||||
System(SystemFont)
|
||||
}
|
||||
|
||||
<%self:simple_system_boilerplate name="font_variant_alternates"></%self:simple_system_boilerplate>
|
||||
|
||||
impl ToCss for VariantAlternates {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
% for value in "swash stylistic ornaments annotation".split():
|
||||
VariantAlternates::${to_camel_case(value)}(ref atom) => {
|
||||
dest.write_str("${value}")?;
|
||||
dest.write_str("(")?;
|
||||
atom.to_css(dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
% endfor
|
||||
% for value in "styleset character-variant".split():
|
||||
VariantAlternates::${to_camel_case(value)}(ref vec) => {
|
||||
dest.write_str("${value}")?;
|
||||
dest.write_str("(")?;
|
||||
let mut iter = vec.iter();
|
||||
iter.next().unwrap().to_css(dest)?;
|
||||
for c in iter {
|
||||
dest.write_str(", ")?;
|
||||
c.to_css(dest)?;
|
||||
}
|
||||
dest.write_str(")")
|
||||
},
|
||||
% endfor
|
||||
VariantAlternates::HistoricalForms => {
|
||||
dest.write_str("historical-forms")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for VariantAlternatesList {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
if self.0.is_empty() {
|
||||
return dest.write_str("normal");
|
||||
}
|
||||
|
||||
let mut iter = self.0.iter();
|
||||
iter.next().unwrap().to_css(dest)?;
|
||||
for alternate in iter {
|
||||
dest.write_str(" ")?;
|
||||
alternate.to_css(dest)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl VariantAlternatesList {
|
||||
/// Returns the length of all variant alternates.
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.iter().fold(0, |acc, alternate| {
|
||||
match *alternate {
|
||||
% for value in "Swash Stylistic Ornaments Annotation".split():
|
||||
VariantAlternates::${value}(_) => {
|
||||
acc + 1
|
||||
},
|
||||
% endfor
|
||||
% for value in "Styleset CharacterVariant".split():
|
||||
VariantAlternates::${value}(ref slice) => {
|
||||
acc + slice.len()
|
||||
}
|
||||
% endfor
|
||||
_ => acc,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub mod computed_value {
|
||||
pub type T = super::VariantAlternatesList;
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
VariantAlternatesList(vec![].into_boxed_slice())
|
||||
}
|
||||
#[inline]
|
||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||
SpecifiedValue::Value(VariantAlternatesList(vec![].into_boxed_slice()))
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||
pub struct ParsingFlags: u8 {
|
||||
const NORMAL = 0;
|
||||
const HISTORICAL_FORMS = 0x01;
|
||||
const STYLISTIC = 0x02;
|
||||
const STYLESET = 0x04;
|
||||
const CHARACTER_VARIANT = 0x08;
|
||||
const SWASH = 0x10;
|
||||
const ORNAMENTS = 0x20;
|
||||
const ANNOTATION = 0x40;
|
||||
}
|
||||
}
|
||||
|
||||
/// normal |
|
||||
/// [ stylistic(<feature-value-name>) ||
|
||||
/// historical-forms ||
|
||||
/// styleset(<feature-value-name> #) ||
|
||||
/// character-variant(<feature-value-name> #) ||
|
||||
/// swash(<feature-value-name>) ||
|
||||
/// ornaments(<feature-value-name>) ||
|
||||
/// annotation(<feature-value-name>) ]
|
||||
pub fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>)
|
||||
-> Result<SpecifiedValue, ParseError<'i>> {
|
||||
let mut alternates = Vec::new();
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(SpecifiedValue::Value(VariantAlternatesList(alternates.into_boxed_slice())));
|
||||
}
|
||||
|
||||
let mut parsed_alternates = ParsingFlags::empty();
|
||||
macro_rules! check_if_parsed(
|
||||
($input:expr, $flag:path) => (
|
||||
if parsed_alternates.contains($flag) {
|
||||
return Err($input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
parsed_alternates |= $flag;
|
||||
)
|
||||
);
|
||||
while let Ok(_) = input.try(|input| {
|
||||
// FIXME: remove clone() when lifetimes are non-lexical
|
||||
match input.next()?.clone() {
|
||||
Token::Ident(ref ident) => {
|
||||
if *ident == "historical-forms" {
|
||||
check_if_parsed!(input, ParsingFlags::HISTORICAL_FORMS);
|
||||
alternates.push(VariantAlternates::HistoricalForms);
|
||||
Ok(())
|
||||
} else {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
},
|
||||
Token::Function(ref name) => {
|
||||
input.parse_nested_block(|i| {
|
||||
match_ignore_ascii_case! { &name,
|
||||
% for value in "swash stylistic ornaments annotation".split():
|
||||
"${value}" => {
|
||||
check_if_parsed!(i, ParsingFlags::${value.upper()});
|
||||
let location = i.current_source_location();
|
||||
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||
alternates.push(VariantAlternates::${to_camel_case(value)}(ident));
|
||||
Ok(())
|
||||
},
|
||||
% endfor
|
||||
% for value in "styleset character-variant".split():
|
||||
"${value}" => {
|
||||
check_if_parsed!(i, ParsingFlags:: ${to_rust_ident(value).upper()});
|
||||
let idents = i.parse_comma_separated(|i| {
|
||||
let location = i.current_source_location();
|
||||
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||
})?;
|
||||
alternates.push(VariantAlternates::${to_camel_case(value)}(idents.into_boxed_slice()));
|
||||
Ok(())
|
||||
},
|
||||
% endfor
|
||||
_ => return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
}
|
||||
})
|
||||
},
|
||||
_ => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
}
|
||||
}) { }
|
||||
|
||||
if parsed_alternates.is_empty() {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(SpecifiedValue::Value(VariantAlternatesList(alternates.into_boxed_slice())))
|
||||
}
|
||||
</%helpers:longhand>
|
||||
${helpers.predefined_type("font-variant-alternates",
|
||||
"FontVariantAlternates",
|
||||
products="gecko",
|
||||
initial_value="computed::FontVariantAlternates::get_initial_value()",
|
||||
initial_specified_value="specified::FontVariantAlternates::get_initial_specified_value()",
|
||||
animation_value_type="discrete",
|
||||
flags="APPLIES_TO_FIRST_LETTER APPLIES_TO_FIRST_LINE APPLIES_TO_PLACEHOLDER",
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-variant-alternates")}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
macro_rules! exclusive_value {
|
||||
|
|
|
@ -265,6 +265,17 @@ impl ToAnimatedValue for FontSizeAdjust {
|
|||
}
|
||||
}
|
||||
|
||||
/// Use VariantAlternatesList as computed type of FontVariantAlternates
|
||||
pub type FontVariantAlternates = specified::VariantAlternatesList;
|
||||
|
||||
impl FontVariantAlternates {
|
||||
#[inline]
|
||||
/// Get initial value with VariantAlternatesList
|
||||
pub fn get_initial_value() -> Self {
|
||||
specified::VariantAlternatesList(vec![].into_boxed_slice())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for specified::MozScriptMinSize {
|
||||
type ComputedValue = MozScriptMinSize;
|
||||
|
||||
|
|
|
@ -36,7 +36,8 @@ pub use self::angle::Angle;
|
|||
pub use self::background::{BackgroundSize, BackgroundRepeat};
|
||||
pub use self::border::{BorderImageSlice, BorderImageWidth, BorderImageSideWidth};
|
||||
pub use self::border::{BorderRadius, BorderCornerRadius, BorderSpacing};
|
||||
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, MozScriptLevel, MozScriptMinSize, XTextZoom};
|
||||
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
|
||||
pub use self::font::{MozScriptLevel, MozScriptMinSize, XTextZoom};
|
||||
pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
|
||||
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
|
||||
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
||||
|
|
|
@ -10,8 +10,11 @@ use app_units::Au;
|
|||
use cssparser::{Parser, Token};
|
||||
use parser::{Parse, ParserContext};
|
||||
use properties::longhands::system_font::SystemFont;
|
||||
#[allow(unused_imports)]
|
||||
use std::ascii::AsciiExt;
|
||||
use std::fmt;
|
||||
use style_traits::{ToCss, StyleParseErrorKind, ParseError};
|
||||
use values::CustomIdent;
|
||||
use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue};
|
||||
use values::specified::{AllowQuirks, LengthOrPercentage, NoCalcLength, Number};
|
||||
use values::specified::length::{AU_PER_PT, AU_PER_PX, FontBaseSize};
|
||||
|
@ -610,6 +613,292 @@ impl Parse for FontSize {
|
|||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
||||
/// Flags of variant alternates in bit
|
||||
struct VariantAlternatesParsingFlags: u8 {
|
||||
/// None of variant alternates enabled
|
||||
const NORMAL = 0;
|
||||
/// Historical forms
|
||||
const HISTORICAL_FORMS = 0x01;
|
||||
/// Stylistic Alternates
|
||||
const STYLISTIC = 0x02;
|
||||
/// Stylistic Sets
|
||||
const STYLESET = 0x04;
|
||||
/// Character Variant
|
||||
const CHARACTER_VARIANT = 0x08;
|
||||
/// Swash glyphs
|
||||
const SWASH = 0x10;
|
||||
/// Ornaments glyphs
|
||||
const ORNAMENTS = 0x20;
|
||||
/// Annotation forms
|
||||
const ANNOTATION = 0x40;
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
||||
/// Set of variant alternates
|
||||
pub enum VariantAlternates {
|
||||
/// Enables display of stylistic alternates
|
||||
Stylistic(CustomIdent),
|
||||
/// Enables display with stylistic sets
|
||||
Styleset(Box<[CustomIdent]>),
|
||||
/// Enables display of specific character variants
|
||||
CharacterVariant(Box<[CustomIdent]>),
|
||||
/// Enables display of swash glyphs
|
||||
Swash(CustomIdent),
|
||||
/// Enables replacement of default glyphs with ornaments
|
||||
Ornaments(CustomIdent),
|
||||
/// Enables display of alternate annotation forms
|
||||
Annotation(CustomIdent),
|
||||
/// Enables display of historical forms
|
||||
HistoricalForms,
|
||||
}
|
||||
|
||||
impl ToCss for VariantAlternates {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
match *self {
|
||||
VariantAlternates::Swash(ref atom) => {
|
||||
dest.write_str("swash")?;
|
||||
dest.write_str("(")?;
|
||||
atom.to_css(dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
VariantAlternates::Stylistic(ref atom) => {
|
||||
dest.write_str("stylistic")?;
|
||||
dest.write_str("(")?;
|
||||
atom.to_css(dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
VariantAlternates::Ornaments(ref atom) => {
|
||||
dest.write_str("ornaments")?;
|
||||
dest.write_str("(")?;
|
||||
atom.to_css(dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
VariantAlternates::Annotation(ref atom) => {
|
||||
dest.write_str("annotation")?;
|
||||
dest.write_str("(")?;
|
||||
atom.to_css(dest)?;
|
||||
dest.write_str(")")
|
||||
},
|
||||
VariantAlternates::Styleset(ref vec) => {
|
||||
dest.write_str("styleset")?;
|
||||
dest.write_str("(")?;
|
||||
let mut iter = vec.iter();
|
||||
iter.next().unwrap().to_css(dest)?;
|
||||
for c in iter {
|
||||
dest.write_str(", ")?;
|
||||
c.to_css(dest)?;
|
||||
}
|
||||
dest.write_str(")")
|
||||
},
|
||||
VariantAlternates::CharacterVariant(ref vec) => {
|
||||
dest.write_str("character-variant")?;
|
||||
dest.write_str("(")?;
|
||||
let mut iter = vec.iter();
|
||||
iter.next().unwrap().to_css(dest)?;
|
||||
for c in iter {
|
||||
dest.write_str(", ")?;
|
||||
c.to_css(dest)?;
|
||||
}
|
||||
dest.write_str(")")
|
||||
},
|
||||
VariantAlternates::HistoricalForms => {
|
||||
dest.write_str("historical-forms")
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
|
||||
/// List of Variant Alternates
|
||||
pub struct VariantAlternatesList(pub Box<[VariantAlternates]>);
|
||||
|
||||
impl VariantAlternatesList {
|
||||
/// Returns the length of all variant alternates.
|
||||
pub fn len(&self) -> usize {
|
||||
self.0.iter().fold(0, |acc, alternate| {
|
||||
match *alternate {
|
||||
VariantAlternates::Swash(_) | VariantAlternates::Stylistic(_) |
|
||||
VariantAlternates::Ornaments(_) | VariantAlternates::Annotation(_) => {
|
||||
acc + 1
|
||||
},
|
||||
VariantAlternates::Styleset(ref slice) |
|
||||
VariantAlternates::CharacterVariant(ref slice) => {
|
||||
acc + slice.len()
|
||||
},
|
||||
_ => acc,
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for VariantAlternatesList {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
if self.0.is_empty() {
|
||||
return dest.write_str("normal");
|
||||
}
|
||||
|
||||
let mut iter = self.0.iter();
|
||||
iter.next().unwrap().to_css(dest)?;
|
||||
for alternate in iter {
|
||||
dest.write_str(" ")?;
|
||||
alternate.to_css(dest)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)]
|
||||
/// Control over the selection of these alternate glyphs
|
||||
pub enum FontVariantAlternates {
|
||||
/// Use alternative glyph from value
|
||||
Value(VariantAlternatesList),
|
||||
/// Use system font glyph
|
||||
System(SystemFont)
|
||||
}
|
||||
|
||||
impl FontVariantAlternates {
|
||||
#[inline]
|
||||
/// Get initial specified value with VariantAlternatesList
|
||||
pub fn get_initial_specified_value() -> Self {
|
||||
FontVariantAlternates::Value(VariantAlternatesList(vec![].into_boxed_slice()))
|
||||
}
|
||||
|
||||
/// Get FontVariantAlternates with system font
|
||||
pub fn system_font(f: SystemFont) -> Self {
|
||||
FontVariantAlternates::System(f)
|
||||
}
|
||||
|
||||
/// Get SystemFont of FontVariantAlternates
|
||||
pub fn get_system(&self) -> Option<SystemFont> {
|
||||
if let FontVariantAlternates::System(s) = *self {
|
||||
Some(s)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for FontVariantAlternates {
|
||||
type ComputedValue = computed::FontVariantAlternates;
|
||||
|
||||
fn to_computed_value(&self, _context: &Context) -> computed::FontVariantAlternates {
|
||||
match *self {
|
||||
FontVariantAlternates::Value(ref v) => v.clone(),
|
||||
FontVariantAlternates::System(_) => {
|
||||
#[cfg(feature = "gecko")] {
|
||||
_context.cached_system_font.as_ref().unwrap().font_variant_alternates.clone()
|
||||
}
|
||||
#[cfg(feature = "servo")] {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn from_computed_value(other: &computed::FontVariantAlternates) -> Self {
|
||||
FontVariantAlternates::Value(other.clone())
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for FontVariantAlternates {
|
||||
/// normal |
|
||||
/// [ stylistic(<feature-value-name>) ||
|
||||
/// historical-forms ||
|
||||
/// styleset(<feature-value-name> #) ||
|
||||
/// character-variant(<feature-value-name> #) ||
|
||||
/// swash(<feature-value-name>) ||
|
||||
/// ornaments(<feature-value-name>) ||
|
||||
/// annotation(<feature-value-name>) ]
|
||||
fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result<FontVariantAlternates, ParseError<'i>> {
|
||||
let mut alternates = Vec::new();
|
||||
if input.try(|input| input.expect_ident_matching("normal")).is_ok() {
|
||||
return Ok(FontVariantAlternates::Value(VariantAlternatesList(alternates.into_boxed_slice())));
|
||||
}
|
||||
|
||||
let mut parsed_alternates = VariantAlternatesParsingFlags::empty();
|
||||
macro_rules! check_if_parsed(
|
||||
($input:expr, $flag:path) => (
|
||||
if parsed_alternates.contains($flag) {
|
||||
return Err($input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||
}
|
||||
parsed_alternates |= $flag;
|
||||
)
|
||||
);
|
||||
while let Ok(_) = input.try(|input| {
|
||||
// FIXME: remove clone() when lifetimes are non-lexical
|
||||
match input.next()?.clone() {
|
||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("historical-forms") => {
|
||||
check_if_parsed!(input, VariantAlternatesParsingFlags::HISTORICAL_FORMS);
|
||||
alternates.push(VariantAlternates::HistoricalForms);
|
||||
Ok(())
|
||||
},
|
||||
Token::Function(ref name) => {
|
||||
input.parse_nested_block(|i| {
|
||||
match_ignore_ascii_case! { &name,
|
||||
"swash" => {
|
||||
check_if_parsed!(i, VariantAlternatesParsingFlags::SWASH);
|
||||
let location = i.current_source_location();
|
||||
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||
alternates.push(VariantAlternates::Swash(ident));
|
||||
Ok(())
|
||||
},
|
||||
"stylistic" => {
|
||||
check_if_parsed!(i, VariantAlternatesParsingFlags::STYLISTIC);
|
||||
let location = i.current_source_location();
|
||||
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||
alternates.push(VariantAlternates::Stylistic(ident));
|
||||
Ok(())
|
||||
},
|
||||
"ornaments" => {
|
||||
check_if_parsed!(i, VariantAlternatesParsingFlags::ORNAMENTS);
|
||||
let location = i.current_source_location();
|
||||
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||
alternates.push(VariantAlternates::Ornaments(ident));
|
||||
Ok(())
|
||||
},
|
||||
"annotation" => {
|
||||
check_if_parsed!(i, VariantAlternatesParsingFlags::ANNOTATION);
|
||||
let location = i.current_source_location();
|
||||
let ident = CustomIdent::from_ident(location, i.expect_ident()?, &[])?;
|
||||
alternates.push(VariantAlternates::Annotation(ident));
|
||||
Ok(())
|
||||
},
|
||||
"styleset" => {
|
||||
check_if_parsed!(i, VariantAlternatesParsingFlags::STYLESET);
|
||||
let idents = i.parse_comma_separated(|i| {
|
||||
let location = i.current_source_location();
|
||||
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||
})?;
|
||||
alternates.push(VariantAlternates::Styleset(idents.into_boxed_slice()));
|
||||
Ok(())
|
||||
},
|
||||
"character-variant" => {
|
||||
check_if_parsed!(i, VariantAlternatesParsingFlags::CHARACTER_VARIANT);
|
||||
let idents = i.parse_comma_separated(|i| {
|
||||
let location = i.current_source_location();
|
||||
CustomIdent::from_ident(location, i.expect_ident()?, &[])
|
||||
})?;
|
||||
alternates.push(VariantAlternates::CharacterVariant(idents.into_boxed_slice()));
|
||||
Ok(())
|
||||
},
|
||||
_ => return Err(i.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
}
|
||||
})
|
||||
},
|
||||
_ => Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||
}
|
||||
}) { }
|
||||
|
||||
if parsed_alternates.is_empty() {
|
||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||
}
|
||||
Ok(FontVariantAlternates::Value(VariantAlternatesList(alternates.into_boxed_slice())))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)]
|
||||
/// Whether user agents are allowed to synthesize bold or oblique font faces
|
||||
/// when a font family lacks bold or italic faces
|
||||
|
|
|
@ -30,7 +30,8 @@ pub use self::align::{AlignItems, AlignJustifyContent, AlignJustifySelf, Justify
|
|||
pub use self::background::{BackgroundRepeat, BackgroundSize};
|
||||
pub use self::border::{BorderCornerRadius, BorderImageSlice, BorderImageWidth};
|
||||
pub use self::border::{BorderImageSideWidth, BorderRadius, BorderSideWidth, BorderSpacing};
|
||||
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, MozScriptLevel, MozScriptMinSize, XTextZoom};
|
||||
pub use self::font::{FontSize, FontSizeAdjust, FontSynthesis, FontWeight, FontVariantAlternates};
|
||||
pub use self::font::{MozScriptLevel, MozScriptMinSize, XTextZoom};
|
||||
pub use self::box_::{AnimationIterationCount, AnimationName, ScrollSnapType, VerticalAlign};
|
||||
pub use self::color::{Color, ColorPropertyValue, RGBAColor};
|
||||
pub use self::effects::{BoxShadow, Filter, SimpleShadow};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue