/* 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/. */
usecrate::error_reporting::ContextualParseError; usecrate::parser::{Parse, ParserContext}; usecrate::properties::longhands::font_language_override; usecrate::shared_lock::{SharedRwLockReadGuard, ToCssWithGuard}; usecrate::str::CssStringWriter; usecrate::values::computed::font::{FamilyName, FontStretch}; usecrate::values::generics::font::FontStyle as GenericFontStyle; usecrate::values::specified::font::{
AbsoluteFontWeight, FontStretch as SpecifiedFontStretch, FontFeatureSettings,
FontVariationSettings, MetricsOverride, SpecifiedFontStyle,
}; usecrate::values::specified::url::SpecifiedUrl; usecrate::values::specified::{Angle, NonNegativePercentage}; use cssparser::UnicodeRange; use cssparser::{
AtRuleParser, CowRcStr, DeclarationParser, Parser, QualifiedRuleParser, RuleBodyItemParser,
RuleBodyParser, SourceLocation,
}; use selectors::parser::SelectorParseErrorKind; use std::fmt::{self, Write}; use style_traits::{CssWriter, ParseError}; use style_traits::{StyleParseErrorKind, ToCss};
/// A source for a font-face rule. #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive(Clone, Debug, Eq, 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, 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, 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, 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)?;
}
};
}
/// 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::gecko::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, 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)
}
}
/// The computed representation of the above, so that Gecko can read them /// easily. #[repr(C)] #[allow(missing_docs)] pubstruct ComputedFontStretchRange(FontStretch, FontStretch);
/// The computed representation of the above, with angles in degrees, so that /// Gecko can read them easily. #[repr(u8)] #[allow(missing_docs)] pubenum ComputedFontStyleDescriptor {
Normal,
Italic,
Oblique(f32, f32),
}
/// Default methods reject all at rules. impl<'a, 'b, 'i> AtRuleParser<'i> for FontFaceRuleParser<'a, 'b> { type Prelude = (); type AtRule = (); type Error = StyleParseErrorKind<'i>;
}
impl<'a, 'b, 'i> QualifiedRuleParser<'i> for FontFaceRuleParser<'a, 'b> { type Prelude = (); type QualifiedRule = (); type Error = StyleParseErrorKind<'i>;
}
impl<'a, 'b, 'i> DeclarationParser<'i> for FontFaceRuleParser<'a, 'b> { type Declaration = (); type Error = StyleParseErrorKind<'i>;
fn parse_value<'t>(
&mutself,
name: CowRcStr<'i>,
input: &mut Parser<'i, 't>,
) -> Result<(), ParseError<'i>> {
match_ignore_ascii_case! { &*name,
$(
$name if is_descriptor_enabled!($name) => { // DeclarationParser also calls parse_entirely // so we’d normally not need to, // but in this case we do because we set the value as a side effect // rather than returning it. let value = input.parse_entirely(|i| Parse::parse(self.context, i))?; self.rule.$ident = Some(value)
},
)*
_ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))),
}
Ok(())
}
}
}
}
impl ToCssWithGuard for FontFaceRuleData { // Serialization of FontFaceRule is not specced. fn to_css(&self, _guard: &SharedRwLockReadGuard, dest: &mutCssStringWriter) -> fmt::Result {
dest.write_str("@font-face { ")?; self.decl_to_css(dest)?;
dest.write_char('}')
}
}
impl FontFaceRuleData { /// Per https://github.com/w3c/csswg-drafts/issues/1133 an @font-face rule /// is valid as far as the CSS parser is concerned even if it doesn’t have /// a font-family or src declaration. /// /// However both are required for the rule to represent an actual font face. #[cfg(feature = "servo")] pubfn font_face(&self) -> Option<FontFace> { if $( self.$m_ident.is_some() )&&* {
Some(FontFace(self))
} else {
None
}
}
}
font_face_descriptors! {
mandatory descriptors = [ /// The name of this font face "font-family" family / mFamily: FamilyName,
/// The alternative sources for this font face. "src" sources / mSrc: SourceList,
]
optional descriptors = [ /// The style of this font face. "font-style" style / mStyle: FontStyle,
/// The weight of this font face. "font-weight" weight / mWeight: FontWeightRange,
/// The stretch of this font face. "font-stretch" stretch / mStretch: FontStretchRange,
/// The display of this font face. "font-display" display / mDisplay: FontDisplay,
/// The ranges of code points outside of which this font face should not be used. "unicode-range" unicode_range / mUnicodeRange: Vec<UnicodeRange>,
/// The feature settings of this font face. "font-feature-settings" feature_settings / mFontFeatureSettings: FontFeatureSettings,
/// The variation settings of this font face. "font-variation-settings" variation_settings / mFontVariationSettings: FontVariationSettings,
/// The language override of this font face. "font-language-override" language_override / mFontLanguageOverride: font_language_override::SpecifiedValue,
/// The ascent override for this font face. "ascent-override" ascent_override / mAscentOverride: MetricsOverride,
/// The descent override for this font face. "descent-override" descent_override / mDescentOverride: MetricsOverride,
/// The line-gap override for this font face. "line-gap-override" line_gap_override / mLineGapOverride: MetricsOverride,
/// The size adjustment for this font face. "size-adjust" size_adjust / mSizeAdjust: NonNegativePercentage,
]
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.20 Sekunden
(vorverarbeitet am 2026-06-19)
¤
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.