style: Make resolutions more like the rest of the CSS values.

Bug: 1460655
Reviewed-by: xidorn
MozReview-Commit-ID: 3Gt8VX1KhjC
This commit is contained in:
Emilio Cobos Álvarez 2018-05-10 18:06:27 +02:00
parent 2688588538
commit 2f18b67ce1
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
5 changed files with 128 additions and 50 deletions

View file

@ -7,7 +7,7 @@
use app_units::AU_PER_PX; use app_units::AU_PER_PX;
use app_units::Au; use app_units::Au;
use context::QuirksMode; use context::QuirksMode;
use cssparser::{BasicParseErrorKind, Parser, Token, RGBA}; use cssparser::{BasicParseErrorKind, Parser, RGBA};
use euclid::Size2D; use euclid::Size2D;
use euclid::TypedScale; use euclid::TypedScale;
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor}; 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::{serialize_atom_identifier, CSSFloat, CustomIdent, KeyframesName};
use values::computed::{self, ToComputedValue}; use values::computed::{self, ToComputedValue};
use values::computed::font::FontSize; 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, /// The `Device` in Gecko wraps a pres context, has a default values computed,
/// and contains all the viewport rule state. /// 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<Self, ParseError<'i>> {
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. /// A value found or expected in a media expression.
/// ///
/// FIXME(emilio): How should calc() serialize in the Number / Integer / /// 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) MediaExpressionValue::IntRatio(a.value() as u32, b.value() as u32)
}, },
nsMediaFeature_ValueType::eResolution => { nsMediaFeature_ValueType::eResolution => {
MediaExpressionValue::Resolution(Resolution::parse(input)?) MediaExpressionValue::Resolution(Resolution::parse(context, input)?)
}, },
nsMediaFeature_ValueType::eEnumerated => { nsMediaFeature_ValueType::eEnumerated => {
let location = input.current_source_location(); let location = input.current_source_location();

View file

@ -56,6 +56,7 @@ pub use self::inherited_box::{ImageOrientation, Orientation};
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
pub use self::gecko::ScrollSnapPoint; pub use self::gecko::ScrollSnapPoint;
pub use self::rect::LengthOrNumberRect; pub use self::rect::LengthOrNumberRect;
pub use self::resolution::Resolution;
pub use super::{Auto, Either, None_}; pub use super::{Auto, Either, None_};
pub use super::specified::{BorderStyle, TextDecorationLine}; pub use super::specified::{BorderStyle, TextDecorationLine};
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage}; pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage};
@ -105,6 +106,7 @@ pub mod outline;
pub mod percentage; pub mod percentage;
pub mod position; pub mod position;
pub mod rect; pub mod rect;
pub mod resolution;
pub mod svg; pub mod svg;
pub mod table; pub mod table;
pub mod text; pub mod text;

View file

@ -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 `<resolution>`.
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<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
where
W: fmt::Write,
{
self.dppx().to_css(dest)?;
dest.write_str("dppx")
}
}

View file

@ -61,6 +61,7 @@ pub use self::list::Quotes;
pub use self::list::ListStyleType; pub use self::list::ListStyleType;
pub use self::outline::OutlineStyle; pub use self::outline::OutlineStyle;
pub use self::rect::LengthOrNumberRect; pub use self::rect::LengthOrNumberRect;
pub use self::resolution::Resolution;
pub use self::percentage::Percentage; pub use self::percentage::Percentage;
pub use self::position::{GridAutoFlow, GridTemplateAreas, Position}; pub use self::position::{GridAutoFlow, GridTemplateAreas, Position};
pub use self::position::{PositionComponent, ZIndex}; pub use self::position::{PositionComponent, ZIndex};
@ -105,6 +106,7 @@ pub mod outline;
pub mod percentage; pub mod percentage;
pub mod position; pub mod position;
pub mod rect; pub mod rect;
pub mod resolution;
pub mod source_size_list; pub mod source_size_list;
pub mod svg; pub mod svg;
pub mod table; pub mod table;

View file

@ -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<Self, ParseError<'i>> {
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())
)),
}
}
}