mirror of
https://github.com/servo/servo.git
synced 2025-07-02 21:13:39 +01:00
265 lines
6.6 KiB
Rust
265 lines
6.6 KiB
Rust
/* 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 http://mozilla.org/MPL/2.0/. */
|
|
|
|
//! Generic types for font stuff.
|
|
|
|
use app_units::Au;
|
|
use byteorder::{BigEndian, ReadBytesExt};
|
|
use cssparser::Parser;
|
|
use num_traits::One;
|
|
use parser::{Parse, ParserContext};
|
|
use std::fmt::{self, Write};
|
|
use std::io::Cursor;
|
|
use style_traits::{CssWriter, KeywordsCollectFn, ParseError};
|
|
use style_traits::{SpecifiedValueInfo, StyleParseErrorKind, ToCss};
|
|
|
|
/// https://drafts.csswg.org/css-fonts-4/#feature-tag-value
|
|
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue)]
|
|
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<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 != Integer::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,
|
|
)]
|
|
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,
|
|
}
|
|
|
|
/// A value both for font-variation-settings and font-feature-settings.
|
|
#[css(comma)]
|
|
#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToComputedValue, ToCss)]
|
|
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(|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)]
|
|
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::{BigEndian, 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()))
|
|
}
|
|
}
|
|
|
|
#[derive(
|
|
Animate,
|
|
Clone,
|
|
ComputeSquaredDistance,
|
|
Copy,
|
|
Debug,
|
|
MallocSizeOf,
|
|
PartialEq,
|
|
ToAnimatedValue,
|
|
ToAnimatedZero,
|
|
ToCss,
|
|
)]
|
|
/// Additional information for keyword-derived font sizes.
|
|
pub struct KeywordInfo<Length> {
|
|
/// The keyword used
|
|
pub kw: KeywordSize,
|
|
/// A factor to be multiplied by the computed size of the keyword
|
|
#[css(skip)]
|
|
pub factor: f32,
|
|
/// An additional Au offset to add to the kw*factor in the case of calcs
|
|
#[css(skip)]
|
|
pub offset: Length,
|
|
}
|
|
|
|
impl<L> KeywordInfo<L>
|
|
where
|
|
Au: Into<L>,
|
|
{
|
|
/// KeywordInfo value for font-size: medium
|
|
pub fn medium() -> Self {
|
|
KeywordSize::Medium.into()
|
|
}
|
|
}
|
|
|
|
impl<L> From<KeywordSize> for KeywordInfo<L>
|
|
where
|
|
Au: Into<L>,
|
|
{
|
|
fn from(x: KeywordSize) -> Self {
|
|
KeywordInfo {
|
|
kw: x,
|
|
factor: 1.,
|
|
offset: Au(0).into(),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl<L> SpecifiedValueInfo for KeywordInfo<L> {
|
|
fn collect_completion_keywords(f: KeywordsCollectFn) {
|
|
<KeywordSize as SpecifiedValueInfo>::collect_completion_keywords(f);
|
|
}
|
|
}
|
|
|
|
/// CSS font keywords
|
|
#[derive(
|
|
Animate,
|
|
Clone,
|
|
ComputeSquaredDistance,
|
|
Copy,
|
|
Debug,
|
|
MallocSizeOf,
|
|
Parse,
|
|
PartialEq,
|
|
SpecifiedValueInfo,
|
|
ToAnimatedValue,
|
|
ToAnimatedZero,
|
|
ToCss,
|
|
)]
|
|
#[allow(missing_docs)]
|
|
pub enum KeywordSize {
|
|
#[css(keyword = "xx-small")]
|
|
XXSmall,
|
|
XSmall,
|
|
Small,
|
|
Medium,
|
|
Large,
|
|
XLarge,
|
|
#[css(keyword = "xx-large")]
|
|
XXLarge,
|
|
// This is not a real font keyword and will not parse
|
|
// HTML font-size 7 corresponds to this value
|
|
#[css(skip)]
|
|
XXXLarge,
|
|
}
|
|
|
|
impl KeywordSize {
|
|
/// Convert to an HTML <font size> value
|
|
#[inline]
|
|
pub fn html_size(self) -> u8 {
|
|
self as u8
|
|
}
|
|
}
|
|
|
|
impl Default for KeywordSize {
|
|
fn default() -> Self {
|
|
KeywordSize::Medium
|
|
}
|
|
}
|
|
|
|
/// 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,
|
|
)]
|
|
pub enum FontStyle<Angle> {
|
|
#[animation(error)]
|
|
Normal,
|
|
#[animation(error)]
|
|
Italic,
|
|
#[value_info(starts_with_keyword)]
|
|
Oblique(Angle),
|
|
}
|