Skip to content

Commit

Permalink
Keep the unit of the serialization of specified::CalcLengthOrPercentage.
Browse files Browse the repository at this point in the history
For the serialization of specified values of calc(), we should keep the
units of absolute lengths, so use AbsoluteLength.
  • Loading branch information
BorisChiou committed Sep 7, 2017
1 parent 5defc56 commit 6607103
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 14 deletions.
4 changes: 2 additions & 2 deletions components/style/values/computed/length.rs
Expand Up @@ -223,7 +223,7 @@ impl specified::CalcLengthOrPercentage {
let mut length = Au(0);

if let Some(absolute) = self.absolute {
length += zoom_fn(absolute);
length += zoom_fn(absolute.to_computed_value(context));
}

for val in &[self.vw.map(ViewportPercentageLength::Vw),
Expand Down Expand Up @@ -269,7 +269,7 @@ impl ToComputedValue for specified::CalcLengthOrPercentage {
fn from_computed_value(computed: &CalcLengthOrPercentage) -> Self {
specified::CalcLengthOrPercentage {
clamping_mode: computed.clamping_mode,
absolute: Some(computed.length),
absolute: Some(AbsoluteLength::from_computed_value(&computed.length)),
percentage: computed.percentage,
..Default::default()
}
Expand Down
34 changes: 23 additions & 11 deletions components/style/values/specified/calc.rs
Expand Up @@ -6,7 +6,6 @@
//!
//! [calc]: https://drafts.csswg.org/css-values/#calc-notation

use app_units::Au;
use cssparser::{Parser, Token, BasicParseError};
use parser::ParserContext;
use std::ascii::AsciiExt;
Expand All @@ -16,7 +15,8 @@ use style_traits::values::specified::AllowedLengthType;
use values::{CSSInteger, CSSFloat};
use values::computed;
use values::specified::{Angle, Time};
use values::specified::length::{FontRelativeLength, NoCalcLength, ViewportPercentageLength};
use values::specified::length::{AbsoluteLength, FontRelativeLength, NoCalcLength};
use values::specified::length::ViewportPercentageLength;

/// A node inside a `Calc` expression's AST.
#[derive(Clone, Debug)]
Expand Down Expand Up @@ -68,7 +68,7 @@ pub enum CalcUnit {
#[allow(missing_docs)]
pub struct CalcLengthOrPercentage {
pub clamping_mode: AllowedLengthType,
pub absolute: Option<Au>,
pub absolute: Option<AbsoluteLength>,
pub vw: Option<CSSFloat>,
pub vh: Option<CSSFloat>,
pub vmin: Option<CSSFloat>,
Expand Down Expand Up @@ -118,6 +118,17 @@ impl ToCss for CalcLengthOrPercentage {
};
}

macro_rules! serialize_abs {
( $( $val:ident ),+ ) => {
$(
if let Some(AbsoluteLength::$val(v)) = self.absolute {
first_value_check!(v);
AbsoluteLength::$val(v.abs()).to_css(dest)?;
}
)+
};
}

dest.write_str("calc(")?;

// NOTE(emilio): Percentages first because of web-compat problems, see:
Expand All @@ -129,18 +140,17 @@ impl ToCss for CalcLengthOrPercentage {

// NOTE(emilio): The order here it's very intentional, and alphabetic
// per the spec linked above.
serialize!(ch, em, ex);
serialize!(ch);
serialize_abs!(Cm);
serialize!(em, ex);
serialize_abs!(In);

#[cfg(feature = "gecko")]
{
serialize!(mozmm);
}

if let Some(val) = self.absolute {
first_value_check!(val);
val.abs().to_css(dest)?;
}

serialize_abs!(Mm, Pc, Pt, Px, Q);
serialize!(rem, vh, vmax, vmin, vw);

dest.write_str(")")
Expand Down Expand Up @@ -349,8 +359,10 @@ impl CalcNode {
match *l {
NoCalcLength::Absolute(abs) => {
ret.absolute = Some(
ret.absolute.unwrap_or(Au(0)) +
Au::from(abs).scale_by(factor)
match ret.absolute {
Some(value) => value + abs * factor,
None => abs * factor,
}
);
}
NoCalcLength::FontRelative(rel) => {
Expand Down
37 changes: 36 additions & 1 deletion components/style/values/specified/length.rs
Expand Up @@ -13,7 +13,7 @@ use font_metrics::FontMetricsQueryResult;
use parser::{Parse, ParserContext};
use std::{cmp, fmt, mem};
use std::ascii::AsciiExt;
use std::ops::Mul;
use std::ops::{Add, Mul};
use style_traits::{ToCss, ParseError, StyleParseError};
use style_traits::values::specified::AllowedLengthType;
use stylesheets::CssRuleType;
Expand Down Expand Up @@ -278,6 +278,23 @@ impl AbsoluteLength {
| AbsoluteLength::Pc(v) => v == 0.,
}
}

/// Convert this into a pixel value.
#[inline]
pub fn to_px(&self) -> CSSFloat {
use std::f32;

let pixel = match *self {
AbsoluteLength::Px(value) => value,
AbsoluteLength::In(value) => value * (AU_PER_IN / AU_PER_PX),
AbsoluteLength::Cm(value) => value * (AU_PER_CM / AU_PER_PX),
AbsoluteLength::Mm(value) => value * (AU_PER_MM / AU_PER_PX),
AbsoluteLength::Q(value) => value * (AU_PER_Q / AU_PER_PX),
AbsoluteLength::Pt(value) => value * (AU_PER_PT / AU_PER_PX),
AbsoluteLength::Pc(value) => value * (AU_PER_PC / AU_PER_PX),
};
pixel.min(f32::MAX).max(f32::MIN)
}
}

impl ToComputedValue for AbsoluteLength {
Expand Down Expand Up @@ -337,6 +354,24 @@ impl Mul<CSSFloat> for AbsoluteLength {
}
}

impl Add<AbsoluteLength> for AbsoluteLength {
type Output = Self;

#[inline]
fn add(self, rhs: Self) -> Self {
match (self, rhs) {
(AbsoluteLength::Px(x), AbsoluteLength::Px(y)) => AbsoluteLength::Px(x + y),
(AbsoluteLength::In(x), AbsoluteLength::In(y)) => AbsoluteLength::In(x + y),
(AbsoluteLength::Cm(x), AbsoluteLength::Cm(y)) => AbsoluteLength::Cm(x + y),
(AbsoluteLength::Mm(x), AbsoluteLength::Mm(y)) => AbsoluteLength::Mm(x + y),
(AbsoluteLength::Q(x), AbsoluteLength::Q(y)) => AbsoluteLength::Q(x + y),
(AbsoluteLength::Pt(x), AbsoluteLength::Pt(y)) => AbsoluteLength::Pt(x + y),
(AbsoluteLength::Pc(x), AbsoluteLength::Pc(y)) => AbsoluteLength::Pc(x + y),
_ => AbsoluteLength::Px(self.to_px() + rhs.to_px()),
}
}
}

/// Represents a physical length (mozmm) based on DPI
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg(feature = "gecko")]
Expand Down

0 comments on commit 6607103

Please sign in to comment.