From 09398d42afd54b3beecbe729c86241fd5c3d295a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 31 Jan 2018 23:53:32 +0100 Subject: [PATCH] style: Move a bunch of font stuff living under generics to the proper module. FontSettingsTagInt and such shouldn't be in the generic module, I know... But that will change in a bit. --- components/style/gecko/rules.rs | 2 +- components/style/properties/gecko.mako.rs | 7 +- .../helpers/animated_properties.mako.rs | 8 +- components/style/values/computed/font.rs | 2 +- components/style/values/generics/font.rs | 131 ++++++++++++++ components/style/values/generics/mod.rs | 169 +----------------- components/style/values/specified/font.rs | 47 ++++- 7 files changed, 189 insertions(+), 177 deletions(-) create mode 100644 components/style/values/generics/font.rs diff --git a/components/style/gecko/rules.rs b/components/style/gecko/rules.rs index 7df6835f67a..97ec34c6bcf 100644 --- a/components/style/gecko/rules.rs +++ b/components/style/gecko/rules.rs @@ -21,7 +21,7 @@ use std::fmt::{self, Write}; use std::str; use str::CssStringWriter; use values::computed::font::FamilyName; -use values::generics::FontSettings; +use values::generics::font::FontSettings; /// A @font-face rule pub type FontFaceRule = RefPtr; diff --git a/components/style/properties/gecko.mako.rs b/components/style/properties/gecko.mako.rs index c4d732df9bd..231b4adfc08 100644 --- a/components/style/properties/gecko.mako.rs +++ b/components/style/properties/gecko.mako.rs @@ -1432,13 +1432,13 @@ impl Clone for ${style_struct.gecko_struct_name} { %> pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) { - use values::generics::FontSettings; + use values::generics::font::FontSettings; let current_settings = &mut self.gecko.mFont.${gecko_ffi_name}; current_settings.clear_pod(); match v { - FontSettings::Normal => (), // do nothing, length is already 0 + FontSettings::Normal => {}, // do nothing, length is already 0 FontSettings::Tag(other_settings) => { unsafe { current_settings.set_len_pod(other_settings.len() as u32) }; @@ -1470,7 +1470,8 @@ impl Clone for ${style_struct.gecko_struct_name} { } pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T { - use values::generics::{FontSettings, FontTag, FontSettingTag, ${tag_type}} ; + use values::generics::font::{FontSettings, FontSettingTag, ${tag_type}}; + use values::specified::font::FontTag; if self.gecko.mFont.${gecko_ffi_name}.len() == 0 { FontSettings::Normal diff --git a/components/style/properties/helpers/animated_properties.mako.rs b/components/style/properties/helpers/animated_properties.mako.rs index b73224c5962..0e839a90645 100644 --- a/components/style/properties/helpers/animated_properties.mako.rs +++ b/components/style/properties/helpers/animated_properties.mako.rs @@ -51,15 +51,15 @@ use values::computed::transform::Translate as ComputedTranslate; use values::computed::transform::Scale as ComputedScale; use values::generics::transform::{self, Rotate, Translate, Scale, Transform, TransformOperation}; use values::distance::{ComputeSquaredDistance, SquaredDistance}; -#[cfg(feature = "gecko")] use values::generics::FontSettings as GenericFontSettings; -#[cfg(feature = "gecko")] use values::generics::FontSettingTag as GenericFontSettingTag; -#[cfg(feature = "gecko")] use values::generics::FontSettingTagFloat; -#[cfg(feature = "gecko")] use values::generics::FontTag; +#[cfg(feature = "gecko")] use values::generics::font::FontSettings as GenericFontSettings; +#[cfg(feature = "gecko")] use values::generics::font::FontSettingTag as GenericFontSettingTag; +#[cfg(feature = "gecko")] use values::generics::font::FontSettingTagFloat; use values::generics::NonNegative; use values::generics::effects::Filter; use values::generics::position as generic_position; use values::generics::svg::{SVGLength, SvgLengthOrPercentageOrNumber, SVGPaint}; use values::generics::svg::{SVGPaintKind, SVGStrokeDashArray, SVGOpacity}; +#[cfg(feature = "gecko")] use values::specified::font::FontTag; /// pub trait RepeatableListAnimatable: Animate {} diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 20a41154ec9..3779c7c9575 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -23,7 +23,7 @@ use style_traits::{CssWriter, ParseError, ToCss}; use values::CSSFloat; use values::animated::{ToAnimatedValue, ToAnimatedZero}; use values::computed::{Context, NonNegativeLength, ToComputedValue}; -use values::generics::{FontSettings, FontSettingTagInt}; +use values::generics::font::{FontSettings, FontSettingTagInt}; use values::specified::font as specified; use values::specified::length::{FontBaseSize, NoCalcLength}; diff --git a/components/style/values/generics/font.rs b/components/style/values/generics/font.rs new file mode 100644 index 00000000000..0b3877620e7 --- /dev/null +++ b/components/style/values/generics/font.rs @@ -0,0 +1,131 @@ +/* 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 std::fmt::{self, Write}; +use cssparser::Parser; +use parser::{Parse, ParserContext}; +use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError, ToCss, StyleParseErrorKind}; +use values::specified::font::FontTag; + +/// A settings tag, defined by a four-character tag and a setting value +/// +/// For font-feature-settings, this is a tag and an integer, for +/// font-variation-settings this is a tag and a float. +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] +pub struct FontSettingTag { + /// A four-character tag, packed into a u32 (one byte per character) + pub tag: FontTag, + /// The actual value. + pub value: T, +} + +impl OneOrMoreSeparated for FontSettingTag { + type S = Comma; +} + +impl Parse for FontSettingTag { + /// + /// + /// settings-control-the-font-variation-settings-property + /// [ on | off | ] + /// + fn parse<'i, 't>( + context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let tag = FontTag::parse(context, input)?; + let value = T::parse(context, input)?; + + Ok(Self { tag, value }) + } +} + +/// A font settings value for font-variation-settings or font-feature-settings +#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] +pub enum FontSettings { + /// No settings (default) + Normal, + /// Set of settings + Tag(Vec>) +} + +impl FontSettings { + #[inline] + /// Default value of font settings as `normal` + pub fn normal() -> Self { + FontSettings::Normal + } +} + +impl Parse for FontSettings { + /// + fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + if input.try(|i| i.expect_ident_matching("normal")).is_ok() { + return Ok(FontSettings::Normal); + } + Vec::parse(context, input).map(FontSettings::Tag) + } +} + +/// An integer that can also parse "on" and "off", +/// for font-feature-settings +#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)] +pub struct FontSettingTagInt(pub u32); + +/// A number value to be used for font-variation-settings. +/// +/// FIXME(emilio): The spec only says , so we should be able to reuse +/// the other code: +/// +/// https://drafts.csswg.org/css-fonts-4/#propdef-font-variation-settings +#[cfg_attr(feature = "gecko", derive(Animate, ComputeSquaredDistance))] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] +pub struct FontSettingTagFloat(pub f32); + +impl ToCss for FontSettingTagInt { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: Write, + { + match self.0 { + 1 => Ok(()), + 0 => dest.write_str("off"), + x => x.to_css(dest), + } + } +} + +impl Parse for FontSettingTagInt { + fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + // FIXME(emilio): This doesn't handle calc properly. + if let Ok(value) = input.try(|input| input.expect_integer()) { + // handle integer, throw if it is negative + if value >= 0 { + Ok(FontSettingTagInt(value as u32)) + } else { + Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) + } + } else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) { + // on is an alias for '1' + Ok(FontSettingTagInt(1)) + } else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) { + // off is an alias for '0' + Ok(FontSettingTagInt(0)) + } else { + // empty value is an alias for '1' + Ok(FontSettingTagInt(1)) + } + } +} + +impl Parse for FontSettingTagFloat { + fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { + // FIXME(emilio): Should handle calc() using Number::parse. + // + // Also why is this not in font.rs? + input.expect_number().map(FontSettingTagFloat).map_err(|e| e.into()) + } +} diff --git a/components/style/values/generics/mod.rs b/components/style/values/generics/mod.rs index 1079dfae130..e29e1d4e1b1 100644 --- a/components/style/values/generics/mod.rs +++ b/components/style/values/generics/mod.rs @@ -8,9 +8,7 @@ use counter_style::{Symbols, parse_counter_style_name}; use cssparser::Parser; use parser::{Parse, ParserContext}; -use std::fmt::{self, Write}; -use style_traits::{Comma, CssWriter, OneOrMoreSeparated, ParseError}; -use style_traits::{StyleParseErrorKind, ToCss}; +use style_traits::{ParseError, StyleParseErrorKind}; use super::CustomIdent; pub mod background; @@ -20,6 +18,7 @@ pub mod border; pub mod box_; pub mod effects; pub mod flex; +pub mod font; #[cfg(feature = "gecko")] pub mod gecko; pub mod grid; @@ -128,170 +127,6 @@ impl Parse for CounterStyleOrNone { } } -/// 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, ToComputedValue)] -pub struct FontTag(pub u32); - -impl Parse for FontTag { - fn parse<'i, 't>( - _context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - use byteorder::{ReadBytesExt, BigEndian}; - use std::io::Cursor; - - let location = input.current_source_location(); - let tag = input.expect_string()?; - - // allowed strings of length 4 containing chars: - 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::().unwrap())) - } -} - -impl ToCss for FontTag { - fn to_css(&self, dest: &mut CssWriter) -> 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) - } -} - -/// A settings tag, defined by a four-character tag and a setting value -/// -/// For font-feature-settings, this is a tag and an integer, for -/// font-variation-settings this is a tag and a float. -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] -pub struct FontSettingTag { - /// A four-character tag, packed into a u32 (one byte per character) - pub tag: FontTag, - /// The actual value. - pub value: T, -} - -impl OneOrMoreSeparated for FontSettingTag { - type S = Comma; -} - -impl Parse for FontSettingTag { - /// - /// - /// settings-control-the-font-variation-settings-property - /// [ on | off | ] - /// - fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result> { - let tag = FontTag::parse(context, input)?; - let value = T::parse(context, input)?; - - Ok(Self { tag, value }) - } -} - -/// A font settings value for font-variation-settings or font-feature-settings -#[derive(Clone, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] -pub enum FontSettings { - /// No settings (default) - Normal, - /// Set of settings - Tag(Vec>) -} - -impl FontSettings { - #[inline] - /// Default value of font settings as `normal` - pub fn normal() -> Self { - FontSettings::Normal - } -} - -impl Parse for FontSettings { - /// - fn parse<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - if input.try(|i| i.expect_ident_matching("normal")).is_ok() { - return Ok(FontSettings::Normal); - } - Vec::parse(context, input).map(FontSettings::Tag) - } -} - -/// An integer that can also parse "on" and "off", -/// for font-feature-settings -#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToComputedValue)] -pub struct FontSettingTagInt(pub u32); - -/// A number value to be used for font-variation-settings. -/// -/// FIXME(emilio): The spec only says , so we should be able to reuse -/// the other code: -/// -/// https://drafts.csswg.org/css-fonts-4/#propdef-font-variation-settings -#[cfg_attr(feature = "gecko", derive(Animate, ComputeSquaredDistance))] -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] -pub struct FontSettingTagFloat(pub f32); - -impl ToCss for FontSettingTagInt { - fn to_css(&self, dest: &mut CssWriter) -> fmt::Result - where - W: Write, - { - match self.0 { - 1 => Ok(()), - 0 => dest.write_str("off"), - x => x.to_css(dest), - } - } -} - -impl Parse for FontSettingTagInt { - fn parse<'i, 't>(_context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - // FIXME(emilio): This doesn't handle calc properly. - if let Ok(value) = input.try(|input| input.expect_integer()) { - // handle integer, throw if it is negative - if value >= 0 { - Ok(FontSettingTagInt(value as u32)) - } else { - Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError)) - } - } else if let Ok(_) = input.try(|input| input.expect_ident_matching("on")) { - // on is an alias for '1' - Ok(FontSettingTagInt(1)) - } else if let Ok(_) = input.try(|input| input.expect_ident_matching("off")) { - // off is an alias for '0' - Ok(FontSettingTagInt(0)) - } else { - // empty value is an alias for '1' - Ok(FontSettingTagInt(1)) - } - } -} - -impl Parse for FontSettingTagFloat { - fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - // FIXME(emilio): Should handle calc() using Number::parse. - // - // Also why is this not in font.rs? - input.expect_number().map(FontSettingTagFloat).map_err(|e| e.into()) - } -} - /// A wrapper of Non-negative values. #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive(Animate, Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf)] diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index e7319b2a4e9..d7bcf838cff 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -21,7 +21,7 @@ use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss}; use values::CustomIdent; use values::computed::{font as computed, Context, Length, NonNegativeLength, ToComputedValue}; use values::computed::font::{SingleFontFamily, FontFamilyList, FamilyName}; -use values::generics::{FontSettings, FontSettingTagFloat}; +use values::generics::font::{FontSettings, FontSettingTagFloat}; use values::specified::{AllowQuirks, LengthOrPercentage, NoCalcLength, Number}; use values::specified::length::{AU_PER_PT, AU_PER_PX, FontBaseSize}; @@ -1962,6 +1962,51 @@ impl Parse for FontLanguageOverride { } } +/// 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, ToComputedValue)] +pub struct FontTag(pub u32); + +impl Parse for FontTag { + fn parse<'i, 't>( + _context: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + use byteorder::{ReadBytesExt, BigEndian}; + use std::io::Cursor; + + let location = input.current_source_location(); + let tag = input.expect_string()?; + + // allowed strings of length 4 containing chars: + 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::().unwrap())) + } +} + +impl ToCss for FontTag { + fn to_css(&self, dest: &mut CssWriter) -> 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) + } +} + + /// This property provides low-level control over OpenType or TrueType font variations. pub type FontVariantSettings = FontSettings;