From 2f18b67ce1497fd975950ce0397b27067b2bc843 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Thu, 10 May 2018 18:06:27 +0200 Subject: [PATCH] style: Make resolutions more like the rest of the CSS values. Bug: 1460655 Reviewed-by: xidorn MozReview-Commit-ID: 3Gt8VX1KhjC --- components/style/gecko/media_queries.rs | 53 +------------- components/style/values/computed/mod.rs | 2 + .../style/values/computed/resolution.rs | 48 ++++++++++++ components/style/values/specified/mod.rs | 2 + .../style/values/specified/resolution.rs | 73 +++++++++++++++++++ 5 files changed, 128 insertions(+), 50 deletions(-) create mode 100644 components/style/values/computed/resolution.rs create mode 100644 components/style/values/specified/resolution.rs diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs index 7d9724cc6c5..554606bb9db 100644 --- a/components/style/gecko/media_queries.rs +++ b/components/style/gecko/media_queries.rs @@ -7,7 +7,7 @@ use app_units::AU_PER_PX; use app_units::Au; use context::QuirksMode; -use cssparser::{BasicParseErrorKind, Parser, Token, RGBA}; +use cssparser::{BasicParseErrorKind, Parser, RGBA}; use euclid::Size2D; use euclid::TypedScale; use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor}; @@ -32,7 +32,7 @@ use stylesheets::Origin; use values::{serialize_atom_identifier, CSSFloat, CustomIdent, KeyframesName}; use values::computed::{self, ToComputedValue}; use values::computed::font::FontSize; -use values::specified::{Integer, Length, Number}; +use values::specified::{Integer, Length, Number, Resolution}; /// The `Device` in Gecko wraps a pres context, has a default values computed, /// and contains all the viewport rule state. @@ -286,53 +286,6 @@ impl PartialEq for Expression { } } -/// A resolution. -#[derive(Clone, Debug, PartialEq, ToCss)] -pub enum Resolution { - /// Dots per inch. - #[css(dimension)] - Dpi(CSSFloat), - /// Dots per pixel. - #[css(dimension)] - Dppx(CSSFloat), - /// Dots per centimeter. - #[css(dimension)] - Dpcm(CSSFloat), -} - -impl Resolution { - fn to_dpi(&self) -> CSSFloat { - match *self { - Resolution::Dpi(f) => f, - Resolution::Dppx(f) => f * 96.0, - Resolution::Dpcm(f) => f * 2.54, - } - } - - fn parse<'i, 't>(input: &mut Parser<'i, 't>) -> Result> { - let location = input.current_source_location(); - let (value, unit) = match *input.next()? { - Token::Dimension { - value, ref unit, .. - } => (value, unit), - ref t => return Err(location.new_unexpected_token_error(t.clone())), - }; - - if value <= 0. { - return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); - } - - (match_ignore_ascii_case! { &unit, - "dpi" => Ok(Resolution::Dpi(value)), - "dppx" => Ok(Resolution::Dppx(value)), - "dpcm" => Ok(Resolution::Dpcm(value)), - _ => Err(()) - }).map_err(|()| { - location.new_custom_error(StyleParseErrorKind::UnexpectedDimension(unit.clone())) - }) - } -} - /// A value found or expected in a media expression. /// /// FIXME(emilio): How should calc() serialize in the Number / Integer / @@ -535,7 +488,7 @@ fn parse_feature_value<'i, 't>( MediaExpressionValue::IntRatio(a.value() as u32, b.value() as u32) }, nsMediaFeature_ValueType::eResolution => { - MediaExpressionValue::Resolution(Resolution::parse(input)?) + MediaExpressionValue::Resolution(Resolution::parse(context, input)?) }, nsMediaFeature_ValueType::eEnumerated => { let location = input.current_source_location(); diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs index 16391ae5d86..0f27225eeb0 100644 --- a/components/style/values/computed/mod.rs +++ b/components/style/values/computed/mod.rs @@ -56,6 +56,7 @@ pub use self::inherited_box::{ImageOrientation, Orientation}; #[cfg(feature = "gecko")] pub use self::gecko::ScrollSnapPoint; pub use self::rect::LengthOrNumberRect; +pub use self::resolution::Resolution; pub use super::{Auto, Either, None_}; pub use super::specified::{BorderStyle, TextDecorationLine}; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage}; @@ -105,6 +106,7 @@ pub mod outline; pub mod percentage; pub mod position; pub mod rect; +pub mod resolution; pub mod svg; pub mod table; pub mod text; diff --git a/components/style/values/computed/resolution.rs b/components/style/values/computed/resolution.rs new file mode 100644 index 00000000000..314cdca3abc --- /dev/null +++ b/components/style/values/computed/resolution.rs @@ -0,0 +1,48 @@ +/* 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/. */ + +//! Resolution values: +//! +//! https://drafts.csswg.org/css-values/#resolution + +use std::fmt::{self, Write}; +use style_traits::{CssWriter, ToCss}; +use values::computed::{Context, ToComputedValue}; +use values::specified; +use values::CSSFloat; + +/// A computed ``. +pub struct Resolution(CSSFloat); + +impl Resolution { + /// Returns this resolution value as dppx. + #[inline] + pub fn dppx(&self) -> CSSFloat { + self.0 + } +} + +impl ToComputedValue for specified::Resolution { + type ComputedValue = Resolution; + + #[inline] + fn to_computed_value(&self, _: &Context) -> Self::ComputedValue { + Resolution(self.to_dppx()) + } + + #[inline] + fn from_computed_value(computed: &Self::ComputedValue) -> Self { + specified::Resolution::Dppx(computed.dppx()) + } +} + +impl ToCss for Resolution { + fn to_css(&self, dest: &mut CssWriter) -> fmt::Result + where + W: fmt::Write, + { + self.dppx().to_css(dest)?; + dest.write_str("dppx") + } +} diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs index 5b07d380c58..b1795acd65b 100644 --- a/components/style/values/specified/mod.rs +++ b/components/style/values/specified/mod.rs @@ -61,6 +61,7 @@ pub use self::list::Quotes; pub use self::list::ListStyleType; pub use self::outline::OutlineStyle; pub use self::rect::LengthOrNumberRect; +pub use self::resolution::Resolution; pub use self::percentage::Percentage; pub use self::position::{GridAutoFlow, GridTemplateAreas, Position}; pub use self::position::{PositionComponent, ZIndex}; @@ -105,6 +106,7 @@ pub mod outline; pub mod percentage; pub mod position; pub mod rect; +pub mod resolution; pub mod source_size_list; pub mod svg; pub mod table; diff --git a/components/style/values/specified/resolution.rs b/components/style/values/specified/resolution.rs new file mode 100644 index 00000000000..37df9412585 --- /dev/null +++ b/components/style/values/specified/resolution.rs @@ -0,0 +1,73 @@ +/* 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/. */ + +//! Resolution values: +//! +//! https://drafts.csswg.org/css-values/#resolution + +use cssparser::{Parser, Token}; +use parser::{Parse, ParserContext}; +use style_traits::{ParseError, StyleParseErrorKind}; +use values::CSSFloat; + +/// A specified resolution. +#[derive(Clone, Debug, PartialEq, ToCss)] +pub enum Resolution { + /// Dots per inch. + #[css(dimension)] + Dpi(CSSFloat), + /// Dots per pixel. + #[css(dimension)] + Dppx(CSSFloat), + /// Dots per centimeter. + #[css(dimension)] + Dpcm(CSSFloat), +} + +impl Resolution { + /// Convert this resolution value to dppx units. + pub fn to_dppx(&self) -> CSSFloat { + match *self { + Resolution::Dppx(f) => f, + _ => self.to_dpi() / 96.0, + } + } + + /// Convert this resolution value to dpi units. + pub fn to_dpi(&self) -> CSSFloat { + match *self { + Resolution::Dpi(f) => f, + Resolution::Dppx(f) => f * 96.0, + Resolution::Dpcm(f) => f * 2.54, + } + } +} + +impl Parse for Resolution { + fn parse<'i, 't>( + _: &ParserContext, + input: &mut Parser<'i, 't>, + ) -> Result> { + let location = input.current_source_location(); + let (value, unit) = match *input.next()? { + Token::Dimension { + value, ref unit, .. + } => (value, unit), + ref t => return Err(location.new_unexpected_token_error(t.clone())), + }; + + if value <= 0. { + return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError)); + } + + match_ignore_ascii_case! { &unit, + "dpi" => Ok(Resolution::Dpi(value)), + "dppx" => Ok(Resolution::Dppx(value)), + "dpcm" => Ok(Resolution::Dpcm(value)), + _ => Err(location.new_custom_error( + StyleParseErrorKind::UnexpectedDimension(unit.clone()) + )), + } + } +}