/* 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 ::derives::*;
use crate ::parser::{Parse, ParserContext};
use crate ::typed_om::{KeywordValue, ToTyped, TypedValue};
use crate ::values::animated::ToAnimatedZero;
use crate ::{One, Zero};
use byteorder::{BigEndian, ReadBytesExt};
use cssparser::Parser;
use std::fmt::{
self , Write};
use std::io::Cursor;
use style_traits::{CssString, CssWriter, ParseError, StyleParseErrorKind, ToCss};
use thin_vec::ThinVec;
/// 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,
ToAnimatedValue,
ToComputedValue,
ToResolvedValue,
ToShmem,
)]
#[ cfg_attr(feature =
"servo" , derive(Deserialize, Hash, Serialize))]
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,
ToAnimatedValue,
ToComputedValue,
ToCss,
ToResolvedValue,
ToShmem,
)]
#[ cfg_attr(feature = "servo" , derive(Deserialize, Serialize))]
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,
ToAnimatedValue,
ToCss,
ToResolvedValue,
ToShmem,
ToTyped,
)]
#[ cfg_attr(feature = "servo" , derive(Deserialize, Hash, Serialize))]
#[ css(comma)]
#[ typed(todo_derive_fields)]
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,
Eq,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToComputedValue,
ToResolvedValue,
ToShmem,
)]
#[ cfg_attr(feature = "servo" , derive(Deserialize, Hash, Serialize))]
pub struct FontTag(pub u32);
impl fmt::Debug for FontTag {
fn fmt(&self , f: &mut fmt::Formatter<'_>) -> fmt::Result {
let tag_bytes = self .0 .to_be_bytes();
let mut tuple = f.debug_tuple("FontTag" );
if let Ok(utf8_tag) = str::from_utf8(&tag_bytes) {
tuple.field(&utf8_tag);
} else {
tuple.field(&tag_bytes);
};
tuple.finish()
}
}
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 = [0 u8; 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,
)]
#[ value_info(other_values = "normal" )]
pub enum FontStyle<Angle> {
// Note that 'oblique 0deg' represents 'normal', and will serialize as such.
#[ value_info(starts_with_keyword)]
Oblique(Angle),
#[ animation(error)]
Italic,
}
impl <Angle: Zero> FontStyle<Angle> {
/// Return the 'normal' value, which is represented as 'oblique 0deg'.
pub fn normal() -> Self {
Self ::Oblique(Angle::zero())
}
}
/// A generic value for the `font-size-adjust` property.
///
/// https://drafts.csswg.org/css-fonts-5/#font-size-adjust-prop
#[ allow(missing_docs)]
#[ repr(u8)]
#[ derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
Hash,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToAnimatedZero,
ToComputedValue,
ToResolvedValue,
ToShmem,
)]
pub enum GenericFontSizeAdjust<Factor> {
#[ animation(error)]
None,
#[ value_info(starts_with_keyword)]
ExHeight(Factor),
#[ value_info(starts_with_keyword)]
CapHeight(Factor),
#[ value_info(starts_with_keyword)]
ChWidth(Factor),
#[ value_info(starts_with_keyword)]
IcWidth(Factor),
#[ value_info(starts_with_keyword)]
IcHeight(Factor),
}
impl <Factor: ToCss> ToCss for GenericFontSizeAdjust<Factor> {
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)
}
}
impl <Factor: ToTyped> ToTyped for GenericFontSizeAdjust<Factor> {
fn to_typed(&self , dest: &mut ThinVec<TypedValue>) -> Result<(), ()> {
match self {
Self ::None => {
dest.push(TypedValue::Keyword(KeywordValue(CssString::from("none" ))));
Ok(())
},
Self ::ExHeight(v) => v.to_typed(dest),
_ => Err(()),
}
}
}
/// A generic value for the `line-height` property.
#[ derive(
Animate,
Clone,
ComputeSquaredDistance,
Copy,
Debug,
MallocSizeOf,
PartialEq,
SpecifiedValueInfo,
ToAnimatedValue,
ToCss,
ToShmem,
Parse,
ToTyped,
)]
#[ cfg_attr(feature = "servo" , derive(Deserialize, Serialize))]
#[ repr(C, u8)]
pub enum GenericLineHeight<N, L> {
/// `normal`
Normal,
/// `-moz-block-height`
#[ cfg(feature = "gecko" )]
#[ parse(condition = "ParserContext::in_ua_sheet" )]
MozBlockHeight,
/// `<number>`
Number(N),
/// `<length-percentage>`
Length(L),
}
pub use self ::GenericLineHeight as LineHeight;
impl <N, L> ToAnimatedZero for LineHeight<N, L> {
#[ inline]
fn to_animated_zero(&self ) -> Result<Self , ()> {
Err(())
}
}
impl <N, L> LineHeight<N, L> {
/// Returns `normal`.
#[ inline]
pub fn normal() -> Self {
LineHeight::Normal
}
/// Returns whether the value is `normal`.
#[ inline]
pub fn is_normal(&self ) -> bool {
matches!(self , Self ::Normal)
}
}
Messung V0.5 in Prozent C=92 H=88 G=89
¤ Dauer der Verarbeitung: 0.5 Sekunden
¤
*© Formatika GbR, Deutschland