/* 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/. */
//! Specified values for font properties
usecrate::context::QuirksMode; usecrate::derives::*; usecrate::parser::{Parse, ParserContext}; usecrate::values::computed::font::{FamilyName, FontFamilyList, SingleFontFamily}; usecrate::values::computed::Percentage as ComputedPercentage; usecrate::values::computed::{font as computed, Length, NonNegativeLength}; usecrate::values::computed::{CSSPixelLength, Context, ToComputedValue}; usecrate::values::generics::font::{ selfas generics, FeatureTagValue, FontSettings, FontTag, GenericLineHeight, VariationValue,
}; usecrate::values::generics::NonNegative; usecrate::values::specified::length::{FontBaseSize, LengthUnit, LineHeightBase, PX_PER_PT}; usecrate::values::specified::{AllowQuirks, Angle, Integer, LengthPercentage}; usecrate::values::specified::{
NoCalcLength, NonNegativeLengthPercentage, NonNegativeNumber, NonNegativePercentage, Number,
}; usecrate::values::{serialize_atom_identifier, CustomIdent, SelectorParseErrorKind}; usecrate::Atom; use cssparser::{match_ignore_ascii_case, Parser, Token}; #[cfg(feature = "gecko")] use malloc_size_of::{MallocSizeOf, MallocSizeOfOps, MallocUnconditionalSizeOf}; use std::fmt::{self, Write}; use style_traits::{CssWriter, KeywordsCollectFn, ParseError}; use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
// FIXME(emilio): The system font code is copy-pasta, and should be cleaned up.
macro_rules! system_font_methods {
($ty:ident, $field:ident) => {
system_font_methods!($ty);
// We don't parse system fonts in servo, but in the interest of not // littering a lot of code with `if engine == "gecko"` conditionals, // we have a dummy system font module that does nothing
#[derive(
Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem,
)] #[allow(missing_docs)] #[cfg(feature = "servo")] /// void enum for system font, can never exist pubenum SystemFont {}
/// Get a specified FontWeight from a gecko keyword pubfn from_gecko_keyword(kw: u32) -> Self {
debug_assert!(kw % 100 == 0);
debug_assert!(kw as f32 <= MAX_FONT_WEIGHT);
FontWeight::Absolute(AbsoluteFontWeight::Weight(Number::new(kw as f32)))
}
}
impl ToComputedValue for FontWeight { type ComputedValue = computed::FontWeight;
impl AbsoluteFontWeight { /// Returns the computed weight for use when computed value context is unavailable. /// Returns None if the weight is a calc expression that requires computed-value context. pubfn compute(&self) -> Option<computed::FontWeight> { matchself {
AbsoluteFontWeight::Weight(weight) => {
Some(computed::FontWeight::from_float(weight.resolve()?))
},
AbsoluteFontWeight::Normal => Some(computed::FontWeight::NORMAL),
AbsoluteFontWeight::Bold => Some(computed::FontWeight::BOLD),
}
}
}
impl ToComputedValue for AbsoluteFontWeight { type ComputedValue = computed::FontWeight;
impl Parse for AbsoluteFontWeight { fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { iflet Ok(number) = input.try_parse(|input| Number::parse(context, input)) { // We could add another AllowedNumericType value, but it doesn't // seem worth it just for a single property with such a weird range, // so we do the clamping here manually. if matches!(number.get(), Some(v) if v < MIN_FONT_WEIGHT || v > MAX_FONT_WEIGHT) { return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
} return Ok(AbsoluteFontWeight::Weight(number));
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self { if *computed == computed::FontStyle::ITALIC { returnSelf::Italic;
} let degrees = computed.oblique_degrees();
generics::FontStyle::Oblique(Angle::from_degrees(degrees))
}
}
/// From https://drafts.csswg.org/css-fonts-4/#valdef-font-style-oblique-angle: /// /// Values less than -90deg or values greater than 90deg are /// invalid and are treated as parse errors. /// /// The maximum angle value that `font-style: oblique` should compute to. pubconst FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES: f32 = 90.;
/// The minimum angle value that `font-style: oblique` should compute to. pubconst FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES: f32 = -90.;
impl SpecifiedFontStyle { /// Gets a clamped angle in degrees from a specified Angle. pubfn compute_angle_degrees(angle: &Angle) -> Option<f32> {
Some(
angle
.degrees()?
.max(FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES)
.min(FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES),
)
}
/// Parse a suitable angle for font-style: oblique. pubfn parse_angle<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Angle, ParseError<'i>> { let angle = Angle::parse(context, input)?; // Calc angles can exceed the range and are clamped at computed-value time. if angle.is_calc() { return Ok(angle);
}
let degrees = angle.degrees().unwrap(); if degrees < FONT_STYLE_OBLIQUE_MIN_ANGLE_DEGREES
|| degrees > FONT_STYLE_OBLIQUE_MAX_ANGLE_DEGREES
{ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
} return Ok(angle);
}
/// The default angle for `font-style: oblique`. pubfn default_angle() -> Angle {
Angle::from_degrees(computed::FontStyle::DEFAULT_OBLIQUE_DEGREES as f32)
}
}
/// The specified value of the `font-style` property. #[derive(
Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, ToTyped,
)] #[allow(missing_docs)] #[typed(todo_derive_fields)] pubenum FontStyle {
Specified(SpecifiedFontStyle), #[css(skip)]
System(SystemFont),
}
impl FontStretchKeyword { /// Turns the keyword into a computed value. pubfn compute(&self) -> computed::FontStretch {
computed::FontStretch::from_keyword(*self)
}
/// Does the opposite operation to `compute`, in order to serialize keywords /// if possible. pubfn from_percentage(p: f32) -> Option<Self> {
computed::FontStretch::from_percentage(p).as_keyword()
}
}
#[derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
ToTyped,
)] #[cfg_attr(feature = "servo", derive(Serialize, Deserialize))] /// Additional information for keyword-derived font sizes. pubstruct KeywordInfo { /// The keyword used pub kw: FontSizeKeyword, /// A factor to be multiplied by the computed size of the keyword #[css(skip)] pub factor: f32, /// An additional fixed offset to add to the kw * factor in the case of /// `calc()`. #[css(skip)] pub offset: CSSPixelLength,
}
impl KeywordInfo { /// KeywordInfo value for font-size: medium pubfn medium() -> Self { Self::new(FontSizeKeyword::Medium)
}
/// KeywordInfo value for font-size: none pubfn none() -> Self { Self::new(FontSizeKeyword::None)
}
/// Computes the final size for this font-size keyword, accounting for /// text-zoom. fn to_computed_value(&self, context: &Context) -> CSSPixelLength {
debug_assert_ne!(self.kw, FontSizeKeyword::None); #[cfg(feature = "gecko")]
debug_assert_ne!(self.kw, FontSizeKeyword::Math); let base = context.maybe_zoom_text(self.kw.to_length(context).0); let zoom_factor = context.style().effective_zoom.value();
CSSPixelLength::new(base.px() * self.factor * zoom_factor)
+ context.maybe_zoom_text(self.offset)
}
/// Given a parent keyword info (self), apply an additional factor/offset to /// it. fn compose(self, factor: f32) -> Self { ifself.kw == FontSizeKeyword::None { returnself;
}
KeywordInfo {
kw: self.kw,
factor: self.factor * factor,
offset: self.offset * factor,
}
}
}
impl SpecifiedValueInfo for KeywordInfo { fn collect_completion_keywords(f: KeywordsCollectFn) {
<FontSizeKeyword as SpecifiedValueInfo>::collect_completion_keywords(f);
}
}
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, ToTyped)] /// A specified font-size value pubenum FontSize { /// A length; e.g. 10px.
Length(LengthPercentage), /// A keyword value, along with a ratio and absolute offset. /// The ratio in any specified keyword value /// will be 1 (with offset 0), but we cascade keywordness even /// after font-relative (percent and em) values /// have been applied, which is where the ratio /// comes in. The offset comes in if we cascaded a calc value, /// where the font-relative portion (em and percentage) will /// go into the ratio, and the remaining units all computed together /// will go into the offset. /// See bug 1355707.
Keyword(KeywordInfo), /// font-size: smaller
Smaller, /// font-size: larger
Larger, /// Derived from a specified system font. #[css(skip)]
System(SystemFont),
}
/// Specifies a prioritized list of font family names or generic family names. #[derive(Clone, Debug, Eq, PartialEq, ToCss, ToShmem, ToTyped)] #[cfg_attr(feature = "servo", derive(Hash))] #[typed(todo_derive_fields)] pubenum FontFamily { /// List of `font-family` #[css(comma)]
Values(#[css(iterable)] FontFamilyList), /// System font #[css(skip)]
System(SystemFont),
}
#[cfg(feature = "gecko")] impl MallocSizeOf for FontFamily { fn size_of(&self, ops: &mut MallocSizeOfOps) -> usize { match *self {
FontFamily::Values(ref v) => { // Although the family list is refcounted, we always attribute // its size to the specified value.
v.list.unconditional_size_of(ops)
},
FontFamily::System(_) => 0,
}
}
}
/// `FamilyName::parse` is based on `SingleFontFamily::parse` and not the other /// way around because we want the former to exclude generic family keywords. impl Parse for FamilyName { fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { match SingleFontFamily::parse(context, input) {
Ok(SingleFontFamily::FamilyName(name)) => Ok(name),
Ok(SingleFontFamily::Generic(_)) => {
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
},
Err(e) => Err(e),
}
}
}
/// A factor for one of the font-size-adjust metrics, which may be either a number /// or the `from-font` keyword. #[derive(
Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem, ToTyped,
)] pubenum FontSizeAdjustFactor { /// An explicitly-specified number.
Number(NonNegativeNumber), /// The from-font keyword: resolve the number from font metrics.
FromFont,
}
/// Specified value for font-size-adjust, intended to help /// preserve the readability of text when font fallback occurs. /// /// https://drafts.csswg.org/css-fonts-5/#font-size-adjust-prop pubtype FontSizeAdjust = generics::GenericFontSizeAdjust<FontSizeAdjustFactor>;
impl Parse for FontSizeAdjust { fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { let location = input.current_source_location(); // First check if we have an adjustment factor without a metrics-basis keyword. iflet Ok(factor) = input.try_parse(|i| FontSizeAdjustFactor::parse(context, i)) { return Ok(Self::ExHeight(factor));
}
/// This is the ratio applied for font-size: larger /// and smaller by both Firefox and Chrome const LARGER_FONT_SIZE_RATIO: f32 = 1.2;
/// The default font size. pubconst FONT_MEDIUM_PX: f32 = 16.0; /// The default line height. pubconst FONT_MEDIUM_LINE_HEIGHT_PX: f32 = FONT_MEDIUM_PX * 1.2; /// The default ex height -- https://drafts.csswg.org/css-values/#ex /// > In the cases where it is impossible or impractical to determine the x-height, a value of 0.5em must be assumed pubconst FONT_MEDIUM_EX_PX: f32 = FONT_MEDIUM_PX * 0.5; /// The default cap height -- https://drafts.csswg.org/css-values/#cap /// > In the cases where it is impossible or impractical to determine the cap-height, the font’s ascent must be used pubconst FONT_MEDIUM_CAP_PX: f32 = FONT_MEDIUM_PX; /// The default advance measure -- https://drafts.csswg.org/css-values/#ch /// > Thus, the ch unit falls back to 0.5em in the general case pubconst FONT_MEDIUM_CH_PX: f32 = FONT_MEDIUM_PX * 0.5; /// The default idographic advance measure -- https://drafts.csswg.org/css-values/#ic /// > In the cases where it is impossible or impractical to determine the ideographic advance measure, it must be assumed to be 1em pubconst FONT_MEDIUM_IC_PX: f32 = FONT_MEDIUM_PX;
impl FontSizeKeyword { #[inline] fn to_length(&self, cx: &Context) -> NonNegativeLength { let font = cx.style().get_font();
#[cfg(feature = "servo")] let family = &font.font_family.families; #[cfg(feature = "gecko")] let family = &font.mFont.family.families;
let generic = family
.single_generic()
.unwrap_or(computed::GenericFontFamily::None);
/// Resolve a keyword length without any context, with explicit arguments. #[inline] pubfn to_length_without_context(
&self,
quirks_mode: QuirksMode,
base_size: Length,
) -> NonNegativeLength { #[cfg(feature = "gecko")]
debug_assert_ne!(*self, FontSizeKeyword::Math); // The tables in this function are originally from // nsRuleNode::CalcFontPointSize in Gecko: // // https://searchfox.org/mozilla-central/rev/c05d9d61188d32b8/layout/style/nsRuleNode.cpp#3150 // // Mapping from base size and HTML size to pixels // The first index is (base_size - 9), the second is the // HTML size. "0" is CSS keyword xx-small, not HTML size 0, // since HTML size 0 is the same as 1. // // xxs xs s m l xl xxl - // - 0/1 2 3 4 5 6 7 static FONT_SIZE_MAPPING: [[i32; 8]; 8] = [
[9, 9, 9, 9, 11, 14, 18, 27],
[9, 9, 9, 10, 12, 15, 20, 30],
[9, 9, 10, 11, 13, 17, 22, 33],
[9, 9, 10, 12, 14, 18, 24, 36],
[9, 10, 12, 13, 16, 20, 26, 39],
[9, 10, 12, 14, 17, 21, 28, 42],
[9, 10, 13, 15, 18, 23, 30, 45],
[9, 10, 13, 16, 18, 24, 32, 48],
];
static FONT_SIZE_FACTORS: [i32; 8] = [60, 75, 89, 100, 120, 150, 200, 300]; let base_size_px = base_size.px().round() as i32; let html_size = self.html_size() as usize;
NonNegative(if base_size_px >= 9 && base_size_px <= 16 { let mapping = if quirks_mode == QuirksMode::Quirks {
QUIRKS_FONT_SIZE_MAPPING
} else {
FONT_SIZE_MAPPING
};
Length::new(mapping[(base_size_px - 9) as usize][html_size] as f32)
} else {
base_size * FONT_SIZE_FACTORS[html_size] as f32 / 100.0
})
}
}
impl FontSize { /// <https://html.spec.whatwg.org/multipage/#rules-for-parsing-a-legacy-font-size> pubfn from_html_size(size: u8) -> Self {
FontSize::Keyword(KeywordInfo::new(match size { // If value is less than 1, let it be 1. 0 | 1 => FontSizeKeyword::XSmall, 2 => FontSizeKeyword::Small, 3 => FontSizeKeyword::Medium, 4 => FontSizeKeyword::Large, 5 => FontSizeKeyword::XLarge, 6 => FontSizeKeyword::XXLarge, // If value is greater than 7, let it be 7.
_ => FontSizeKeyword::XXXLarge,
}))
}
/// Compute it against a given base font size pubfn to_computed_value_against(
&self,
context: &Context,
base_size: FontBaseSize,
line_height_base: LineHeightBase,
) -> computed::FontSize { let compose_keyword = |factor| {
context
.style()
.get_parent_font()
.clone_font_size()
.keyword_info
.compose(factor)
}; letmut info = KeywordInfo::none(); let size = match *self {
FontSize::Length(LengthPercentage::Length(ref l)) => { if l.length_unit() == LengthUnit::Em { // If the parent font was keyword-derived, this is // too. Tack the em unit onto the factor
info = compose_keyword(l.unitless_value());
} let result =
l.to_computed_value_with_base_size(context, base_size, line_height_base); if l.should_zoom_text() {
context.maybe_zoom_text(result)
} else {
result
}
},
FontSize::Length(LengthPercentage::Percentage(pc)) => { // If the parent font was keyword-derived, this is too. // Tack the % onto the factor
info = compose_keyword(pc.get());
(base_size.resolve(context).computed_size() * pc.get()).normalized()
},
FontSize::Length(LengthPercentage::Calc(ref calc)) => { let calc = calc.to_computed_value_zoomed(context, base_size, line_height_base);
calc.resolve(base_size.resolve(context).computed_size())
},
FontSize::Keyword(i) => { if i.kw.is_math() { // Scaling is done in recompute_math_font_size_if_needed().
info = compose_keyword(1.); // i.kw will always be FontSizeKeyword::Math here. But writing it this // allows this code to compile for servo where the Math variant is cfg'd out.
info.kw = i.kw;
NoCalcLength::from_em(1.).to_computed_value_with_base_size(
context,
base_size,
line_height_base,
)
} else { // As a specified keyword, this is keyword derived
info = i;
i.to_computed_value(context).clamp_to_non_negative()
}
},
FontSize::Smaller => {
info = compose_keyword(1. / LARGER_FONT_SIZE_RATIO);
NoCalcLength::from_em(1. / LARGER_FONT_SIZE_RATIO)
.to_computed_value_with_base_size(context, base_size, line_height_base)
},
FontSize::Larger => {
info = compose_keyword(LARGER_FONT_SIZE_RATIO);
NoCalcLength::from_em(LARGER_FONT_SIZE_RATIO).to_computed_value_with_base_size(
context,
base_size,
line_height_base,
)
},
FontSize::System(_) => { #[cfg(feature = "servo")]
{
unreachable!()
} #[cfg(feature = "gecko")]
{
context
.cached_system_font
.as_ref()
.unwrap()
.font_size
.computed_size()
.zoom(context.builder.effective_zoom)
}
},
};
computed::FontSize {
computed_size: NonNegative(size),
used_size: NonNegative(size),
keyword_info: info,
}
}
}
impl ToComputedValue for FontSize { type ComputedValue = computed::FontSize;
impl FontVariantEastAsian { /// The number of variants. pubconst COUNT: usize = 9;
fn validate_mixed_flags(&self) -> bool { ifself.contains(Self::FULL_WIDTH | Self::PROPORTIONAL_WIDTH) { // full-width and proportional-width are exclusive with each other. returnfalse;
} let jis = self.intersection(Self::JIS_GROUP); if !jis.is_empty() && !jis.bits().is_power_of_two() { returnfalse;
} true
}
}
#[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
ToTyped,
)] #[cfg_attr(feature = "servo", derive(Deserialize, Hash, Serialize))] #[css(bitflags(
single = "normal,none",
mixed = "common-ligatures,no-common-ligatures,discretionary-ligatures,no-discretionary-ligatures,historical-ligatures,no-historical-ligatures,contextual,no-contextual",
validate_mixed = "Self::validate_mixed_flags",
))] #[repr(C)] /// Variants of ligatures pubstruct FontVariantLigatures(u16);
bitflags! { impl FontVariantLigatures: u16 { /// Specifies that common default features are enabled const NORMAL = 0; /// Specifies that no features are enabled; const NONE = 1; /// Enables display of common ligatures const COMMON_LIGATURES = 1 << 1; /// Disables display of common ligatures const NO_COMMON_LIGATURES = 1 << 2; /// Enables display of discretionary ligatures const DISCRETIONARY_LIGATURES = 1 << 3; /// Disables display of discretionary ligatures const NO_DISCRETIONARY_LIGATURES = 1 << 4; /// Enables display of historical ligatures const HISTORICAL_LIGATURES = 1 << 5; /// Disables display of historical ligatures const NO_HISTORICAL_LIGATURES = 1 << 6; /// Enables display of contextual alternates const CONTEXTUAL = 1 << 7; /// Disables display of contextual alternates const NO_CONTEXTUAL = 1 << 8;
}
}
impl FontVariantLigatures { /// The number of variants. pubconst COUNT: usize = 9;
fn validate_mixed_flags(&self) -> bool { // Mixing a value and its disabling value is forbidden. ifself.contains(Self::COMMON_LIGATURES | Self::NO_COMMON_LIGATURES)
|| self.contains(Self::DISCRETIONARY_LIGATURES | Self::NO_DISCRETIONARY_LIGATURES)
|| self.contains(Self::HISTORICAL_LIGATURES | Self::NO_HISTORICAL_LIGATURES)
|| self.contains(Self::CONTEXTUAL | Self::NO_CONTEXTUAL)
{ returnfalse;
} true
}
}
/// Variants of numeric values #[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
PartialEq,
Parse,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
ToTyped,
)] #[css(bitflags(
single = "normal",
mixed = "lining-nums,oldstyle-nums,proportional-nums,tabular-nums,diagonal-fractions,stacked-fractions,ordinal,slashed-zero",
validate_mixed = "Self::validate_mixed_flags",
))] #[cfg_attr(feature = "servo", derive(Serialize, Deserialize, Hash))] #[repr(C)] pubstruct FontVariantNumeric(u8);
bitflags! { impl FontVariantNumeric : u8 { /// Specifies that common default features are enabled const NORMAL = 0; /// Enables display of lining numerals. const LINING_NUMS = 1 << 0; /// Enables display of old-style numerals. const OLDSTYLE_NUMS = 1 << 1; /// Enables display of proportional numerals. const PROPORTIONAL_NUMS = 1 << 2; /// Enables display of tabular numerals. const TABULAR_NUMS = 1 << 3; /// Enables display of lining diagonal fractions. const DIAGONAL_FRACTIONS = 1 << 4; /// Enables display of lining stacked fractions. const STACKED_FRACTIONS = 1 << 5; /// Enables display of slashed zeros. const SLASHED_ZERO = 1 << 6; /// Enables display of letter forms used with ordinal numbers. const ORDINAL = 1 << 7;
}
}
impl FontVariantNumeric { /// The number of variants. pubconst COUNT: usize = 8;
/// This property provides low-level control over OpenType or TrueType font features. pubtype FontFeatureSettings = FontSettings<FeatureTagValue<Integer>>;
impl FontFeatureSettings { /// Like `parse`, but rejects calc expressions that cannot be resolved at parse time, /// since @font-face descriptors require concrete values. pubfn parse_for_font_face_rule<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { let settings = FontFeatureSettings::parse(context, input)?; if settings
.0
.iter()
.any(|setting| setting.value.resolve().is_none())
{ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(settings)
}
}
/// For font-language-override, use the same representation as the computed value. pubusecrate::values::computed::font::FontLanguageOverride;
/// A value for any of the font-synthesis-{weight,small-caps,position} properties. #[repr(u8)] #[derive(
Clone,
Copy,
Debug,
Eq,
Hash,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
ToTyped,
)] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] pubenum FontSynthesis { /// This attribute may be synthesized if not supported by a face.
Auto, /// Do not attempt to synthesis this style attribute.
None,
}
/// A value for the font-synthesis-style property. #[repr(u8)] #[derive(
Clone,
Copy,
Debug,
Eq,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
ToTyped,
)] pubenum FontSynthesisStyle { /// This attribute may be synthesized if not supported by a face.
Auto, /// Do not attempt to synthesis this style attribute.
None, /// Allow synthesis for oblique, but not for italic.
ObliqueOnly,
}
#[derive(
Clone,
Debug,
Eq,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToResolvedValue,
ToShmem,
ToTyped,
)] #[repr(C)] #[typed(todo_derive_fields)] /// Allows authors to choose a palette from those supported by a color font /// (and potentially @font-palette-values overrides). pubstruct FontPalette(Atom);
impl ToCss for FontPalette { fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result where
W: Write,
{
serialize_atom_identifier(&self.0, dest)
}
}
/// This property provides low-level control over OpenType or TrueType font /// variations. pubtype FontVariationSettings = FontSettings<VariationValue<Number>>;
impl Parse for FeatureTagValue<Integer> { /// https://drafts.csswg.org/css-fonts-4/#feature-tag-value fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { let tag = FontTag::parse(context, input)?; let value = input
.try_parse(|i| parse_one_feature_value(context, i))
.unwrap_or_else(|_| Integer::new(1));
Ok(Self { tag, value })
}
}
impl Parse for VariationValue<Number> { /// This is the `<string> <number>` part of the font-variation-settings /// syntax. fn parse<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { let tag = FontTag::parse(context, input)?; let value = Number::parse(context, input)?;
Ok(Self { tag, value })
}
}
impl FontVariationSettings { /// Like `parse`, but rejects calc expressions that cannot be resolved at parse time, /// since @font-face descriptors require concrete values. pubfn parse_for_font_face_rule<'i, 't>(
context: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<Self, ParseError<'i>> { let settings = FontVariationSettings::parse(context, input)?; if settings
.0
.iter()
.any(|setting| setting.value.resolve().is_none())
{ return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
}
Ok(settings)
}
}
/// A metrics override value for a @font-face descriptor /// /// https://drafts.csswg.org/css-fonts/#font-metrics-override-desc #[derive(Clone, Debug, MallocSizeOf, Parse, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)] pubenum MetricsOverride { /// A non-negative `<percentage>` of the computed font size Override(NonNegativePercentage), /// Normal metrics from the font.
Normal,
}
impl MetricsOverride { #[inline] /// Get default value with `normal` pubfn normal() -> MetricsOverride {
MetricsOverride::Normal
}
/// The ToComputedValue implementation, used for @font-face descriptors. /// /// Valid override percentages must be non-negative; we return -1.0 to indicate /// the absence of an override (i.e. 'normal'). Returns None if the value contains /// a calc expression that cannot be resolved at parse time. #[inline] pubfn compute(&self) -> Option<ComputedPercentage> {
Some(ComputedPercentage(matchself {
MetricsOverride::Normal => -1.0,
MetricsOverride::Override(percent) => percent.compute()?.0,
}))
}
}
#[derive(
Clone,
Copy,
Debug,
MallocSizeOf,
Parse,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
ToTyped,
)] #[repr(u8)] /// How to do font-size scaling. pubenum XTextScale { /// Both min-font-size and text zoom are enabled.
All, /// Text-only zoom is enabled, but min-font-size is not honored.
ZoomOnly, /// Neither of them is enabled.
None,
}
#[cfg_attr(feature = "gecko", derive(MallocSizeOf))] #[derive(
Clone,
Copy,
Debug,
PartialEq,
SpecifiedValueInfo,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)] /// Specifies the multiplier to be used to adjust font size /// due to changes in scriptlevel. /// /// Ref: https://www.w3.org/TR/MathML3/chapter3.html#presm.mstyle.attrs pubstruct MozScriptSizeMultiplier(pub f32);
impl MozScriptSizeMultiplier { #[inline] /// Get default value of `-moz-script-size-multiplier` pubfn get_initial_value() -> MozScriptSizeMultiplier {
MozScriptSizeMultiplier(DEFAULT_SCRIPT_SIZE_MULTIPLIER as f32)
}
}
impl Parse for MozScriptSizeMultiplier { fn parse<'i, 't>(
_: &ParserContext,
input: &mut Parser<'i, 't>,
) -> Result<MozScriptSizeMultiplier, ParseError<'i>> {
debug_assert!( false, "Should be set directly by presentation attributes only."
);
Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
}
}
/// Flags for the query_font_metrics() function. #[repr(C)] pubstruct QueryFontMetricsFlags(u8);
bitflags! { impl QueryFontMetricsFlags: u8 { /// Should we use the user font set? const USE_USER_FONT_SET = 1 << 0; /// Does the caller need the `ch` unit (width of the ZERO glyph)? const NEEDS_CH = 1 << 1; /// Does the caller need the `ic` unit (width of the WATER ideograph)? const NEEDS_IC = 1 << 2; /// Does the caller need math scales to be retrieved? const NEEDS_MATH_SCALES = 1 << 3;
}
}
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.