style: Make numbers keep track of whether they were specified as calc().

This commit is contained in:
Emilio Cobos Álvarez 2017-03-26 21:43:05 +02:00
parent c20bbb920c
commit c7ce2ff483
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C
9 changed files with 271 additions and 119 deletions

View file

@ -65,7 +65,8 @@ impl From<SpecifiedTimingFunction> for nsTimingFunction {
tf.set_as_step(nsTimingFunction_Type::StepEnd, steps); tf.set_as_step(nsTimingFunction_Type::StepEnd, steps);
}, },
SpecifiedTimingFunction::CubicBezier(p1, p2) => { SpecifiedTimingFunction::CubicBezier(p1, p2) => {
tf.set_as_cubic_bezier(p1, p2); tf.set_as_cubic_bezier(Point2D::new(p1.x.value, p1.y.value),
Point2D::new(p2.x.value, p2.y.value));
}, },
SpecifiedTimingFunction::Keyword(keyword) => { SpecifiedTimingFunction::Keyword(keyword) => {
match keyword { match keyword {

View file

@ -1283,7 +1283,7 @@ fn static_assert() {
use properties::longhands::font_size_adjust::computed_value::T; use properties::longhands::font_size_adjust::computed_value::T;
match v { match v {
T::None => self.gecko.mFont.sizeAdjust = -1.0 as f32, T::None => self.gecko.mFont.sizeAdjust = -1.0 as f32,
T::Number(n) => self.gecko.mFont.sizeAdjust = n.0 as f32, T::Number(n) => self.gecko.mFont.sizeAdjust = n,
} }
} }
@ -1293,11 +1293,10 @@ fn static_assert() {
pub fn clone_font_size_adjust(&self) -> longhands::font_size_adjust::computed_value::T { pub fn clone_font_size_adjust(&self) -> longhands::font_size_adjust::computed_value::T {
use properties::longhands::font_size_adjust::computed_value::T; use properties::longhands::font_size_adjust::computed_value::T;
use values::specified::Number;
match self.gecko.mFont.sizeAdjust { match self.gecko.mFont.sizeAdjust {
-1.0 => T::None, -1.0 => T::None,
_ => T::Number(Number(self.gecko.mFont.sizeAdjust)), _ => T::Number(self.gecko.mFont.sizeAdjust),
} }
} }

View file

@ -223,7 +223,7 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
#[inline] #[inline]
pub fn get_initial_specified_value() -> SpecifiedValue { pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue(vec![Either::Second(Number(0.0))]) SpecifiedValue(vec![Either::Second(Number::new(0.0))])
} }
impl ToComputedValue for SpecifiedValue { impl ToComputedValue for SpecifiedValue {
@ -486,7 +486,7 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
#[inline] #[inline]
pub fn get_initial_specified_value() -> SpecifiedValue { pub fn get_initial_specified_value() -> SpecifiedValue {
SpecifiedValue(vec![SingleSpecifiedValue::Number(Number(1.0))]) SpecifiedValue(vec![SingleSpecifiedValue::Number(Number::new(1.0))])
} }
impl ToComputedValue for SpecifiedValue { impl ToComputedValue for SpecifiedValue {

View file

@ -440,7 +440,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
extra_prefixes="moz webkit" extra_prefixes="moz webkit"
spec="https://drafts.csswg.org/css-transitions/#propdef-transition-timing-function"> spec="https://drafts.csswg.org/css-transitions/#propdef-transition-timing-function">
use self::computed_value::StartEnd; use self::computed_value::StartEnd;
use values::specified::Number;
use euclid::point::{Point2D, TypedPoint2D}; use euclid::point::{Point2D, TypedPoint2D};
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
@ -450,31 +450,31 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
#[inline(always)] #[inline(always)]
fn ease() -> computed_value::T { fn ease() -> computed_value::T {
computed_value::T::CubicBezier(TypedPoint2D::new(0.25, 0.1), computed_value::T::CubicBezier(TypedPoint2D::new(0.25, 0.1),
TypedPoint2D::new(0.25, 1.0)) TypedPoint2D::new(0.25, 1.0))
} }
#[inline(always)] #[inline(always)]
fn linear() -> computed_value::T { fn linear() -> computed_value::T {
computed_value::T::CubicBezier(TypedPoint2D::new(0.0, 0.0), computed_value::T::CubicBezier(TypedPoint2D::new(0.0, 0.0),
TypedPoint2D::new(1.0, 1.0)) TypedPoint2D::new(1.0, 1.0))
} }
#[inline(always)] #[inline(always)]
fn ease_in() -> computed_value::T { fn ease_in() -> computed_value::T {
computed_value::T::CubicBezier(TypedPoint2D::new(0.42, 0.0), computed_value::T::CubicBezier(TypedPoint2D::new(0.42, 0.0),
TypedPoint2D::new(1.0, 1.0)) TypedPoint2D::new(1.0, 1.0))
} }
#[inline(always)] #[inline(always)]
fn ease_out() -> computed_value::T { fn ease_out() -> computed_value::T {
computed_value::T::CubicBezier(TypedPoint2D::new(0.0, 0.0), computed_value::T::CubicBezier(TypedPoint2D::new(0.0, 0.0),
TypedPoint2D::new(0.58, 1.0)) TypedPoint2D::new(0.58, 1.0))
} }
#[inline(always)] #[inline(always)]
fn ease_in_out() -> computed_value::T { fn ease_in_out() -> computed_value::T {
computed_value::T::CubicBezier(TypedPoint2D::new(0.42, 0.0), computed_value::T::CubicBezier(TypedPoint2D::new(0.42, 0.0),
TypedPoint2D::new(0.58, 1.0)) TypedPoint2D::new(0.58, 1.0))
} }
static STEP_START: computed_value::T = static STEP_START: computed_value::T =
@ -547,7 +547,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue { pub enum SpecifiedValue {
CubicBezier(Point2D<f32>, Point2D<f32>), CubicBezier(Point2D<Number>, Point2D<Number>),
Steps(u32, StartEnd), Steps(u32, StartEnd),
Keyword(FunctionKeyword), Keyword(FunctionKeyword),
} }
@ -557,7 +557,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
if let Ok(function_name) = input.try(|input| input.expect_function()) { if let Ok(function_name) = input.try(|input| input.expect_function()) {
return match_ignore_ascii_case! { &function_name, return match_ignore_ascii_case! { &function_name,
"cubic-bezier" => { "cubic-bezier" => {
let (mut p1x, mut p1y, mut p2x, mut p2y) = (0.0, 0.0, 0.0, 0.0); let (mut p1x, mut p1y, mut p2x, mut p2y) =
(Number::new(0.0), Number::new(0.0), Number::new(0.0), Number::new(0.0));
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
p1x = try!(specified::parse_number(input)); p1x = try!(specified::parse_number(input));
try!(input.expect_comma()); try!(input.expect_comma());
@ -568,7 +569,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
p2y = try!(specified::parse_number(input)); p2y = try!(specified::parse_number(input));
Ok(()) Ok(())
})); }));
if p1x < 0.0 || p1x > 1.0 || p2x < 0.0 || p2x > 1.0 { if p1x.value < 0.0 || p1x.value > 1.0 ||
p2x.value < 0.0 || p2x.value > 1.0 {
return Err(()) return Err(())
} }
@ -651,10 +653,12 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
type ComputedValue = computed_value::T; type ComputedValue = computed_value::T;
#[inline] #[inline]
fn to_computed_value(&self, _context: &Context) -> computed_value::T { fn to_computed_value(&self, context: &Context) -> computed_value::T {
match *self { match *self {
SpecifiedValue::CubicBezier(p1, p2) => { SpecifiedValue::CubicBezier(p1, p2) => {
computed_value::T::CubicBezier(p1, p2) computed_value::T::CubicBezier(
Point2D::new(p1.x.to_computed_value(context), p1.y.to_computed_value(context)),
Point2D::new(p2.x.to_computed_value(context), p2.y.to_computed_value(context)))
}, },
SpecifiedValue::Steps(count, start_end) => { SpecifiedValue::Steps(count, start_end) => {
computed_value::T::Steps(count, start_end) computed_value::T::Steps(count, start_end)
@ -676,7 +680,11 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
fn from_computed_value(computed: &computed_value::T) -> Self { fn from_computed_value(computed: &computed_value::T) -> Self {
match *computed { match *computed {
computed_value::T::CubicBezier(p1, p2) => { computed_value::T::CubicBezier(p1, p2) => {
SpecifiedValue::CubicBezier(p1, p2) SpecifiedValue::CubicBezier(
Point2D::new(Number::from_computed_value(&p1.x),
Number::from_computed_value(&p1.y)),
Point2D::new(Number::from_computed_value(&p2.x),
Number::from_computed_value(&p2.y)))
}, },
computed_value::T::Steps(count, start_end) => { computed_value::T::Steps(count, start_end) => {
SpecifiedValue::Steps(count, start_end) SpecifiedValue::Steps(count, start_end)
@ -1083,6 +1091,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
fixpos_cb="True" fixpos_cb="True"
spec="https://drafts.csswg.org/css-transforms/#propdef-transform"> spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
use app_units::Au; use app_units::Au;
use values::specified::Number;
use style_traits::ToCss; use style_traits::ToCss;
use values::CSSFloat; use values::CSSFloat;
use values::HasViewportPercentage; use values::HasViewportPercentage;
@ -1131,7 +1140,60 @@ ${helpers.predefined_type("scroll-snap-coordinate",
pub struct T(pub Option<Vec<ComputedOperation>>); pub struct T(pub Option<Vec<ComputedOperation>>);
} }
pub use self::computed_value::ComputedMatrix as SpecifiedMatrix; #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct SpecifiedMatrix {
pub m11: Number, pub m12: Number, pub m13: Number, pub m14: Number,
pub m21: Number, pub m22: Number, pub m23: Number, pub m24: Number,
pub m31: Number, pub m32: Number, pub m33: Number, pub m34: Number,
pub m41: Number, pub m42: Number, pub m43: Number, pub m44: Number,
}
impl ToComputedValue for SpecifiedMatrix {
type ComputedValue = computed_value::ComputedMatrix;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
computed_value::ComputedMatrix {
m11: self.m11.to_computed_value(context),
m12: self.m12.to_computed_value(context),
m13: self.m13.to_computed_value(context),
m14: self.m14.to_computed_value(context),
m21: self.m21.to_computed_value(context),
m22: self.m22.to_computed_value(context),
m23: self.m23.to_computed_value(context),
m24: self.m24.to_computed_value(context),
m31: self.m31.to_computed_value(context),
m32: self.m32.to_computed_value(context),
m33: self.m33.to_computed_value(context),
m34: self.m34.to_computed_value(context),
m41: self.m41.to_computed_value(context),
m42: self.m42.to_computed_value(context),
m43: self.m43.to_computed_value(context),
m44: self.m44.to_computed_value(context),
}
}
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
SpecifiedMatrix {
m11: Number::from_computed_value(&computed.m11),
m12: Number::from_computed_value(&computed.m12),
m13: Number::from_computed_value(&computed.m13),
m14: Number::from_computed_value(&computed.m14),
m21: Number::from_computed_value(&computed.m21),
m22: Number::from_computed_value(&computed.m22),
m23: Number::from_computed_value(&computed.m23),
m24: Number::from_computed_value(&computed.m24),
m31: Number::from_computed_value(&computed.m31),
m32: Number::from_computed_value(&computed.m32),
m33: Number::from_computed_value(&computed.m33),
m34: Number::from_computed_value(&computed.m34),
m41: Number::from_computed_value(&computed.m41),
m42: Number::from_computed_value(&computed.m42),
m43: Number::from_computed_value(&computed.m43),
m44: Number::from_computed_value(&computed.m44),
}
}
}
fn parse_two_lengths_or_percentages(context: &ParserContext, input: &mut Parser) fn parse_two_lengths_or_percentages(context: &ParserContext, input: &mut Parser)
-> Result<(specified::LengthOrPercentage, -> Result<(specified::LengthOrPercentage,
@ -1144,7 +1206,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
Ok((first, second)) Ok((first, second))
} }
fn parse_two_floats(input: &mut Parser) -> Result<(CSSFloat,CSSFloat),()> { fn parse_two_numbers(input: &mut Parser) -> Result<(Number, Number), ()> {
let first = try!(specified::parse_number(input)); let first = try!(specified::parse_number(input));
let second = input.try(|input| { let second = input.try(|input| {
try!(input.expect_comma()); try!(input.expect_comma());
@ -1182,8 +1244,8 @@ ${helpers.predefined_type("scroll-snap-coordinate",
specified::LengthOrPercentage, specified::LengthOrPercentage,
specified::LengthOrPercentage, specified::LengthOrPercentage,
specified::Length), specified::Length),
Scale(CSSFloat, CSSFloat, CSSFloat), Scale(Number, Number, Number),
Rotate(CSSFloat, CSSFloat, CSSFloat, specified::Angle), Rotate(Number, Number, Number, specified::Angle),
Perspective(specified::Length), Perspective(specified::Length),
} }
@ -1323,31 +1385,29 @@ ${helpers.predefined_type("scroll-snap-coordinate",
if values.len() != 6 { if values.len() != 6 {
return Err(()) return Err(())
} }
result.push(SpecifiedOperation::Matrix( let matrix = SpecifiedMatrix {
SpecifiedMatrix { m11: values[0], m12: values[1], m13: Number::new(0.0), m14: Number::new(0.0),
m11: values[0], m12: values[1], m13: 0.0, m14: 0.0, m21: values[2], m22: values[3], m23: Number::new(0.0), m24: Number::new(0.0),
m21: values[2], m22: values[3], m23: 0.0, m24: 0.0, m31: Number::new(0.0), m32: Number::new(0.0), m33: Number::new(1.0), m34: Number::new(0.0),
m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0, m41: values[4], m42: values[5], m43: Number::new(0.0), m44: Number::new(1.0),
m41: values[4], m42: values[5], m43: 0.0, m44: 1.0 };
})); result.push(SpecifiedOperation::Matrix(matrix));
Ok(()) Ok(())
})) }))
}, },
"matrix3d" => { "matrix3d" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let values = try!(input.parse_comma_separated(|input| { let values = try!(input.parse_comma_separated(specified::parse_number));
specified::parse_number(input)
}));
if values.len() != 16 { if values.len() != 16 {
return Err(()) return Err(())
} }
result.push(SpecifiedOperation::Matrix( result.push(SpecifiedOperation::Matrix(
SpecifiedMatrix { SpecifiedMatrix {
m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3], m11: values[ 0], m12: values[ 1], m13: values[ 2], m14: values[ 3],
m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7], m21: values[ 4], m22: values[ 5], m23: values[ 6], m24: values[ 7],
m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11], m31: values[ 8], m32: values[ 9], m33: values[10], m34: values[11],
m41: values[12], m42: values[13], m43: values[14], m44: values[15] m41: values[12], m42: values[13], m43: values[14], m44: values[15]
})); }));
Ok(()) Ok(())
})) }))
}, },
@ -1412,29 +1472,37 @@ ${helpers.predefined_type("scroll-snap-coordinate",
}, },
"scale" => { "scale" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let (sx, sy) = try!(parse_two_floats(input)); let (sx, sy) = try!(parse_two_numbers(input));
result.push(SpecifiedOperation::Scale(sx, sy, 1.0)); result.push(SpecifiedOperation::Scale(sx,
sy,
Number::new(1.0)));
Ok(()) Ok(())
})) }))
}, },
"scalex" => { "scalex" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let sx = try!(specified::parse_number(input)); let sx = try!(specified::parse_number(input));
result.push(SpecifiedOperation::Scale(sx, 1.0, 1.0)); result.push(SpecifiedOperation::Scale(sx,
Number::new(1.0),
Number::new(1.0)));
Ok(()) Ok(())
})) }))
}, },
"scaley" => { "scaley" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let sy = try!(specified::parse_number(input)); let sy = try!(specified::parse_number(input));
result.push(SpecifiedOperation::Scale(1.0, sy, 1.0)); result.push(SpecifiedOperation::Scale(Number::new(1.0),
sy,
Number::new(1.0)));
Ok(()) Ok(())
})) }))
}, },
"scalez" => { "scalez" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let sz = try!(specified::parse_number(input)); let sz = try!(specified::parse_number(input));
result.push(SpecifiedOperation::Scale(1.0, 1.0, sz)); result.push(SpecifiedOperation::Scale(Number::new(1.0),
Number::new(1.0),
sz));
Ok(()) Ok(())
})) }))
}, },
@ -1452,28 +1520,40 @@ ${helpers.predefined_type("scroll-snap-coordinate",
"rotate" => { "rotate" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse(context,input)); let theta = try!(specified::Angle::parse(context,input));
result.push(SpecifiedOperation::Rotate(0.0, 0.0, 1.0, theta)); result.push(SpecifiedOperation::Rotate(Number::new(0.0),
Number::new(0.0),
Number::new(1.0),
theta));
Ok(()) Ok(())
})) }))
}, },
"rotatex" => { "rotatex" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse(context,input)); let theta = try!(specified::Angle::parse(context,input));
result.push(SpecifiedOperation::Rotate(1.0, 0.0, 0.0, theta)); result.push(SpecifiedOperation::Rotate(Number::new(1.0),
Number::new(0.0),
Number::new(0.0),
theta));
Ok(()) Ok(())
})) }))
}, },
"rotatey" => { "rotatey" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse(context,input)); let theta = try!(specified::Angle::parse(context,input));
result.push(SpecifiedOperation::Rotate(0.0, 1.0, 0.0, theta)); result.push(SpecifiedOperation::Rotate(Number::new(0.0),
Number::new(1.0),
Number::new(0.0),
theta));
Ok(()) Ok(())
})) }))
}, },
"rotatez" => { "rotatez" => {
try!(input.parse_nested_block(|input| { try!(input.parse_nested_block(|input| {
let theta = try!(specified::Angle::parse(context,input)); let theta = try!(specified::Angle::parse(context,input));
result.push(SpecifiedOperation::Rotate(0.0, 0.0, 1.0, theta)); result.push(SpecifiedOperation::Rotate(Number::new(0.0),
Number::new(0.0),
Number::new(1.0),
theta));
Ok(()) Ok(())
})) }))
}, },
@ -1543,7 +1623,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
for operation in &self.0 { for operation in &self.0 {
match *operation { match *operation {
SpecifiedOperation::Matrix(ref matrix) => { SpecifiedOperation::Matrix(ref matrix) => {
result.push(computed_value::ComputedOperation::Matrix(*matrix)); result.push(computed_value::ComputedOperation::Matrix(matrix.to_computed_value(context)));
} }
SpecifiedOperation::Translate(_, ref tx, ref ty, ref tz) => { SpecifiedOperation::Translate(_, ref tx, ref ty, ref tz) => {
result.push(computed_value::ComputedOperation::Translate(tx.to_computed_value(context), result.push(computed_value::ComputedOperation::Translate(tx.to_computed_value(context),
@ -1551,9 +1631,15 @@ ${helpers.predefined_type("scroll-snap-coordinate",
tz.to_computed_value(context))); tz.to_computed_value(context)));
} }
SpecifiedOperation::Scale(sx, sy, sz) => { SpecifiedOperation::Scale(sx, sy, sz) => {
let sx = sx.to_computed_value(context);
let sy = sy.to_computed_value(context);
let sz = sz.to_computed_value(context);
result.push(computed_value::ComputedOperation::Scale(sx, sy, sz)); result.push(computed_value::ComputedOperation::Scale(sx, sy, sz));
} }
SpecifiedOperation::Rotate(ax, ay, az, theta) => { SpecifiedOperation::Rotate(ax, ay, az, theta) => {
let ax = ax.to_computed_value(context);
let ay = ay.to_computed_value(context);
let az = az.to_computed_value(context);
let len = (ax * ax + ay * ay + az * az).sqrt(); let len = (ax * ax + ay * ay + az * az).sqrt();
result.push(computed_value::ComputedOperation::Rotate(ax / len, ay / len, az / len, theta)); result.push(computed_value::ComputedOperation::Rotate(ax / len, ay / len, az / len, theta));
} }
@ -1576,7 +1662,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
for operation in computed { for operation in computed {
match *operation { match *operation {
computed_value::ComputedOperation::Matrix(ref matrix) => { computed_value::ComputedOperation::Matrix(ref matrix) => {
result.push(SpecifiedOperation::Matrix(*matrix)); result.push(SpecifiedOperation::Matrix(SpecifiedMatrix::from_computed_value(matrix)));
} }
computed_value::ComputedOperation::Translate(ref tx, ref ty, ref tz) => { computed_value::ComputedOperation::Translate(ref tx, ref ty, ref tz) => {
// XXXManishearth we lose information here; perhaps we should try to // XXXManishearth we lose information here; perhaps we should try to
@ -1586,11 +1672,18 @@ ${helpers.predefined_type("scroll-snap-coordinate",
ToComputedValue::from_computed_value(ty), ToComputedValue::from_computed_value(ty),
ToComputedValue::from_computed_value(tz))); ToComputedValue::from_computed_value(tz)));
} }
computed_value::ComputedOperation::Scale(sx, sy, sz) => { computed_value::ComputedOperation::Scale(ref sx, ref sy, ref sz) => {
result.push(SpecifiedOperation::Scale(sx, sy, sz)); result.push(SpecifiedOperation::Scale(
Number::from_computed_value(sx),
Number::from_computed_value(sy),
Number::from_computed_value(sz)));
} }
computed_value::ComputedOperation::Rotate(ax, ay, az, theta) => { computed_value::ComputedOperation::Rotate(ref ax, ref ay, ref az, theta) => {
result.push(SpecifiedOperation::Rotate(ax, ay, az, theta)); result.push(SpecifiedOperation::Rotate(
Number::from_computed_value(ax),
Number::from_computed_value(ay),
Number::from_computed_value(az),
theta));
} }
computed_value::ComputedOperation::Skew(theta_x, theta_y) => { computed_value::ComputedOperation::Skew(theta_x, theta_y) => {
result.push(SpecifiedOperation::Skew(theta_x, theta_y)); result.push(SpecifiedOperation::Skew(theta_x, theta_y));

View file

@ -655,30 +655,65 @@ ${helpers.single_keyword("font-variant-caps",
<%helpers:longhand products="gecko" name="font-size-adjust" animatable="True" <%helpers:longhand products="gecko" name="font-size-adjust" animatable="True"
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust"> spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust">
use std::fmt;
use style_traits::ToCss;
use values::HasViewportPercentage; use values::HasViewportPercentage;
use values::computed::ComputedValueAsSpecified;
use values::specified::Number;
impl ComputedValueAsSpecified for SpecifiedValue {}
no_viewport_percentage!(SpecifiedValue); no_viewport_percentage!(SpecifiedValue);
#[derive(Copy, Clone, Debug, PartialEq)] #[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum SpecifiedValue { pub enum SpecifiedValue {
None, None,
Number(Number), Number(specified::Number),
}
impl ToCss for SpecifiedValue {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
match *self {
SpecifiedValue::None => dest.write_str("none"),
SpecifiedValue::Number(number) => number.to_css(dest),
}
}
}
impl ToComputedValue for SpecifiedValue {
type ComputedValue = computed_value::T;
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
match *self {
SpecifiedValue::None => computed_value::T::None,
SpecifiedValue::Number(ref n) => computed_value::T::Number(n.to_computed_value(context)),
}
}
fn from_computed_value(computed: &computed_value::T) -> Self {
match *computed {
computed_value::T::None => SpecifiedValue::None,
computed_value::T::Number(ref v) => SpecifiedValue::Number(specified::Number::from_computed_value(v)),
}
}
} }
pub mod computed_value { pub mod computed_value {
use style_traits::ToCss;
use std::fmt;
use properties::animated_properties::Interpolate; use properties::animated_properties::Interpolate;
use values::specified::Number; use std::fmt;
use style_traits::ToCss;
use values::CSSFloat;
pub use super::SpecifiedValue as T; #[derive(Copy, Clone, Debug, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub enum T {
None,
Number(CSSFloat),
}
impl ToCss for T { impl ToCss for T {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result
where W: fmt::Write,
{
match *self { match *self {
T::None => dest.write_str("none"), T::None => dest.write_str("none"),
T::Number(number) => number.to_css(dest), T::Number(number) => number.to_css(dest),
@ -690,14 +725,15 @@ ${helpers.single_keyword("font-variant-caps",
fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> { fn interpolate(&self, other: &Self, time: f64) -> Result<Self, ()> {
match (*self, *other) { match (*self, *other) {
(T::Number(ref number), T::Number(ref other)) => (T::Number(ref number), T::Number(ref other)) =>
Ok(T::Number(Number(try!(number.0.interpolate(&other.0, time))))), Ok(T::Number(try!(number.interpolate(other, time)))),
_ => Err(()), _ => Err(()),
} }
} }
} }
} }
#[inline] pub fn get_initial_value() -> computed_value::T { #[inline]
pub fn get_initial_value() -> computed_value::T {
computed_value::T::None computed_value::T::None
} }

View file

@ -10,7 +10,7 @@
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height"> spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height">
use std::fmt; use std::fmt;
use style_traits::ToCss; use style_traits::ToCss;
use values::{CSSFloat, HasViewportPercentage}; use values::HasViewportPercentage;
impl HasViewportPercentage for SpecifiedValue { impl HasViewportPercentage for SpecifiedValue {
fn has_viewport_percentage(&self) -> bool { fn has_viewport_percentage(&self) -> bool {
@ -28,7 +28,7 @@
% if product == "gecko": % if product == "gecko":
MozBlockHeight, MozBlockHeight,
% endif % endif
Number(CSSFloat), Number(specified::Number),
LengthOrPercentage(specified::LengthOrPercentage), LengthOrPercentage(specified::LengthOrPercentage),
} }
@ -40,7 +40,7 @@
SpecifiedValue::MozBlockHeight => dest.write_str("-moz-block-height"), SpecifiedValue::MozBlockHeight => dest.write_str("-moz-block-height"),
% endif % endif
SpecifiedValue::LengthOrPercentage(ref value) => value.to_css(dest), SpecifiedValue::LengthOrPercentage(ref value) => value.to_css(dest),
SpecifiedValue::Number(number) => write!(dest, "{}", number), SpecifiedValue::Number(number) => number.to_css(dest),
} }
} }
} }
@ -52,24 +52,24 @@
// parsed as a plain Number rather than a Length (0px); this matches the behaviour // parsed as a plain Number rather than a Length (0px); this matches the behaviour
// of all major browsers // of all major browsers
input.try(specified::Number::parse_non_negative) input.try(specified::Number::parse_non_negative)
.map(|n| SpecifiedValue::Number(n.0)) .map(SpecifiedValue::Number)
.or_else(|()| {
input.try(specified::LengthOrPercentage::parse_non_negative)
.map(SpecifiedValue::LengthOrPercentage)
.or_else(|()| { .or_else(|()| {
match try!(input.next()) { input.try(specified::LengthOrPercentage::parse_non_negative)
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => { .map(SpecifiedValue::LengthOrPercentage)
Ok(SpecifiedValue::Normal) .or_else(|()| {
match try!(input.next()) {
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => {
Ok(SpecifiedValue::Normal)
}
% if product == "gecko":
Token::Ident(ref value) if value.eq_ignore_ascii_case("-moz-block-height") => {
Ok(SpecifiedValue::MozBlockHeight)
}
% endif
_ => Err(()),
} }
% if product == "gecko": })
Token::Ident(ref value) if value.eq_ignore_ascii_case("-moz-block-height") => {
Ok(SpecifiedValue::MozBlockHeight)
}
% endif
_ => Err(()),
}
}) })
})
} }
pub mod computed_value { pub mod computed_value {
use app_units::Au; use app_units::Au;
@ -116,7 +116,7 @@
% if product == "gecko": % if product == "gecko":
SpecifiedValue::MozBlockHeight => computed_value::T::MozBlockHeight, SpecifiedValue::MozBlockHeight => computed_value::T::MozBlockHeight,
% endif % endif
SpecifiedValue::Number(value) => computed_value::T::Number(value), SpecifiedValue::Number(value) => computed_value::T::Number(value.to_computed_value(context)),
SpecifiedValue::LengthOrPercentage(ref value) => { SpecifiedValue::LengthOrPercentage(ref value) => {
match *value { match *value {
specified::LengthOrPercentage::Length(ref value) => specified::LengthOrPercentage::Length(ref value) =>
@ -144,7 +144,9 @@
% if product == "gecko": % if product == "gecko":
computed_value::T::MozBlockHeight => SpecifiedValue::MozBlockHeight, computed_value::T::MozBlockHeight => SpecifiedValue::MozBlockHeight,
% endif % endif
computed_value::T::Number(value) => SpecifiedValue::Number(value), computed_value::T::Number(ref value) => {
SpecifiedValue::Number(specified::Number::from_computed_value(value))
},
computed_value::T::Length(au) => { computed_value::T::Length(au) => {
SpecifiedValue::LengthOrPercentage(specified::LengthOrPercentage::Length( SpecifiedValue::LengthOrPercentage(specified::LengthOrPercentage::Length(
ToComputedValue::from_computed_value(&au) ToComputedValue::from_computed_value(&au)

View file

@ -70,8 +70,8 @@
if input.try(|input| input.expect_ident_matching("none")).is_ok() { if input.try(|input| input.expect_ident_matching("none")).is_ok() {
return Ok(Longhands { return Ok(Longhands {
flex_grow: Number(0.0), flex_grow: Number::new(0.0),
flex_shrink: Number(0.0), flex_shrink: Number::new(0.0),
% if product == "gecko": % if product == "gecko":
flex_basis: LengthOrPercentageOrAuto::Auto flex_basis: LengthOrPercentageOrAuto::Auto
% else: % else:
@ -105,8 +105,8 @@
return Err(()) return Err(())
} }
Ok(Longhands { Ok(Longhands {
flex_grow: grow.unwrap_or(Number(1.0)), flex_grow: grow.unwrap_or(Number::new(1.0)),
flex_shrink: shrink.unwrap_or(Number(1.0)), flex_shrink: shrink.unwrap_or(Number::new(1.0)),
% if product == "gecko": % if product == "gecko":
flex_basis: basis.unwrap_or(LengthOrPercentageOrAuto::Length(NoCalcLength::zero())) flex_basis: basis.unwrap_or(LengthOrPercentageOrAuto::Length(NoCalcLength::zero()))
% else: % else:

View file

@ -219,17 +219,15 @@ pub fn parse_integer(input: &mut Parser) -> Result<CSSInteger, ()> {
} }
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn parse_number(input: &mut Parser) -> Result<f32, ()> { pub fn parse_number(input: &mut Parser) -> Result<Number, ()> {
use std::f32;
match try!(input.next()) { match try!(input.next()) {
Token::Number(ref value) => { Token::Number(ref value) => {
use std::f32; Ok(Number {
if value.value.is_finite() { value: value.value.min(f32::MAX).max(f32::MIN),
Ok(value.value) was_calc: false,
} else if value.value.is_sign_positive() { })
Ok(f32::MAX)
} else {
Ok(f32::MIN)
}
}, },
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => { Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
let ast = try!(input.parse_nested_block(|i| CalcLengthOrPercentage::parse_sum(i, CalcUnit::Number))); let ast = try!(input.parse_nested_block(|i| CalcLengthOrPercentage::parse_sum(i, CalcUnit::Number)));
@ -245,7 +243,12 @@ pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
} }
match result { match result {
Some(result) => Ok(result), Some(result) => {
Ok(Number {
value: result.min(f32::MAX).max(f32::MIN),
was_calc: true,
})
},
_ => Err(()) _ => Err(())
} }
} }
@ -525,24 +528,39 @@ impl ToCss for Time {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct Number(pub CSSFloat); pub struct Number {
/// The numeric value itself.
pub value: CSSFloat,
/// Whether this came from a `calc()` expression. This is needed for
/// serialization purposes, since `calc(1)` should still serialize to
/// `calc(1)`, not just `1`.
was_calc: bool,
}
no_viewport_percentage!(Number); no_viewport_percentage!(Number);
impl Parse for Number { impl Parse for Number {
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> { fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
parse_number(input).map(Number) parse_number(input)
} }
} }
impl Number { impl Number {
fn parse_with_minimum(input: &mut Parser, min: CSSFloat) -> Result<Number, ()> { fn parse_with_minimum(input: &mut Parser, min: CSSFloat) -> Result<Number, ()> {
match parse_number(input) { match parse_number(input) {
Ok(value) if value >= min => Ok(Number(value)), Ok(value) if value.value >= min => Ok(value),
_ => Err(()), _ => Err(()),
} }
} }
/// Returns a new number with the value `val`.
pub fn new(val: CSSFloat) -> Self {
Number {
value: val,
was_calc: false,
}
}
#[allow(missing_docs)] #[allow(missing_docs)]
pub fn parse_non_negative(input: &mut Parser) -> Result<Number, ()> { pub fn parse_non_negative(input: &mut Parser) -> Result<Number, ()> {
Number::parse_with_minimum(input, 0.0) Number::parse_with_minimum(input, 0.0)
@ -558,17 +576,27 @@ impl ToComputedValue for Number {
type ComputedValue = CSSFloat; type ComputedValue = CSSFloat;
#[inline] #[inline]
fn to_computed_value(&self, _: &Context) -> CSSFloat { self.0 } fn to_computed_value(&self, _: &Context) -> CSSFloat { self.value }
#[inline] #[inline]
fn from_computed_value(computed: &CSSFloat) -> Self { fn from_computed_value(computed: &CSSFloat) -> Self {
Number(*computed) Number {
value: *computed,
was_calc: false,
}
} }
} }
impl ToCss for Number { impl ToCss for Number {
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write { fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
self.0.to_css(dest) if self.was_calc {
dest.write_str("calc(")?;
}
self.value.to_css(dest)?;
if self.was_calc {
dest.write_str(")")?;
}
Ok(())
} }
} }
@ -606,7 +634,7 @@ impl ToCss for NumberOrPercentage {
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)] #[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct Opacity(pub CSSFloat); pub struct Opacity(Number);
no_viewport_percentage!(Opacity); no_viewport_percentage!(Opacity);
@ -620,19 +648,13 @@ impl ToComputedValue for Opacity {
type ComputedValue = CSSFloat; type ComputedValue = CSSFloat;
#[inline] #[inline]
fn to_computed_value(&self, _: &Context) -> CSSFloat { fn to_computed_value(&self, context: &Context) -> CSSFloat {
if self.0 < 0.0 { self.0.to_computed_value(context).min(1.0).max(0.0)
0.0
} else if self.0 > 1.0 {
1.0
} else {
self.0
}
} }
#[inline] #[inline]
fn from_computed_value(computed: &CSSFloat) -> Self { fn from_computed_value(computed: &CSSFloat) -> Self {
Opacity(*computed) Opacity(Number::from_computed_value(computed))
} }
} }

View file

@ -573,15 +573,14 @@ mod shorthand_serialization {
#[test] #[test]
fn flex_should_serialize_all_available_properties() { fn flex_should_serialize_all_available_properties() {
use style::values::specified::Number as NumberContainer; use style::values::specified::{Number, Percentage};
use style::values::specified::Percentage as PercentageContainer;
let mut properties = Vec::new(); let mut properties = Vec::new();
let grow = NumberContainer(2f32); let grow = Number::new(2f32);
let shrink = NumberContainer(3f32); let shrink = Number::new(3f32);
let basis = let basis =
LengthOrPercentageOrAutoOrContent::Percentage(PercentageContainer(0.5f32)); LengthOrPercentageOrAutoOrContent::Percentage(Percentage(0.5f32));
properties.push(PropertyDeclaration::FlexGrow(grow)); properties.push(PropertyDeclaration::FlexGrow(grow));
properties.push(PropertyDeclaration::FlexShrink(shrink)); properties.push(PropertyDeclaration::FlexShrink(shrink));