diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-07 17:32:43 +0000 |
commit | 6bf0a5cb5034a7e684dcc3500e841785237ce2dd (patch) | |
tree | a68f146d7fa01f0134297619fbe7e33db084e0aa /servo/components/style/values/generics/font.rs | |
parent | Initial commit. (diff) | |
download | thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.tar.xz thunderbird-6bf0a5cb5034a7e684dcc3500e841785237ce2dd.zip |
Adding upstream version 1:115.7.0.upstream/1%115.7.0upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'servo/components/style/values/generics/font.rs')
-rw-r--r-- | servo/components/style/values/generics/font.rs | 271 |
1 files changed, 271 insertions, 0 deletions
diff --git a/servo/components/style/values/generics/font.rs b/servo/components/style/values/generics/font.rs new file mode 100644 index 0000000000..09ed542e97 --- /dev/null +++ b/servo/components/style/values/generics/font.rs @@ -0,0 +1,271 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ + +//! Generic types for font stuff. + +use crate::parser::{Parse, ParserContext}; +use crate::One; +use byteorder::{BigEndian, ReadBytesExt}; +use cssparser::Parser; +use std::fmt::{self, Write}; +use std::io::Cursor; +use style_traits::{CssWriter, ParseError}; +use style_traits::{StyleParseErrorKind, ToCss}; + +/// A trait for values that are labelled with a FontTag (for feature and +/// variation settings). +pub trait TaggedFontValue { + /// The value's tag. + fn tag(&self) -> FontTag; +} + +/// https://drafts.csswg.org/css-fonts-4/#feature-tag-value +#[derive( + Clone, + Debug, + Eq, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +pub struct FeatureTagValue<Integer> { + /// A four-character tag, packed into a u32 (one byte per character). + pub tag: FontTag, + /// The actual value. + pub value: Integer, +} + +impl<T> TaggedFontValue for FeatureTagValue<T> { + fn tag(&self) -> FontTag { + self.tag + } +} + +impl<Integer> ToCss for FeatureTagValue<Integer> +where + Integer: One + ToCss + PartialEq, +{ + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: Write, + { + self.tag.to_css(dest)?; + // Don't serialize the default value. + if !self.value.is_one() { + dest.write_char(' ')?; + self.value.to_css(dest)?; + } + + Ok(()) + } +} + +/// Variation setting for a single feature, see: +/// +/// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Debug, + Eq, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToCss, + ToResolvedValue, + ToShmem, +)] +pub struct VariationValue<Number> { + /// A four-character tag, packed into a u32 (one byte per character). + #[animation(constant)] + pub tag: FontTag, + /// The actual value. + pub value: Number, +} + +impl<T> TaggedFontValue for VariationValue<T> { + fn tag(&self) -> FontTag { + self.tag + } +} + +/// A value both for font-variation-settings and font-feature-settings. +#[derive( + Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToResolvedValue, ToShmem, +)] +#[css(comma)] +pub struct FontSettings<T>(#[css(if_empty = "normal", iterable)] pub Box<[T]>); + +impl<T> FontSettings<T> { + /// Default value of font settings as `normal`. + #[inline] + pub fn normal() -> Self { + FontSettings(vec![].into_boxed_slice()) + } +} + +impl<T: Parse> Parse for FontSettings<T> { + /// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-feature-settings + /// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + if input + .try_parse(|i| i.expect_ident_matching("normal")) + .is_ok() + { + return Ok(Self::normal()); + } + + Ok(FontSettings( + input + .parse_comma_separated(|i| T::parse(context, i))? + .into_boxed_slice(), + )) + } +} + +/// A font four-character tag, represented as a u32 for convenience. +/// +/// See: +/// https://drafts.csswg.org/css-fonts-4/#font-variation-settings-def +/// https://drafts.csswg.org/css-fonts-4/#descdef-font-face-font-feature-settings +/// +#[derive( + Clone, + Copy, + Debug, + Eq, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +pub struct FontTag(pub u32); + +impl ToCss for FontTag { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: Write, + { + use byteorder::ByteOrder; + use std::str; + + let mut raw = [0u8; 4]; + BigEndian::write_u32(&mut raw, self.0); + str::from_utf8(&raw).unwrap_or_default().to_css(dest) + } +} + +impl Parse for FontTag { + fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result<Self, ParseError<'i>> { + let location = input.current_source_location(); + let tag = input.expect_string()?; + + // allowed strings of length 4 containing chars: <U+20, U+7E> + if tag.len() != 4 || tag.as_bytes().iter().any(|c| *c < b' ' || *c > b'~') { + return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + + let mut raw = Cursor::new(tag.as_bytes()); + Ok(FontTag(raw.read_u32::<BigEndian>().unwrap())) + } +} + +/// A generic value for the `font-style` property. +/// +/// https://drafts.csswg.org/css-fonts-4/#font-style-prop +#[allow(missing_docs)] +#[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToResolvedValue, + ToShmem, +)] +pub enum FontStyle<Angle> { + #[animation(error)] + Normal, + #[animation(error)] + Italic, + #[value_info(starts_with_keyword)] + Oblique(Angle), +} + +/// A generic value for the `font-size-adjust` property. +/// +/// https://www.w3.org/TR/css-fonts-4/#font-size-adjust-prop +/// https://github.com/w3c/csswg-drafts/issues/6160 +/// https://github.com/w3c/csswg-drafts/issues/6288 +#[allow(missing_docs)] +#[repr(u8)] +#[derive( + Animate, + Clone, + ComputeSquaredDistance, + Copy, + Debug, + Hash, + MallocSizeOf, + PartialEq, + SpecifiedValueInfo, + ToAnimatedValue, + ToAnimatedZero, + ToComputedValue, + ToResolvedValue, + ToShmem, +)] +pub enum GenericFontSizeAdjust<Number> { + #[animation(error)] + None, + // 'ex-height' is the implied basis, so the keyword can be omitted + ExHeight(Number), + #[value_info(starts_with_keyword)] + CapHeight(Number), + #[value_info(starts_with_keyword)] + ChWidth(Number), + #[value_info(starts_with_keyword)] + IcWidth(Number), + #[value_info(starts_with_keyword)] + IcHeight(Number), +} + +impl<Number: ToCss> ToCss for GenericFontSizeAdjust<Number> { + fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result + where + W: Write, + { + let (prefix, value) = match self { + Self::None => return dest.write_str("none"), + Self::ExHeight(v) => ("", v), + Self::CapHeight(v) => ("cap-height ", v), + Self::ChWidth(v) => ("ch-width ", v), + Self::IcWidth(v) => ("ic-width ", v), + Self::IcHeight(v) => ("ic-height ", v), + }; + + dest.write_str(prefix)?; + value.to_css(dest) + } +} |