mirror of
https://github.com/servo/servo.git
synced 2025-08-07 14:35:33 +01:00
style: Add support for the @font-face src descriptor's tech() function
WPT tests to be added in a following patch. Differential Revision: https://phabricator.services.mozilla.com/D154399
This commit is contained in:
parent
52d1e07ee2
commit
fa8b5f17e3
1 changed files with 124 additions and 4 deletions
|
@ -70,6 +70,111 @@ pub enum FontFaceSourceFormatKeyword {
|
||||||
Unknown,
|
Unknown,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bitflags! {
|
||||||
|
/// Flags for the @font-face tech() function, indicating font technologies
|
||||||
|
/// required by the resource.
|
||||||
|
#[derive(ToShmem)]
|
||||||
|
#[repr(C)]
|
||||||
|
pub struct FontFaceSourceTechFlags: u16 {
|
||||||
|
/// Font requires OpenType feature support.
|
||||||
|
const FEATURE_OPENTYPE = 1 << 0;
|
||||||
|
/// Font requires Apple Advanced Typography support.
|
||||||
|
const FEATURE_AAT = 1 << 1;
|
||||||
|
/// Font requires Graphite shaping support.
|
||||||
|
const FEATURE_GRAPHITE = 1 << 2;
|
||||||
|
/// Font requires COLRv0 rendering support (simple list of colored layers).
|
||||||
|
const COLOR_COLRV0 = 1 << 3;
|
||||||
|
/// Font requires COLRv1 rendering support (graph of paint operations).
|
||||||
|
const COLOR_COLRV1 = 1 << 4;
|
||||||
|
/// Font requires SVG glyph rendering support.
|
||||||
|
const COLOR_SVG = 1 << 5;
|
||||||
|
/// Font has bitmap glyphs in 'sbix' format.
|
||||||
|
const COLOR_SBIX = 1 << 6;
|
||||||
|
/// Font has bitmap glyphs in 'CBDT' format.
|
||||||
|
const COLOR_CBDT = 1 << 7;
|
||||||
|
/// Font requires OpenType Variations support.
|
||||||
|
const VARIATIONS = 1 << 8;
|
||||||
|
/// Font requires CPAL palette selection support.
|
||||||
|
const PALETTES = 1 << 9;
|
||||||
|
/// Font requires support for incremental downloading.
|
||||||
|
const INCREMENTAL = 1 << 10;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Parse for FontFaceSourceTechFlags {
|
||||||
|
fn parse<'i, 't>(
|
||||||
|
_context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
) -> Result<Self, ParseError<'i>> {
|
||||||
|
let location = input.current_source_location();
|
||||||
|
// We don't actually care about the return value of parse_comma_separated,
|
||||||
|
// 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)),
|
||||||
|
};
|
||||||
|
result.insert(flag);
|
||||||
|
Ok(())
|
||||||
|
})?;
|
||||||
|
if !result.is_empty() {
|
||||||
|
Ok(result)
|
||||||
|
} else {
|
||||||
|
Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[allow(unused_assignments)]
|
||||||
|
impl ToCss for FontFaceSourceTechFlags {
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: fmt::Write,
|
||||||
|
{
|
||||||
|
let mut first = true;
|
||||||
|
|
||||||
|
macro_rules! write_if_flag {
|
||||||
|
($s:expr => $f:ident) => {
|
||||||
|
if self.contains(Self::$f) {
|
||||||
|
if first {
|
||||||
|
first = false;
|
||||||
|
} else {
|
||||||
|
dest.write_str(", ")?;
|
||||||
|
}
|
||||||
|
dest.write_str($s)?;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
write_if_flag!("feature-opentype" => FEATURE_OPENTYPE);
|
||||||
|
write_if_flag!("feature-aat" => FEATURE_AAT);
|
||||||
|
write_if_flag!("feature-graphite" => FEATURE_GRAPHITE);
|
||||||
|
write_if_flag!("color-colrv0" => COLOR_COLRV0);
|
||||||
|
write_if_flag!("color-colrv1" => COLOR_COLRV1);
|
||||||
|
write_if_flag!("color-svg" => COLOR_SVG);
|
||||||
|
write_if_flag!("color-sbix" => COLOR_SBIX);
|
||||||
|
write_if_flag!("color-cbdt" => COLOR_CBDT);
|
||||||
|
write_if_flag!("variations" => VARIATIONS);
|
||||||
|
write_if_flag!("palettes" => PALETTES);
|
||||||
|
write_if_flag!("incremental" => INCREMENTAL);
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A POD representation for Gecko. All pointers here are non-owned and as such
|
/// A POD representation for Gecko. All pointers here are non-owned and as such
|
||||||
/// can't outlive the rule they came from, but we can't enforce that via C++.
|
/// can't outlive the rule they came from, but we can't enforce that via C++.
|
||||||
///
|
///
|
||||||
|
@ -86,6 +191,7 @@ pub enum FontFaceSourceListComponent {
|
||||||
length: usize,
|
length: usize,
|
||||||
utf8_bytes: *const u8,
|
utf8_bytes: *const u8,
|
||||||
},
|
},
|
||||||
|
TechFlags(FontFaceSourceTechFlags),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
|
#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
|
||||||
|
@ -108,6 +214,8 @@ pub struct UrlSource {
|
||||||
pub url: SpecifiedUrl,
|
pub url: SpecifiedUrl,
|
||||||
/// The format hint specified with the `format()` function, if present.
|
/// The format hint specified with the `format()` function, if present.
|
||||||
pub format_hint: Option<FontFaceSourceFormat>,
|
pub format_hint: Option<FontFaceSourceFormat>,
|
||||||
|
/// The font technology flags specified with the `tech()` function, if any.
|
||||||
|
pub tech_flags: FontFaceSourceTechFlags,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for UrlSource {
|
impl ToCss for UrlSource {
|
||||||
|
@ -121,6 +229,11 @@ impl ToCss for UrlSource {
|
||||||
hint.to_css(dest)?;
|
hint.to_css(dest)?;
|
||||||
dest.write_char(')')?;
|
dest.write_char(')')?;
|
||||||
}
|
}
|
||||||
|
if !self.tech_flags.is_empty() {
|
||||||
|
dest.write_str(" tech(")?;
|
||||||
|
self.tech_flags.to_css(dest)?;
|
||||||
|
dest.write_char(')')?;
|
||||||
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -447,10 +560,17 @@ impl Parse for Source {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(Source::Url(UrlSource {
|
// Parse optional tech()
|
||||||
url: url,
|
let tech_flags = if input
|
||||||
format_hint: format_hint,
|
.try_parse(|input| input.expect_function_matching("tech"))
|
||||||
}))
|
.is_ok()
|
||||||
|
{
|
||||||
|
input.parse_nested_block(|input| FontFaceSourceTechFlags::parse(context, input))?
|
||||||
|
} else {
|
||||||
|
FontFaceSourceTechFlags::empty()
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(Source::Url(UrlSource { url, format_hint, tech_flags }))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue