mirror of
https://github.com/servo/servo.git
synced 2025-08-04 21:20:23 +01:00
Auto merge of #16144 - emilio:number-calc, r=heycam
style: Make numbers keep track of whether they were specified as calc(). Fixes #15960 <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/16144) <!-- Reviewable:end -->
This commit is contained in:
commit
b6bc49225e
28 changed files with 778 additions and 319 deletions
|
@ -200,7 +200,7 @@ impl ToFilterOps for filter::T {
|
|||
Filter::Brightness(amount) => result.push(webrender_traits::FilterOp::Brightness(amount)),
|
||||
Filter::Contrast(amount) => result.push(webrender_traits::FilterOp::Contrast(amount)),
|
||||
Filter::Grayscale(amount) => result.push(webrender_traits::FilterOp::Grayscale(amount)),
|
||||
Filter::HueRotate(angle) => result.push(webrender_traits::FilterOp::HueRotate(angle.0)),
|
||||
Filter::HueRotate(angle) => result.push(webrender_traits::FilterOp::HueRotate(angle.radians())),
|
||||
Filter::Invert(amount) => result.push(webrender_traits::FilterOp::Invert(amount)),
|
||||
Filter::Opacity(amount) => result.push(webrender_traits::FilterOp::Opacity(amount.into())),
|
||||
Filter::Saturate(amount) => result.push(webrender_traits::FilterOp::Saturate(amount)),
|
||||
|
|
|
@ -496,8 +496,8 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
|||
shared_lock,
|
||||
PropertyDeclaration::BorderSpacing(
|
||||
Box::new(border_spacing::SpecifiedValue {
|
||||
horizontal: width_value.clone(),
|
||||
vertical: width_value,
|
||||
horizontal: width_value,
|
||||
vertical: None,
|
||||
}))));
|
||||
}
|
||||
|
||||
|
|
|
@ -343,7 +343,7 @@ impl PropertyAnimation {
|
|||
|
||||
#[inline]
|
||||
fn does_animate(&self) -> bool {
|
||||
self.property.does_animate() && self.duration != Time(0.0)
|
||||
self.property.does_animate() && self.duration.seconds() != 0.0
|
||||
}
|
||||
|
||||
/// Whether this animation has the same end value as another one.
|
||||
|
@ -681,7 +681,7 @@ pub fn update_style_for_animation(context: &SharedStyleContext,
|
|||
transition_property, name);
|
||||
match PropertyAnimation::from_transition_property(*transition_property,
|
||||
timing_function,
|
||||
Time(relative_duration as f32),
|
||||
Time::from_seconds(relative_duration as f32),
|
||||
&from_style,
|
||||
&target_style) {
|
||||
Some(property_animation) => {
|
||||
|
|
|
@ -59,13 +59,16 @@ impl From<SpecifiedTimingFunction> for nsTimingFunction {
|
|||
|
||||
match function {
|
||||
SpecifiedTimingFunction::Steps(steps, StartEnd::Start) => {
|
||||
tf.set_as_step(nsTimingFunction_Type::StepStart, steps);
|
||||
debug_assert!(steps.value() >= 0);
|
||||
tf.set_as_step(nsTimingFunction_Type::StepStart, steps.value() as u32);
|
||||
},
|
||||
SpecifiedTimingFunction::Steps(steps, StartEnd::End) => {
|
||||
tf.set_as_step(nsTimingFunction_Type::StepEnd, steps);
|
||||
debug_assert!(steps.value() >= 0);
|
||||
tf.set_as_step(nsTimingFunction_Type::StepEnd, steps.value() as u32);
|
||||
},
|
||||
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) => {
|
||||
match keyword {
|
||||
|
|
|
@ -1283,7 +1283,7 @@ fn static_assert() {
|
|||
use properties::longhands::font_size_adjust::computed_value::T;
|
||||
match v {
|
||||
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 {
|
||||
use properties::longhands::font_size_adjust::computed_value::T;
|
||||
use values::specified::Number;
|
||||
|
||||
match self.gecko.mFont.sizeAdjust {
|
||||
-1.0 => T::None,
|
||||
_ => T::Number(Number(self.gecko.mFont.sizeAdjust)),
|
||||
_ => T::Number(self.gecko.mFont.sizeAdjust),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1356,8 +1355,8 @@ fn static_assert() {
|
|||
#[allow(non_snake_case)]
|
||||
pub fn ${type}_${ident}_at(&self, index: usize)
|
||||
-> longhands::${type}_${ident}::computed_value::SingleComputedValue {
|
||||
use values::specified::Time;
|
||||
Time(self.gecko.m${type.capitalize()}s[index].m${gecko_ffi_name} / 1000.)
|
||||
use values::computed::Time;
|
||||
Time::from_seconds(self.gecko.m${type.capitalize()}s[index].m${gecko_ffi_name} / 1000.)
|
||||
}
|
||||
${impl_animation_or_transition_count(type, ident, gecko_ffi_name)}
|
||||
${impl_copy_animation_or_transition_value(type, ident, gecko_ffi_name)}
|
||||
|
@ -1665,7 +1664,7 @@ fn static_assert() {
|
|||
"length" : "bindings::Gecko_CSSValue_SetAbsoluteLength(%s, %s.0)",
|
||||
"percentage" : "bindings::Gecko_CSSValue_SetPercentage(%s, %s)",
|
||||
"lop" : "%s.set_lop(%s)",
|
||||
"angle" : "bindings::Gecko_CSSValue_SetAngle(%s, %s.0)",
|
||||
"angle" : "bindings::Gecko_CSSValue_SetAngle(%s, %s.radians())",
|
||||
"number" : "bindings::Gecko_CSSValue_SetNumber(%s, %s)",
|
||||
}
|
||||
%>
|
||||
|
@ -1739,7 +1738,7 @@ fn static_assert() {
|
|||
css_value_getters = {
|
||||
"length" : "Au(bindings::Gecko_CSSValue_GetAbsoluteLength(%s))",
|
||||
"lop" : "%s.get_lop()",
|
||||
"angle" : "Angle(bindings::Gecko_CSSValue_GetAngle(%s))",
|
||||
"angle" : "Angle::from_radians(bindings::Gecko_CSSValue_GetAngle(%s))",
|
||||
"number" : "bindings::Gecko_CSSValue_GetNumber(%s)",
|
||||
}
|
||||
%>
|
||||
|
|
|
@ -19,7 +19,9 @@
|
|||
#[inline] pub fn get_initial_specified_value() -> SpecifiedValue { ${initial_specified_value} }
|
||||
% endif
|
||||
#[allow(unused_variables)]
|
||||
#[inline] pub fn parse(context: &ParserContext, input: &mut Parser)
|
||||
#[inline]
|
||||
pub fn parse(context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<SpecifiedValue, ()> {
|
||||
% if needs_context:
|
||||
specified::${type}::${parse_method}(context, input)
|
||||
|
|
|
@ -36,7 +36,6 @@ use values::computed::{CalcLengthOrPercentage, Context, LengthOrPercentage};
|
|||
use values::computed::{MaxLength, MinLength};
|
||||
use values::computed::position::{HorizontalPosition, Position, VerticalPosition};
|
||||
use values::computed::ToComputedValue;
|
||||
use values::specified::Angle as SpecifiedAngle;
|
||||
|
||||
|
||||
|
||||
|
@ -455,7 +454,7 @@ impl Interpolate for i32 {
|
|||
impl Interpolate for Angle {
|
||||
#[inline]
|
||||
fn interpolate(&self, other: &Angle, progress: f64) -> Result<Self, ()> {
|
||||
self.radians().interpolate(&other.radians(), progress).map(Angle)
|
||||
self.radians().interpolate(&other.radians(), progress).map(Angle::from_radians)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -952,7 +951,7 @@ fn build_identity_transform_list(list: &[TransformOperation]) -> Vec<TransformOp
|
|||
result.push(TransformOperation::Matrix(identity));
|
||||
}
|
||||
TransformOperation::Skew(..) => {
|
||||
result.push(TransformOperation::Skew(Angle(0.0), Angle(0.0)));
|
||||
result.push(TransformOperation::Skew(Angle::zero(), Angle::zero()))
|
||||
}
|
||||
TransformOperation::Translate(..) => {
|
||||
result.push(TransformOperation::Translate(LengthOrPercentage::zero(),
|
||||
|
@ -963,7 +962,7 @@ fn build_identity_transform_list(list: &[TransformOperation]) -> Vec<TransformOp
|
|||
result.push(TransformOperation::Scale(1.0, 1.0, 1.0));
|
||||
}
|
||||
TransformOperation::Rotate(..) => {
|
||||
result.push(TransformOperation::Rotate(0.0, 0.0, 1.0, Angle(0.0)));
|
||||
result.push(TransformOperation::Rotate(0.0, 0.0, 1.0, Angle::zero()));
|
||||
}
|
||||
TransformOperation::Perspective(..) => {
|
||||
// http://dev.w3.org/csswg/css-transforms/#identity-transform-function
|
||||
|
@ -1052,7 +1051,7 @@ fn interpolate_transform_list(from_list: &[TransformOperation],
|
|||
}
|
||||
|
||||
/// https://drafts.csswg.org/css-transforms/#Rotate3dDefined
|
||||
fn rotate_to_matrix(x: f32, y: f32, z: f32, a: SpecifiedAngle) -> ComputedMatrix {
|
||||
fn rotate_to_matrix(x: f32, y: f32, z: f32, a: Angle) -> ComputedMatrix {
|
||||
let half_rad = a.radians() / 2.0;
|
||||
let sc = (half_rad).sin() * (half_rad).cos();
|
||||
let sq = (half_rad).sin().powi(2);
|
||||
|
|
|
@ -223,7 +223,7 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
|
|||
|
||||
#[inline]
|
||||
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 {
|
||||
|
@ -486,7 +486,7 @@ ${helpers.single_keyword("-moz-float-edge", "content-box margin-box",
|
|||
|
||||
#[inline]
|
||||
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 {
|
||||
|
|
|
@ -419,13 +419,13 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> Time {
|
||||
Time(0.0)
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T::zero()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_specified_value() -> SpecifiedValue {
|
||||
SpecifiedValue(0.0)
|
||||
Time::zero()
|
||||
}
|
||||
|
||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
|
@ -440,7 +440,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
extra_prefixes="moz webkit"
|
||||
spec="https://drafts.csswg.org/css-transitions/#propdef-transition-timing-function">
|
||||
use self::computed_value::StartEnd;
|
||||
|
||||
use values::specified::Number;
|
||||
use euclid::point::{Point2D, TypedPoint2D};
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
|
@ -487,6 +487,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
use parser::{Parse, ParserContext};
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::specified;
|
||||
|
||||
pub use super::parse;
|
||||
|
||||
|
@ -498,7 +499,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
}
|
||||
|
||||
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 {
|
||||
T::CubicBezier(p1, p2) => {
|
||||
try!(dest.write_str("cubic-bezier("));
|
||||
|
@ -512,7 +515,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
dest.write_str(")")
|
||||
}
|
||||
T::Steps(steps, start_end) => {
|
||||
super::serialize_steps(dest, steps, start_end)
|
||||
super::serialize_steps(dest, specified::Integer::new(steps as i32), start_end)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -526,7 +529,9 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
}
|
||||
|
||||
impl ToCss for StartEnd {
|
||||
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 {
|
||||
StartEnd::Start => dest.write_str("start"),
|
||||
StartEnd::End => dest.write_str("end"),
|
||||
|
@ -547,8 +552,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum SpecifiedValue {
|
||||
CubicBezier(Point2D<f32>, Point2D<f32>),
|
||||
Steps(u32, StartEnd),
|
||||
CubicBezier(Point2D<Number>, Point2D<Number>),
|
||||
Steps(specified::Integer, StartEnd),
|
||||
Keyword(FunctionKeyword),
|
||||
}
|
||||
|
||||
|
@ -557,7 +562,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
if let Ok(function_name) = input.try(|input| input.expect_function()) {
|
||||
return match_ignore_ascii_case! { &function_name,
|
||||
"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| {
|
||||
p1x = try!(specified::parse_number(input));
|
||||
try!(input.expect_comma());
|
||||
|
@ -568,7 +574,8 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
p2y = try!(specified::parse_number(input));
|
||||
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(())
|
||||
}
|
||||
|
||||
|
@ -576,10 +583,10 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
Ok(SpecifiedValue::CubicBezier(p1, p2))
|
||||
},
|
||||
"steps" => {
|
||||
let (mut step_count, mut start_end) = (0, StartEnd::End);
|
||||
let (mut step_count, mut start_end) = (specified::Integer::new(0), StartEnd::End);
|
||||
try!(input.parse_nested_block(|input| {
|
||||
step_count = try!(specified::parse_integer(input));
|
||||
if step_count < 1 {
|
||||
if step_count.value() < 1 {
|
||||
return Err(())
|
||||
}
|
||||
|
||||
|
@ -593,7 +600,7 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
}
|
||||
Ok(())
|
||||
}));
|
||||
Ok(SpecifiedValue::Steps(step_count as u32, start_end))
|
||||
Ok(SpecifiedValue::Steps(step_count, start_end))
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
|
@ -602,8 +609,11 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
}
|
||||
}
|
||||
|
||||
fn serialize_steps<W>(dest: &mut W, steps: u32,
|
||||
start_end: StartEnd) -> fmt::Result where W: fmt::Write {
|
||||
fn serialize_steps<W>(dest: &mut W,
|
||||
steps: specified::Integer,
|
||||
start_end: StartEnd) -> fmt::Result
|
||||
where W: fmt::Write,
|
||||
{
|
||||
try!(dest.write_str("steps("));
|
||||
try!(steps.to_css(dest));
|
||||
if let StartEnd::Start = start_end {
|
||||
|
@ -633,10 +643,10 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
SpecifiedValue::Keyword(keyword) => {
|
||||
match keyword {
|
||||
FunctionKeyword::StepStart => {
|
||||
serialize_steps(dest, 1, StartEnd::Start)
|
||||
serialize_steps(dest, specified::Integer::new(1), StartEnd::Start)
|
||||
},
|
||||
FunctionKeyword::StepEnd => {
|
||||
serialize_steps(dest, 1, StartEnd::End)
|
||||
serialize_steps(dest, specified::Integer::new(1), StartEnd::End)
|
||||
},
|
||||
_ => {
|
||||
keyword.to_css(dest)
|
||||
|
@ -651,13 +661,15 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _context: &Context) -> computed_value::T {
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
match *self {
|
||||
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) => {
|
||||
computed_value::T::Steps(count, start_end)
|
||||
computed_value::T::Steps(count.to_computed_value(context) as u32, start_end)
|
||||
},
|
||||
SpecifiedValue::Keyword(keyword) => {
|
||||
match keyword {
|
||||
|
@ -676,10 +688,15 @@ ${helpers.single_keyword("overflow-x", "visible hidden scroll auto",
|
|||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
match *computed {
|
||||
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) => {
|
||||
SpecifiedValue::Steps(count, start_end)
|
||||
let int_count = count as i32;
|
||||
SpecifiedValue::Steps(specified::Integer::from_computed_value(&int_count), start_end)
|
||||
},
|
||||
}
|
||||
}
|
||||
|
@ -1083,6 +1100,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
fixpos_cb="True"
|
||||
spec="https://drafts.csswg.org/css-transforms/#propdef-transform">
|
||||
use app_units::Au;
|
||||
use values::specified::Number;
|
||||
use style_traits::ToCss;
|
||||
use values::CSSFloat;
|
||||
use values::HasViewportPercentage;
|
||||
|
@ -1131,7 +1149,60 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
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)
|
||||
-> Result<(specified::LengthOrPercentage,
|
||||
|
@ -1144,7 +1215,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
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 second = input.try(|input| {
|
||||
try!(input.expect_comma());
|
||||
|
@ -1159,7 +1230,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
let second = input.try(|input| {
|
||||
try!(input.expect_comma());
|
||||
specified::Angle::parse(context, input)
|
||||
}).unwrap_or(specified::Angle(0.0));
|
||||
}).unwrap_or(specified::Angle::zero());
|
||||
Ok((first, second))
|
||||
}
|
||||
|
||||
|
@ -1182,8 +1253,8 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
specified::LengthOrPercentage,
|
||||
specified::LengthOrPercentage,
|
||||
specified::Length),
|
||||
Scale(CSSFloat, CSSFloat, CSSFloat),
|
||||
Rotate(CSSFloat, CSSFloat, CSSFloat, specified::Angle),
|
||||
Scale(Number, Number, Number),
|
||||
Rotate(Number, Number, Number, specified::Angle),
|
||||
Perspective(specified::Length),
|
||||
}
|
||||
|
||||
|
@ -1323,21 +1394,19 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
if values.len() != 6 {
|
||||
return Err(())
|
||||
}
|
||||
result.push(SpecifiedOperation::Matrix(
|
||||
SpecifiedMatrix {
|
||||
m11: values[0], m12: values[1], m13: 0.0, m14: 0.0,
|
||||
m21: values[2], m22: values[3], m23: 0.0, m24: 0.0,
|
||||
m31: 0.0, m32: 0.0, m33: 1.0, m34: 0.0,
|
||||
m41: values[4], m42: values[5], m43: 0.0, m44: 1.0
|
||||
}));
|
||||
let matrix = SpecifiedMatrix {
|
||||
m11: values[0], m12: values[1], m13: Number::new(0.0), m14: Number::new(0.0),
|
||||
m21: values[2], m22: values[3], m23: Number::new(0.0), m24: Number::new(0.0),
|
||||
m31: Number::new(0.0), m32: Number::new(0.0), m33: Number::new(1.0), m34: Number::new(0.0),
|
||||
m41: values[4], m42: values[5], m43: Number::new(0.0), m44: Number::new(1.0),
|
||||
};
|
||||
result.push(SpecifiedOperation::Matrix(matrix));
|
||||
Ok(())
|
||||
}))
|
||||
},
|
||||
"matrix3d" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let values = try!(input.parse_comma_separated(|input| {
|
||||
specified::parse_number(input)
|
||||
}));
|
||||
let values = try!(input.parse_comma_separated(specified::parse_number));
|
||||
if values.len() != 16 {
|
||||
return Err(())
|
||||
}
|
||||
|
@ -1412,29 +1481,37 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
},
|
||||
"scale" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let (sx, sy) = try!(parse_two_floats(input));
|
||||
result.push(SpecifiedOperation::Scale(sx, sy, 1.0));
|
||||
let (sx, sy) = try!(parse_two_numbers(input));
|
||||
result.push(SpecifiedOperation::Scale(sx,
|
||||
sy,
|
||||
Number::new(1.0)));
|
||||
Ok(())
|
||||
}))
|
||||
},
|
||||
"scalex" => {
|
||||
try!(input.parse_nested_block(|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(())
|
||||
}))
|
||||
},
|
||||
"scaley" => {
|
||||
try!(input.parse_nested_block(|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(())
|
||||
}))
|
||||
},
|
||||
"scalez" => {
|
||||
try!(input.parse_nested_block(|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(())
|
||||
}))
|
||||
},
|
||||
|
@ -1452,28 +1529,40 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
"rotate" => {
|
||||
try!(input.parse_nested_block(|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(())
|
||||
}))
|
||||
},
|
||||
"rotatex" => {
|
||||
try!(input.parse_nested_block(|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(())
|
||||
}))
|
||||
},
|
||||
"rotatey" => {
|
||||
try!(input.parse_nested_block(|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(())
|
||||
}))
|
||||
},
|
||||
"rotatez" => {
|
||||
try!(input.parse_nested_block(|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(())
|
||||
}))
|
||||
},
|
||||
|
@ -1501,14 +1590,14 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
"skewx" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let theta_x = try!(specified::Angle::parse(context,input));
|
||||
result.push(SpecifiedOperation::Skew(theta_x, specified::Angle(0.0)));
|
||||
result.push(SpecifiedOperation::Skew(theta_x, specified::Angle::zero()));
|
||||
Ok(())
|
||||
}))
|
||||
},
|
||||
"skewy" => {
|
||||
try!(input.parse_nested_block(|input| {
|
||||
let theta_y = try!(specified::Angle::parse(context,input));
|
||||
result.push(SpecifiedOperation::Skew(specified::Angle(0.0), theta_y));
|
||||
result.push(SpecifiedOperation::Skew(specified::Angle::zero(), theta_y));
|
||||
Ok(())
|
||||
}))
|
||||
},
|
||||
|
@ -1543,7 +1632,7 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
for operation in &self.0 {
|
||||
match *operation {
|
||||
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) => {
|
||||
result.push(computed_value::ComputedOperation::Translate(tx.to_computed_value(context),
|
||||
|
@ -1551,14 +1640,22 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
tz.to_computed_value(context)));
|
||||
}
|
||||
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));
|
||||
}
|
||||
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 theta = theta.to_computed_value(context);
|
||||
let len = (ax * ax + ay * ay + az * az).sqrt();
|
||||
result.push(computed_value::ComputedOperation::Rotate(ax / len, ay / len, az / len, theta));
|
||||
}
|
||||
SpecifiedOperation::Skew(theta_x, theta_y) => {
|
||||
result.push(computed_value::ComputedOperation::Skew(theta_x, theta_y));
|
||||
result.push(computed_value::ComputedOperation::Skew(theta_x.to_computed_value(context),
|
||||
theta_y.to_computed_value(context)));
|
||||
}
|
||||
SpecifiedOperation::Perspective(ref d) => {
|
||||
result.push(computed_value::ComputedOperation::Perspective(d.to_computed_value(context)));
|
||||
|
@ -1572,11 +1669,11 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
#[inline]
|
||||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
SpecifiedValue(computed.0.as_ref().map(|computed| {
|
||||
let mut result = vec!();
|
||||
let mut result = vec![];
|
||||
for operation in computed {
|
||||
match *operation {
|
||||
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) => {
|
||||
// XXXManishearth we lose information here; perhaps we should try to
|
||||
|
@ -1586,14 +1683,23 @@ ${helpers.predefined_type("scroll-snap-coordinate",
|
|||
ToComputedValue::from_computed_value(ty),
|
||||
ToComputedValue::from_computed_value(tz)));
|
||||
}
|
||||
computed_value::ComputedOperation::Scale(sx, sy, sz) => {
|
||||
result.push(SpecifiedOperation::Scale(sx, sy, sz));
|
||||
computed_value::ComputedOperation::Scale(ref sx, ref sy, ref 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) => {
|
||||
result.push(SpecifiedOperation::Rotate(ax, ay, az, theta));
|
||||
computed_value::ComputedOperation::Rotate(ref ax, ref ay, ref az, ref theta) => {
|
||||
result.push(SpecifiedOperation::Rotate(
|
||||
Number::from_computed_value(ax),
|
||||
Number::from_computed_value(ay),
|
||||
Number::from_computed_value(az),
|
||||
specified::Angle::from_computed_value(theta)));
|
||||
}
|
||||
computed_value::ComputedOperation::Skew(theta_x, theta_y) => {
|
||||
result.push(SpecifiedOperation::Skew(theta_x, theta_y));
|
||||
computed_value::ComputedOperation::Skew(ref theta_x, ref theta_y) => {
|
||||
result.push(SpecifiedOperation::Skew(
|
||||
specified::Angle::from_computed_value(theta_x),
|
||||
specified::Angle::from_computed_value(theta_y)))
|
||||
}
|
||||
computed_value::ComputedOperation::Perspective(ref d) => {
|
||||
result.push(SpecifiedOperation::Perspective(
|
||||
|
|
|
@ -246,31 +246,28 @@
|
|||
use style_traits::ToCss;
|
||||
use super::content;
|
||||
use values::HasViewportPercentage;
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
|
||||
use cssparser::{Token, serialize_identifier};
|
||||
use std::borrow::{Cow, ToOwned};
|
||||
|
||||
pub use self::computed_value::T as SpecifiedValue;
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
pub struct SpecifiedValue(pub Vec<(String, specified::Integer)>);
|
||||
|
||||
pub mod computed_value {
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
|
||||
#[derive(Debug, Clone, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct T(pub Vec<(String,i32)>);
|
||||
}
|
||||
pub struct T(pub Vec<(String, i32)>);
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T(Vec::new())
|
||||
}
|
||||
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
no_viewport_percentage!(SpecifiedValue);
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
impl ToCss for T {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write,
|
||||
{
|
||||
use cssparser::serialize_identifier;
|
||||
if self.0.is_empty() {
|
||||
return dest.write_str("none");
|
||||
return dest.write_str("none")
|
||||
}
|
||||
|
||||
let mut first = true;
|
||||
|
@ -280,18 +277,64 @@
|
|||
}
|
||||
first = false;
|
||||
try!(serialize_identifier(&pair.0, dest));
|
||||
try!(write!(dest, " {}", pair.1));
|
||||
try!(dest.write_str(" "));
|
||||
try!(pair.1.to_css(dest));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
fn to_computed_value(&self, context: &Context) -> Self::ComputedValue {
|
||||
computed_value::T(self.0.iter().map(|entry| {
|
||||
(entry.0.clone(), entry.1.to_computed_value(context))
|
||||
}).collect::<Vec<_>>())
|
||||
}
|
||||
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
SpecifiedValue(computed.0.iter().map(|entry| {
|
||||
(entry.0.clone(), specified::Integer::from_computed_value(&entry.1))
|
||||
}).collect::<Vec<_>>())
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T(Vec::new())
|
||||
}
|
||||
|
||||
no_viewport_percentage!(SpecifiedValue);
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write,
|
||||
{
|
||||
if self.0.is_empty() {
|
||||
return dest.write_str("none");
|
||||
}
|
||||
let mut first = true;
|
||||
for pair in &self.0 {
|
||||
if !first {
|
||||
try!(dest.write_str(" "));
|
||||
}
|
||||
first = false;
|
||||
try!(serialize_identifier(&pair.0, dest));
|
||||
try!(dest.write_str(" "));
|
||||
try!(pair.1.to_css(dest));
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
parse_common(1, input)
|
||||
}
|
||||
|
||||
pub fn parse_common(default_value: i32, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
pub fn parse_common(default_value: i32, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(SpecifiedValue(Vec::new()))
|
||||
}
|
||||
|
@ -307,7 +350,7 @@
|
|||
return Err(())
|
||||
}
|
||||
let counter_delta =
|
||||
input.try(|input| specified::parse_integer(input)).unwrap_or(default_value);
|
||||
input.try(|input| specified::parse_integer(input)).unwrap_or(specified::Integer::new(default_value));
|
||||
counters.push((counter_name, counter_delta))
|
||||
}
|
||||
|
||||
|
@ -322,7 +365,7 @@
|
|||
<%helpers:longhand name="counter-reset" animatable="False"
|
||||
spec="https://drafts.csswg.org/css-lists-3/#propdef-counter-reset">
|
||||
pub use super::counter_increment::{SpecifiedValue, computed_value, get_initial_value};
|
||||
use super::counter_increment::{parse_common};
|
||||
use super::counter_increment::parse_common;
|
||||
|
||||
pub fn parse(_: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||
parse_common(0, input)
|
||||
|
|
|
@ -655,30 +655,65 @@ ${helpers.single_keyword("font-variant-caps",
|
|||
|
||||
<%helpers:longhand products="gecko" name="font-size-adjust" animatable="True"
|
||||
spec="https://drafts.csswg.org/css-fonts/#propdef-font-size-adjust">
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::HasViewportPercentage;
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
use values::specified::Number;
|
||||
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
no_viewport_percentage!(SpecifiedValue);
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub enum SpecifiedValue {
|
||||
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 {
|
||||
use style_traits::ToCss;
|
||||
use std::fmt;
|
||||
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 {
|
||||
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 {
|
||||
T::None => dest.write_str("none"),
|
||||
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, ()> {
|
||||
match (*self, *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(()),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[inline] pub fn get_initial_value() -> computed_value::T {
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T::None
|
||||
}
|
||||
|
||||
|
|
|
@ -96,7 +96,7 @@ ${helpers.single_keyword("image-rendering",
|
|||
|
||||
use std::f32::consts::PI;
|
||||
use values::CSSFloat;
|
||||
const TWO_PI: CSSFloat = 2.0*PI;
|
||||
const TWO_PI: CSSFloat = 2.0 * PI;
|
||||
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
@ -125,7 +125,7 @@ ${helpers.single_keyword("image-rendering",
|
|||
}
|
||||
|
||||
pub mod computed_value {
|
||||
use values::specified::Angle;
|
||||
use values::computed::Angle;
|
||||
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
|
@ -135,36 +135,35 @@ ${helpers.single_keyword("image-rendering",
|
|||
}
|
||||
}
|
||||
|
||||
const INITIAL_ANGLE: Angle = Angle(0.0);
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
computed_value::T::AngleWithFlipped(INITIAL_ANGLE, false)
|
||||
computed_value::T::AngleWithFlipped(computed::Angle::zero(), false)
|
||||
}
|
||||
|
||||
// According to CSS Content Module Level 3:
|
||||
// The computed value of the property is calculated by rounding the specified angle
|
||||
// to the nearest quarter-turn, rounding away from 0, then moduloing the value by 1 turn.
|
||||
#[inline]
|
||||
fn normalize_angle(angle: &Angle) -> Angle {
|
||||
fn normalize_angle(angle: &computed::Angle) -> computed::Angle {
|
||||
let radians = angle.radians();
|
||||
let rounded_quarter_turns = (4.0 * radians / TWO_PI).round();
|
||||
let normalized_quarter_turns = (rounded_quarter_turns % 4.0 + 4.0) % 4.0;
|
||||
let normalized_radians = normalized_quarter_turns/4.0 * TWO_PI;
|
||||
Angle::from_radians(normalized_radians)
|
||||
computed::Angle::from_radians(normalized_radians)
|
||||
}
|
||||
|
||||
impl ToComputedValue for SpecifiedValue {
|
||||
type ComputedValue = computed_value::T;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> computed_value::T {
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
if let Some(ref angle) = self.angle {
|
||||
let normalized_angle = normalize_angle(angle);
|
||||
let angle = angle.to_computed_value(context);
|
||||
let normalized_angle = normalize_angle(&angle);
|
||||
computed_value::T::AngleWithFlipped(normalized_angle, self.flipped)
|
||||
} else {
|
||||
if self.flipped {
|
||||
computed_value::T::AngleWithFlipped(INITIAL_ANGLE, true)
|
||||
computed_value::T::AngleWithFlipped(computed::Angle::zero(), true)
|
||||
} else {
|
||||
computed_value::T::FromImage
|
||||
}
|
||||
|
@ -175,8 +174,12 @@ ${helpers.single_keyword("image-rendering",
|
|||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
match *computed {
|
||||
computed_value::T::FromImage => SpecifiedValue { angle: None, flipped: false },
|
||||
computed_value::T::AngleWithFlipped(angle, flipped) =>
|
||||
SpecifiedValue { angle: Some(angle), flipped: flipped },
|
||||
computed_value::T::AngleWithFlipped(ref angle, flipped) => {
|
||||
SpecifiedValue {
|
||||
angle: Some(Angle::from_computed_value(angle)),
|
||||
flipped: flipped,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -205,7 +208,7 @@ ${helpers.single_keyword("image-rendering",
|
|||
let angle = input.try(|input| Angle::parse(context, input)).ok();
|
||||
let flipped = input.try(|input| input.expect_ident_matching("flip")).is_ok();
|
||||
let explicit_angle = if angle.is_none() && !flipped {
|
||||
Some(INITIAL_ANGLE)
|
||||
Some(Angle::zero())
|
||||
} else {
|
||||
angle
|
||||
};
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||
<%namespace name="helpers" file="/helpers.mako.rs" />
|
||||
|
||||
<% data.new_style_struct("InheritedTable", inherited=True, gecko_name="TableBorder") %>
|
||||
|
||||
|
@ -52,7 +52,8 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
|||
|
||||
impl HasViewportPercentage for SpecifiedValue {
|
||||
fn has_viewport_percentage(&self) -> bool {
|
||||
return self.horizontal.has_viewport_percentage() || self.vertical.has_viewport_percentage()
|
||||
self.horizontal.has_viewport_percentage() ||
|
||||
self.vertical.as_ref().map_or(false, |v| v.has_viewport_percentage())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -60,7 +61,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
|||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct SpecifiedValue {
|
||||
pub horizontal: specified::Length,
|
||||
pub vertical: specified::Length,
|
||||
pub vertical: Option<specified::Length>,
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -72,10 +73,15 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
|||
}
|
||||
|
||||
impl ToCss for SpecifiedValue {
|
||||
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,
|
||||
{
|
||||
try!(self.horizontal.to_css(dest));
|
||||
if let Some(vertical) = self.vertical.as_ref() {
|
||||
try!(dest.write_str(" "));
|
||||
self.vertical.to_css(dest)
|
||||
vertical.to_css(dest)?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -92,9 +98,10 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
|||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, context: &Context) -> computed_value::T {
|
||||
let horizontal = self.horizontal.to_computed_value(context);
|
||||
computed_value::T {
|
||||
horizontal: self.horizontal.to_computed_value(context),
|
||||
vertical: self.vertical.to_computed_value(context),
|
||||
horizontal: horizontal,
|
||||
vertical: self.vertical.as_ref().map_or(horizontal, |v| v.to_computed_value(context)),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,7 +109,7 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
|||
fn from_computed_value(computed: &computed_value::T) -> Self {
|
||||
SpecifiedValue {
|
||||
horizontal: ToComputedValue::from_computed_value(&computed.horizontal),
|
||||
vertical: ToComputedValue::from_computed_value(&computed.vertical),
|
||||
vertical: Some(ToComputedValue::from_computed_value(&computed.vertical)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -123,17 +130,17 @@ ${helpers.single_keyword("caption-side", "top bottom",
|
|||
(None, None) => Err(()),
|
||||
(Some(length), None) => {
|
||||
Ok(SpecifiedValue {
|
||||
horizontal: length.clone(),
|
||||
vertical: length,
|
||||
horizontal: length,
|
||||
vertical: None,
|
||||
})
|
||||
}
|
||||
(Some(horizontal), Some(vertical)) => {
|
||||
Ok(SpecifiedValue {
|
||||
horizontal: horizontal,
|
||||
vertical: vertical,
|
||||
vertical: Some(vertical),
|
||||
})
|
||||
}
|
||||
(None, Some(_)) => panic!("shouldn't happen"),
|
||||
(None, Some(_)) => unreachable!(),
|
||||
}
|
||||
}
|
||||
</%helpers:longhand>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
spec="https://drafts.csswg.org/css2/visudet.html#propdef-line-height">
|
||||
use std::fmt;
|
||||
use style_traits::ToCss;
|
||||
use values::{CSSFloat, HasViewportPercentage};
|
||||
use values::HasViewportPercentage;
|
||||
|
||||
impl HasViewportPercentage for SpecifiedValue {
|
||||
fn has_viewport_percentage(&self) -> bool {
|
||||
|
@ -28,7 +28,7 @@
|
|||
% if product == "gecko":
|
||||
MozBlockHeight,
|
||||
% endif
|
||||
Number(CSSFloat),
|
||||
Number(specified::Number),
|
||||
LengthOrPercentage(specified::LengthOrPercentage),
|
||||
}
|
||||
|
||||
|
@ -40,7 +40,7 @@
|
|||
SpecifiedValue::MozBlockHeight => dest.write_str("-moz-block-height"),
|
||||
% endif
|
||||
SpecifiedValue::LengthOrPercentage(ref value) => value.to_css(dest),
|
||||
SpecifiedValue::Number(number) => write!(dest, "{}", number),
|
||||
SpecifiedValue::Number(number) => number.to_css(dest),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -52,7 +52,7 @@
|
|||
// parsed as a plain Number rather than a Length (0px); this matches the behaviour
|
||||
// of all major browsers
|
||||
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)
|
||||
|
@ -116,7 +116,7 @@
|
|||
% if product == "gecko":
|
||||
SpecifiedValue::MozBlockHeight => computed_value::T::MozBlockHeight,
|
||||
% 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) => {
|
||||
match *value {
|
||||
specified::LengthOrPercentage::Length(ref value) =>
|
||||
|
@ -144,7 +144,9 @@
|
|||
% if product == "gecko":
|
||||
computed_value::T::MozBlockHeight => SpecifiedValue::MozBlockHeight,
|
||||
% 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) => {
|
||||
SpecifiedValue::LengthOrPercentage(specified::LengthOrPercentage::Length(
|
||||
ToComputedValue::from_computed_value(&au)
|
||||
|
|
|
@ -130,27 +130,9 @@ ${helpers.predefined_type("flex-shrink", "Number",
|
|||
% endif
|
||||
|
||||
// https://drafts.csswg.org/css-flexbox/#propdef-order
|
||||
<%helpers:longhand name="order" animatable="True" extra_prefixes="webkit"
|
||||
spec="https://drafts.csswg.org/css-flexbox/#order-property">
|
||||
use values::computed::ComputedValueAsSpecified;
|
||||
|
||||
impl ComputedValueAsSpecified for SpecifiedValue {}
|
||||
|
||||
pub type SpecifiedValue = computed_value::T;
|
||||
|
||||
pub mod computed_value {
|
||||
pub type T = i32;
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn get_initial_value() -> computed_value::T {
|
||||
0
|
||||
}
|
||||
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||
specified::parse_integer(input)
|
||||
}
|
||||
</%helpers:longhand>
|
||||
${helpers.predefined_type("order", "Integer", "0",
|
||||
animatable=True,
|
||||
spec="https://drafts.csswg.org/css-flexbox/#order-property")}
|
||||
|
||||
// FIXME: Gecko doesn't support content value yet.
|
||||
// FIXME: This property should be animatable.
|
||||
|
|
|
@ -70,8 +70,8 @@
|
|||
|
||||
if input.try(|input| input.expect_ident_matching("none")).is_ok() {
|
||||
return Ok(Longhands {
|
||||
flex_grow: Number(0.0),
|
||||
flex_shrink: Number(0.0),
|
||||
flex_grow: Number::new(0.0),
|
||||
flex_shrink: Number::new(0.0),
|
||||
% if product == "gecko":
|
||||
flex_basis: LengthOrPercentageOrAuto::Auto
|
||||
% else:
|
||||
|
@ -105,8 +105,8 @@
|
|||
return Err(())
|
||||
}
|
||||
Ok(Longhands {
|
||||
flex_grow: grow.unwrap_or(Number(1.0)),
|
||||
flex_shrink: shrink.unwrap_or(Number(1.0)),
|
||||
flex_grow: grow.unwrap_or(Number::new(1.0)),
|
||||
flex_shrink: shrink.unwrap_or(Number::new(1.0)),
|
||||
% if product == "gecko":
|
||||
flex_basis: basis.unwrap_or(LengthOrPercentageOrAuto::Length(NoCalcLength::zero()))
|
||||
% else:
|
||||
|
|
|
@ -537,27 +537,27 @@ impl ToComputedValue for specified::AngleOrCorner {
|
|||
type ComputedValue = AngleOrCorner;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> AngleOrCorner {
|
||||
fn to_computed_value(&self, context: &Context) -> AngleOrCorner {
|
||||
match *self {
|
||||
specified::AngleOrCorner::None => {
|
||||
AngleOrCorner::Angle(Angle(PI))
|
||||
AngleOrCorner::Angle(Angle::from_radians(PI))
|
||||
},
|
||||
specified::AngleOrCorner::Angle(angle) => {
|
||||
AngleOrCorner::Angle(angle)
|
||||
AngleOrCorner::Angle(angle.to_computed_value(context))
|
||||
},
|
||||
specified::AngleOrCorner::Corner(horizontal, vertical) => {
|
||||
match (horizontal, vertical) {
|
||||
(None, Some(VerticalDirection::Top)) => {
|
||||
AngleOrCorner::Angle(Angle(0.0))
|
||||
AngleOrCorner::Angle(Angle::from_radians(0.0))
|
||||
},
|
||||
(Some(HorizontalDirection::Right), None) => {
|
||||
AngleOrCorner::Angle(Angle(PI * 0.5))
|
||||
AngleOrCorner::Angle(Angle::from_radians(PI * 0.5))
|
||||
},
|
||||
(None, Some(VerticalDirection::Bottom)) => {
|
||||
AngleOrCorner::Angle(Angle(PI))
|
||||
AngleOrCorner::Angle(Angle::from_radians(PI))
|
||||
},
|
||||
(Some(HorizontalDirection::Left), None) => {
|
||||
AngleOrCorner::Angle(Angle(PI * 1.5))
|
||||
AngleOrCorner::Angle(Angle::from_radians(PI * 1.5))
|
||||
},
|
||||
(Some(horizontal), Some(vertical)) => {
|
||||
AngleOrCorner::Corner(horizontal, vertical)
|
||||
|
@ -573,8 +573,8 @@ impl ToComputedValue for specified::AngleOrCorner {
|
|||
#[inline]
|
||||
fn from_computed_value(computed: &AngleOrCorner) -> Self {
|
||||
match *computed {
|
||||
AngleOrCorner::Angle(angle) => {
|
||||
specified::AngleOrCorner::Angle(angle)
|
||||
AngleOrCorner::Angle(ref angle) => {
|
||||
specified::AngleOrCorner::Angle(specified::Angle::from_computed_value(angle))
|
||||
},
|
||||
AngleOrCorner::Corner(horizontal, vertical) => {
|
||||
specified::AngleOrCorner::Corner(Some(horizontal), Some(vertical))
|
||||
|
|
|
@ -20,7 +20,7 @@ pub use self::image::{LengthOrKeyword, LengthOrPercentageOrKeyword};
|
|||
pub use super::{Auto, Either, None_};
|
||||
#[cfg(feature = "gecko")]
|
||||
pub use super::specified::{AlignItems, AlignJustifyContent, AlignJustifySelf, JustifyItems};
|
||||
pub use super::specified::{Angle, BorderStyle, GridLine, Percentage, Time, UrlOrNone};
|
||||
pub use super::specified::{BorderStyle, GridLine, Percentage, UrlOrNone};
|
||||
pub use super::specified::url::SpecifiedUrl;
|
||||
pub use self::length::{CalcLengthOrPercentage, Length, LengthOrNumber, LengthOrPercentage, LengthOrPercentageOrAuto};
|
||||
pub use self::length::{LengthOrPercentageOrAutoOrContent, LengthOrPercentageOrNone, LengthOrNone};
|
||||
|
@ -114,6 +114,76 @@ impl<T> ToComputedValue for T
|
|||
}
|
||||
}
|
||||
|
||||
/// A computed `<angle>` value.
|
||||
#[derive(Clone, PartialEq, PartialOrd, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
|
||||
pub struct Angle {
|
||||
radians: CSSFloat,
|
||||
}
|
||||
|
||||
impl Angle {
|
||||
/// Construct a computed `Angle` value from a radian amount.
|
||||
pub fn from_radians(radians: CSSFloat) -> Self {
|
||||
Angle {
|
||||
radians: radians,
|
||||
}
|
||||
}
|
||||
|
||||
/// Return the amount of radians this angle represents.
|
||||
#[inline]
|
||||
pub fn radians(&self) -> CSSFloat {
|
||||
self.radians
|
||||
}
|
||||
|
||||
/// Returns an angle that represents a rotation of zero radians.
|
||||
pub fn zero() -> Self {
|
||||
Self::from_radians(0.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for Angle {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write,
|
||||
{
|
||||
write!(dest, "{}rad", self.radians())
|
||||
}
|
||||
}
|
||||
|
||||
/// A computed `<time>` value.
|
||||
#[derive(Clone, PartialEq, PartialOrd, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
|
||||
pub struct Time {
|
||||
seconds: CSSFloat,
|
||||
}
|
||||
|
||||
impl Time {
|
||||
/// Construct a computed `Time` value from a seconds amount.
|
||||
pub fn from_seconds(seconds: CSSFloat) -> Self {
|
||||
Time {
|
||||
seconds: seconds,
|
||||
}
|
||||
}
|
||||
|
||||
/// Construct a computed `Time` value that represents zero seconds.
|
||||
pub fn zero() -> Self {
|
||||
Self::from_seconds(0.0)
|
||||
}
|
||||
|
||||
/// Return the amount of seconds this time represents.
|
||||
#[inline]
|
||||
pub fn seconds(&self) -> CSSFloat {
|
||||
self.seconds
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for Time {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write,
|
||||
{
|
||||
write!(dest, "{}s", self.seconds())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for specified::Color {
|
||||
type ComputedValue = RGBA;
|
||||
|
||||
|
|
|
@ -507,8 +507,8 @@ pub struct CalcProductNode {
|
|||
#[allow(missing_docs)]
|
||||
pub enum CalcValueNode {
|
||||
Length(NoCalcLength),
|
||||
Angle(Angle),
|
||||
Time(Time),
|
||||
Angle(CSSFloat),
|
||||
Time(CSSFloat),
|
||||
Percentage(CSSFloat),
|
||||
Number(CSSFloat),
|
||||
Sum(Box<CalcSumNode>),
|
||||
|
@ -615,10 +615,14 @@ impl CalcLengthOrPercentage {
|
|||
NoCalcLength::parse_dimension(value.value, unit).map(CalcValueNode::Length)
|
||||
}
|
||||
(Token::Dimension(ref value, ref unit), CalcUnit::Angle) => {
|
||||
Angle::parse_dimension(value.value, unit).map(CalcValueNode::Angle)
|
||||
Angle::parse_dimension(value.value, unit).map(|angle| {
|
||||
CalcValueNode::Angle(angle.radians())
|
||||
})
|
||||
}
|
||||
(Token::Dimension(ref value, ref unit), CalcUnit::Time) => {
|
||||
Time::parse_dimension(value.value, unit).map(CalcValueNode::Time)
|
||||
Time::parse_dimension(value.value, unit).map(|time| {
|
||||
CalcValueNode::Time(time.seconds())
|
||||
})
|
||||
}
|
||||
(Token::Percentage(ref value), CalcUnit::LengthOrPercentage) =>
|
||||
Ok(CalcValueNode::Percentage(value.unit_value)),
|
||||
|
@ -802,14 +806,14 @@ impl CalcLengthOrPercentage {
|
|||
|
||||
for value in simplified {
|
||||
match value {
|
||||
SimplifiedValueNode::Time(Time(val)) =>
|
||||
SimplifiedValueNode::Time(val) =>
|
||||
time = Some(time.unwrap_or(0.) + val),
|
||||
_ => return Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
match time {
|
||||
Some(time) => Ok(Time(time)),
|
||||
Some(time) => Ok(Time::from_calc(time)),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -831,16 +835,23 @@ impl CalcLengthOrPercentage {
|
|||
|
||||
for value in simplified {
|
||||
match value {
|
||||
SimplifiedValueNode::Angle(Angle(val)) =>
|
||||
angle = Some(angle.unwrap_or(0.) + val),
|
||||
SimplifiedValueNode::Number(val) => number = Some(number.unwrap_or(0.) + val),
|
||||
SimplifiedValueNode::Angle(val) => {
|
||||
angle = Some(angle.unwrap_or(0.) + val)
|
||||
}
|
||||
// TODO(emilio): This `Number` logic looks fishy.
|
||||
//
|
||||
// In particular, this allows calc(2 - 2) to parse as an
|
||||
// `Angle`, which doesn't seem desired to me.
|
||||
SimplifiedValueNode::Number(val) => {
|
||||
number = Some(number.unwrap_or(0.) + val)
|
||||
}
|
||||
_ => unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
match (angle, number) {
|
||||
(Some(angle), None) => Ok(Angle(angle)),
|
||||
(None, Some(value)) if value == 0. => Ok(Angle(0.)),
|
||||
(Some(angle), None) => Ok(Angle::from_calc(angle)),
|
||||
(None, Some(value)) if value == 0. => Ok(Angle::from_calc(0.)),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -899,12 +910,24 @@ impl ToCss for CalcLengthOrPercentage {
|
|||
/// A percentage value.
|
||||
///
|
||||
/// [0 .. 100%] maps to [0.0 .. 1.0]
|
||||
///
|
||||
/// FIXME(emilio): There's no standard property that requires a `<percentage>`
|
||||
/// without requiring also a `<length>`. If such a property existed, we'd need
|
||||
/// to add special handling for `calc()` and percentages in here in the same way
|
||||
/// as for `Angle` and `Time`, but the lack of this this is otherwise
|
||||
/// undistinguishable (we handle it correctly from `CalcLengthOrPercentage`).
|
||||
///
|
||||
/// As of today, only `-moz-image-rect` supports percentages without length.
|
||||
/// This is not a regression, and that's a non-standard extension anyway, so I'm
|
||||
/// not implementing it for now.
|
||||
#[derive(Clone, PartialEq, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct Percentage(pub CSSFloat);
|
||||
|
||||
impl ToCss for Percentage {
|
||||
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,
|
||||
{
|
||||
write!(dest, "{}%", self.0 * 100.)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ use std::fmt;
|
|||
use std::ops::Mul;
|
||||
use style_traits::ToCss;
|
||||
use super::{Auto, CSSFloat, CSSInteger, HasViewportPercentage, Either, None_};
|
||||
use super::computed::{ComputedValueAsSpecified, Context};
|
||||
use super::computed::{self, Context};
|
||||
use super::computed::{Shadow as ComputedShadow, ToComputedValue};
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
|
@ -166,8 +166,8 @@ impl<'a> Mul<CSSFloat> for &'a SimplifiedSumNode {
|
|||
#[allow(missing_docs)]
|
||||
pub enum SimplifiedValueNode {
|
||||
Length(NoCalcLength),
|
||||
Angle(Angle),
|
||||
Time(Time),
|
||||
Angle(CSSFloat),
|
||||
Time(CSSFloat),
|
||||
Percentage(CSSFloat),
|
||||
Number(CSSFloat),
|
||||
Sum(Box<SimplifiedSumNode>),
|
||||
|
@ -179,25 +179,37 @@ impl<'a> Mul<CSSFloat> for &'a SimplifiedValueNode {
|
|||
#[inline]
|
||||
fn mul(self, scalar: CSSFloat) -> SimplifiedValueNode {
|
||||
match *self {
|
||||
SimplifiedValueNode::Length(ref l) => SimplifiedValueNode::Length(l.clone() * scalar),
|
||||
SimplifiedValueNode::Percentage(p) => SimplifiedValueNode::Percentage(p * scalar),
|
||||
SimplifiedValueNode::Angle(Angle(a)) => SimplifiedValueNode::Angle(Angle(a * scalar)),
|
||||
SimplifiedValueNode::Time(Time(t)) => SimplifiedValueNode::Time(Time(t * scalar)),
|
||||
SimplifiedValueNode::Number(n) => SimplifiedValueNode::Number(n * scalar),
|
||||
SimplifiedValueNode::Length(ref l) => {
|
||||
SimplifiedValueNode::Length(l.clone() * scalar)
|
||||
},
|
||||
SimplifiedValueNode::Percentage(p) => {
|
||||
SimplifiedValueNode::Percentage(p * scalar)
|
||||
},
|
||||
SimplifiedValueNode::Angle(a) => {
|
||||
SimplifiedValueNode::Angle(a * scalar)
|
||||
},
|
||||
SimplifiedValueNode::Time(t) => {
|
||||
SimplifiedValueNode::Time(t * scalar)
|
||||
},
|
||||
SimplifiedValueNode::Number(n) => {
|
||||
SimplifiedValueNode::Number(n * scalar)
|
||||
},
|
||||
SimplifiedValueNode::Sum(ref s) => {
|
||||
let sum = &**s * scalar;
|
||||
SimplifiedValueNode::Sum(Box::new(sum))
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_integer(input: &mut Parser) -> Result<CSSInteger, ()> {
|
||||
pub fn parse_integer(input: &mut Parser) -> Result<Integer, ()> {
|
||||
match try!(input.next()) {
|
||||
Token::Number(ref value) => value.int_value.ok_or(()),
|
||||
Token::Number(ref value) => value.int_value.ok_or(()).map(Integer::new),
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||
let ast = try!(input.parse_nested_block(|i| CalcLengthOrPercentage::parse_sum(i, CalcUnit::Integer)));
|
||||
let ast = try!(input.parse_nested_block(|i| {
|
||||
CalcLengthOrPercentage::parse_sum(i, CalcUnit::Integer)
|
||||
}));
|
||||
|
||||
let mut result = None;
|
||||
|
||||
|
@ -210,7 +222,7 @@ pub fn parse_integer(input: &mut Parser) -> Result<CSSInteger, ()> {
|
|||
}
|
||||
|
||||
match result {
|
||||
Some(result) => Ok(result),
|
||||
Some(result) => Ok(Integer::from_calc(result)),
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -219,17 +231,15 @@ pub fn parse_integer(input: &mut Parser) -> Result<CSSInteger, ()> {
|
|||
}
|
||||
|
||||
#[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()) {
|
||||
Token::Number(ref value) => {
|
||||
use std::f32;
|
||||
if value.value.is_finite() {
|
||||
Ok(value.value)
|
||||
} else if value.value.is_sign_positive() {
|
||||
Ok(f32::MAX)
|
||||
} else {
|
||||
Ok(f32::MIN)
|
||||
}
|
||||
Ok(Number {
|
||||
value: value.value.min(f32::MAX).max(f32::MIN),
|
||||
was_calc: false,
|
||||
})
|
||||
},
|
||||
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)));
|
||||
|
@ -245,7 +255,12 @@ pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
|
|||
}
|
||||
|
||||
match result {
|
||||
Some(result) => Ok(result),
|
||||
Some(result) => {
|
||||
Ok(Number {
|
||||
value: result.min(f32::MAX).max(f32::MIN),
|
||||
was_calc: true,
|
||||
})
|
||||
},
|
||||
_ => Err(())
|
||||
}
|
||||
}
|
||||
|
@ -299,11 +314,36 @@ impl ToCss for BorderRadiusSize {
|
|||
#[derive(Clone, PartialEq, PartialOrd, Copy, Debug)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf, Deserialize, Serialize))]
|
||||
/// An angle, normalized to radians.
|
||||
pub struct Angle(pub CSSFloat);
|
||||
pub struct Angle {
|
||||
radians: CSSFloat,
|
||||
was_calc: bool,
|
||||
}
|
||||
|
||||
impl ToCss for Angle {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
write!(dest, "{}rad", self.0)
|
||||
if self.was_calc {
|
||||
dest.write_str("calc(")?;
|
||||
}
|
||||
write!(dest, "{}rad", self.radians)?;
|
||||
if self.was_calc {
|
||||
dest.write_str(")")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ToComputedValue for Angle {
|
||||
type ComputedValue = computed::Angle;
|
||||
|
||||
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue {
|
||||
computed::Angle::from_radians(self.radians())
|
||||
}
|
||||
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
Angle {
|
||||
radians: computed.radians(),
|
||||
was_calc: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -311,13 +351,29 @@ impl Angle {
|
|||
#[inline]
|
||||
#[allow(missing_docs)]
|
||||
pub fn radians(self) -> f32 {
|
||||
self.0
|
||||
self.radians
|
||||
}
|
||||
|
||||
/// Returns an angle value that represents zero radians.
|
||||
pub fn zero() -> Self {
|
||||
Self::from_radians(0.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
#[allow(missing_docs)]
|
||||
pub fn from_radians(r: f32) -> Self {
|
||||
Angle(r)
|
||||
Angle {
|
||||
radians: r,
|
||||
was_calc: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns an `Angle` parsed from a `calc()` expression.
|
||||
pub fn from_calc(radians: CSSFloat) -> Self {
|
||||
Angle {
|
||||
radians: radians,
|
||||
was_calc: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -330,7 +386,7 @@ impl Parse for Angle {
|
|||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
match try!(input.next()) {
|
||||
Token::Dimension(ref value, ref unit) => Angle::parse_dimension(value.value, unit),
|
||||
Token::Number(ref value) if value.value == 0. => Ok(Angle(0.)),
|
||||
Token::Number(ref value) if value.value == 0. => Ok(Angle::zero()),
|
||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||
input.parse_nested_block(CalcLengthOrPercentage::parse_angle)
|
||||
},
|
||||
|
@ -342,13 +398,18 @@ impl Parse for Angle {
|
|||
impl Angle {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Angle, ()> {
|
||||
match_ignore_ascii_case! { unit,
|
||||
"deg" => Ok(Angle(value * RAD_PER_DEG)),
|
||||
"grad" => Ok(Angle(value * RAD_PER_GRAD)),
|
||||
"turn" => Ok(Angle(value * RAD_PER_TURN)),
|
||||
"rad" => Ok(Angle(value)),
|
||||
_ => Err(())
|
||||
}
|
||||
let radians = match_ignore_ascii_case! { unit,
|
||||
"deg" => value * RAD_PER_DEG,
|
||||
"grad" => value * RAD_PER_GRAD,
|
||||
"turn" => value * RAD_PER_TURN,
|
||||
"rad" => value,
|
||||
_ => return Err(())
|
||||
};
|
||||
|
||||
Ok(Angle {
|
||||
radians: radians,
|
||||
was_calc: false,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,28 +540,67 @@ impl BorderStyle {
|
|||
/// A time in seconds according to CSS-VALUES § 6.2.
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
pub struct Time(pub CSSFloat);
|
||||
pub struct Time {
|
||||
seconds: CSSFloat,
|
||||
was_calc: bool,
|
||||
}
|
||||
|
||||
impl Time {
|
||||
/// Return a `<time>` value that represents `seconds` seconds.
|
||||
pub fn from_seconds(seconds: CSSFloat) -> Self {
|
||||
Time {
|
||||
seconds: seconds,
|
||||
was_calc: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a time that represents a duration of zero.
|
||||
pub fn zero() -> Self {
|
||||
Self::from_seconds(0.0)
|
||||
}
|
||||
|
||||
/// Returns the time in fractional seconds.
|
||||
pub fn seconds(self) -> f32 {
|
||||
let Time(seconds) = self;
|
||||
seconds
|
||||
pub fn seconds(self) -> CSSFloat {
|
||||
self.seconds
|
||||
}
|
||||
|
||||
/// Parses a time according to CSS-VALUES § 6.2.
|
||||
fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Time, ()> {
|
||||
if unit.eq_ignore_ascii_case("s") {
|
||||
Ok(Time(value))
|
||||
} else if unit.eq_ignore_ascii_case("ms") {
|
||||
Ok(Time(value / 1000.0))
|
||||
} else {
|
||||
Err(())
|
||||
let seconds = match_ignore_ascii_case! { unit,
|
||||
"s" => value,
|
||||
"ms" => value / 1000.0,
|
||||
_ => return Err(()),
|
||||
};
|
||||
|
||||
Ok(Time {
|
||||
seconds: seconds,
|
||||
was_calc: false,
|
||||
})
|
||||
}
|
||||
|
||||
/// Returns a `Time` value from a CSS `calc()` expression.
|
||||
pub fn from_calc(seconds: CSSFloat) -> Self {
|
||||
Time {
|
||||
seconds: seconds,
|
||||
was_calc: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ComputedValueAsSpecified for Time {}
|
||||
impl ToComputedValue for Time {
|
||||
type ComputedValue = computed::Time;
|
||||
|
||||
fn to_computed_value(&self, _context: &Context) -> Self::ComputedValue {
|
||||
computed::Time::from_seconds(self.seconds())
|
||||
}
|
||||
|
||||
fn from_computed_value(computed: &Self::ComputedValue) -> Self {
|
||||
Time {
|
||||
seconds: computed.seconds(),
|
||||
was_calc: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for Time {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
|
@ -518,31 +618,53 @@ impl Parse for Time {
|
|||
|
||||
impl ToCss for Time {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
write!(dest, "{}s", self.0)
|
||||
if self.was_calc {
|
||||
dest.write_str("calc(")?;
|
||||
}
|
||||
write!(dest, "{}s", self.seconds)?;
|
||||
if self.was_calc {
|
||||
dest.write_str(")")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[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);
|
||||
|
||||
impl Parse for Number {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
parse_number(input).map(Number)
|
||||
parse_number(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl Number {
|
||||
fn parse_with_minimum(input: &mut Parser, min: CSSFloat) -> Result<Number, ()> {
|
||||
match parse_number(input) {
|
||||
Ok(value) if value >= min => Ok(Number(value)),
|
||||
Ok(value) if value.value >= min => Ok(value),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a new number with the value `val`.
|
||||
pub fn new(val: CSSFloat) -> Self {
|
||||
Number {
|
||||
value: val,
|
||||
was_calc: false,
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_non_negative(input: &mut Parser) -> Result<Number, ()> {
|
||||
Number::parse_with_minimum(input, 0.0)
|
||||
|
@ -558,17 +680,29 @@ impl ToComputedValue for Number {
|
|||
type ComputedValue = CSSFloat;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> CSSFloat { self.0 }
|
||||
fn to_computed_value(&self, _: &Context) -> CSSFloat { self.value }
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &CSSFloat) -> Self {
|
||||
Number(*computed)
|
||||
Number {
|
||||
value: *computed,
|
||||
was_calc: false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for Number {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
self.0.to_css(dest)
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write,
|
||||
{
|
||||
if self.was_calc {
|
||||
dest.write_str("calc(")?;
|
||||
}
|
||||
self.value.to_css(dest)?;
|
||||
if self.was_calc {
|
||||
dest.write_str(")")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -606,7 +740,7 @@ impl ToCss for NumberOrPercentage {
|
|||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[allow(missing_docs)]
|
||||
pub struct Opacity(pub CSSFloat);
|
||||
pub struct Opacity(Number);
|
||||
|
||||
no_viewport_percentage!(Opacity);
|
||||
|
||||
|
@ -620,19 +754,13 @@ impl ToComputedValue for Opacity {
|
|||
type ComputedValue = CSSFloat;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> CSSFloat {
|
||||
if self.0 < 0.0 {
|
||||
0.0
|
||||
} else if self.0 > 1.0 {
|
||||
1.0
|
||||
} else {
|
||||
self.0
|
||||
}
|
||||
fn to_computed_value(&self, context: &Context) -> CSSFloat {
|
||||
self.0.to_computed_value(context).min(1.0).max(0.0)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &CSSFloat) -> Self {
|
||||
Opacity(*computed)
|
||||
Opacity(Number::from_computed_value(computed))
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -645,21 +773,47 @@ impl ToCss for Opacity {
|
|||
#[derive(Clone, Copy, Debug, PartialEq, PartialOrd)]
|
||||
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
||||
#[allow(missing_docs)]
|
||||
pub struct Integer(pub CSSInteger);
|
||||
pub struct Integer {
|
||||
value: CSSInteger,
|
||||
was_calc: bool,
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
/// Trivially constructs a new `Integer` value.
|
||||
pub fn new(val: CSSInteger) -> Self {
|
||||
Integer {
|
||||
value: val,
|
||||
was_calc: false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the integer value associated with this value.
|
||||
pub fn value(&self) -> CSSInteger {
|
||||
self.value
|
||||
}
|
||||
|
||||
/// Trivially constructs a new integer value from a `calc()` expression.
|
||||
pub fn from_calc(val: CSSInteger) -> Self {
|
||||
Integer {
|
||||
value: val,
|
||||
was_calc: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
no_viewport_percentage!(Integer);
|
||||
|
||||
impl Parse for Integer {
|
||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<Self, ()> {
|
||||
parse_integer(input).map(Integer)
|
||||
parse_integer(input)
|
||||
}
|
||||
}
|
||||
|
||||
impl Integer {
|
||||
fn parse_with_minimum(input: &mut Parser, min: i32) -> Result<Integer, ()> {
|
||||
match parse_integer(input) {
|
||||
Ok(value) if value < min => Err(()),
|
||||
value => value.map(Integer),
|
||||
Ok(value) if value.value() >= min => Ok(value),
|
||||
_ => Err(()),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -678,17 +832,26 @@ impl ToComputedValue for Integer {
|
|||
type ComputedValue = i32;
|
||||
|
||||
#[inline]
|
||||
fn to_computed_value(&self, _: &Context) -> i32 { self.0 }
|
||||
fn to_computed_value(&self, _: &Context) -> i32 { self.value }
|
||||
|
||||
#[inline]
|
||||
fn from_computed_value(computed: &i32) -> Self {
|
||||
Integer(*computed)
|
||||
Integer::new(*computed)
|
||||
}
|
||||
}
|
||||
|
||||
impl ToCss for Integer {
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||
write!(dest, "{}", self.0)
|
||||
fn to_css<W>(&self, dest: &mut W) -> fmt::Result
|
||||
where W: fmt::Write,
|
||||
{
|
||||
if self.was_calc {
|
||||
dest.write_str("calc(")?;
|
||||
}
|
||||
write!(dest, "{}", self.value)?;
|
||||
if self.was_calc {
|
||||
dest.write_str(")")?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -697,9 +860,11 @@ pub type IntegerOrAuto = Either<Integer, Auto>;
|
|||
|
||||
impl IntegerOrAuto {
|
||||
#[allow(missing_docs)]
|
||||
pub fn parse_positive(context: &ParserContext, input: &mut Parser) -> Result<IntegerOrAuto, ()> {
|
||||
pub fn parse_positive(context: &ParserContext,
|
||||
input: &mut Parser)
|
||||
-> Result<IntegerOrAuto, ()> {
|
||||
match IntegerOrAuto::parse(context, input) {
|
||||
Ok(Either::First(Integer(value))) if value <= 0 => Err(()),
|
||||
Ok(Either::First(integer)) if integer.value() <= 0 => Err(()),
|
||||
result => result,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1202,7 +1202,7 @@ pub extern "C" fn Servo_DeclarationBlock_SetPixelValue(declarations:
|
|||
BorderSpacing => Box::new(
|
||||
BorderSpacing {
|
||||
horizontal: nocalc.into(),
|
||||
vertical: nocalc.into(),
|
||||
vertical: None,
|
||||
}
|
||||
),
|
||||
};
|
||||
|
|
|
@ -55,7 +55,7 @@ fn test_linear_gradient() {
|
|||
font_metrics_provider: None,
|
||||
};
|
||||
assert_eq!(specified::AngleOrCorner::None.to_computed_value(&specified_context),
|
||||
computed::AngleOrCorner::Angle(Angle(PI)));
|
||||
computed::AngleOrCorner::Angle(Angle::from_radians(PI)));
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
|
|
@ -573,15 +573,14 @@ mod shorthand_serialization {
|
|||
|
||||
#[test]
|
||||
fn flex_should_serialize_all_available_properties() {
|
||||
use style::values::specified::Number as NumberContainer;
|
||||
use style::values::specified::Percentage as PercentageContainer;
|
||||
use style::values::specified::{Number, Percentage};
|
||||
|
||||
let mut properties = Vec::new();
|
||||
|
||||
let grow = NumberContainer(2f32);
|
||||
let shrink = NumberContainer(3f32);
|
||||
let grow = Number::new(2f32);
|
||||
let shrink = Number::new(3f32);
|
||||
let basis =
|
||||
LengthOrPercentageOrAutoOrContent::Percentage(PercentageContainer(0.5f32));
|
||||
LengthOrPercentageOrAutoOrContent::Percentage(Percentage(0.5f32));
|
||||
|
||||
properties.push(PropertyDeclaration::FlexGrow(grow));
|
||||
properties.push(PropertyDeclaration::FlexShrink(shrink));
|
||||
|
@ -1174,13 +1173,14 @@ mod shorthand_serialization {
|
|||
mod counter_increment {
|
||||
pub use super::*;
|
||||
pub use style::properties::longhands::counter_increment::SpecifiedValue as CounterIncrement;
|
||||
use style::values::specified::Integer;
|
||||
|
||||
#[test]
|
||||
fn counter_increment_with_properties_should_serialize_correctly() {
|
||||
let mut properties = Vec::new();
|
||||
|
||||
properties.push(("counter1".to_owned(), 1));
|
||||
properties.push(("counter2".to_owned(), -4));
|
||||
properties.push(("counter1".to_owned(), Integer::new(1)));
|
||||
properties.push(("counter2".to_owned(), Integer::new(-4)));
|
||||
|
||||
let counter_increment = CounterIncrement(properties);
|
||||
let counter_increment_css = "counter1 1 counter2 -4";
|
||||
|
|
|
@ -1,13 +1,5 @@
|
|||
[serialize-values.html]
|
||||
type: testharness
|
||||
[border-spacing: 0px]
|
||||
expected: FAIL
|
||||
|
||||
[border-spacing: 1px]
|
||||
expected: FAIL
|
||||
|
||||
[border-spacing: .1em]
|
||||
expected: FAIL
|
||||
|
||||
[content: url("http://localhost/")]
|
||||
expected: FAIL
|
||||
|
|
|
@ -11057,6 +11057,12 @@
|
|||
{}
|
||||
]
|
||||
],
|
||||
"css/calc-number-serialization.html": [
|
||||
[
|
||||
"/_mozilla/css/calc-number-serialization.html",
|
||||
{}
|
||||
]
|
||||
],
|
||||
"css/empty-keyframes.html": [
|
||||
[
|
||||
"/_mozilla/css/empty-keyframes.html",
|
||||
|
@ -20700,6 +20706,10 @@
|
|||
"94dc4aac4c546a74add074be0d3e604c8b196888",
|
||||
"reftest"
|
||||
],
|
||||
"css/calc-number-serialization.html": [
|
||||
"b9e77c824d0c96e51d51fb8f1e923d3ab67be027",
|
||||
"testharness"
|
||||
],
|
||||
"css/canvas_as_block_element_a.html": [
|
||||
"668d93da2dab9722998cc7c5785c20e2ab9a1ced",
|
||||
"reftest"
|
||||
|
@ -25113,7 +25123,7 @@
|
|||
"testharness"
|
||||
],
|
||||
"mozilla/calc.html": [
|
||||
"c333be7c567aebd1ed2f763d0ed644165ae8bd3b",
|
||||
"c239c441c90e4d4ed94458eae5b2defabb47e984",
|
||||
"testharness"
|
||||
],
|
||||
"mozilla/canvas.initial.reset.2dstate.html": [
|
||||
|
|
|
@ -1,14 +1,3 @@
|
|||
[calc.html]
|
||||
type: testharness
|
||||
[calc for border-width]
|
||||
expected: FAIL
|
||||
|
||||
[calc for column-width]
|
||||
expected: FAIL
|
||||
|
||||
[calc for column-gap]
|
||||
expected: FAIL
|
||||
|
||||
[calc for column-count]
|
||||
expected: FAIL
|
||||
|
||||
prefs: [layout.column-count.enabled:true,layout.column-width.enabled:true,layout.column-gap.enabled:true]
|
||||
|
|
18
tests/wpt/mozilla/tests/css/calc-number-serialization.html
Normal file
18
tests/wpt/mozilla/tests/css/calc-number-serialization.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
<!doctype html>
|
||||
<meta charset="utf-8">
|
||||
<title>CSS test: Calc expressions with numbers should still serialize as calc()</title>
|
||||
<script src="/resources/testharness.js"></script>
|
||||
<script src="/resources/testharnessreport.js"></script>
|
||||
<div id="test"></div>
|
||||
<script>
|
||||
var div = document.querySelector('#test');
|
||||
test(function() {
|
||||
div.style.lineHeight = "calc(1)";
|
||||
assert_equals(div.style.lineHeight, "calc(1)");
|
||||
}, "calc of an integer expression should be preserved");
|
||||
|
||||
test(function() {
|
||||
div.style.lineHeight = "calc(1 + 3)";
|
||||
assert_equals(div.style.lineHeight, "calc(4)");
|
||||
}, "expressions on calc() should be simplified");
|
||||
</script>
|
|
@ -6,6 +6,10 @@
|
|||
#outer {
|
||||
width: 1000px;
|
||||
}
|
||||
#inner {
|
||||
border-style: solid; /* So used border == computed border */
|
||||
outline-style: solid; /* So used outline-width == computed outline-width */
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
@ -76,7 +80,9 @@ var lengthProperties = [
|
|||
lengthProperties.forEach(function(prop) {
|
||||
test(function() {
|
||||
div.style.setProperty(prop, 'calc(1px)');
|
||||
assert_equals(div.style.getPropertyValue(prop), 'calc(1px)');
|
||||
assert_equals(div.style.getPropertyValue(prop), 'calc(1px)', div.style.getPropertyValue(prop));
|
||||
let computed = getComputedStyle(div).getPropertyValue(prop);
|
||||
assert_equals(computed, '1px', prop + ': expected 1px, got ' + computed);
|
||||
}, 'calc for ' + prop);
|
||||
});
|
||||
|
||||
|
@ -112,12 +118,14 @@ var timeProperties = [
|
|||
timeProperties.forEach(function(prop) {
|
||||
test(function() {
|
||||
div.style.setProperty(prop, 'calc(1s)');
|
||||
assert_equals(div.style.getPropertyValue(prop), '1s');
|
||||
assert_equals(div.style.getPropertyValue(prop), 'calc(1s)');
|
||||
assert_equals(getComputedStyle(div).getPropertyValue(prop), '1s');
|
||||
}, 'calc for ' + prop);
|
||||
});
|
||||
|
||||
var numberProperties = [
|
||||
'z-index',
|
||||
'order',
|
||||
'column-count',
|
||||
'opacity',
|
||||
];
|
||||
|
@ -125,13 +133,14 @@ var numberProperties = [
|
|||
numberProperties.forEach(function(prop) {
|
||||
test(function() {
|
||||
div.style.setProperty(prop, 'calc(1)');
|
||||
assert_equals(div.style.getPropertyValue(prop), '1');
|
||||
assert_equals(div.style.getPropertyValue(prop), 'calc(1)');
|
||||
assert_equals(getComputedStyle(div).getPropertyValue(prop), '1');
|
||||
}, 'calc for ' + prop);
|
||||
});
|
||||
|
||||
var otherProperties = [
|
||||
['border-width', 'calc(1px)', '1px 1px 1px 1px'],
|
||||
['border-spacing', 'calc(1px)', 'calc(1px) calc(1px)'],
|
||||
['border-width', 'calc(1px)', 'calc(1px)'],
|
||||
['border-spacing', 'calc(1px)', 'calc(1px)'],
|
||||
['transform-origin', 'calc(1px + 0%)', 'calc(1px + 0%) 50% 0px'],
|
||||
['perspective-origin', 'calc(1px + 0%)', 'calc(1px + 0%) 50%'],
|
||||
['background-size', 'calc(1px + 0%)', 'calc(1px + 0%) auto'],
|
||||
|
@ -140,6 +149,7 @@ var otherProperties = [
|
|||
['border-bottom-left-radius', 'calc(1px + 0%)', 'calc(1px + 0%) calc(1px + 0%)'],
|
||||
['border-top-right-radius', 'calc(1px + 0%)', 'calc(1px + 0%) calc(1px + 0%)'],
|
||||
['border-bottom-right-radius', 'calc(1px + 0%)', 'calc(1px + 0%) calc(1px + 0%)'],
|
||||
['counter-increment', 'foo calc(1 + 1)', 'foo calc(2)'],
|
||||
];
|
||||
|
||||
otherProperties.forEach(function(testcase) {
|
||||
|
@ -150,7 +160,7 @@ otherProperties.forEach(function(testcase) {
|
|||
});
|
||||
|
||||
/* TODO: test these:
|
||||
counter-increment, counter-reset,
|
||||
counter-reset,
|
||||
color, box-shadow, clip, text-shadow, transform
|
||||
transition-timing-function
|
||||
angles
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue