/* This Source Code Form is subject to the terms of the Mozilla Public *License,v.2.0.IfacopyoftheMPLwasnotdistributedwiththis
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
/// A source for a font-face rule. #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToShmem)] pubenum Source { /// A `url()` source.
Url(UrlSource), /// A `local()` source. #[css(function)]
Local(FamilyName),
}
/// A list of sources for the font-face src descriptor. #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToCss, ToShmem)] #[css(comma)] pubstruct SourceList(#[css(iterable)] pub Vec<Source>);
// We can't just use OneOrMoreSeparated to derive Parse for the Source list, // because we want to filter out components that parsed as None, then fail if no // valid components remain. So we provide our own implementation here. impl Parse for SourceList { fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { // Parse the comma-separated list, then let filter_map discard any None items. let list = input
.parse_comma_separated(|input| { let s = input.parse_entirely(|input| Source::parse(context, input)); while input.next().is_ok() {}
Ok(s.ok())
})?
.into_iter()
.filter_map(|s| s)
.collect::<Vec<Source>>(); if list.is_empty() {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
} else {
Ok(SourceList(list))
}
}
}
/// Keywords for the font-face src descriptor's format() function. /// ('None' and 'Unknown' are for internal use in gfx, not exposed to CSS.) #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToCss, ToShmem)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[repr(u8)] #[allow(missing_docs)] pubenum FontFaceSourceFormatKeyword { #[css(skip)]
None,
Collection,
EmbeddedOpentype,
Opentype,
Svg,
Truetype,
Woff,
Woff2, #[css(skip)]
Unknown,
}
/// Flags for the @font-face tech() function, indicating font technologies /// required by the resource. #[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[repr(C)] pubstruct FontFaceSourceTechFlags(u16);
bitflags! { impl FontFaceSourceTechFlags: u16 { /// Font requires OpenType feature support. const FEATURES_OPENTYPE = 1 << 0; /// Font requires Apple Advanced Typography support. const FEATURES_AAT = 1 << 1; /// Font requires Graphite shaping support. const FEATURES_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. letmut result = Self::empty();
input.parse_comma_separated(|input| { let flag = Self::parse_one(input)?;
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,
{ letmut first = true;
macro_rules! write_if_flag {
($s:expr => $f:ident) => { ifself.contains(Self::$f) { if first {
first = false;
} else {
dest.write_str(", ")?;
}
dest.write_str($s)?;
}
};
}
/// <https://drafts.csswg.org/css-fonts/#font-face-rule> #[derive(Clone, Debug, ToShmem, PartialEq)] pubstruct FontFaceRule { /// The descriptors of the @font-face rule. pub descriptors: Descriptors, /// The parser location of the rule. pub source_location: SourceLocation,
}
/// 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++. /// /// All the strings are of course utf8. #[cfg(feature = "gecko")] #[derive(Clone, Copy, Debug, Eq, PartialEq)] #[repr(u8)] #[allow(missing_docs)] pubenum FontFaceSourceListComponent {
Url(*constcrate::url::CssUrl),
Local(*mutcrate::gecko_bindings::structs::nsAtom),
FormatHintKeyword(FontFaceSourceFormatKeyword),
FormatHintString {
length: usize,
utf8_bytes: *const u8,
},
TechFlags(FontFaceSourceTechFlags),
}
/// A `UrlSource` represents a font-face source that has been specified with a /// `url()` function. /// /// <https://drafts.csswg.org/css-fonts/#src-desc> #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)] pubstruct UrlSource { /// The specified url. 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,
}
/// A font-display value for a @font-face rule. /// The font-display descriptor determines how a font face is displayed based /// on whether and when it is downloaded and ready to use. #[allow(missing_docs)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive(
Clone, Copy, Debug, Eq, MallocSizeOf, Parse, PartialEq, ToComputedValue, ToCss, ToShmem,
)] #[repr(u8)] pubenum FontDisplay {
Auto,
Block,
Swap,
Fallback,
Optional,
}
/// The computed representation of the above so Gecko can read them easily. /// /// This one is needed because cbindgen doesn't know how to generate /// specified::Number. #[repr(C)] #[allow(missing_docs)] pubstruct ComputedFontWeightRange(f32, f32);
#[inline] fn sort_range<T: PartialOrd>(a: T, b: T) -> (T, T) { if a > b {
(b, a)
} else {
(a, b)
}
}
impl FontWeightRange { /// Returns a computed font-weight range, or None if either bound is an unresolvable calc. pubfn compute(&self) -> Option<ComputedFontWeightRange> { let (min, max) = sort_range(self.0.compute()?.value(), self.1.compute()?.value());
Some(ComputedFontWeightRange(min, max))
}
}
/// The computed representation of the above, so that Gecko can read them /// easily. #[repr(C)] #[allow(missing_docs)] pubstruct ComputedFontStretchRange(FontStretch, FontStretch);
impl FontStretchRange { /// Returns a computed font-stretch range, or None if any value contains a calc /// expression that cannot be resolved at parse time. pubfn compute(&self) -> Option<ComputedFontStretchRange> { fn compute_stretch(s: &SpecifiedFontStretch) -> Option<FontStretch> { match *s {
SpecifiedFontStretch::Keyword(ref kw) => Some(kw.compute()),
SpecifiedFontStretch::Stretch(ref p) => {
Some(FontStretch::from_percentage(p.compute()?.0))
},
SpecifiedFontStretch::System(..) => unreachable!(),
}
}
let (min, max) = sort_range(compute_stretch(&self.0)?, compute_stretch(&self.1)?);
Some(ComputedFontStretchRange(min, max))
}
}
/// The computed representation of the above, with angles in degrees, so that /// Gecko can read them easily. #[repr(u8)] #[allow(missing_docs)] pubenum ComputedFontStyleDescriptor {
Italic,
Oblique(f32, f32),
}
impl Parse for FontStyle { fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { // We parse 'normal' explicitly here to distinguish it from 'oblique 0deg', // because we must not accept a following angle. if input
.try_parse(|i| i.expect_ident_matching("normal"))
.is_ok()
{ return Ok(FontStyle::Oblique(Angle::zero(), Angle::zero()));
}
impl ToCss for FontStyle { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where
W: fmt::Write,
{ match *self {
FontStyle::Italic => dest.write_str("italic"),
FontStyle::Oblique(ref first, ref second) => { // Not first.is_zero() because we don't want to serialize // `oblique calc(0deg)` as `normal`. if *first == Angle::zero() && first == second { return dest.write_str("normal");
}
dest.write_str("oblique")?; if *first != SpecifiedFontStyle::default_angle() || first != second {
dest.write_char(' ')?;
first.to_css(dest)?;
} if first != second {
dest.write_char(' ')?;
second.to_css(dest)?;
}
Ok(())
},
}
}
}
impl FontStyle { /// Returns a computed font-style descriptor. pubfn compute(&self) -> Option<ComputedFontStyleDescriptor> { match *self {
FontStyle::Italic => Some(ComputedFontStyleDescriptor::Italic),
FontStyle::Oblique(ref first, ref second) => { let first = SpecifiedFontStyle::compute_angle_degrees(first)?; let second = SpecifiedFontStyle::compute_angle_degrees(second)?; let (min, max) = sort_range(first, second);
Some(ComputedFontStyleDescriptor::Oblique(min, max))
},
}
}
}
/// Parse the block inside a `@font-face` rule. /// /// Note that the prelude parsing code lives in the `stylesheets` module. pubfn parse_font_face_block(
context: &ParserContext,
input: &mut Parser,
source_location: SourceLocation,
) -> FontFaceRule { letmut rule = FontFaceRule::empty(source_location);
{ letmut parser = DescriptorParser {
context,
descriptors: &mut rule.descriptors,
}; letmut iter = RuleBodyParser::new(input, &mut parser); whilelet Some(declaration) = iter.next() { iflet Err((error, slice)) = declaration { let location = error.location; let error = ContextualParseError::UnsupportedFontFaceDescriptor(slice, error);
context.log_css_error(location, error)
}
}
}
rule
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.