aboutsummaryrefslogtreecommitdiffstats
path: root/components/style/font_face.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/style/font_face.rs')
-rw-r--r--components/style/font_face.rs128
1 files changed, 124 insertions, 4 deletions
diff --git a/components/style/font_face.rs b/components/style/font_face.rs
index bb1e49d7596..519b14bfd0c 100644
--- a/components/style/font_face.rs
+++ b/components/style/font_face.rs
@@ -70,6 +70,111 @@ pub enum FontFaceSourceFormatKeyword {
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
/// 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,
utf8_bytes: *const u8,
},
+ TechFlags(FontFaceSourceTechFlags),
}
#[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem)]
@@ -108,6 +214,8 @@ pub struct UrlSource {
pub url: SpecifiedUrl,
/// The format hint specified with the `format()` function, if present.
pub format_hint: Option<FontFaceSourceFormat>,
+ /// The font technology flags specified with the `tech()` function, if any.
+ pub tech_flags: FontFaceSourceTechFlags,
}
impl ToCss for UrlSource {
@@ -121,6 +229,11 @@ impl ToCss for UrlSource {
hint.to_css(dest)?;
dest.write_char(')')?;
}
+ if !self.tech_flags.is_empty() {
+ dest.write_str(" tech(")?;
+ self.tech_flags.to_css(dest)?;
+ dest.write_char(')')?;
+ }
Ok(())
}
}
@@ -447,10 +560,17 @@ impl Parse for Source {
None
};
- Ok(Source::Url(UrlSource {
- url: url,
- format_hint: format_hint,
- }))
+ // Parse optional tech()
+ let tech_flags = if input
+ .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 }))
}
}