From 06f8f0384b8298e50b261854aa45f79cfe377e3b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 11 Nov 2017 14:27:31 +0100 Subject: [PATCH 1/6] style: add css(function, iterable), and derive ToCss for VariantAlternates. --- components/style/values/specified/font.rs | 64 +++-------------------- components/style_derive/to_css.rs | 21 ++++++-- 2 files changed, 25 insertions(+), 60 deletions(-) diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index da2fa9432e8..aa56b39336f 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -636,81 +636,31 @@ bitflags! { } } -#[derive(Clone, Debug, MallocSizeOf, PartialEq)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] /// Set of variant alternates pub enum VariantAlternates { /// Enables display of stylistic alternates + #[css(function)] Stylistic(CustomIdent), /// Enables display with stylistic sets + #[css(comma, function, iterable)] Styleset(Box<[CustomIdent]>), /// Enables display of specific character variants + #[css(comma, function, iterable)] CharacterVariant(Box<[CustomIdent]>), /// Enables display of swash glyphs + #[css(function)] Swash(CustomIdent), /// Enables replacement of default glyphs with ornaments + #[css(function)] Ornaments(CustomIdent), /// Enables display of alternate annotation forms + #[css(function)] Annotation(CustomIdent), /// Enables display of historical forms HistoricalForms, } -impl ToCss for VariantAlternates { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - VariantAlternates::Swash(ref atom) => { - dest.write_str("swash")?; - dest.write_str("(")?; - atom.to_css(dest)?; - dest.write_str(")") - }, - VariantAlternates::Stylistic(ref atom) => { - dest.write_str("stylistic")?; - dest.write_str("(")?; - atom.to_css(dest)?; - dest.write_str(")") - }, - VariantAlternates::Ornaments(ref atom) => { - dest.write_str("ornaments")?; - dest.write_str("(")?; - atom.to_css(dest)?; - dest.write_str(")") - }, - VariantAlternates::Annotation(ref atom) => { - dest.write_str("annotation")?; - dest.write_str("(")?; - atom.to_css(dest)?; - dest.write_str(")") - }, - VariantAlternates::Styleset(ref vec) => { - dest.write_str("styleset")?; - dest.write_str("(")?; - let mut iter = vec.iter(); - iter.next().unwrap().to_css(dest)?; - for c in iter { - dest.write_str(", ")?; - c.to_css(dest)?; - } - dest.write_str(")") - }, - VariantAlternates::CharacterVariant(ref vec) => { - dest.write_str("character-variant")?; - dest.write_str("(")?; - let mut iter = vec.iter(); - iter.next().unwrap().to_css(dest)?; - for c in iter { - dest.write_str(", ")?; - c.to_css(dest)?; - } - dest.write_str(")") - }, - VariantAlternates::HistoricalForms => { - dest.write_str("historical-forms") - }, - } - } -} - #[derive(Clone, Debug, MallocSizeOf, PartialEq)] /// List of Variant Alternates pub struct VariantAlternatesList(pub Box<[VariantAlternates]>); diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index 6ae438ccbd2..70fb01692a7 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -21,13 +21,27 @@ pub fn derive(input: DeriveInput) -> Tokens { let separator = if variant_attrs.comma { ", " } else { " " }; let mut expr = if !bindings.is_empty() { let mut expr = quote! {}; - for binding in bindings { - where_clause.add_trait_bound(&binding.field.ty); + + if variant_attrs.function && variant_attrs.iterable { + assert_eq!(bindings.len(), 1); + let binding = &bindings[0]; expr = quote! { #expr - writer.item(#binding)?; + + for item in #binding.iter() { + writer.item(item)?; + } }; + } else { + for binding in bindings { + where_clause.add_trait_bound(&binding.field.ty); + expr = quote! { + #expr + writer.item(#binding)?; + }; + } } + quote! {{ let mut writer = ::style_traits::values::SequenceWriter::new(&mut *dest, #separator); #expr @@ -89,6 +103,7 @@ struct CssInputAttrs { #[derive(Default, FromVariant)] struct CssVariantAttrs { function: bool, + iterable: bool, comma: bool, } From 1b533f9bdcdd5a8c4524926ace61f88836a74f28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sat, 11 Nov 2017 14:30:14 +0100 Subject: [PATCH 2/6] style: Derive ToCss for MozScriptLevel. --- components/style/values/specified/font.rs | 24 ++++++++--------------- 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index aa56b39336f..cc1286a9803 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -977,33 +977,25 @@ impl Parse for MozScriptMinSize { } #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Copy, Debug, PartialEq)] +#[derive(Clone, Copy, Debug, PartialEq, ToCss)] /// Changes the scriptlevel in effect for the children. /// Ref: https://wiki.mozilla.org/MathML:mstyle /// /// The main effect of scriptlevel is to control the font size. /// https://www.w3.org/TR/MathML3/chapter3.html#presm.scriptlevel pub enum MozScriptLevel { - /// Change `font-size` relatively + /// Change `font-size` relatively. Relative(i32), - /// Change `font-size` absolutely + /// Change `font-size` absolutely. + /// + /// Should only be serialized by presentation attributes, so even though + /// serialization for this would look the same as for the `Relative` + /// variant, it is unexposed, so no big deal. Absolute(i32), - /// Change `font-size` automatically + /// Change `font-size` automatically. Auto } -impl ToCss for MozScriptLevel { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - MozScriptLevel::Auto => dest.write_str("auto"), - MozScriptLevel::Relative(rel) => rel.to_css(dest), - // can only be specified by pres attrs; should not - // serialize to anything else - MozScriptLevel::Absolute(_) => Ok(()), - } - } -} - impl Parse for MozScriptLevel { fn parse<'i, 't>(_: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { if let Ok(i) = input.try(|i| i.expect_integer()) { 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 3/6] 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)), From 92944cd5ebb037ca6327fe4a8166c4cb0041dd39 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 12 Nov 2017 15:50:12 +0100 Subject: [PATCH 4/6] style: Make css(dimension) apply to the variant. --- components/style/gecko/media_queries.rs | 4 +++- components/style/gecko/values.rs | 4 ++-- components/style/values/computed/angle.rs | 5 ++++- components/style/values/generics/grid.rs | 25 +++++++-------------- components/style/values/mod.rs | 8 ------- components/style/values/specified/grid.rs | 2 +- components/style/values/specified/length.rs | 22 ++++++++++++++---- components/style_derive/to_css.rs | 6 ++--- 8 files changed, 39 insertions(+), 37 deletions(-) diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 954463ae91d..625802eecf6 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -263,13 +263,15 @@ impl PartialEq for Expression { /// A resolution. #[derive(Clone, Debug, PartialEq, ToCss)] -#[css(dimension)] pub enum Resolution { /// Dots per inch. + #[css(dimension)] Dpi(CSSFloat), /// Dots per pixel. + #[css(dimension)] Dppx(CSSFloat), /// Dots per centimeter. + #[css(dimension)] Dpcm(CSSFloat), } diff --git a/components/style/gecko/values.rs b/components/style/gecko/values.rs index 4f1b3cbb851..fc5d75bbe4b 100644 --- a/components/style/gecko/values.rs +++ b/components/style/gecko/values.rs @@ -214,7 +214,7 @@ impl GeckoStyleCoordConvertible for TrackBreadth< fn to_gecko_style_coord(&self, coord: &mut T) { match *self { TrackBreadth::Breadth(ref lop) => lop.to_gecko_style_coord(coord), - TrackBreadth::Flex(fr) => coord.set_value(CoordDataValue::FlexFraction(fr)), + TrackBreadth::Fr(fr) => coord.set_value(CoordDataValue::FlexFraction(fr)), TrackBreadth::Keyword(TrackKeyword::Auto) => coord.set_value(CoordDataValue::Auto), TrackBreadth::Keyword(TrackKeyword::MinContent) => coord.set_value(CoordDataValue::Enumerated(StyleGridTrackBreadth::MinContent as u32)), @@ -235,7 +235,7 @@ impl GeckoStyleCoordConvertible for TrackBreadth< None } }, - CoordDataValue::FlexFraction(fr) => Some(TrackBreadth::Flex(fr)), + CoordDataValue::FlexFraction(fr) => Some(TrackBreadth::Fr(fr)), CoordDataValue::Auto => Some(TrackBreadth::Keyword(TrackKeyword::Auto)), _ => L::from_gecko_style_coord(coord).map(TrackBreadth::Breadth), } diff --git a/components/style/values/computed/angle.rs b/components/style/values/computed/angle.rs index 1896a530d5a..7cc10e97c4d 100644 --- a/components/style/values/computed/angle.rs +++ b/components/style/values/computed/angle.rs @@ -16,15 +16,18 @@ use values::distance::{ComputeSquaredDistance, SquaredDistance}; #[cfg_attr(feature = "servo", derive(Deserialize, Serialize))] #[derive(Animate, Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] #[derive(PartialOrd, ToAnimatedZero)] -#[css(dimension)] pub enum Angle { /// An angle with degree unit. + #[css(dimension)] Deg(CSSFloat), /// An angle with gradian unit. + #[css(dimension)] Grad(CSSFloat), /// An angle with radian unit. + #[css(dimension)] Rad(CSSFloat), /// An angle with turn unit. + #[css(dimension)] Turn(CSSFloat), } diff --git a/components/style/values/generics/grid.rs b/components/style/values/generics/grid.rs index db2e4721075..bd0dc82507f 100644 --- a/components/style/values/generics/grid.rs +++ b/components/style/values/generics/grid.rs @@ -9,7 +9,7 @@ use cssparser::Parser; use parser::{Parse, ParserContext}; use std::{fmt, mem, usize}; use style_traits::{ToCss, ParseError, StyleParseErrorKind}; -use values::{CSSFloat, CustomIdent, serialize_dimension}; +use values::{CSSFloat, CustomIdent}; use values::computed::{Context, ToComputedValue}; use values::specified; use values::specified::grid::parse_line_names; @@ -143,12 +143,13 @@ add_impls_for_keyword_enum!(TrackKeyword); /// avoid re-implementing it for the computed type. /// /// -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)] +#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue, ToCss)] pub enum TrackBreadth { /// The generic type is almost always a non-negative `` Breadth(L), /// A flex fraction specified in `fr` units. - Flex(CSSFloat), + #[css(dimension)] + Fr(CSSFloat), /// One of the track-sizing keywords (`auto`, `min-content`, `max-content`) Keyword(TrackKeyword), } @@ -166,16 +167,6 @@ impl TrackBreadth { } } -impl ToCss for TrackBreadth { - fn to_css(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { - match *self { - TrackBreadth::Breadth(ref lop) => lop.to_css(dest), - TrackBreadth::Flex(ref value) => serialize_dimension(*value, "fr", dest), - TrackBreadth::Keyword(ref k) => k.to_css(dest), - } - } -} - /// A `` type for explicit grid track sizing. Like ``, this is /// generic only to avoid code bloat. It only takes `` /// @@ -212,7 +203,7 @@ impl TrackSize { } match *breadth_1 { - TrackBreadth::Flex(_) => false, // should be at this point + TrackBreadth::Fr(_) => false, // should be at this point _ => breadth_2.is_fixed(), } }, @@ -242,7 +233,7 @@ impl ToCss for TrackSize { // According to gecko minmax(auto, ) is equivalent to , // and both are serialized as . if let TrackBreadth::Keyword(TrackKeyword::Auto) = *min { - if let TrackBreadth::Flex(_) = *max { + if let TrackBreadth::Fr(_) = *max { return max.to_css(dest); } } @@ -268,7 +259,7 @@ impl ToComputedValue for TrackSize { #[inline] fn to_computed_value(&self, context: &Context) -> Self::ComputedValue { match *self { - TrackSize::Breadth(TrackBreadth::Flex(ref f)) => { + TrackSize::Breadth(TrackBreadth::Fr(ref f)) => { // outside `minmax()` expands to `mimmax(auto, )` // https://drafts.csswg.org/css-grid/#valdef-grid-template-columns-flex // FIXME(nox): This sounds false, the spec just says that @@ -276,7 +267,7 @@ impl ToComputedValue for TrackSize { // into `minmax` at computed value time. TrackSize::Minmax( TrackBreadth::Keyword(TrackKeyword::Auto), - TrackBreadth::Flex(f.to_computed_value(context)), + TrackBreadth::Fr(f.to_computed_value(context)), ) }, TrackSize::Breadth(ref b) => { diff --git a/components/style/values/mod.rs b/components/style/values/mod.rs index 7a690662acc..0aa1ae4ccf3 100644 --- a/components/style/values/mod.rs +++ b/components/style/values/mod.rs @@ -41,14 +41,6 @@ pub fn serialize_percentage(value: CSSFloat, dest: &mut W) dest.write_str("%") } -/// Serialize a value with given unit into dest. -pub fn serialize_dimension(value: CSSFloat, unit: &str, dest: &mut W) - -> fmt::Result where W: fmt::Write -{ - value.to_css(dest)?; - dest.write_str(unit) -} - /// Convenience void type to disable some properties and values through types. #[cfg_attr(feature = "servo", derive(Deserialize, MallocSizeOf, Serialize))] #[derive(Clone, Copy, Debug, PartialEq, ToComputedValue, ToCss)] diff --git a/components/style/values/specified/grid.rs b/components/style/values/specified/grid.rs index b951082aea9..f2b8453c46c 100644 --- a/components/style/values/specified/grid.rs +++ b/components/style/values/specified/grid.rs @@ -33,7 +33,7 @@ impl Parse for TrackBreadth { } if let Ok(f) = input.try(parse_flex) { - return Ok(TrackBreadth::Flex(f)) + return Ok(TrackBreadth::Fr(f)) } TrackKeyword::parse(input).map(TrackBreadth::Keyword) diff --git a/components/style/values/specified/length.rs b/components/style/values/specified/length.rs index 0f677e27838..19eeb33bbcd 100644 --- a/components/style/values/specified/length.rs +++ b/components/style/values/specified/length.rs @@ -53,15 +53,18 @@ pub fn au_to_int_px(au: f32) -> i32 { /// 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 + #[css(dimension)] Em(CSSFloat), /// A "ex" value: https://drafts.csswg.org/css-values/#ex + #[css(dimension)] Ex(CSSFloat), /// A "ch" value: https://drafts.csswg.org/css-values/#ch + #[css(dimension)] Ch(CSSFloat), /// A "rem" value: https://drafts.csswg.org/css-values/#rem + #[css(dimension)] Rem(CSSFloat) } @@ -197,15 +200,18 @@ impl FontRelativeLength { /// /// #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] -#[css(dimension)] pub enum ViewportPercentageLength { /// A vw unit: https://drafts.csswg.org/css-values/#vw + #[css(dimension)] Vw(CSSFloat), /// A vh unit: https://drafts.csswg.org/css-values/#vh + #[css(dimension)] Vh(CSSFloat), /// + #[css(dimension)] Vmin(CSSFloat), /// + #[css(dimension)] Vmax(CSSFloat) } @@ -251,21 +257,27 @@ impl CharacterWidth { /// Represents an absolute length with its unit #[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] -#[css(dimension)] pub enum AbsoluteLength { /// An absolute length in pixels (px) + #[css(dimension)] Px(CSSFloat), /// An absolute length in inches (in) + #[css(dimension)] In(CSSFloat), /// An absolute length in centimeters (cm) + #[css(dimension)] Cm(CSSFloat), /// An absolute length in millimeters (mm) + #[css(dimension)] Mm(CSSFloat), /// An absolute length in quarter-millimeters (q) + #[css(dimension)] Q(CSSFloat), /// An absolute length in points (pt) + #[css(dimension)] Pt(CSSFloat), /// An absolute length in pica (pc) + #[css(dimension)] Pc(CSSFloat), } @@ -348,11 +360,13 @@ impl Add for AbsoluteLength { } /// Represents a physical length based on DPI. +/// +/// FIXME(emilio): Unship (https://bugzilla.mozilla.org/show_bug.cgi?id=1416564) #[derive(Clone, Copy, Debug, PartialEq, ToCss)] #[derive(MallocSizeOf)] -#[css(dimension)] pub enum PhysicalLength { /// A physical length in millimetres. + #[css(dimension)] Mozmm(CSSFloat), } diff --git a/components/style_derive/to_css.rs b/components/style_derive/to_css.rs index fa545b00211..59cc4f4236b 100644 --- a/components/style_derive/to_css.rs +++ b/components/style_derive/to_css.rs @@ -20,7 +20,7 @@ pub fn derive(input: DeriveInput) -> Tokens { let variant_attrs = cg::parse_variant_attrs::(variant); let separator = if variant_attrs.comma { ", " } else { " " }; - if input_attrs.dimension { + if variant_attrs.dimension { assert_eq!(bindings.len(), 1); assert!(!variant_attrs.function, "That makes no sense"); } @@ -58,7 +58,7 @@ pub fn derive(input: DeriveInput) -> Tokens { } }; - if input_attrs.dimension { + if variant_attrs.dimension { // FIXME(emilio): Remove when bug 1416564 lands. if identifier == "-mozmm" { identifier = "mozmm".into(); @@ -112,7 +112,6 @@ pub fn derive(input: DeriveInput) -> Tokens { struct CssInputAttrs { derive_debug: bool, function: bool, - dimension: bool, comma: bool, } @@ -122,6 +121,7 @@ struct CssVariantAttrs { function: bool, iterable: bool, comma: bool, + dimension: bool, } /// Transforms "FooBar" to "foo-bar". From 194c2712b575b0eea29fee9fc23a20f79a87e77c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 12 Nov 2017 16:14:20 +0100 Subject: [PATCH 5/6] style: Make MozScriptLevel::Absolute serialize as -moz-absolute(foo). --- components/style/values/computed/font.rs | 4 ++-- components/style/values/specified/font.rs | 3 ++- ports/geckolib/glue.rs | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/components/style/values/computed/font.rs b/components/style/values/computed/font.rs index 98c3e014c4b..1613e64892b 100644 --- a/components/style/values/computed/font.rs +++ b/components/style/values/computed/font.rs @@ -326,12 +326,12 @@ impl ToComputedValue for specified::MozScriptLevel { let parent = cx.builder.get_parent_font().clone__moz_script_level(); parent as i32 + rel } - specified::MozScriptLevel::Absolute(abs) => abs, + specified::MozScriptLevel::MozAbsolute(abs) => abs, }; cmp::min(int, i8::MAX as i32) as i8 } fn from_computed_value(other: &i8) -> Self { - specified::MozScriptLevel::Absolute(*other as i32) + specified::MozScriptLevel::MozAbsolute(*other as i32) } } diff --git a/components/style/values/specified/font.rs b/components/style/values/specified/font.rs index cc1286a9803..f0f2c2e9be8 100644 --- a/components/style/values/specified/font.rs +++ b/components/style/values/specified/font.rs @@ -991,7 +991,8 @@ pub enum MozScriptLevel { /// Should only be serialized by presentation attributes, so even though /// serialization for this would look the same as for the `Relative` /// variant, it is unexposed, so no big deal. - Absolute(i32), + #[css(function)] + MozAbsolute(i32), /// Change `font-size` automatically. Auto } diff --git a/ports/geckolib/glue.rs b/ports/geckolib/glue.rs index 6ae160f7d37..07d05379628 100644 --- a/ports/geckolib/glue.rs +++ b/ports/geckolib/glue.rs @@ -3202,7 +3202,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetNumberValue( let prop = match_wrap_declared! { long, MozScriptSizeMultiplier => value, // Gecko uses Number values to signal that it is absolute - MozScriptLevel => MozScriptLevel::Absolute(value as i32), + MozScriptLevel => MozScriptLevel::MozAbsolute(value as i32), }; write_locked_arc(declarations, |decls: &mut PropertyDeclarationBlock| { decls.push(prop, Importance::Normal, DeclarationSource::CssOm); From b750f7096ca82a0b7caa13cf06138818b58a6872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Sun, 12 Nov 2017 16:18:15 +0100 Subject: [PATCH 6/6] style: Document css(iterable) and css(dimension). --- components/style_traits/values.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/components/style_traits/values.rs b/components/style_traits/values.rs index 9b2b308d5d1..3e951548e6c 100644 --- a/components/style_traits/values.rs +++ b/components/style_traits/values.rs @@ -24,6 +24,12 @@ use std::fmt::{self, Write}; /// commas, otherwise, by spaces; /// * if `#[css(function)]` is found on a variant, the variant name gets /// serialised like unit variants and its fields are surrounded by parentheses; +/// * if `#[css(iterable)]` is found on a function variant, that variant needs +/// to have a single member, and that member needs to be iterable. The +/// iterable will be serialized as the arguments for the function. +/// * if `#[css(dimension)]` is found on a variant, that variant needs +/// to have a single member. The variant would be serialized as a CSS +/// dimension token, like: . /// * finally, one can put `#[css(derive_debug)]` on the whole type, to /// implement `Debug` by a single call to `ToCss::to_css`. pub trait ToCss {