From 4927786d90b0d7da6419ed7fb9f7dade18d928ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 11 Nov 2017 14:57:12 +0100 Subject: [PATCH] style: Implement css(dimension) and derive ToCss for a bunch of stuff. For css(dimension), it'd be nice to derive(Parse) too, I think... --- components/layout/display_list_builder.rs | 8 +- components/style/gecko/conversions.rs | 18 +-- components/style/gecko/media_queries.rs | 17 +-- components/style/gecko/values.rs | 6 +- components/style/values/computed/angle.rs | 41 ++----- components/style/values/specified/angle.rs | 8 +- components/style/values/specified/calc.rs | 8 +- components/style/values/specified/length.rs | 122 ++++++-------------- components/style_derive/to_css.rs | 21 +++- ports/geckolib/glue.rs | 2 +- 10 files changed, 98 insertions(+), 153 deletions(-) diff --git a/components/layout/display_list_builder.rs b/components/layout/display_list_builder.rs index c8c2f043b0f..cda9f31d878 100644 --- a/components/layout/display_list_builder.rs +++ b/components/layout/display_list_builder.rs @@ -1315,14 +1315,14 @@ impl FragmentDisplayListBuilding for Fragment { LineDirection::Angle(angle) => angle.radians(), LineDirection::Horizontal(x) => { match x { - X::Left => Angle::Degree(270.).radians(), - X::Right => Angle::Degree(90.).radians(), + X::Left => Angle::Deg(270.).radians(), + X::Right => Angle::Deg(90.).radians(), } }, LineDirection::Vertical(y) => { match y { - Y::Top => Angle::Degree(0.).radians(), - Y::Bottom => Angle::Degree(180.).radians(), + Y::Top => Angle::Deg(0.).radians(), + Y::Bottom => Angle::Deg(180.).radians(), } }, LineDirection::Corner(horizontal, vertical) => { diff --git a/components/style/gecko/conversions.rs b/components/style/gecko/conversions.rs index 4603de3b260..cc879dfd78c 100644 --- a/components/style/gecko/conversions.rs +++ b/components/style/gecko/conversions.rs @@ -116,9 +116,9 @@ impl From for LengthOrPercentageOrAuto { impl From for CoordDataValue { fn from(reference: Angle) -> Self { match reference { - Angle::Degree(val) => CoordDataValue::Degree(val), - Angle::Gradian(val) => CoordDataValue::Grad(val), - Angle::Radian(val) => CoordDataValue::Radian(val), + Angle::Deg(val) => CoordDataValue::Degree(val), + Angle::Grad(val) => CoordDataValue::Grad(val), + Angle::Rad(val) => CoordDataValue::Radian(val), Angle::Turn(val) => CoordDataValue::Turn(val), } } @@ -128,9 +128,9 @@ impl Angle { /// Converts Angle struct into (value, unit) pair. pub fn to_gecko_values(&self) -> (f32, nsCSSUnit) { match *self { - Angle::Degree(val) => (val, nsCSSUnit::eCSSUnit_Degree), - Angle::Gradian(val) => (val, nsCSSUnit::eCSSUnit_Grad), - Angle::Radian(val) => (val, nsCSSUnit::eCSSUnit_Radian), + Angle::Deg(val) => (val, nsCSSUnit::eCSSUnit_Degree), + Angle::Grad(val) => (val, nsCSSUnit::eCSSUnit_Grad), + Angle::Rad(val) => (val, nsCSSUnit::eCSSUnit_Radian), Angle::Turn(val) => (val, nsCSSUnit::eCSSUnit_Turn), } } @@ -138,9 +138,9 @@ impl Angle { /// Converts gecko (value, unit) pair into Angle struct pub fn from_gecko_values(value: f32, unit: nsCSSUnit) -> Angle { match unit { - nsCSSUnit::eCSSUnit_Degree => Angle::Degree(value), - nsCSSUnit::eCSSUnit_Grad => Angle::Gradian(value), - nsCSSUnit::eCSSUnit_Radian => Angle::Radian(value), + nsCSSUnit::eCSSUnit_Degree => Angle::Deg(value), + nsCSSUnit::eCSSUnit_Grad => Angle::Grad(value), + nsCSSUnit::eCSSUnit_Radian => Angle::Rad(value), nsCSSUnit::eCSSUnit_Turn => Angle::Turn(value), _ => panic!("Unexpected unit {:?} for angle", unit), } diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 95a4ec2e42a..954463ae91d 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -29,7 +29,7 @@ use style_traits::{CSSPixel, DevicePixel}; use style_traits::{ToCss, ParseError, StyleParseErrorKind}; use style_traits::viewport::ViewportConstraints; use stylesheets::Origin; -use values::{CSSFloat, CustomIdent, serialize_dimension}; +use values::{CSSFloat, CustomIdent}; use values::computed::{self, ToComputedValue}; use values::computed::font::FontSize; use values::specified::Length; @@ -262,7 +262,8 @@ impl PartialEq for Expression { } /// A resolution. -#[derive(Clone, Debug, PartialEq)] +#[derive(Clone, Debug, PartialEq, ToCss)] +#[css(dimension)] pub enum Resolution { /// Dots per inch. Dpi(CSSFloat), @@ -303,18 +304,6 @@ impl Resolution { } } -impl ToCss for Resolution { - fn to_css(&self, dest: &mut W) -> fmt::Result - where W: fmt::Write, - { - match *self { - Resolution::Dpi(v) => serialize_dimension(v, "dpi", dest), - Resolution::Dppx(v) => serialize_dimension(v, "dppx", dest), - Resolution::Dpcm(v) => serialize_dimension(v, "dpcm", dest), - } - } -} - /// A value found or expected in a media expression. #[derive(Clone, Debug, PartialEq)] pub enum MediaExpressionValue { diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 09a796c5980..4f1b3cbb851 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -291,9 +291,9 @@ impl GeckoStyleCoordConvertible for Angle { fn from_gecko_style_coord(coord: &T) -> Option { match coord.as_value() { - CoordDataValue::Degree(val) => Some(Angle::Degree(val)), - CoordDataValue::Grad(val) => Some(Angle::Gradian(val)), - CoordDataValue::Radian(val) => Some(Angle::Radian(val)), + CoordDataValue::Degree(val) => Some(Angle::Deg(val)), + CoordDataValue::Grad(val) => Some(Angle::Grad(val)), + CoordDataValue::Radian(val) => Some(Angle::Rad(val)), CoordDataValue::Turn(val) => Some(Angle::Turn(val)), _ => None, } diff --git a/components/style/values/computed/angle.rs b/components/style/values/computed/angle.rs index fdaecf93ab1..1896a530d5a 100644 --- a/components/style/values/computed/angle.rs +++ b/components/style/values/computed/angle.rs @@ -5,9 +5,8 @@ //! Computed angles. use euclid::Radians; -use std::{f32, f64, fmt}; +use std::{f32, f64}; use std::f64::consts::PI; -use style_traits::ToCss; use values::CSSFloat; use values::animated::{Animate, Procedure}; use values::distance::{ComputeSquaredDistance, SquaredDistance}; @@ -15,15 +14,16 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance}; /// A computed angle. #[animate(fallback = "Self::animate_fallback")] #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] -#[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq)] +#[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(PartialOrd, ToAnimatedZero)] +#[css(dimension)] pub enum Angle { /// An angle with degree unit. - Degree(CSSFloat), + Deg(CSSFloat), /// An angle with gradian unit. - Gradian(CSSFloat), + Grad(CSSFloat), /// An angle with radian unit. - Radian(CSSFloat), + Rad(CSSFloat), /// An angle with turn unit. Turn(CSSFloat), } @@ -31,7 +31,7 @@ pub enum Angle { impl Angle { /// Creates a computed `Angle` value from a radian amount. pub fn from_radians(radians: CSSFloat) -> Self { - Angle::Radian(radians) + Angle::Rad(radians) } /// Returns the amount of radians this angle represents. @@ -53,17 +53,17 @@ impl Angle { const RAD_PER_TURN: f64 = PI * 2.0; let radians = match *self { - Angle::Degree(val) => val as f64 * RAD_PER_DEG, - Angle::Gradian(val) => val as f64 * RAD_PER_GRAD, + Angle::Deg(val) => val as f64 * RAD_PER_DEG, + Angle::Grad(val) => val as f64 * RAD_PER_GRAD, Angle::Turn(val) => val as f64 * RAD_PER_TURN, - Angle::Radian(val) => val as f64, + Angle::Rad(val) => val as f64, }; radians.min(f64::MAX).max(f64::MIN) } /// Returns an angle that represents a rotation of zero radians. pub fn zero() -> Self { - Angle::Radian(0.0) + Self::from_radians(0.0) } /// @@ -82,25 +82,6 @@ impl ComputeSquaredDistance for Angle { } } -impl ToCss for Angle { - fn to_css(&self, dest: &mut W) -> fmt::Result - where - W: fmt::Write, - { - let mut write = |value: CSSFloat, unit: &str| { - value.to_css(dest)?; - dest.write_str(unit) - }; - - match *self { - Angle::Degree(val) => write(val, "deg"), - Angle::Gradian(val) => write(val, "grad"), - Angle::Radian(val) => write(val, "rad"), - Angle::Turn(val) => write(val, "turn"), - } - } -} - impl From for Radians { #[inline] fn from(a: Angle) -> Self { diff --git a/components/style/values/specified/angle.rs b/components/style/values/specified/angle.rs index e3714a5babf..863a436ab4f 100644 --- a/components/style/values/specified/angle.rs +++ b/components/style/values/specified/angle.rs @@ -57,12 +57,12 @@ impl ToComputedValue for Angle { impl Angle { /// Creates an angle with the given value in degrees. pub fn from_degrees(value: CSSFloat, was_calc: bool) -> Self { - Angle { value: ComputedAngle::Degree(value), was_calc } + Angle { value: ComputedAngle::Deg(value), was_calc } } /// Creates an angle with the given value in gradians. pub fn from_gradians(value: CSSFloat, was_calc: bool) -> Self { - Angle { value: ComputedAngle::Gradian(value), was_calc } + Angle { value: ComputedAngle::Grad(value), was_calc } } /// Creates an angle with the given value in turns. @@ -72,7 +72,7 @@ impl Angle { /// Creates an angle with the given value in radians. pub fn from_radians(value: CSSFloat, was_calc: bool) -> Self { - Angle { value: ComputedAngle::Radian(value), was_calc } + Angle { value: ComputedAngle::Rad(value), was_calc } } /// Returns the amount of radians this angle represents. @@ -89,7 +89,7 @@ impl Angle { /// Returns an `Angle` parsed from a `calc()` expression. pub fn from_calc(radians: CSSFloat) -> Self { Angle { - value: ComputedAngle::Radian(radians), + value: ComputedAngle::Rad(radians), was_calc: true, } } diff --git a/components/style/values/specified/calc.rs b/components/style/values/specified/calc.rs index f88105fdb61..295e9488f61 100644 --- a/components/style/values/specified/calc.rs +++ b/components/style/values/specified/calc.rs @@ -400,7 +400,13 @@ impl CalcNode { NoCalcLength::ServoCharacterWidth(..) => unreachable!(), #[cfg(feature = "gecko")] NoCalcLength::Physical(physical) => { - ret.mozmm = Some(ret.mozmm.unwrap_or(0.) + physical.0 * factor); + use values::specified::length::PhysicalLength; + + match physical { + PhysicalLength::Mozmm(mozmm) => { + ret.mozmm = Some(ret.mozmm.unwrap_or(0.) + mozmm * factor); + } + } } } } diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index f2e802d38cb..0f677e27838 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -11,15 +11,14 @@ use cssparser::{Parser, Token}; use euclid::Size2D; use font_metrics::FontMetricsQueryResult; use parser::{Parse, ParserContext}; -use std::{cmp, fmt, mem}; +use std::{cmp, mem}; #[allow(unused_imports)] use std::ascii::AsciiExt; use std::ops::{Add, Mul}; -use style_traits::{ToCss, ParseError, StyleParseErrorKind}; +use style_traits::{ParseError, StyleParseErrorKind}; use style_traits::values::specified::AllowedNumericType; use stylesheets::CssRuleType; use super::{AllowQuirks, Number, ToComputedValue, Percentage}; -use values::{Auto, CSSFloat, Either, None_, Normal}; -use values::{ExtremumLength, serialize_dimension}; +use values::{Auto, CSSFloat, Either, ExtremumLength, None_, Normal}; use values::computed::{self, CSSPixelLength, Context}; use values::generics::NonNegative; use values::specified::NonNegativeNumber; @@ -52,8 +51,9 @@ pub fn au_to_int_px(au: f32) -> i32 { (au / AU_PER_PX).round() as i32 } -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] /// A font relative length. +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] +#[css(dimension)] pub enum FontRelativeLength { /// A "em" value: https://drafts.csswg.org/css-values/#em Em(CSSFloat), @@ -65,19 +65,6 @@ pub enum FontRelativeLength { Rem(CSSFloat) } -impl ToCss for FontRelativeLength { - fn to_css(&self, dest: &mut W) -> fmt::Result - where W: fmt::Write - { - match *self { - FontRelativeLength::Em(length) => serialize_dimension(length, "em", dest), - FontRelativeLength::Ex(length) => serialize_dimension(length, "ex", dest), - FontRelativeLength::Ch(length) => serialize_dimension(length, "ch", dest), - FontRelativeLength::Rem(length) => serialize_dimension(length, "rem", dest) - } - } -} - /// A source to resolve font-relative units against #[derive(Clone, Copy, Debug, PartialEq)] pub enum FontBaseSize { @@ -206,10 +193,11 @@ impl FontRelativeLength { } } -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] /// A viewport-relative length. /// /// +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] +#[css(dimension)] pub enum ViewportPercentageLength { /// A vw unit: https://drafts.csswg.org/css-values/#vw Vw(CSSFloat), @@ -221,17 +209,6 @@ pub enum ViewportPercentageLength { Vmax(CSSFloat) } -impl ToCss for ViewportPercentageLength { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - ViewportPercentageLength::Vw(length) => serialize_dimension(length, "vw", dest), - ViewportPercentageLength::Vh(length) => serialize_dimension(length, "vh", dest), - ViewportPercentageLength::Vmin(length) => serialize_dimension(length, "vmin", dest), - ViewportPercentageLength::Vmax(length) => serialize_dimension(length, "vmax", dest) - } - } -} - impl ViewportPercentageLength { /// Computes the given viewport-relative length for the given viewport size. pub fn to_computed_value(&self, viewport_size: Size2D) -> CSSPixelLength { @@ -255,7 +232,7 @@ impl ViewportPercentageLength { } /// HTML5 "character width", as defined in HTML5 ยง 14.5.4. -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] pub struct CharacterWidth(pub i32); impl CharacterWidth { @@ -273,7 +250,8 @@ impl CharacterWidth { } /// Represents an absolute length with its unit -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] +#[css(dimension)] pub enum AbsoluteLength { /// An absolute length in pixels (px) Px(CSSFloat), @@ -334,20 +312,6 @@ impl ToComputedValue for AbsoluteLength { } } -impl ToCss for AbsoluteLength { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - AbsoluteLength::Px(length) => serialize_dimension(length, "px", dest), - AbsoluteLength::In(length) => serialize_dimension(length, "in", dest), - AbsoluteLength::Cm(length) => serialize_dimension(length, "cm", dest), - AbsoluteLength::Mm(length) => serialize_dimension(length, "mm", dest), - AbsoluteLength::Q(length) => serialize_dimension(length, "q", dest), - AbsoluteLength::Pt(length) => serialize_dimension(length, "pt", dest), - AbsoluteLength::Pc(length) => serialize_dimension(length, "pc", dest), - } - } -} - impl Mul for AbsoluteLength { type Output = AbsoluteLength; @@ -383,19 +347,25 @@ impl Add for AbsoluteLength { } } -/// Represents a physical length (mozmm) based on DPI -#[derive(Clone, Copy, Debug, PartialEq)] -#[cfg(feature = "gecko")] +/// Represents a physical length based on DPI. +#[derive(Clone, Copy, Debug, PartialEq, ToCss)] #[derive(MallocSizeOf)] -pub struct PhysicalLength(pub CSSFloat); +#[css(dimension)] +pub enum PhysicalLength { + /// A physical length in millimetres. + Mozmm(CSSFloat), +} -#[cfg(feature = "gecko")] impl PhysicalLength { - fn is_zero(&self) -> bool { - self.0 == 0. + /// Checks whether the length value is zero. + pub fn is_zero(&self) -> bool { + match *self { + PhysicalLength::Mozmm(v) => v == 0., + } } /// Computes the given character width. + #[cfg(feature = "gecko")] pub fn to_computed_value(&self, context: &Context) -> CSSPixelLength { use gecko_bindings::bindings; use std::f32; @@ -408,32 +378,31 @@ impl PhysicalLength { }; let px_per_physical_inch = au_per_physical_inch / AU_PER_PX; - let pixel = self.0 * px_per_physical_inch * INCH_PER_MM; + + let mm = match *self { + PhysicalLength::Mozmm(v) => v, + }; + + let pixel = mm * px_per_physical_inch * INCH_PER_MM; CSSPixelLength::new(pixel.min(f32::MAX).max(f32::MIN)) } } -#[cfg(feature = "gecko")] -impl ToCss for PhysicalLength { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - serialize_dimension(self.0, "mozmm", dest) - } -} - -#[cfg(feature = "gecko")] impl Mul for PhysicalLength { - type Output = PhysicalLength; + type Output = Self ; #[inline] - fn mul(self, scalar: CSSFloat) -> PhysicalLength { - PhysicalLength(self.0 * scalar) + fn mul(self, scalar: CSSFloat) -> Self { + match self { + PhysicalLength::Mozmm(v) => PhysicalLength::Mozmm(v * scalar), + } } } /// A `` without taking `calc` expressions into account /// /// -#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] pub enum NoCalcLength { /// An absolute length /// @@ -454,6 +423,7 @@ pub enum NoCalcLength { /// /// This cannot be specified by the user directly and is only generated by /// `Stylist::synthesize_rules_for_legacy_attributes()`. + #[css(function)] ServoCharacterWidth(CharacterWidth), /// A physical length (mozmm) based on DPI @@ -461,24 +431,6 @@ pub enum NoCalcLength { Physical(PhysicalLength), } -impl ToCss for NoCalcLength { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - NoCalcLength::Absolute(length) => length.to_css(dest), - NoCalcLength::FontRelative(length) => length.to_css(dest), - NoCalcLength::ViewportPercentage(length) => length.to_css(dest), - /* This should only be reached from style dumping code */ - NoCalcLength::ServoCharacterWidth(CharacterWidth(i)) => { - dest.write_str("CharWidth(")?; - i.to_css(dest)?; - dest.write_char(')') - } - #[cfg(feature = "gecko")] - NoCalcLength::Physical(length) => length.to_css(dest), - } - } -} - impl Mul for NoCalcLength { type Output = NoCalcLength; @@ -539,7 +491,7 @@ impl NoCalcLength { Ok(NoCalcLength::ViewportPercentage(ViewportPercentageLength::Vmax(value))) }, #[cfg(feature = "gecko")] - "mozmm" => Ok(NoCalcLength::Physical(PhysicalLength(value))), + "mozmm" => Ok(NoCalcLength::Physical(PhysicalLength::Mozmm(value))), _ => Err(()) } } diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index 70fb01692a7..fa545b00211 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -19,9 +19,14 @@ pub fn derive(input: DeriveInput) -> Tokens { let mut identifier = to_css_identifier(variant.ident.as_ref()); let variant_attrs = cg::parse_variant_attrs::(variant); let separator = if variant_attrs.comma { ", " } else { " " }; + + if input_attrs.dimension { + assert_eq!(bindings.len(), 1); + assert!(!variant_attrs.function, "That makes no sense"); + } + let mut expr = if !bindings.is_empty() { let mut expr = quote! {}; - if variant_attrs.function && variant_attrs.iterable { assert_eq!(bindings.len(), 1); let binding = &bindings[0]; @@ -52,7 +57,18 @@ pub fn derive(input: DeriveInput) -> Tokens { ::std::fmt::Write::write_str(dest, #identifier) } }; - if variant_attrs.function { + + if input_attrs.dimension { + // FIXME(emilio): Remove when bug 1416564 lands. + if identifier == "-mozmm" { + identifier = "mozmm".into(); + } + + expr = quote! { + #expr?; + ::std::fmt::Write::write_str(dest, #identifier) + } + } else if variant_attrs.function { identifier.push_str("("); expr = quote! { ::std::fmt::Write::write_str(dest, #identifier)?; @@ -96,6 +112,7 @@ pub fn derive(input: DeriveInput) -> Tokens { struct CssInputAttrs { derive_debug: bool, function: bool, + dimension: bool, comma: bool, } diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index bb443057b6d..6ae160f7d37 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -3171,7 +3171,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetLengthValue( structs::nsCSSUnit::eCSSUnit_Inch => NoCalcLength::Absolute(AbsoluteLength::In(value)), structs::nsCSSUnit::eCSSUnit_Centimeter => NoCalcLength::Absolute(AbsoluteLength::Cm(value)), structs::nsCSSUnit::eCSSUnit_Millimeter => NoCalcLength::Absolute(AbsoluteLength::Mm(value)), - structs::nsCSSUnit::eCSSUnit_PhysicalMillimeter => NoCalcLength::Physical(PhysicalLength(value)), + structs::nsCSSUnit::eCSSUnit_PhysicalMillimeter => NoCalcLength::Physical(PhysicalLength::Mozmm(value)), structs::nsCSSUnit::eCSSUnit_Point => NoCalcLength::Absolute(AbsoluteLength::Pt(value)), structs::nsCSSUnit::eCSSUnit_Pica => NoCalcLength::Absolute(AbsoluteLength::Pc(value)), structs::nsCSSUnit::eCSSUnit_Quarter => NoCalcLength::Absolute(AbsoluteLength::Q(value)),