style: Implement CSS @supports font-format(...) and font-tech(...) functions

These are gated by the same layout.css.font-tech.enabled pref as the
closely-related `tech()` function for the @font-face src descriptor;
once the spec questions are settled, we should enable them all together.

Differential Revision: https://phabricator.services.mozilla.com/D155359
This commit is contained in:
Jonathan Kew 2022-08-25 12:19:21 +00:00 committed by Martin Robinson
parent 6f2861e466
commit 2fb319ede2
2 changed files with 55 additions and 16 deletions

View file

@ -102,6 +102,25 @@ bitflags! {
}
}
impl FontFaceSourceTechFlags {
/// Parse a single font-technology keyword and return its flag.
pub fn parse_one<'i, 't>(input: &mut Parser<'i, 't>) -> Result<Self, ParseError<'i>> {
Ok(try_match_ident_ignore_ascii_case! { input,
"feature-opentype" => Self::FEATURE_OPENTYPE,
"feature-aat" => Self::FEATURE_AAT,
"feature-graphite" => Self::FEATURE_GRAPHITE,
"color-colrv0" => Self::COLOR_COLRV0,
"color-colrv1" => Self::COLOR_COLRV1,
"color-svg" => Self::COLOR_SVG,
"color-sbix" => Self::COLOR_SBIX,
"color-cbdt" => Self::COLOR_CBDT,
"variations" => Self::VARIATIONS,
"palettes" => Self::PALETTES,
"incremental" => Self::INCREMENTAL,
})
}
}
impl Parse for FontFaceSourceTechFlags {
fn parse<'i, 't>(
_context: &ParserContext,
@ -112,22 +131,7 @@ impl Parse for FontFaceSourceTechFlags {
// because we insert the flags into result as we go.
let mut result = Self::empty();
input.parse_comma_separated(|input| {
let location = input.current_source_location();
let ident = input.expect_ident()?;
let flag = match_ignore_ascii_case! { ident,
"feature-opentype" => Self::FEATURE_OPENTYPE,
"feature-aat" => Self::FEATURE_AAT,
"feature-graphite" => Self::FEATURE_GRAPHITE,
"color-colrv0" => Self::COLOR_COLRV0,
"color-colrv1" => Self::COLOR_COLRV1,
"color-svg" => Self::COLOR_SVG,
"color-sbix" => Self::COLOR_SBIX,
"color-cbdt" => Self::COLOR_CBDT,
"variations" => Self::VARIATIONS,
"palettes" => Self::PALETTES,
"incremental" => Self::INCREMENTAL,
_ => return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
};
let flag = Self::parse_one(input)?;
result.insert(flag);
Ok(())
})?;

View file

@ -11,6 +11,7 @@ use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
use crate::str::CssStringWriter;
use crate::stylesheets::{CssRuleType, CssRules, Namespaces};
use crate::font_face::{FontFaceSourceFormatKeyword, FontFaceSourceTechFlags};
use cssparser::parse_important;
use cssparser::{Delimiter, Parser, SourceLocation, Token};
use cssparser::{ParseError as CssParseError, ParserInput};
@ -94,6 +95,10 @@ pub enum SupportsCondition {
/// Since we need to pass it through FFI to get the pref value,
/// we store it as CString directly.
MozBoolPref(CString),
/// `font-format(<font-format>)`
FontFormat(FontFaceSourceFormatKeyword),
/// `font-tech(<font-tech>)`
FontTech(FontFaceSourceTechFlags),
/// `(any tokens)` or `func(any tokens)`
FutureSyntax(String),
}
@ -165,6 +170,14 @@ impl SupportsCondition {
input.slice_from(pos).to_owned()
)))
},
"font-format" if static_prefs::pref!("layout.css.font-tech.enabled") => {
let kw = FontFaceSourceFormatKeyword::parse(input)?;
Ok(SupportsCondition::FontFormat(kw))
},
"font-tech" if static_prefs::pref!("layout.css.font-tech.enabled") => {
let flag = FontFaceSourceTechFlags::parse_one(input)?;
Ok(SupportsCondition::FontTech(flag))
},
_ => {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
},
@ -215,6 +228,8 @@ impl SupportsCondition {
SupportsCondition::Declaration(ref decl) => decl.eval(cx),
SupportsCondition::MozBoolPref(ref name) => eval_moz_bool_pref(name, cx),
SupportsCondition::Selector(ref selector) => selector.eval(cx, namespaces),
SupportsCondition::FontFormat(ref format) => eval_font_format(format),
SupportsCondition::FontTech(ref tech) => eval_font_tech(tech),
SupportsCondition::FutureSyntax(_) => false,
}
}
@ -229,6 +244,16 @@ fn eval_moz_bool_pref(name: &CStr, cx: &ParserContext) -> bool {
unsafe { bindings::Gecko_GetBoolPrefValue(name.as_ptr()) }
}
fn eval_font_format(kw: &FontFaceSourceFormatKeyword) -> bool {
use crate::gecko_bindings::bindings;
unsafe { bindings::Gecko_IsFontFormatSupported(*kw) }
}
fn eval_font_tech(flag: &FontFaceSourceTechFlags) -> bool {
use crate::gecko_bindings::bindings;
unsafe { bindings::Gecko_IsFontTechSupported(*flag) }
}
#[cfg(feature = "servo")]
fn eval_moz_bool_pref(_: &CStr, _: &ParserContext) -> bool {
false
@ -300,6 +325,16 @@ impl ToCss for SupportsCondition {
name.to_css(dest)?;
dest.write_str(")")
},
SupportsCondition::FontFormat(ref kw) => {
dest.write_str("font-format(")?;
kw.to_css(dest)?;
dest.write_str(")")
},
SupportsCondition::FontTech(ref flag) => {
dest.write_str("font-tech(")?;
flag.to_css(dest)?;
dest.write_str(")")
},
SupportsCondition::FutureSyntax(ref s) => dest.write_str(&s),
}
}