mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
style: Add resolution support to calc()
Differential Revision: https://phabricator.services.mozilla.com/D172338
This commit is contained in:
parent
76e8eeda72
commit
2c986f0005
6 changed files with 171 additions and 47 deletions
|
@ -770,7 +770,7 @@ impl specified::CalcLengthPercentage {
|
||||||
result
|
result
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
Leaf::Number(..) | Leaf::Angle(..) | Leaf::Time(..) => {
|
Leaf::Number(..) | Leaf::Angle(..) | Leaf::Time(..) | Leaf::Resolution(..) => {
|
||||||
unreachable!("Shouldn't have parsed")
|
unreachable!("Shouldn't have parsed")
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -36,12 +36,12 @@ impl ToComputedValue for specified::Resolution {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
|
fn to_computed_value(&self, _: &Context) -> Self::ComputedValue {
|
||||||
Resolution(self.to_dppx())
|
Resolution(self.dppx())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||||
specified::Resolution::Dppx(computed.dppx())
|
specified::Resolution::from_dppx(computed.dppx())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -101,6 +101,7 @@ pub enum SortKey {
|
||||||
Cqmin,
|
Cqmin,
|
||||||
Cqw,
|
Cqw,
|
||||||
Deg,
|
Deg,
|
||||||
|
Dppx,
|
||||||
Dvb,
|
Dvb,
|
||||||
Dvh,
|
Dvh,
|
||||||
Dvi,
|
Dvi,
|
||||||
|
|
|
@ -11,7 +11,7 @@ use crate::values::generics::calc as generic;
|
||||||
use crate::values::generics::calc::{MinMaxOp, ModRemOp, RoundingStrategy, SortKey};
|
use crate::values::generics::calc::{MinMaxOp, ModRemOp, RoundingStrategy, SortKey};
|
||||||
use crate::values::specified::length::{AbsoluteLength, FontRelativeLength, NoCalcLength};
|
use crate::values::specified::length::{AbsoluteLength, FontRelativeLength, NoCalcLength};
|
||||||
use crate::values::specified::length::{ContainerRelativeLength, ViewportPercentageLength};
|
use crate::values::specified::length::{ContainerRelativeLength, ViewportPercentageLength};
|
||||||
use crate::values::specified::{self, Angle, Time};
|
use crate::values::specified::{self, Angle, Resolution, Time};
|
||||||
use crate::values::{CSSFloat, CSSInteger};
|
use crate::values::{CSSFloat, CSSInteger};
|
||||||
use cssparser::{AngleOrNumber, CowRcStr, NumberOrPercentage, Parser, Token};
|
use cssparser::{AngleOrNumber, CowRcStr, NumberOrPercentage, Parser, Token};
|
||||||
use smallvec::SmallVec;
|
use smallvec::SmallVec;
|
||||||
|
@ -107,6 +107,8 @@ pub enum Leaf {
|
||||||
Angle(Angle),
|
Angle(Angle),
|
||||||
/// `<time>`
|
/// `<time>`
|
||||||
Time(Time),
|
Time(Time),
|
||||||
|
/// `<resolution>`
|
||||||
|
Resolution(Resolution),
|
||||||
/// `<percentage>`
|
/// `<percentage>`
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
/// `<number>`
|
/// `<number>`
|
||||||
|
@ -130,6 +132,7 @@ impl ToCss for Leaf {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Length(ref l) => l.to_css(dest),
|
Self::Length(ref l) => l.to_css(dest),
|
||||||
Self::Number(ref n) => n.to_css(dest),
|
Self::Number(ref n) => n.to_css(dest),
|
||||||
|
Self::Resolution(ref r) => r.to_css(dest),
|
||||||
Self::Percentage(p) => crate::values::serialize_percentage(p, dest),
|
Self::Percentage(p) => crate::values::serialize_percentage(p, dest),
|
||||||
Self::Angle(ref a) => a.to_css(dest),
|
Self::Angle(ref a) => a.to_css(dest),
|
||||||
Self::Time(ref t) => t.to_css(dest),
|
Self::Time(ref t) => t.to_css(dest),
|
||||||
|
@ -148,10 +151,11 @@ bitflags! {
|
||||||
const PERCENTAGE = 1 << 1;
|
const PERCENTAGE = 1 << 1;
|
||||||
const ANGLE = 1 << 2;
|
const ANGLE = 1 << 2;
|
||||||
const TIME = 1 << 3;
|
const TIME = 1 << 3;
|
||||||
|
const RESOLUTION = 1 << 3;
|
||||||
|
|
||||||
const LENGTH_PERCENTAGE = Self::LENGTH.bits | Self::PERCENTAGE.bits;
|
const LENGTH_PERCENTAGE = Self::LENGTH.bits | Self::PERCENTAGE.bits;
|
||||||
// NOTE: When you add to this, make sure to make Atan2 deal with these.
|
// NOTE: When you add to this, make sure to make Atan2 deal with these.
|
||||||
const ALL = Self::LENGTH.bits | Self::PERCENTAGE.bits | Self::ANGLE.bits | Self::TIME.bits;
|
const ALL = Self::LENGTH.bits | Self::PERCENTAGE.bits | Self::ANGLE.bits | Self::TIME.bits | Self::RESOLUTION.bits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -208,10 +212,12 @@ impl PartialOrd for Leaf {
|
||||||
(&Length(ref one), &Length(ref other)) => one.partial_cmp(other),
|
(&Length(ref one), &Length(ref other)) => one.partial_cmp(other),
|
||||||
(&Angle(ref one), &Angle(ref other)) => one.degrees().partial_cmp(&other.degrees()),
|
(&Angle(ref one), &Angle(ref other)) => one.degrees().partial_cmp(&other.degrees()),
|
||||||
(&Time(ref one), &Time(ref other)) => one.seconds().partial_cmp(&other.seconds()),
|
(&Time(ref one), &Time(ref other)) => one.seconds().partial_cmp(&other.seconds()),
|
||||||
|
(&Resolution(ref one), &Resolution(ref other)) => one.dppx().partial_cmp(&other.dppx()),
|
||||||
(&Number(ref one), &Number(ref other)) => one.partial_cmp(other),
|
(&Number(ref one), &Number(ref other)) => one.partial_cmp(other),
|
||||||
_ => {
|
_ => {
|
||||||
match *self {
|
match *self {
|
||||||
Length(..) | Percentage(..) | Angle(..) | Time(..) | Number(..) => {},
|
Length(..) | Percentage(..) | Angle(..) | Time(..) | Number(..) |
|
||||||
|
Resolution(..) => {},
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
debug_unreachable!("Forgot a branch?");
|
debug_unreachable!("Forgot a branch?");
|
||||||
|
@ -226,6 +232,7 @@ impl generic::CalcNodeLeaf for Leaf {
|
||||||
match *self {
|
match *self {
|
||||||
Self::Length(ref l) => l.unitless_value(),
|
Self::Length(ref l) => l.unitless_value(),
|
||||||
Self::Percentage(n) | Self::Number(n) => n,
|
Self::Percentage(n) | Self::Number(n) => n,
|
||||||
|
Self::Resolution(ref r) => r.dppx(),
|
||||||
Self::Angle(ref a) => a.degrees(),
|
Self::Angle(ref a) => a.degrees(),
|
||||||
Self::Time(ref t) => t.seconds(),
|
Self::Time(ref t) => t.seconds(),
|
||||||
}
|
}
|
||||||
|
@ -244,6 +251,9 @@ impl generic::CalcNodeLeaf for Leaf {
|
||||||
Self::Angle(ref mut a) => {
|
Self::Angle(ref mut a) => {
|
||||||
*a = Angle::from_calc(a.degrees() * scalar);
|
*a = Angle::from_calc(a.degrees() * scalar);
|
||||||
},
|
},
|
||||||
|
Self::Resolution(ref mut r) => {
|
||||||
|
*r = Resolution::from_dppx(r.dppx() * scalar);
|
||||||
|
},
|
||||||
Self::Time(ref mut t) => {
|
Self::Time(ref mut t) => {
|
||||||
*t = Time::from_seconds(t.seconds() * scalar);
|
*t = Time::from_seconds(t.seconds() * scalar);
|
||||||
},
|
},
|
||||||
|
@ -258,6 +268,7 @@ impl generic::CalcNodeLeaf for Leaf {
|
||||||
Self::Number(..) => SortKey::Number,
|
Self::Number(..) => SortKey::Number,
|
||||||
Self::Percentage(..) => SortKey::Percentage,
|
Self::Percentage(..) => SortKey::Percentage,
|
||||||
Self::Time(..) => SortKey::Sec,
|
Self::Time(..) => SortKey::Sec,
|
||||||
|
Self::Resolution(..) => SortKey::Dppx,
|
||||||
Self::Angle(..) => SortKey::Deg,
|
Self::Angle(..) => SortKey::Deg,
|
||||||
Self::Length(ref l) => match *l {
|
Self::Length(ref l) => match *l {
|
||||||
NoCalcLength::Absolute(..) => SortKey::Px,
|
NoCalcLength::Absolute(..) => SortKey::Px,
|
||||||
|
@ -336,12 +347,16 @@ impl generic::CalcNodeLeaf for Leaf {
|
||||||
(&mut Time(ref mut one), &Time(ref other)) => {
|
(&mut Time(ref mut one), &Time(ref other)) => {
|
||||||
*one = specified::Time::from_seconds(one.seconds() + other.seconds());
|
*one = specified::Time::from_seconds(one.seconds() + other.seconds());
|
||||||
},
|
},
|
||||||
|
(&mut Resolution(ref mut one), &Resolution(ref other)) => {
|
||||||
|
*one = specified::Resolution::from_dppx(one.dppx() + other.dppx());
|
||||||
|
},
|
||||||
(&mut Length(ref mut one), &Length(ref other)) => {
|
(&mut Length(ref mut one), &Length(ref other)) => {
|
||||||
*one = one.try_op(other, std::ops::Add::add)?;
|
*one = one.try_op(other, std::ops::Add::add)?;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
match *other {
|
match *other {
|
||||||
Number(..) | Percentage(..) | Angle(..) | Time(..) | Length(..) => {},
|
Number(..) | Percentage(..) | Angle(..) | Time(..) | Resolution(..) |
|
||||||
|
Length(..) => {},
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
debug_unreachable!();
|
debug_unreachable!();
|
||||||
|
@ -375,6 +390,12 @@ impl generic::CalcNodeLeaf for Leaf {
|
||||||
other.degrees(),
|
other.degrees(),
|
||||||
))));
|
))));
|
||||||
},
|
},
|
||||||
|
(&Resolution(ref one), &Resolution(ref other)) => {
|
||||||
|
return Ok(Leaf::Resolution(specified::Resolution::from_dppx(op(
|
||||||
|
one.dppx(),
|
||||||
|
other.dppx(),
|
||||||
|
))));
|
||||||
|
},
|
||||||
(&Time(ref one), &Time(ref other)) => {
|
(&Time(ref one), &Time(ref other)) => {
|
||||||
return Ok(Leaf::Time(specified::Time::from_seconds(op(
|
return Ok(Leaf::Time(specified::Time::from_seconds(op(
|
||||||
one.seconds(),
|
one.seconds(),
|
||||||
|
@ -386,7 +407,8 @@ impl generic::CalcNodeLeaf for Leaf {
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
match *other {
|
match *other {
|
||||||
Number(..) | Percentage(..) | Angle(..) | Time(..) | Length(..) => {},
|
Number(..) | Percentage(..) | Angle(..) | Time(..) | Length(..) |
|
||||||
|
Resolution(..) => {},
|
||||||
}
|
}
|
||||||
unsafe {
|
unsafe {
|
||||||
debug_unreachable!();
|
debug_unreachable!();
|
||||||
|
@ -432,6 +454,11 @@ impl CalcNode {
|
||||||
return Ok(CalcNode::Leaf(Leaf::Time(t)));
|
return Ok(CalcNode::Leaf(Leaf::Time(t)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if allowed_units.intersects(CalcUnits::RESOLUTION) {
|
||||||
|
if let Ok(t) = Resolution::parse_dimension(value, unit) {
|
||||||
|
return Ok(CalcNode::Leaf(Leaf::Resolution(t)));
|
||||||
|
}
|
||||||
|
}
|
||||||
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
return Err(location.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||||
},
|
},
|
||||||
&Token::Percentage { unit_value, .. }
|
&Token::Percentage { unit_value, .. }
|
||||||
|
@ -606,6 +633,11 @@ impl CalcNode {
|
||||||
return Ok(a.radians().atan2(b.radians()));
|
return Ok(a.radians().atan2(b.radians()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if let Ok(a) = a.to_resolution() {
|
||||||
|
let b = b.to_resolution()?;
|
||||||
|
return Ok(a.dppx().atan2(b.dppx()));
|
||||||
|
}
|
||||||
|
|
||||||
let a = a.into_length_or_percentage(AllowedNumericType::All)?;
|
let a = a.into_length_or_percentage(AllowedNumericType::All)?;
|
||||||
let b = b.into_length_or_percentage(AllowedNumericType::All)?;
|
let b = b.into_length_or_percentage(AllowedNumericType::All)?;
|
||||||
let (a, b) = CalcLengthPercentage::same_unit_length_as(&a, &b).ok_or(())?;
|
let (a, b) = CalcLengthPercentage::same_unit_length_as(&a, &b).ok_or(())?;
|
||||||
|
@ -831,12 +863,24 @@ impl CalcNode {
|
||||||
_ => Err(()),
|
_ => Err(()),
|
||||||
})?;
|
})?;
|
||||||
|
|
||||||
let result = Time::from_seconds_with_calc_clamping_mode(if nan_inf_enabled() {
|
Ok(Time::from_seconds_with_calc_clamping_mode(
|
||||||
seconds
|
if nan_inf_enabled() { seconds } else { crate::values::normalize(seconds) },
|
||||||
|
clamping_mode
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Tries to simplify the expression into a `<resolution>` value.
|
||||||
|
fn to_resolution(&self) -> Result<Resolution, ()> {
|
||||||
|
let dppx = self.resolve(|leaf| match *leaf {
|
||||||
|
Leaf::Resolution(ref r) => Ok(r.dppx()),
|
||||||
|
_ => Err(()),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
Ok(Resolution::from_dppx_calc(if nan_inf_enabled() {
|
||||||
|
dppx
|
||||||
} else {
|
} else {
|
||||||
crate::values::normalize(seconds)
|
crate::values::normalize(dppx)
|
||||||
}, clamping_mode);
|
}))
|
||||||
Ok(result)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to simplify this expression into an `Angle` value.
|
/// Tries to simplify this expression into an `Angle` value.
|
||||||
|
@ -984,6 +1028,17 @@ impl CalcNode {
|
||||||
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Convenience parsing function for `<resolution>`.
|
||||||
|
pub fn parse_resolution<'i, 't>(
|
||||||
|
context: &ParserContext,
|
||||||
|
input: &mut Parser<'i, 't>,
|
||||||
|
function: MathFunction,
|
||||||
|
) -> Result<Resolution, ParseError<'i>> {
|
||||||
|
Self::parse(context, input, function, CalcUnits::RESOLUTION)?
|
||||||
|
.to_resolution()
|
||||||
|
.map_err(|()| input.new_custom_error(StyleParseErrorKind::UnspecifiedError))
|
||||||
|
}
|
||||||
|
|
||||||
/// Convenience parsing function for `<number>` or `<percentage>`.
|
/// Convenience parsing function for `<number>` or `<percentage>`.
|
||||||
pub fn parse_number_or_percentage<'i, 't>(
|
pub fn parse_number_or_percentage<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
|
|
|
@ -441,7 +441,7 @@ impl ImageSetItem {
|
||||||
.ok();
|
.ok();
|
||||||
}
|
}
|
||||||
|
|
||||||
let resolution = resolution.unwrap_or(Resolution::X(1.0));
|
let resolution = resolution.unwrap_or_else(|| Resolution::from_x(1.0));
|
||||||
let has_mime_type = mime_type.is_some();
|
let has_mime_type = mime_type.is_some();
|
||||||
let mime_type = mime_type.unwrap_or_default();
|
let mime_type = mime_type.unwrap_or_default();
|
||||||
|
|
||||||
|
|
|
@ -7,67 +7,135 @@
|
||||||
//! https://drafts.csswg.org/css-values/#resolution
|
//! https://drafts.csswg.org/css-values/#resolution
|
||||||
|
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
|
use crate::values::specified::CalcNode;
|
||||||
use crate::values::CSSFloat;
|
use crate::values::CSSFloat;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
use style_traits::{ParseError, StyleParseErrorKind};
|
use std::fmt::{self, Write};
|
||||||
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
|
||||||
/// A specified resolution.
|
/// A specified resolution.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToShmem)]
|
||||||
pub enum Resolution {
|
pub struct Resolution {
|
||||||
|
value: CSSFloat,
|
||||||
|
unit: ResolutionUnit,
|
||||||
|
was_calc: bool,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, SpecifiedValueInfo, ToCss, ToShmem)]
|
||||||
|
enum ResolutionUnit {
|
||||||
/// Dots per inch.
|
/// Dots per inch.
|
||||||
#[css(dimension)]
|
Dpi,
|
||||||
Dpi(CSSFloat),
|
|
||||||
/// An alias unit for dots per pixel.
|
/// An alias unit for dots per pixel.
|
||||||
#[css(dimension)]
|
X,
|
||||||
X(CSSFloat),
|
|
||||||
/// Dots per pixel.
|
/// Dots per pixel.
|
||||||
#[css(dimension)]
|
Dppx,
|
||||||
Dppx(CSSFloat),
|
|
||||||
/// Dots per centimeter.
|
/// Dots per centimeter.
|
||||||
#[css(dimension)]
|
Dpcm,
|
||||||
Dpcm(CSSFloat),
|
}
|
||||||
|
|
||||||
|
impl ResolutionUnit {
|
||||||
|
fn as_str(self) -> &'static str {
|
||||||
|
match self {
|
||||||
|
Self::Dpi => "dpi",
|
||||||
|
Self::X => "x",
|
||||||
|
Self::Dppx => "dppx",
|
||||||
|
Self::Dpcm => "dpcm",
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Resolution {
|
impl Resolution {
|
||||||
|
/// Returns a resolution value from dppx units.
|
||||||
|
pub fn from_dppx(value: CSSFloat) -> Self {
|
||||||
|
Self {
|
||||||
|
value,
|
||||||
|
unit: ResolutionUnit::Dppx,
|
||||||
|
was_calc: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a resolution value from dppx units.
|
||||||
|
pub fn from_x(value: CSSFloat) -> Self {
|
||||||
|
Self {
|
||||||
|
value,
|
||||||
|
unit: ResolutionUnit::X,
|
||||||
|
was_calc: false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Returns a resolution value from dppx units.
|
||||||
|
pub fn from_dppx_calc(value: CSSFloat) -> Self {
|
||||||
|
Self {
|
||||||
|
value,
|
||||||
|
unit: ResolutionUnit::Dppx,
|
||||||
|
was_calc: true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Convert this resolution value to dppx units.
|
/// Convert this resolution value to dppx units.
|
||||||
pub fn to_dppx(&self) -> CSSFloat {
|
pub fn dppx(&self) -> CSSFloat {
|
||||||
match *self {
|
match self.unit {
|
||||||
Resolution::X(f) | Resolution::Dppx(f) => f,
|
ResolutionUnit::X | ResolutionUnit::Dppx => self.value,
|
||||||
_ => self.to_dpi() / 96.0,
|
_ => self.dpi() / 96.0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert this resolution value to dpi units.
|
/// Convert this resolution value to dpi units.
|
||||||
pub fn to_dpi(&self) -> CSSFloat {
|
pub fn dpi(&self) -> CSSFloat {
|
||||||
match *self {
|
match self.unit {
|
||||||
Resolution::Dpi(f) => f,
|
ResolutionUnit::Dpi => self.value,
|
||||||
Resolution::X(f) | Resolution::Dppx(f) => f * 96.0,
|
ResolutionUnit::X | ResolutionUnit::Dppx => self.value * 96.0,
|
||||||
Resolution::Dpcm(f) => f * 2.54,
|
ResolutionUnit::Dpcm => self.value * 2.54,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Parse a resolution given a value and unit.
|
||||||
|
pub fn parse_dimension<'i, 't>(value: CSSFloat, unit: &str) -> Result<Self, ()> {
|
||||||
|
let unit = match_ignore_ascii_case! { &unit,
|
||||||
|
"dpi" => ResolutionUnit::Dpi,
|
||||||
|
"dppx" => ResolutionUnit::Dppx,
|
||||||
|
"dpcm" => ResolutionUnit::Dpcm,
|
||||||
|
"x" => ResolutionUnit::X,
|
||||||
|
_ => return Err(())
|
||||||
|
};
|
||||||
|
Ok(Self {
|
||||||
|
value,
|
||||||
|
unit,
|
||||||
|
was_calc: false,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for Resolution {
|
||||||
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
|
where
|
||||||
|
W: Write,
|
||||||
|
{
|
||||||
|
crate::values::serialize_specified_dimension(
|
||||||
|
self.value,
|
||||||
|
self.unit.as_str(),
|
||||||
|
self.was_calc,
|
||||||
|
dest,
|
||||||
|
)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Parse for Resolution {
|
impl Parse for Resolution {
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
_: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let location = input.current_source_location();
|
let location = input.current_source_location();
|
||||||
let (value, unit) = match *input.next()? {
|
match *input.next()? {
|
||||||
Token::Dimension {
|
Token::Dimension {
|
||||||
value, ref unit, ..
|
value, ref unit, ..
|
||||||
} => (value, unit),
|
} => Self::parse_dimension(value, unit)
|
||||||
|
.map_err(|()| location.new_custom_error(StyleParseErrorKind::UnspecifiedError)),
|
||||||
|
Token::Function(ref name) => {
|
||||||
|
let function = CalcNode::math_function(name, location)?;
|
||||||
|
CalcNode::parse_resolution(context, input, function)
|
||||||
|
},
|
||||||
ref t => return Err(location.new_unexpected_token_error(t.clone())),
|
ref t => return Err(location.new_unexpected_token_error(t.clone())),
|
||||||
};
|
|
||||||
|
|
||||||
match_ignore_ascii_case! { &unit,
|
|
||||||
"dpi" => Ok(Resolution::Dpi(value)),
|
|
||||||
"dppx" => Ok(Resolution::Dppx(value)),
|
|
||||||
"dpcm" => Ok(Resolution::Dpcm(value)),
|
|
||||||
"x" => Ok(Resolution::X(value)),
|
|
||||||
_ => Err(location.new_custom_error(
|
|
||||||
StyleParseErrorKind::UnexpectedDimension(unit.clone())
|
|
||||||
)),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue