mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Implement calc expressions for more value types
This commit is contained in:
parent
35b452660b
commit
00980ea595
9 changed files with 383 additions and 312 deletions
|
@ -340,6 +340,10 @@ impl CandidateBSizeIterator {
|
||||||
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
|
(LengthOrPercentageOrNone::Percentage(percent), Some(block_container_block_size)) => {
|
||||||
Some(block_container_block_size.scale_by(percent))
|
Some(block_container_block_size.scale_by(percent))
|
||||||
}
|
}
|
||||||
|
(LengthOrPercentageOrNone::Calc(calc), Some(block_container_block_size)) => {
|
||||||
|
Some(block_container_block_size.scale_by(calc.percentage()) + calc.length())
|
||||||
|
}
|
||||||
|
(LengthOrPercentageOrNone::Calc(_), _) |
|
||||||
(LengthOrPercentageOrNone::Percentage(_), None) |
|
(LengthOrPercentageOrNone::Percentage(_), None) |
|
||||||
(LengthOrPercentageOrNone::None, _) => None,
|
(LengthOrPercentageOrNone::None, _) => None,
|
||||||
(LengthOrPercentageOrNone::Length(length), _) => Some(length),
|
(LengthOrPercentageOrNone::Length(length), _) => Some(length),
|
||||||
|
|
|
@ -27,6 +27,7 @@ use std::{fmt, isize, mem};
|
||||||
use style::computed_values::{display, overflow_x, position, text_align, text_justify};
|
use style::computed_values::{display, overflow_x, position, text_align, text_justify};
|
||||||
use style::computed_values::{text_overflow, vertical_align, white_space};
|
use style::computed_values::{text_overflow, vertical_align, white_space};
|
||||||
use style::properties::ComputedValues;
|
use style::properties::ComputedValues;
|
||||||
|
use style::values::computed::LengthOrPercentage;
|
||||||
use text;
|
use text;
|
||||||
use unicode_bidi;
|
use unicode_bidi;
|
||||||
use util;
|
use util;
|
||||||
|
@ -953,15 +954,15 @@ impl InlineFlow {
|
||||||
offset_from_baseline = offset_from_baseline - *depth_below_baseline
|
offset_from_baseline = offset_from_baseline - *depth_below_baseline
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
vertical_align::T::Length(length) => {
|
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Length(length)) => {
|
||||||
offset_from_baseline = offset_from_baseline - length
|
offset_from_baseline = offset_from_baseline - length
|
||||||
}
|
}
|
||||||
vertical_align::T::Percentage(p) => {
|
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Percentage(p)) => {
|
||||||
let line_height = fragment.calculate_line_height(layout_context);
|
let line_height = fragment.calculate_line_height(layout_context);
|
||||||
let percent_offset = line_height.scale_by(p);
|
let percent_offset = line_height.scale_by(p);
|
||||||
offset_from_baseline = offset_from_baseline - percent_offset
|
offset_from_baseline = offset_from_baseline - percent_offset
|
||||||
}
|
}
|
||||||
vertical_align::T::Calc(calc) => {
|
vertical_align::T::LengthOrPercentage(LengthOrPercentage::Calc(calc)) => {
|
||||||
let line_height = fragment.calculate_line_height(layout_context);
|
let line_height = fragment.calculate_line_height(layout_context);
|
||||||
let percent_offset = line_height.scale_by(calc.percentage());
|
let percent_offset = line_height.scale_by(calc.percentage());
|
||||||
offset_from_baseline = offset_from_baseline - percent_offset - calc.length()
|
offset_from_baseline = offset_from_baseline - percent_offset - calc.length()
|
||||||
|
|
|
@ -411,6 +411,8 @@ pub fn specified_or_none(length: LengthOrPercentageOrNone, containing_length: Au
|
||||||
match length {
|
match length {
|
||||||
LengthOrPercentageOrNone::None => None,
|
LengthOrPercentageOrNone::None => None,
|
||||||
LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent)),
|
LengthOrPercentageOrNone::Percentage(percent) => Some(containing_length.scale_by(percent)),
|
||||||
|
LengthOrPercentageOrNone::Calc(calc) =>
|
||||||
|
Some(containing_length.scale_by(calc.percentage()) + calc.length()),
|
||||||
LengthOrPercentageOrNone::Length(length) => Some(length),
|
LengthOrPercentageOrNone::Length(length) => Some(length),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -80,7 +80,7 @@ use style::properties::DeclaredValue;
|
||||||
use style::properties::longhands::{self, background_image, border_spacing, font_family, font_size};
|
use style::properties::longhands::{self, background_image, border_spacing, font_family, font_size};
|
||||||
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
|
use style::properties::{PropertyDeclaration, PropertyDeclarationBlock, parse_style_attribute};
|
||||||
use style::values::CSSFloat;
|
use style::values::CSSFloat;
|
||||||
use style::values::specified::{self, CSSColor, CSSRGBA};
|
use style::values::specified::{self, CSSColor, CSSRGBA, LengthOrPercentage};
|
||||||
use url::UrlParser;
|
use url::UrlParser;
|
||||||
use util::mem::HeapSizeOf;
|
use util::mem::HeapSizeOf;
|
||||||
use util::str::{DOMString, LengthOrPercentageOrAuto};
|
use util::str::{DOMString, LengthOrPercentageOrAuto};
|
||||||
|
@ -347,7 +347,8 @@ impl LayoutElementHelpers for LayoutJS<Element> {
|
||||||
hints.push(from_declaration(
|
hints.push(from_declaration(
|
||||||
PropertyDeclaration::FontSize(
|
PropertyDeclaration::FontSize(
|
||||||
DeclaredValue::Value(
|
DeclaredValue::Value(
|
||||||
font_size::SpecifiedValue(font_size)))))
|
font_size::SpecifiedValue(
|
||||||
|
LengthOrPercentage::Length(font_size))))))
|
||||||
}
|
}
|
||||||
|
|
||||||
let cellspacing = if let Some(this) = self.downcast::<HTMLTableElement>() {
|
let cellspacing = if let Some(this) = self.downcast::<HTMLTableElement>() {
|
||||||
|
|
|
@ -28,7 +28,7 @@ use std::iter::repeat;
|
||||||
use util::bezier::Bezier;
|
use util::bezier::Bezier;
|
||||||
use values::CSSFloat;
|
use values::CSSFloat;
|
||||||
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
use values::computed::{Angle, LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
|
||||||
use values::computed::{Calc, Length, LengthOrPercentage, Time};
|
use values::computed::{CalcLengthOrPercentage, Length, LengthOrPercentage, Time};
|
||||||
|
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
pub struct PropertyAnimation {
|
pub struct PropertyAnimation {
|
||||||
|
@ -461,10 +461,10 @@ impl Interpolate for VerticalAlign {
|
||||||
fn interpolate(&self, other: &VerticalAlign, time: f64)
|
fn interpolate(&self, other: &VerticalAlign, time: f64)
|
||||||
-> Option<VerticalAlign> {
|
-> Option<VerticalAlign> {
|
||||||
match (*self, *other) {
|
match (*self, *other) {
|
||||||
(VerticalAlign::Length(ref this),
|
(VerticalAlign::LengthOrPercentage(LengthOrPercentage::Length(ref this)),
|
||||||
VerticalAlign::Length(ref other)) => {
|
VerticalAlign::LengthOrPercentage(LengthOrPercentage::Length(ref other))) => {
|
||||||
this.interpolate(other, time).and_then(|value| {
|
this.interpolate(other, time).and_then(|value| {
|
||||||
Some(VerticalAlign::Length(value))
|
Some(VerticalAlign::LengthOrPercentage(LengthOrPercentage::Length(value)))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(_, _) => None,
|
(_, _) => None,
|
||||||
|
@ -513,11 +513,11 @@ impl Interpolate for Color {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Interpolate for Calc {
|
impl Interpolate for CalcLengthOrPercentage {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn interpolate(&self, other: &Calc, time: f64)
|
fn interpolate(&self, other: &CalcLengthOrPercentage, time: f64)
|
||||||
-> Option<Calc> {
|
-> Option<CalcLengthOrPercentage> {
|
||||||
Some(Calc {
|
Some(CalcLengthOrPercentage {
|
||||||
length: self.length().interpolate(&other.length(), time),
|
length: self.length().interpolate(&other.length(), time),
|
||||||
percentage: self.percentage().interpolate(&other.percentage(), time),
|
percentage: self.percentage().interpolate(&other.percentage(), time),
|
||||||
})
|
})
|
||||||
|
@ -542,8 +542,8 @@ impl Interpolate for LengthOrPercentage {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
(this, other) => {
|
(this, other) => {
|
||||||
let this: Calc = From::from(this);
|
let this: CalcLengthOrPercentage = From::from(this);
|
||||||
let other: Calc = From::from(other);
|
let other: CalcLengthOrPercentage = From::from(other);
|
||||||
this.interpolate(&other, time).and_then(|value| {
|
this.interpolate(&other, time).and_then(|value| {
|
||||||
Some(LengthOrPercentage::Calc(value))
|
Some(LengthOrPercentage::Calc(value))
|
||||||
})
|
})
|
||||||
|
@ -573,8 +573,8 @@ impl Interpolate for LengthOrPercentageOrAuto {
|
||||||
Some(LengthOrPercentageOrAuto::Auto)
|
Some(LengthOrPercentageOrAuto::Auto)
|
||||||
}
|
}
|
||||||
(this, other) => {
|
(this, other) => {
|
||||||
let this: Option<Calc> = From::from(this);
|
let this: Option<CalcLengthOrPercentage> = From::from(this);
|
||||||
let other: Option<Calc> = From::from(other);
|
let other: Option<CalcLengthOrPercentage> = From::from(other);
|
||||||
this.interpolate(&other, time).unwrap_or(None).and_then(|value| {
|
this.interpolate(&other, time).unwrap_or(None).and_then(|value| {
|
||||||
Some(LengthOrPercentageOrAuto::Calc(value))
|
Some(LengthOrPercentageOrAuto::Calc(value))
|
||||||
})
|
})
|
||||||
|
|
|
@ -611,7 +611,7 @@ pub mod longhands {
|
||||||
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
||||||
Ok(computed_value::T::Auto)
|
Ok(computed_value::T::Auto)
|
||||||
} else {
|
} else {
|
||||||
Ok(computed_value::T::Number(try!(input.expect_integer()) as i32))
|
specified::parse_integer(input).map(computed_value::T::Number)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</%self:longhand>
|
</%self:longhand>
|
||||||
|
@ -658,18 +658,16 @@ pub mod longhands {
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
pub enum SpecifiedValue {
|
pub enum SpecifiedValue {
|
||||||
Normal,
|
Normal,
|
||||||
Length(specified::Length),
|
|
||||||
Number(CSSFloat),
|
Number(CSSFloat),
|
||||||
Percentage(CSSFloat),
|
LengthOrPercentage(specified::LengthOrPercentage),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for SpecifiedValue {
|
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 {
|
||||||
match *self {
|
match *self {
|
||||||
SpecifiedValue::Normal => dest.write_str("normal"),
|
SpecifiedValue::Normal => dest.write_str("normal"),
|
||||||
SpecifiedValue::Length(length) => length.to_css(dest),
|
SpecifiedValue::LengthOrPercentage(value) => value.to_css(dest),
|
||||||
SpecifiedValue::Number(number) => write!(dest, "{}", number),
|
SpecifiedValue::Number(number) => write!(dest, "{}", number),
|
||||||
SpecifiedValue::Percentage(number) => write!(dest, "{}%", number * 100.),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -677,22 +675,19 @@ pub mod longhands {
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
use cssparser::Token;
|
use cssparser::Token;
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
match try!(input.next()) {
|
input.try(specified::LengthOrPercentage::parse_non_negative)
|
||||||
Token::Number(ref value) if value.value >= 0. => {
|
.map(SpecifiedValue::LengthOrPercentage)
|
||||||
Ok(SpecifiedValue::Number(value.value))
|
.or_else(|()| {
|
||||||
|
match try!(input.next()) {
|
||||||
|
Token::Number(ref value) if value.value >= 0. => {
|
||||||
|
Ok(SpecifiedValue::Number(value.value))
|
||||||
|
}
|
||||||
|
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => {
|
||||||
|
Ok(SpecifiedValue::Normal)
|
||||||
|
}
|
||||||
|
_ => Err(()),
|
||||||
}
|
}
|
||||||
Token::Percentage(ref value) if value.unit_value >= 0. => {
|
})
|
||||||
Ok(SpecifiedValue::Percentage(value.unit_value))
|
|
||||||
}
|
|
||||||
Token::Dimension(ref value, ref unit) if value.value >= 0. => {
|
|
||||||
specified::Length::parse_dimension(value.value, unit)
|
|
||||||
.map(SpecifiedValue::Length)
|
|
||||||
}
|
|
||||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("normal") => {
|
|
||||||
Ok(SpecifiedValue::Normal)
|
|
||||||
}
|
|
||||||
_ => Err(()),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
|
@ -733,13 +728,22 @@ pub mod longhands {
|
||||||
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::Normal => computed_value::T::Normal,
|
SpecifiedValue::Normal => computed_value::T::Normal,
|
||||||
SpecifiedValue::Length(value) => {
|
|
||||||
computed_value::T::Length(value.to_computed_value(context))
|
|
||||||
}
|
|
||||||
SpecifiedValue::Number(value) => computed_value::T::Number(value),
|
SpecifiedValue::Number(value) => computed_value::T::Number(value),
|
||||||
SpecifiedValue::Percentage(value) => {
|
SpecifiedValue::LengthOrPercentage(value) => {
|
||||||
let fr = specified::Length::FontRelative(specified::FontRelativeLength::Em(value));
|
match value {
|
||||||
computed_value::T::Length(fr.to_computed_value(context))
|
specified::LengthOrPercentage::Length(value) =>
|
||||||
|
computed_value::T::Length(value.to_computed_value(context)),
|
||||||
|
specified::LengthOrPercentage::Percentage(specified::Percentage(value)) => {
|
||||||
|
let fr = specified::Length::FontRelative(specified::FontRelativeLength::Em(value));
|
||||||
|
computed_value::T::Length(fr.to_computed_value(context))
|
||||||
|
},
|
||||||
|
specified::LengthOrPercentage::Calc(calc) => {
|
||||||
|
let calc = calc.to_computed_value(context);
|
||||||
|
let fr = specified::FontRelativeLength::Em(calc.percentage());
|
||||||
|
let fr = specified::Length::FontRelative(fr);
|
||||||
|
computed_value::T::Length(calc.length() + fr.to_computed_value(context))
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -804,9 +808,7 @@ pub mod longhands {
|
||||||
% for keyword in vertical_align_keywords:
|
% for keyword in vertical_align_keywords:
|
||||||
${to_rust_ident(keyword)},
|
${to_rust_ident(keyword)},
|
||||||
% endfor
|
% endfor
|
||||||
Length(Au),
|
LengthOrPercentage(computed::LengthOrPercentage),
|
||||||
Percentage(CSSFloat),
|
|
||||||
Calc(computed::Calc),
|
|
||||||
}
|
}
|
||||||
impl fmt::Debug for T {
|
impl fmt::Debug for T {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
@ -814,9 +816,7 @@ pub mod longhands {
|
||||||
% for keyword in vertical_align_keywords:
|
% for keyword in vertical_align_keywords:
|
||||||
T::${to_rust_ident(keyword)} => write!(f, "${keyword}"),
|
T::${to_rust_ident(keyword)} => write!(f, "${keyword}"),
|
||||||
% endfor
|
% endfor
|
||||||
T::Length(length) => write!(f, "{:?}", length),
|
T::LengthOrPercentage(value) => write!(f, "{:?}", value),
|
||||||
T::Percentage(number) => write!(f, "{}%", number),
|
|
||||||
T::Calc(calc) => write!(f, "{:?}", calc)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -826,9 +826,7 @@ pub mod longhands {
|
||||||
% for keyword in vertical_align_keywords:
|
% for keyword in vertical_align_keywords:
|
||||||
T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
|
T::${to_rust_ident(keyword)} => dest.write_str("${keyword}"),
|
||||||
% endfor
|
% endfor
|
||||||
T::Length(value) => value.to_css(dest),
|
T::LengthOrPercentage(value) => value.to_css(dest),
|
||||||
T::Percentage(percentage) => write!(dest, "{}%", percentage * 100.),
|
|
||||||
T::Calc(calc) => calc.to_css(dest),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -847,16 +845,8 @@ pub mod longhands {
|
||||||
computed_value::T::${to_rust_ident(keyword)}
|
computed_value::T::${to_rust_ident(keyword)}
|
||||||
}
|
}
|
||||||
% endfor
|
% endfor
|
||||||
SpecifiedValue::LengthOrPercentage(value) => {
|
SpecifiedValue::LengthOrPercentage(value) =>
|
||||||
match value.to_computed_value(context) {
|
computed_value::T::LengthOrPercentage(value.to_computed_value(context)),
|
||||||
computed::LengthOrPercentage::Length(value) =>
|
|
||||||
computed_value::T::Length(value),
|
|
||||||
computed::LengthOrPercentage::Percentage(value) =>
|
|
||||||
computed_value::T::Percentage(value),
|
|
||||||
computed::LengthOrPercentage::Calc(value) =>
|
|
||||||
computed_value::T::Calc(value),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1311,7 +1301,8 @@ pub mod longhands {
|
||||||
if content::counter_name_is_illegal(&counter_name) {
|
if content::counter_name_is_illegal(&counter_name) {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
let counter_delta = input.try(|input| input.expect_integer()).unwrap_or(1) as i32;
|
let counter_delta =
|
||||||
|
input.try(|input| specified::parse_integer(input)).unwrap_or(1);
|
||||||
counters.push((counter_name, counter_delta))
|
counters.push((counter_name, counter_delta))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1478,8 +1469,7 @@ pub mod longhands {
|
||||||
PositionCategory::VerticalKeyword,
|
PositionCategory::VerticalKeyword,
|
||||||
specified::PositionComponent::Center =>
|
specified::PositionComponent::Center =>
|
||||||
PositionCategory::OtherKeyword,
|
PositionCategory::OtherKeyword,
|
||||||
specified::PositionComponent::Length(_) |
|
specified::PositionComponent::LengthOrPercentage(_) =>
|
||||||
specified::PositionComponent::Percentage(_) =>
|
|
||||||
PositionCategory::LengthOrPercentage,
|
PositionCategory::LengthOrPercentage,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1929,7 +1919,7 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
pub struct SpecifiedValue(pub specified::Length); // Percentages are the same as em.
|
pub struct SpecifiedValue(pub specified::LengthOrPercentage);
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
pub type T = Au;
|
pub type T = Au;
|
||||||
|
@ -1949,17 +1939,14 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
/// <length> | <percentage> | <absolute-size> | <relative-size>
|
/// <length> | <percentage> | <absolute-size> | <relative-size>
|
||||||
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
pub fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
|
use values::specified::{Length, LengthOrPercentage};
|
||||||
|
|
||||||
input.try(specified::LengthOrPercentage::parse_non_negative)
|
input.try(specified::LengthOrPercentage::parse_non_negative)
|
||||||
.and_then(|value| match value {
|
|
||||||
specified::LengthOrPercentage::Length(value) => Ok(value),
|
|
||||||
specified::LengthOrPercentage::Percentage(value) =>
|
|
||||||
Ok(specified::Length::FontRelative(specified::FontRelativeLength::Em(value.0))),
|
|
||||||
// FIXME(dzbarsky) handle calc for font-size
|
|
||||||
specified::LengthOrPercentage::Calc(_) => Err(())
|
|
||||||
})
|
|
||||||
.or_else(|()| {
|
.or_else(|()| {
|
||||||
let ident = try!(input.expect_ident());
|
let ident = try!(input.expect_ident());
|
||||||
specified::Length::from_str(&ident as &str).ok_or(())
|
specified::Length::from_str(&ident as &str)
|
||||||
|
.ok_or(())
|
||||||
|
.map(specified::LengthOrPercentage::Length)
|
||||||
})
|
})
|
||||||
.map(SpecifiedValue)
|
.map(SpecifiedValue)
|
||||||
}
|
}
|
||||||
|
@ -2649,7 +2636,7 @@ pub mod longhands {
|
||||||
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
if input.try(|input| input.expect_ident_matching("auto")).is_ok() {
|
||||||
Ok(SpecifiedValue::Auto)
|
Ok(SpecifiedValue::Auto)
|
||||||
} else {
|
} else {
|
||||||
let count = try!(input.expect_integer());
|
let count = try!(specified::parse_integer(input));
|
||||||
// Zero is invalid
|
// Zero is invalid
|
||||||
if count <= 0 {
|
if count <= 0 {
|
||||||
return Err(())
|
return Err(())
|
||||||
|
@ -2763,7 +2750,7 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
fn parse(_context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue, ()> {
|
||||||
input.expect_number().map(SpecifiedValue)
|
specified::parse_number(input).map(SpecifiedValue)
|
||||||
}
|
}
|
||||||
</%self:longhand>
|
</%self:longhand>
|
||||||
|
|
||||||
|
@ -3628,10 +3615,10 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_two_floats(input: &mut Parser) -> Result<(CSSFloat,CSSFloat),()> {
|
fn parse_two_floats(input: &mut Parser) -> Result<(CSSFloat,CSSFloat),()> {
|
||||||
let first = try!(input.expect_number());
|
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());
|
||||||
input.expect_number()
|
specified::parse_number(input)
|
||||||
}).unwrap_or(first);
|
}).unwrap_or(first);
|
||||||
Ok((first, second))
|
Ok((first, second))
|
||||||
}
|
}
|
||||||
|
@ -3771,7 +3758,7 @@ pub mod longhands {
|
||||||
"matrix" => {
|
"matrix" => {
|
||||||
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(|input| {
|
||||||
input.expect_number()
|
specified::parse_number(input)
|
||||||
}));
|
}));
|
||||||
if values.len() != 6 {
|
if values.len() != 6 {
|
||||||
return Err(())
|
return Err(())
|
||||||
|
@ -3789,7 +3776,7 @@ pub mod longhands {
|
||||||
"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(|input| {
|
||||||
input.expect_number()
|
specified::parse_number(input)
|
||||||
}));
|
}));
|
||||||
if values.len() != 16 {
|
if values.len() != 16 {
|
||||||
return Err(())
|
return Err(())
|
||||||
|
@ -3872,32 +3859,32 @@ pub mod longhands {
|
||||||
},
|
},
|
||||||
"scalex" => {
|
"scalex" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let sx = try!(input.expect_number());
|
let sx = try!(specified::parse_number(input));
|
||||||
result.push(SpecifiedOperation::Scale(sx, 1.0, 1.0));
|
result.push(SpecifiedOperation::Scale(sx, 1.0, 1.0));
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"scaley" => {
|
"scaley" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let sy = try!(input.expect_number());
|
let sy = try!(specified::parse_number(input));
|
||||||
result.push(SpecifiedOperation::Scale(1.0, sy, 1.0));
|
result.push(SpecifiedOperation::Scale(1.0, sy, 1.0));
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"scalez" => {
|
"scalez" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let sz = try!(input.expect_number());
|
let sz = try!(specified::parse_number(input));
|
||||||
result.push(SpecifiedOperation::Scale(1.0, 1.0, sz));
|
result.push(SpecifiedOperation::Scale(1.0, 1.0, sz));
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
},
|
},
|
||||||
"scale3d" => {
|
"scale3d" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let sx = try!(input.expect_number());
|
let sx = try!(specified::parse_number(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
let sy = try!(input.expect_number());
|
let sy = try!(specified::parse_number(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
let sz = try!(input.expect_number());
|
let sz = try!(specified::parse_number(input));
|
||||||
result.push(SpecifiedOperation::Scale(sx, sy, sz));
|
result.push(SpecifiedOperation::Scale(sx, sy, sz));
|
||||||
Ok(())
|
Ok(())
|
||||||
}))
|
}))
|
||||||
|
@ -3932,11 +3919,11 @@ pub mod longhands {
|
||||||
},
|
},
|
||||||
"rotate3d" => {
|
"rotate3d" => {
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
let ax = try!(input.expect_number());
|
let ax = try!(specified::parse_number(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
let ay = try!(input.expect_number());
|
let ay = try!(specified::parse_number(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
let az = try!(input.expect_number());
|
let az = try!(specified::parse_number(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
let theta = try!(specified::Angle::parse(input));
|
let theta = try!(specified::Angle::parse(input));
|
||||||
// TODO(gw): Check the axis can be normalized!!
|
// TODO(gw): Check the axis can be normalized!!
|
||||||
|
@ -4539,13 +4526,13 @@ pub mod longhands {
|
||||||
"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) = (0.0, 0.0, 0.0, 0.0);
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
p1x = try!(input.expect_number());
|
p1x = try!(specified::parse_number(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
p1y = try!(input.expect_number());
|
p1y = try!(specified::parse_number(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
p2x = try!(input.expect_number());
|
p2x = try!(specified::parse_number(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
p2y = try!(input.expect_number());
|
p2y = try!(specified::parse_number(input));
|
||||||
Ok(())
|
Ok(())
|
||||||
}));
|
}));
|
||||||
let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y));
|
let (p1, p2) = (Point2D::new(p1x, p1y), Point2D::new(p2x, p2y));
|
||||||
|
@ -4554,7 +4541,7 @@ pub mod longhands {
|
||||||
"steps" => {
|
"steps" => {
|
||||||
let (mut step_count, mut start_end) = (0, computed_value::StartEnd::Start);
|
let (mut step_count, mut start_end) = (0, computed_value::StartEnd::Start);
|
||||||
try!(input.parse_nested_block(|input| {
|
try!(input.parse_nested_block(|input| {
|
||||||
step_count = try!(input.expect_integer());
|
step_count = try!(specified::parse_integer(input));
|
||||||
try!(input.expect_comma());
|
try!(input.expect_comma());
|
||||||
start_end = try!(match_ignore_ascii_case! {
|
start_end = try!(match_ignore_ascii_case! {
|
||||||
try!(input.expect_ident()),
|
try!(input.expect_ident()),
|
||||||
|
@ -6520,6 +6507,7 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
||||||
// Initialize `context`
|
// Initialize `context`
|
||||||
// Declarations blocks are already stored in increasing precedence order.
|
// Declarations blocks are already stored in increasing precedence order.
|
||||||
for sub_list in applicable_declarations {
|
for sub_list in applicable_declarations {
|
||||||
|
use values::specified::{LengthOrPercentage, Percentage};
|
||||||
// Declarations are stored in reverse source order, we want them in forward order here.
|
// Declarations are stored in reverse source order, we want them in forward order here.
|
||||||
for declaration in sub_list.declarations.iter().rev() {
|
for declaration in sub_list.declarations.iter().rev() {
|
||||||
match *declaration {
|
match *declaration {
|
||||||
|
@ -6528,14 +6516,23 @@ pub fn cascade(viewport_size: Size2D<Au>,
|
||||||
value, &custom_properties, |value| match *value {
|
value, &custom_properties, |value| match *value {
|
||||||
DeclaredValue::Value(ref specified_value) => {
|
DeclaredValue::Value(ref specified_value) => {
|
||||||
match specified_value.0 {
|
match specified_value.0 {
|
||||||
Length::FontRelative(value) => {
|
LengthOrPercentage::Length(Length::FontRelative(value)) => {
|
||||||
value.to_computed_value(context.inherited_font_size,
|
value.to_computed_value(context.inherited_font_size,
|
||||||
context.root_font_size)
|
context.root_font_size)
|
||||||
}
|
}
|
||||||
Length::ServoCharacterWidth(value) => {
|
LengthOrPercentage::Length(Length::ServoCharacterWidth(value)) => {
|
||||||
value.to_computed_value(context.inherited_font_size)
|
value.to_computed_value(context.inherited_font_size)
|
||||||
}
|
}
|
||||||
_ => specified_value.0.to_computed_value(&context)
|
LengthOrPercentage::Length(l) => {
|
||||||
|
l.to_computed_value(&context)
|
||||||
|
}
|
||||||
|
LengthOrPercentage::Percentage(Percentage(value)) => {
|
||||||
|
context.inherited_font_size.scale_by(value)
|
||||||
|
}
|
||||||
|
LengthOrPercentage::Calc(calc) => {
|
||||||
|
let calc = calc.to_computed_value(&context);
|
||||||
|
calc.length() + context.inherited_font_size.scale_by(calc.percentage())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
DeclaredValue::Initial => longhands::font_size::get_initial_value(),
|
DeclaredValue::Initial => longhands::font_size::get_initial_value(),
|
||||||
|
|
|
@ -232,6 +232,8 @@ pub mod specified {
|
||||||
/// This cannot be specified by the user directly and is only generated by
|
/// This cannot be specified by the user directly and is only generated by
|
||||||
/// `Stylist::synthesize_rules_for_legacy_attributes()`.
|
/// `Stylist::synthesize_rules_for_legacy_attributes()`.
|
||||||
ServoCharacterWidth(CharacterWidth),
|
ServoCharacterWidth(CharacterWidth),
|
||||||
|
|
||||||
|
Calc(CalcLengthOrPercentage),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for Length {
|
impl ToCss for Length {
|
||||||
|
@ -240,6 +242,7 @@ pub mod specified {
|
||||||
Length::Absolute(length) => write!(dest, "{}px", length.to_f32_px()),
|
Length::Absolute(length) => write!(dest, "{}px", length.to_f32_px()),
|
||||||
Length::FontRelative(length) => length.to_css(dest),
|
Length::FontRelative(length) => length.to_css(dest),
|
||||||
Length::ViewportPercentage(length) => length.to_css(dest),
|
Length::ViewportPercentage(length) => length.to_css(dest),
|
||||||
|
Length::Calc(calc) => calc.to_css(dest),
|
||||||
Length::ServoCharacterWidth(_)
|
Length::ServoCharacterWidth(_)
|
||||||
=> panic!("internal CSS values should never be serialized"),
|
=> panic!("internal CSS values should never be serialized"),
|
||||||
}
|
}
|
||||||
|
@ -255,6 +258,7 @@ pub mod specified {
|
||||||
Length::Absolute(Au(v)) => Length::Absolute(Au(((v as f32) * scalar) as i32)),
|
Length::Absolute(Au(v)) => Length::Absolute(Au(((v as f32) * scalar) as i32)),
|
||||||
Length::FontRelative(v) => Length::FontRelative(v * scalar),
|
Length::FontRelative(v) => Length::FontRelative(v * scalar),
|
||||||
Length::ViewportPercentage(v) => Length::ViewportPercentage(v * scalar),
|
Length::ViewportPercentage(v) => Length::ViewportPercentage(v * scalar),
|
||||||
|
Length::Calc(_) => panic!("Can't multiply Calc!"),
|
||||||
Length::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
|
Length::ServoCharacterWidth(_) => panic!("Can't multiply ServoCharacterWidth!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -292,6 +296,7 @@ pub mod specified {
|
||||||
const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
|
const AU_PER_IN: CSSFloat = AU_PER_PX * 96.;
|
||||||
const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
|
const AU_PER_CM: CSSFloat = AU_PER_IN / 2.54;
|
||||||
const AU_PER_MM: CSSFloat = AU_PER_IN / 25.4;
|
const AU_PER_MM: CSSFloat = AU_PER_IN / 25.4;
|
||||||
|
const AU_PER_Q: CSSFloat = AU_PER_MM / 4.;
|
||||||
const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
|
const AU_PER_PT: CSSFloat = AU_PER_IN / 72.;
|
||||||
const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
|
const AU_PER_PC: CSSFloat = AU_PER_PT * 12.;
|
||||||
impl Length {
|
impl Length {
|
||||||
|
@ -320,6 +325,8 @@ pub mod specified {
|
||||||
Length::parse_dimension(value.value, unit),
|
Length::parse_dimension(value.value, unit),
|
||||||
Token::Number(ref value) if value.value == 0. =>
|
Token::Number(ref value) if value.value == 0. =>
|
||||||
Ok(Length::Absolute(Au(0))),
|
Ok(Length::Absolute(Au(0))),
|
||||||
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") =>
|
||||||
|
input.parse_nested_block(CalcLengthOrPercentage::parse_length),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -335,6 +342,7 @@ pub mod specified {
|
||||||
"in" => Ok(Length::Absolute(Au((value * AU_PER_IN) as i32))),
|
"in" => Ok(Length::Absolute(Au((value * AU_PER_IN) as i32))),
|
||||||
"cm" => Ok(Length::Absolute(Au((value * AU_PER_CM) as i32))),
|
"cm" => Ok(Length::Absolute(Au((value * AU_PER_CM) as i32))),
|
||||||
"mm" => Ok(Length::Absolute(Au((value * AU_PER_MM) as i32))),
|
"mm" => Ok(Length::Absolute(Au((value * AU_PER_MM) as i32))),
|
||||||
|
"q" => Ok(Length::Absolute(Au((value * AU_PER_Q) as i32))),
|
||||||
"pt" => Ok(Length::Absolute(Au((value * AU_PER_PT) as i32))),
|
"pt" => Ok(Length::Absolute(Au((value * AU_PER_PT) as i32))),
|
||||||
"pc" => Ok(Length::Absolute(Au((value * AU_PER_PC) as i32))),
|
"pc" => Ok(Length::Absolute(Au((value * AU_PER_PC) as i32))),
|
||||||
// font-relative
|
// font-relative
|
||||||
|
@ -369,6 +377,8 @@ pub mod specified {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum CalcValueNode {
|
enum CalcValueNode {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
|
Angle(Angle),
|
||||||
|
Time(Time),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
Number(CSSFloat),
|
Number(CSSFloat),
|
||||||
Sum(Box<CalcSumNode>),
|
Sum(Box<CalcSumNode>),
|
||||||
|
@ -392,6 +402,8 @@ pub mod specified {
|
||||||
#[derive(Clone, Debug)]
|
#[derive(Clone, Debug)]
|
||||||
enum SimplifiedValueNode {
|
enum SimplifiedValueNode {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
|
Angle(Angle),
|
||||||
|
Time(Time),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
Number(CSSFloat),
|
Number(CSSFloat),
|
||||||
Sum(Box<SimplifiedSumNode>),
|
Sum(Box<SimplifiedSumNode>),
|
||||||
|
@ -404,6 +416,8 @@ pub mod specified {
|
||||||
match *self {
|
match *self {
|
||||||
SimplifiedValueNode::Length(l) => SimplifiedValueNode::Length(l * scalar),
|
SimplifiedValueNode::Length(l) => SimplifiedValueNode::Length(l * scalar),
|
||||||
SimplifiedValueNode::Percentage(p) => SimplifiedValueNode::Percentage(p * 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::Number(n) => SimplifiedValueNode::Number(n * scalar),
|
||||||
SimplifiedValueNode::Sum(box ref s) => {
|
SimplifiedValueNode::Sum(box ref s) => {
|
||||||
let sum = s * scalar;
|
let sum = s * scalar;
|
||||||
|
@ -413,8 +427,68 @@ pub mod specified {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_integer(input: &mut Parser) -> Result<i32, ()> {
|
||||||
|
match try!(input.next()) {
|
||||||
|
Token::Number(ref value) => value.int_value.ok_or(()),
|
||||||
|
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 mut result = None;
|
||||||
|
|
||||||
|
for ref node in ast.products {
|
||||||
|
match try!(CalcLengthOrPercentage::simplify_product(node)) {
|
||||||
|
SimplifiedValueNode::Number(val) =>
|
||||||
|
result = Some(result.unwrap_or(0) + val as i32),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Some(result) => Ok(result),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_number(input: &mut Parser) -> Result<f32, ()> {
|
||||||
|
match try!(input.next()) {
|
||||||
|
Token::Number(ref value) => Ok(value.value),
|
||||||
|
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 mut result = None;
|
||||||
|
|
||||||
|
for ref node in ast.products {
|
||||||
|
match try!(CalcLengthOrPercentage::simplify_product(node)) {
|
||||||
|
SimplifiedValueNode::Number(val) =>
|
||||||
|
result = Some(result.unwrap_or(0.) + val),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match result {
|
||||||
|
Some(result) => Ok(result),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Copy, PartialEq)]
|
||||||
|
enum CalcUnit {
|
||||||
|
Number,
|
||||||
|
Integer,
|
||||||
|
Length,
|
||||||
|
LengthOrPercentage,
|
||||||
|
Angle,
|
||||||
|
Time,
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
pub struct Calc {
|
pub struct CalcLengthOrPercentage {
|
||||||
pub absolute: Option<Au>,
|
pub absolute: Option<Au>,
|
||||||
pub vw: Option<ViewportPercentageLength>,
|
pub vw: Option<ViewportPercentageLength>,
|
||||||
pub vh: Option<ViewportPercentageLength>,
|
pub vh: Option<ViewportPercentageLength>,
|
||||||
|
@ -426,18 +500,18 @@ pub mod specified {
|
||||||
pub rem: Option<FontRelativeLength>,
|
pub rem: Option<FontRelativeLength>,
|
||||||
pub percentage: Option<Percentage>,
|
pub percentage: Option<Percentage>,
|
||||||
}
|
}
|
||||||
impl Calc {
|
impl CalcLengthOrPercentage {
|
||||||
fn parse_sum(input: &mut Parser) -> Result<CalcSumNode, ()> {
|
fn parse_sum(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcSumNode, ()> {
|
||||||
let mut products = Vec::new();
|
let mut products = Vec::new();
|
||||||
products.push(try!(Calc::parse_product(input)));
|
products.push(try!(CalcLengthOrPercentage::parse_product(input, expected_unit)));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::Delim('+')) => {
|
Ok(Token::Delim('+')) => {
|
||||||
products.push(try!(Calc::parse_product(input)));
|
products.push(try!(CalcLengthOrPercentage::parse_product(input, expected_unit)));
|
||||||
}
|
}
|
||||||
Ok(Token::Delim('-')) => {
|
Ok(Token::Delim('-')) => {
|
||||||
let mut right = try!(Calc::parse_product(input));
|
let mut right = try!(CalcLengthOrPercentage::parse_product(input, expected_unit));
|
||||||
right.values.push(CalcValueNode::Number(-1.));
|
right.values.push(CalcValueNode::Number(-1.));
|
||||||
products.push(right);
|
products.push(right);
|
||||||
}
|
}
|
||||||
|
@ -449,17 +523,17 @@ pub mod specified {
|
||||||
Ok(CalcSumNode { products: products })
|
Ok(CalcSumNode { products: products })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_product(input: &mut Parser) -> Result<CalcProductNode, ()> {
|
fn parse_product(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcProductNode, ()> {
|
||||||
let mut values = Vec::new();
|
let mut values = Vec::new();
|
||||||
values.push(try!(Calc::parse_value(input)));
|
values.push(try!(CalcLengthOrPercentage::parse_value(input, expected_unit)));
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let position = input.position();
|
let position = input.position();
|
||||||
match input.next() {
|
match input.next() {
|
||||||
Ok(Token::Delim('*')) => {
|
Ok(Token::Delim('*')) => {
|
||||||
values.push(try!(Calc::parse_value(input)));
|
values.push(try!(CalcLengthOrPercentage::parse_value(input, expected_unit)));
|
||||||
}
|
}
|
||||||
Ok(Token::Delim('/')) => {
|
Ok(Token::Delim('/')) if expected_unit != CalcUnit::Integer => {
|
||||||
if let Ok(Token::Number(ref value)) = input.next() {
|
if let Ok(Token::Number(ref value)) = input.next() {
|
||||||
if value.value == 0. {
|
if value.value == 0. {
|
||||||
return Err(());
|
return Err(());
|
||||||
|
@ -479,16 +553,24 @@ pub mod specified {
|
||||||
Ok(CalcProductNode { values: values })
|
Ok(CalcProductNode { values: values })
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_value(input: &mut Parser) -> Result<CalcValueNode, ()> {
|
fn parse_value(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcValueNode, ()> {
|
||||||
match input.next() {
|
match (try!(input.next()), expected_unit) {
|
||||||
Ok(Token::Number(ref value)) => Ok(CalcValueNode::Number(value.value)),
|
(Token::Number(ref value), _) => Ok(CalcValueNode::Number(value.value)),
|
||||||
Ok(Token::Dimension(ref value, ref unit)) =>
|
(Token::Dimension(ref value, ref unit), CalcUnit::Length) |
|
||||||
Length::parse_dimension(value.value, unit).map(CalcValueNode::Length),
|
(Token::Dimension(ref value, ref unit), CalcUnit::LengthOrPercentage) => {
|
||||||
Ok(Token::Percentage(ref value)) =>
|
Length::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)
|
||||||
|
}
|
||||||
|
(Token::Dimension(ref value, ref unit), CalcUnit::Time) => {
|
||||||
|
Time::parse_dimension(value.value, unit).map(CalcValueNode::Time)
|
||||||
|
}
|
||||||
|
(Token::Percentage(ref value), CalcUnit::LengthOrPercentage) =>
|
||||||
Ok(CalcValueNode::Percentage(value.unit_value)),
|
Ok(CalcValueNode::Percentage(value.unit_value)),
|
||||||
Ok(Token::ParenthesisBlock) => {
|
(Token::ParenthesisBlock, _) => {
|
||||||
let result = try!(input.parse_nested_block(Calc::parse_sum));
|
input.parse_nested_block(|i| CalcLengthOrPercentage::parse_sum(i, expected_unit))
|
||||||
Ok(CalcValueNode::Sum(box result))
|
.map(|result| CalcValueNode::Sum(box result))
|
||||||
},
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
|
@ -497,7 +579,7 @@ pub mod specified {
|
||||||
fn simplify_value_to_number(node: &CalcValueNode) -> Option<CSSFloat> {
|
fn simplify_value_to_number(node: &CalcValueNode) -> Option<CSSFloat> {
|
||||||
match *node {
|
match *node {
|
||||||
CalcValueNode::Number(number) => Some(number),
|
CalcValueNode::Number(number) => Some(number),
|
||||||
CalcValueNode::Sum(box ref sum) => Calc::simplify_sum_to_number(sum),
|
CalcValueNode::Sum(box ref sum) => CalcLengthOrPercentage::simplify_sum_to_number(sum),
|
||||||
_ => None
|
_ => None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -505,7 +587,7 @@ pub mod specified {
|
||||||
fn simplify_sum_to_number(node: &CalcSumNode) -> Option<CSSFloat> {
|
fn simplify_sum_to_number(node: &CalcSumNode) -> Option<CSSFloat> {
|
||||||
let mut sum = 0.;
|
let mut sum = 0.;
|
||||||
for ref product in &node.products {
|
for ref product in &node.products {
|
||||||
match Calc::simplify_product_to_number(product) {
|
match CalcLengthOrPercentage::simplify_product_to_number(product) {
|
||||||
Some(number) => sum += number,
|
Some(number) => sum += number,
|
||||||
_ => return None
|
_ => return None
|
||||||
}
|
}
|
||||||
|
@ -516,7 +598,7 @@ pub mod specified {
|
||||||
fn simplify_product_to_number(node: &CalcProductNode) -> Option<CSSFloat> {
|
fn simplify_product_to_number(node: &CalcProductNode) -> Option<CSSFloat> {
|
||||||
let mut product = 1.;
|
let mut product = 1.;
|
||||||
for ref value in &node.values {
|
for ref value in &node.values {
|
||||||
match Calc::simplify_value_to_number(value) {
|
match CalcLengthOrPercentage::simplify_value_to_number(value) {
|
||||||
Some(number) => product *= number,
|
Some(number) => product *= number,
|
||||||
_ => return None
|
_ => return None
|
||||||
}
|
}
|
||||||
|
@ -527,7 +609,7 @@ pub mod specified {
|
||||||
fn simplify_products_in_sum(node: &CalcSumNode) -> Result<SimplifiedValueNode, ()> {
|
fn simplify_products_in_sum(node: &CalcSumNode) -> Result<SimplifiedValueNode, ()> {
|
||||||
let mut simplified = Vec::new();
|
let mut simplified = Vec::new();
|
||||||
for product in &node.products {
|
for product in &node.products {
|
||||||
match try!(Calc::simplify_product(product)) {
|
match try!(CalcLengthOrPercentage::simplify_product(product)) {
|
||||||
SimplifiedValueNode::Sum(box sum) => simplified.push_all(&sum.values),
|
SimplifiedValueNode::Sum(box sum) => simplified.push_all(&sum.values),
|
||||||
val => simplified.push(val),
|
val => simplified.push(val),
|
||||||
}
|
}
|
||||||
|
@ -544,13 +626,15 @@ pub mod specified {
|
||||||
let mut multiplier = 1.;
|
let mut multiplier = 1.;
|
||||||
let mut node_with_unit = None;
|
let mut node_with_unit = None;
|
||||||
for node in &node.values {
|
for node in &node.values {
|
||||||
match Calc::simplify_value_to_number(&node) {
|
match CalcLengthOrPercentage::simplify_value_to_number(&node) {
|
||||||
Some(number) => multiplier *= number,
|
Some(number) => multiplier *= number,
|
||||||
_ if node_with_unit.is_none() => {
|
_ if node_with_unit.is_none() => {
|
||||||
node_with_unit = Some(match *node {
|
node_with_unit = Some(match *node {
|
||||||
CalcValueNode::Sum(box ref sum) =>
|
CalcValueNode::Sum(box ref sum) =>
|
||||||
try!(Calc::simplify_products_in_sum(sum)),
|
try!(CalcLengthOrPercentage::simplify_products_in_sum(sum)),
|
||||||
CalcValueNode::Length(l) => SimplifiedValueNode::Length(l),
|
CalcValueNode::Length(l) => SimplifiedValueNode::Length(l),
|
||||||
|
CalcValueNode::Angle(a) => SimplifiedValueNode::Angle(a),
|
||||||
|
CalcValueNode::Time(t) => SimplifiedValueNode::Time(t),
|
||||||
CalcValueNode::Percentage(p) => SimplifiedValueNode::Percentage(p),
|
CalcValueNode::Percentage(p) => SimplifiedValueNode::Percentage(p),
|
||||||
_ => unreachable!("Numbers should have been handled by simplify_value_to_nubmer")
|
_ => unreachable!("Numbers should have been handled by simplify_value_to_nubmer")
|
||||||
})
|
})
|
||||||
|
@ -565,12 +649,20 @@ pub mod specified {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse(input: &mut Parser) -> Result<Calc, ()> {
|
fn parse_length(input: &mut Parser) -> Result<Length, ()> {
|
||||||
let ast = try!(Calc::parse_sum(input));
|
CalcLengthOrPercentage::parse(input, CalcUnit::Length).map(Length::Calc)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_length_or_percentage(input: &mut Parser) -> Result<CalcLengthOrPercentage, ()> {
|
||||||
|
CalcLengthOrPercentage::parse(input, CalcUnit::LengthOrPercentage)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse(input: &mut Parser, expected_unit: CalcUnit) -> Result<CalcLengthOrPercentage, ()> {
|
||||||
|
let ast = try!(CalcLengthOrPercentage::parse_sum(input, expected_unit));
|
||||||
|
|
||||||
let mut simplified = Vec::new();
|
let mut simplified = Vec::new();
|
||||||
for ref node in ast.products {
|
for ref node in ast.products {
|
||||||
match try!(Calc::simplify_product(node)) {
|
match try!(CalcLengthOrPercentage::simplify_product(node)) {
|
||||||
SimplifiedValueNode::Sum(sum) => simplified.push_all(&sum.values),
|
SimplifiedValueNode::Sum(sum) => simplified.push_all(&sum.values),
|
||||||
value => simplified.push(value),
|
value => simplified.push(value),
|
||||||
}
|
}
|
||||||
|
@ -617,11 +709,11 @@ pub mod specified {
|
||||||
rem = Some(rem.unwrap_or(0.) + val),
|
rem = Some(rem.unwrap_or(0.) + val),
|
||||||
},
|
},
|
||||||
SimplifiedValueNode::Number(val) => number = Some(number.unwrap_or(0.) + val),
|
SimplifiedValueNode::Number(val) => number = Some(number.unwrap_or(0.) + val),
|
||||||
_ => unreachable!()
|
_ => return Err(()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Calc {
|
Ok(CalcLengthOrPercentage {
|
||||||
absolute: absolute.map(Au),
|
absolute: absolute.map(Au),
|
||||||
vw: vw.map(ViewportPercentageLength::Vw),
|
vw: vw.map(ViewportPercentageLength::Vw),
|
||||||
vh: vh.map(ViewportPercentageLength::Vh),
|
vh: vh.map(ViewportPercentageLength::Vh),
|
||||||
|
@ -634,9 +726,66 @@ pub mod specified {
|
||||||
percentage: percentage.map(Percentage),
|
percentage: percentage.map(Percentage),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn parse_time(input: &mut Parser) -> Result<Time, ()> {
|
||||||
|
let ast = try!(CalcLengthOrPercentage::parse_sum(input, CalcUnit::Time));
|
||||||
|
|
||||||
|
let mut simplified = Vec::new();
|
||||||
|
for ref node in ast.products {
|
||||||
|
match try!(CalcLengthOrPercentage::simplify_product(node)) {
|
||||||
|
SimplifiedValueNode::Sum(sum) => simplified.push_all(&sum.values),
|
||||||
|
value => simplified.push(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut time = None;
|
||||||
|
|
||||||
|
for value in simplified {
|
||||||
|
match value {
|
||||||
|
SimplifiedValueNode::Time(Time(val)) =>
|
||||||
|
time = Some(time.unwrap_or(0.) + val),
|
||||||
|
_ => return Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match time {
|
||||||
|
Some(time) => Ok(Time(time)),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse_angle(input: &mut Parser) -> Result<Angle, ()> {
|
||||||
|
let ast = try!(CalcLengthOrPercentage::parse_sum(input, CalcUnit::Angle));
|
||||||
|
|
||||||
|
let mut simplified = Vec::new();
|
||||||
|
for ref node in ast.products {
|
||||||
|
match try!(CalcLengthOrPercentage::simplify_product(node)) {
|
||||||
|
SimplifiedValueNode::Sum(sum) => simplified.push_all(&sum.values),
|
||||||
|
value => simplified.push(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut angle = None;
|
||||||
|
let mut number = None;
|
||||||
|
|
||||||
|
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),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match (angle, number) {
|
||||||
|
(Some(angle), None) => Ok(Angle(angle)),
|
||||||
|
(None, Some(value)) if value == 0. => Ok(Angle(0.)),
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for Calc {
|
impl ToCss for CalcLengthOrPercentage {
|
||||||
#[allow(unused_assignments)]
|
#[allow(unused_assignments)]
|
||||||
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 {
|
||||||
|
|
||||||
|
@ -701,7 +850,7 @@ pub mod specified {
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(Percentage),
|
Percentage(Percentage),
|
||||||
Calc(Calc),
|
Calc(CalcLengthOrPercentage),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for LengthOrPercentage {
|
impl ToCss for LengthOrPercentage {
|
||||||
|
@ -729,7 +878,7 @@ pub mod specified {
|
||||||
Token::Number(ref value) if value.value == 0. =>
|
Token::Number(ref value) if value.value == 0. =>
|
||||||
Ok(LengthOrPercentage::Length(Length::Absolute(Au(0)))),
|
Ok(LengthOrPercentage::Length(Length::Absolute(Au(0)))),
|
||||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
let calc = try!(input.parse_nested_block(Calc::parse));
|
let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage));
|
||||||
Ok(LengthOrPercentage::Calc(calc))
|
Ok(LengthOrPercentage::Calc(calc))
|
||||||
},
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
|
@ -750,7 +899,7 @@ pub mod specified {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(Percentage),
|
Percentage(Percentage),
|
||||||
Auto,
|
Auto,
|
||||||
Calc(Calc),
|
Calc(CalcLengthOrPercentage),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for LengthOrPercentageOrAuto {
|
impl ToCss for LengthOrPercentageOrAuto {
|
||||||
|
@ -778,7 +927,7 @@ pub mod specified {
|
||||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") =>
|
Token::Ident(ref value) if value.eq_ignore_ascii_case("auto") =>
|
||||||
Ok(LengthOrPercentageOrAuto::Auto),
|
Ok(LengthOrPercentageOrAuto::Auto),
|
||||||
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
let calc = try!(input.parse_nested_block(Calc::parse));
|
let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage));
|
||||||
Ok(LengthOrPercentageOrAuto::Calc(calc))
|
Ok(LengthOrPercentageOrAuto::Calc(calc))
|
||||||
},
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
|
@ -798,6 +947,7 @@ pub mod specified {
|
||||||
pub enum LengthOrPercentageOrNone {
|
pub enum LengthOrPercentageOrNone {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(Percentage),
|
Percentage(Percentage),
|
||||||
|
Calc(CalcLengthOrPercentage),
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -806,6 +956,7 @@ pub mod specified {
|
||||||
match *self {
|
match *self {
|
||||||
LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
|
LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
|
||||||
LengthOrPercentageOrNone::Percentage(percentage) => percentage.to_css(dest),
|
LengthOrPercentageOrNone::Percentage(percentage) => percentage.to_css(dest),
|
||||||
|
LengthOrPercentageOrNone::Calc(calc) => calc.to_css(dest),
|
||||||
LengthOrPercentageOrNone::None => dest.write_str("none"),
|
LengthOrPercentageOrNone::None => dest.write_str("none"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -821,6 +972,10 @@ pub mod specified {
|
||||||
Ok(LengthOrPercentageOrNone::Percentage(Percentage(value.unit_value))),
|
Ok(LengthOrPercentageOrNone::Percentage(Percentage(value.unit_value))),
|
||||||
Token::Number(ref value) if value.value == 0. =>
|
Token::Number(ref value) if value.value == 0. =>
|
||||||
Ok(LengthOrPercentageOrNone::Length(Length::Absolute(Au(0)))),
|
Ok(LengthOrPercentageOrNone::Length(Length::Absolute(Au(0)))),
|
||||||
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
|
let calc = try!(input.parse_nested_block(CalcLengthOrPercentage::parse_length_or_percentage));
|
||||||
|
Ok(LengthOrPercentageOrNone::Calc(calc))
|
||||||
|
},
|
||||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
||||||
Ok(LengthOrPercentageOrNone::None),
|
Ok(LengthOrPercentageOrNone::None),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
|
@ -859,6 +1014,8 @@ pub mod specified {
|
||||||
Length::parse_dimension(value.value, unit).map(LengthOrNone::Length),
|
Length::parse_dimension(value.value, unit).map(LengthOrNone::Length),
|
||||||
Token::Number(ref value) if value.value == 0. =>
|
Token::Number(ref value) if value.value == 0. =>
|
||||||
Ok(LengthOrNone::Length(Length::Absolute(Au(0)))),
|
Ok(LengthOrNone::Length(Length::Absolute(Au(0)))),
|
||||||
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") =>
|
||||||
|
input.parse_nested_block(CalcLengthOrPercentage::parse_length).map(LengthOrNone::Length),
|
||||||
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
||||||
Ok(LengthOrNone::None),
|
Ok(LengthOrNone::None),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
|
@ -911,8 +1068,7 @@ pub mod specified {
|
||||||
// http://dev.w3.org/csswg/css2/colors.html#propdef-background-position
|
// http://dev.w3.org/csswg/css2/colors.html#propdef-background-position
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
pub enum PositionComponent {
|
pub enum PositionComponent {
|
||||||
Length(Length),
|
LengthOrPercentage(LengthOrPercentage),
|
||||||
Percentage(Percentage),
|
|
||||||
Center,
|
Center,
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
|
@ -921,35 +1077,29 @@ pub mod specified {
|
||||||
}
|
}
|
||||||
impl PositionComponent {
|
impl PositionComponent {
|
||||||
pub fn parse(input: &mut Parser) -> Result<PositionComponent, ()> {
|
pub fn parse(input: &mut Parser) -> Result<PositionComponent, ()> {
|
||||||
match try!(input.next()) {
|
|
||||||
Token::Dimension(ref value, ref unit) => {
|
input.try(LengthOrPercentage::parse)
|
||||||
Length::parse_dimension(value.value, unit)
|
.map(PositionComponent::LengthOrPercentage)
|
||||||
.map(PositionComponent::Length)
|
.or_else(|()| {
|
||||||
|
match try!(input.next()) {
|
||||||
|
Token::Ident(value) => {
|
||||||
|
match_ignore_ascii_case! { value,
|
||||||
|
"center" => Ok(PositionComponent::Center),
|
||||||
|
"left" => Ok(PositionComponent::Left),
|
||||||
|
"right" => Ok(PositionComponent::Right),
|
||||||
|
"top" => Ok(PositionComponent::Top),
|
||||||
|
"bottom" => Ok(PositionComponent::Bottom)
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => Err(())
|
||||||
}
|
}
|
||||||
Token::Percentage(ref value) => {
|
})
|
||||||
Ok(PositionComponent::Percentage(Percentage(value.unit_value)))
|
|
||||||
}
|
|
||||||
Token::Number(ref value) if value.value == 0. => {
|
|
||||||
Ok(PositionComponent::Length(Length::Absolute(Au(0))))
|
|
||||||
}
|
|
||||||
Token::Ident(value) => {
|
|
||||||
match_ignore_ascii_case! { value,
|
|
||||||
"center" => Ok(PositionComponent::Center),
|
|
||||||
"left" => Ok(PositionComponent::Left),
|
|
||||||
"right" => Ok(PositionComponent::Right),
|
|
||||||
"top" => Ok(PositionComponent::Top),
|
|
||||||
"bottom" => Ok(PositionComponent::Bottom)
|
|
||||||
_ => Err(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
_ => Err(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
|
pub fn to_length_or_percentage(self) -> LengthOrPercentage {
|
||||||
match self {
|
match self {
|
||||||
PositionComponent::Length(x) => LengthOrPercentage::Length(x),
|
PositionComponent::LengthOrPercentage(value) => value,
|
||||||
PositionComponent::Percentage(x) => LengthOrPercentage::Percentage(x),
|
|
||||||
PositionComponent::Center => LengthOrPercentage::Percentage(Percentage(0.5)),
|
PositionComponent::Center => LengthOrPercentage::Percentage(Percentage(0.5)),
|
||||||
PositionComponent::Left |
|
PositionComponent::Left |
|
||||||
PositionComponent::Top => LengthOrPercentage::Percentage(Percentage(0.0)),
|
PositionComponent::Top => LengthOrPercentage::Percentage(Percentage(0.0)),
|
||||||
|
@ -984,19 +1134,24 @@ pub mod specified {
|
||||||
/// Parses an angle according to CSS-VALUES § 6.1.
|
/// Parses an angle according to CSS-VALUES § 6.1.
|
||||||
pub fn parse(input: &mut Parser) -> Result<Angle, ()> {
|
pub fn parse(input: &mut Parser) -> Result<Angle, ()> {
|
||||||
match try!(input.next()) {
|
match try!(input.next()) {
|
||||||
Token::Dimension(value, unit) => {
|
Token::Dimension(ref value, ref unit) => Angle::parse_dimension(value.value, unit),
|
||||||
match_ignore_ascii_case! { unit,
|
|
||||||
"deg" => Ok(Angle(value.value * RAD_PER_DEG)),
|
|
||||||
"grad" => Ok(Angle(value.value * RAD_PER_GRAD)),
|
|
||||||
"turn" => Ok(Angle(value.value * RAD_PER_TURN)),
|
|
||||||
"rad" => Ok(Angle(value.value))
|
|
||||||
_ => Err(())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Token::Number(ref value) if value.value == 0. => Ok(Angle(0.)),
|
Token::Number(ref value) if value.value == 0. => Ok(Angle(0.)),
|
||||||
|
Token::Function(ref name) if name.eq_ignore_ascii_case("calc") => {
|
||||||
|
input.parse_nested_block(CalcLengthOrPercentage::parse_angle)
|
||||||
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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(())
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Specified values for an image according to CSS-IMAGES.
|
/// Specified values for an image according to CSS-IMAGES.
|
||||||
|
@ -1235,7 +1390,10 @@ pub mod specified {
|
||||||
Ok(Token::Dimension(ref value, ref unit)) => {
|
Ok(Token::Dimension(ref value, ref unit)) => {
|
||||||
Time::parse_dimension(value.value, &unit)
|
Time::parse_dimension(value.value, &unit)
|
||||||
}
|
}
|
||||||
_ => Err(()),
|
Ok(Token::Function(ref name)) if name.eq_ignore_ascii_case("calc") => {
|
||||||
|
input.parse_nested_block(CalcLengthOrPercentage::parse_time)
|
||||||
|
}
|
||||||
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1251,7 +1409,7 @@ pub mod specified {
|
||||||
|
|
||||||
impl ToCss for Time {
|
impl ToCss for Time {
|
||||||
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, "{}ms", self.0)
|
write!(dest, "{}s", self.0)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1328,6 +1486,7 @@ pub mod computed {
|
||||||
fn to_computed_value(&self, context: &Context) -> Au {
|
fn to_computed_value(&self, context: &Context) -> Au {
|
||||||
match *self {
|
match *self {
|
||||||
specified::Length::Absolute(length) => length,
|
specified::Length::Absolute(length) => length,
|
||||||
|
specified::Length::Calc(calc) => calc.to_computed_value(context).length(),
|
||||||
specified::Length::FontRelative(length) =>
|
specified::Length::FontRelative(length) =>
|
||||||
length.to_computed_value(context.font_size, context.root_font_size),
|
length.to_computed_value(context.font_size, context.root_font_size),
|
||||||
specified::Length::ViewportPercentage(length) =>
|
specified::Length::ViewportPercentage(length) =>
|
||||||
|
@ -1339,12 +1498,12 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
pub struct Calc {
|
pub struct CalcLengthOrPercentage {
|
||||||
pub length: Option<Au>,
|
pub length: Option<Au>,
|
||||||
pub percentage: Option<CSSFloat>,
|
pub percentage: Option<CSSFloat>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Calc {
|
impl CalcLengthOrPercentage {
|
||||||
pub fn length(&self) -> Au {
|
pub fn length(&self) -> Au {
|
||||||
self.length.unwrap_or(Au(0))
|
self.length.unwrap_or(Au(0))
|
||||||
}
|
}
|
||||||
|
@ -1354,17 +1513,17 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LengthOrPercentage> for Calc {
|
impl From<LengthOrPercentage> for CalcLengthOrPercentage {
|
||||||
fn from(len: LengthOrPercentage) -> Calc {
|
fn from(len: LengthOrPercentage) -> CalcLengthOrPercentage {
|
||||||
match len {
|
match len {
|
||||||
LengthOrPercentage::Percentage(this) => {
|
LengthOrPercentage::Percentage(this) => {
|
||||||
Calc {
|
CalcLengthOrPercentage {
|
||||||
length: None,
|
length: None,
|
||||||
percentage: Some(this),
|
percentage: Some(this),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LengthOrPercentage::Length(this) => {
|
LengthOrPercentage::Length(this) => {
|
||||||
Calc {
|
CalcLengthOrPercentage {
|
||||||
length: Some(this),
|
length: Some(this),
|
||||||
percentage: None,
|
percentage: None,
|
||||||
}
|
}
|
||||||
|
@ -1376,17 +1535,17 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl From<LengthOrPercentageOrAuto> for Option<Calc> {
|
impl From<LengthOrPercentageOrAuto> for Option<CalcLengthOrPercentage> {
|
||||||
fn from(len: LengthOrPercentageOrAuto) -> Option<Calc> {
|
fn from(len: LengthOrPercentageOrAuto) -> Option<CalcLengthOrPercentage> {
|
||||||
match len {
|
match len {
|
||||||
LengthOrPercentageOrAuto::Percentage(this) => {
|
LengthOrPercentageOrAuto::Percentage(this) => {
|
||||||
Some(Calc {
|
Some(CalcLengthOrPercentage {
|
||||||
length: None,
|
length: None,
|
||||||
percentage: Some(this),
|
percentage: Some(this),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
LengthOrPercentageOrAuto::Length(this) => {
|
LengthOrPercentageOrAuto::Length(this) => {
|
||||||
Some(Calc {
|
Some(CalcLengthOrPercentage {
|
||||||
length: Some(this),
|
length: Some(this),
|
||||||
percentage: None,
|
percentage: None,
|
||||||
})
|
})
|
||||||
|
@ -1401,7 +1560,7 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ::cssparser::ToCss for Calc {
|
impl ::cssparser::ToCss for CalcLengthOrPercentage {
|
||||||
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.length, self.percentage) {
|
match (self.length, self.percentage) {
|
||||||
(None, Some(p)) => write!(dest, "{}%", p * 100.),
|
(None, Some(p)) => write!(dest, "{}%", p * 100.),
|
||||||
|
@ -1412,10 +1571,10 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToComputedValue for specified::Calc {
|
impl ToComputedValue for specified::CalcLengthOrPercentage {
|
||||||
type ComputedValue = Calc;
|
type ComputedValue = CalcLengthOrPercentage;
|
||||||
|
|
||||||
fn to_computed_value(&self, context: &Context) -> Calc {
|
fn to_computed_value(&self, context: &Context) -> CalcLengthOrPercentage {
|
||||||
let mut length = None;
|
let mut length = None;
|
||||||
|
|
||||||
if let Some(absolute) = self.absolute {
|
if let Some(absolute) = self.absolute {
|
||||||
|
@ -1435,7 +1594,7 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Calc { length: length, percentage: self.percentage.map(|p| p.0) }
|
CalcLengthOrPercentage { length: length, percentage: self.percentage.map(|p| p.0) }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1474,7 +1633,7 @@ pub mod computed {
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
Calc(Calc),
|
Calc(CalcLengthOrPercentage),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthOrPercentage {
|
impl LengthOrPercentage {
|
||||||
|
@ -1527,7 +1686,7 @@ pub mod computed {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
Auto,
|
Auto,
|
||||||
Calc(Calc),
|
Calc(CalcLengthOrPercentage),
|
||||||
}
|
}
|
||||||
impl fmt::Debug for LengthOrPercentageOrAuto {
|
impl fmt::Debug for LengthOrPercentageOrAuto {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
|
@ -1578,6 +1737,7 @@ pub mod computed {
|
||||||
pub enum LengthOrPercentageOrNone {
|
pub enum LengthOrPercentageOrNone {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
|
Calc(CalcLengthOrPercentage),
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
impl fmt::Debug for LengthOrPercentageOrNone {
|
impl fmt::Debug for LengthOrPercentageOrNone {
|
||||||
|
@ -1585,6 +1745,7 @@ pub mod computed {
|
||||||
match *self {
|
match *self {
|
||||||
LengthOrPercentageOrNone::Length(length) => write!(f, "{:?}", length),
|
LengthOrPercentageOrNone::Length(length) => write!(f, "{:?}", length),
|
||||||
LengthOrPercentageOrNone::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
|
LengthOrPercentageOrNone::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
|
||||||
|
LengthOrPercentageOrNone::Calc(calc) => write!(f, "{:?}", calc),
|
||||||
LengthOrPercentageOrNone::None => write!(f, "none"),
|
LengthOrPercentageOrNone::None => write!(f, "none"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1602,6 +1763,9 @@ pub mod computed {
|
||||||
specified::LengthOrPercentageOrNone::Percentage(value) => {
|
specified::LengthOrPercentageOrNone::Percentage(value) => {
|
||||||
LengthOrPercentageOrNone::Percentage(value.0)
|
LengthOrPercentageOrNone::Percentage(value.0)
|
||||||
}
|
}
|
||||||
|
specified::LengthOrPercentageOrNone::Calc(calc) => {
|
||||||
|
LengthOrPercentageOrNone::Calc(calc.to_computed_value(context))
|
||||||
|
}
|
||||||
specified::LengthOrPercentageOrNone::None => {
|
specified::LengthOrPercentageOrNone::None => {
|
||||||
LengthOrPercentageOrNone::None
|
LengthOrPercentageOrNone::None
|
||||||
}
|
}
|
||||||
|
@ -1615,6 +1779,7 @@ pub mod computed {
|
||||||
LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
|
LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
|
||||||
LengthOrPercentageOrNone::Percentage(percentage) =>
|
LengthOrPercentageOrNone::Percentage(percentage) =>
|
||||||
write!(dest, "{}%", percentage * 100.),
|
write!(dest, "{}%", percentage * 100.),
|
||||||
|
LengthOrPercentageOrNone::Calc(calc) => calc.to_css(dest),
|
||||||
LengthOrPercentageOrNone::None => dest.write_str("none"),
|
LengthOrPercentageOrNone::None => dest.write_str("none"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1640,6 +1805,9 @@ pub mod computed {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> LengthOrNone {
|
fn to_computed_value(&self, context: &Context) -> LengthOrNone {
|
||||||
match *self {
|
match *self {
|
||||||
|
specified::LengthOrNone::Length(specified::Length::Calc(calc)) => {
|
||||||
|
LengthOrNone::Length(calc.to_computed_value(context).length())
|
||||||
|
}
|
||||||
specified::LengthOrNone::Length(value) => {
|
specified::LengthOrNone::Length(value) => {
|
||||||
LengthOrNone::Length(value.to_computed_value(context))
|
LengthOrNone::Length(value.to_computed_value(context))
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,123 +6,15 @@
|
||||||
[calc(0px + 0pt + 0pc + 0in + 0cm + 0mm + 0rem + 0em + 0ex + 0% + 0vw + 0vh + 0vmin + 0vmax)]
|
[calc(0px + 0pt + 0pc + 0in + 0cm + 0mm + 0rem + 0em + 0ex + 0% + 0vw + 0vh + 0vmin + 0vmax)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[calc for border-width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-top-width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-left-width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-right-width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-bottom-width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for outline-width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for outline-offset]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for letter-spacing]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for word-spacing]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-spacing]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for column-width]
|
[calc for column-width]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[calc for column-gap]
|
[calc for column-gap]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[calc for perspective]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-top-left-radius]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-bottom-left-radius]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-top-right-radius]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for border-bottom-right-radius]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for top]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for left]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for bottom]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for right]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for height]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for min-width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for min-height]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for max-width]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for max-height]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for line-height]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for vertical-align]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for background-position]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for background-size]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for font-size]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for text-indent]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for transform-origin]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for perspective-origin]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for transition-delay]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for z-index]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for column-count]
|
[calc for column-count]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[calc for opacity]
|
[calc(0ch + 0px + 0pt + 0pc + 0in + 0cm + 0mm + 0rem + 0em + 0ex + 0% + 0vw + 0vh + 0vmin + 0vmax)]
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[calc for transition-duration]
|
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -39,8 +39,8 @@ var widthTests = [
|
||||||
['calc(1px + 1pt + 1pc + 1in + 1cm + 1mm)', '155.88333333333333px', '155.88333333333333px'],
|
['calc(1px + 1pt + 1pc + 1in + 1cm + 1mm)', '155.88333333333333px', '155.88333333333333px'],
|
||||||
|
|
||||||
// Alphabetical order
|
// Alphabetical order
|
||||||
['calc(0px + 0pt + 0pc + 0in + 0cm + 0mm + 0rem + 0em + 0ex + 0% + 0vw + 0vh + 0vmin + 0vmax)',
|
['calc(0ch + 0px + 0pt + 0pc + 0in + 0cm + 0mm + 0rem + 0em + 0ex + 0% + 0vw + 0vh + 0vmin + 0vmax)',
|
||||||
'calc(0em + 0ex + 0px + 0rem + 0vh + 0vmax + 0vmin + 0vw + 0%)',
|
'calc(0ch + 0em + 0ex + 0px + 0rem + 0vh + 0vmax + 0vmin + 0vw + 0%)',
|
||||||
'0px'],
|
'0px'],
|
||||||
|
|
||||||
// Simplification
|
// Simplification
|
||||||
|
@ -59,7 +59,6 @@ widthTests.forEach(function(item) {
|
||||||
});
|
});
|
||||||
|
|
||||||
var lengthProperties = [
|
var lengthProperties = [
|
||||||
'border-width',
|
|
||||||
'border-top-width',
|
'border-top-width',
|
||||||
'border-left-width',
|
'border-left-width',
|
||||||
'border-right-width',
|
'border-right-width',
|
||||||
|
@ -68,7 +67,6 @@ var lengthProperties = [
|
||||||
'outline-offset',
|
'outline-offset',
|
||||||
'letter-spacing',
|
'letter-spacing',
|
||||||
'word-spacing',
|
'word-spacing',
|
||||||
'border-spacing',
|
|
||||||
'column-width',
|
'column-width',
|
||||||
'column-gap',
|
'column-gap',
|
||||||
'perspective',
|
'perspective',
|
||||||
|
@ -78,15 +76,10 @@ lengthProperties.forEach(function(prop) {
|
||||||
test(function() {
|
test(function() {
|
||||||
div.style.setProperty(prop, 'calc(1px)');
|
div.style.setProperty(prop, 'calc(1px)');
|
||||||
assert_equals(div.style.getPropertyValue(prop), '1px');
|
assert_equals(div.style.getPropertyValue(prop), '1px');
|
||||||
assert_equals(window.getComputedStyle(div).getPropertyValue(prop), '1px');
|
|
||||||
}, 'calc for ' + prop);
|
}, 'calc for ' + prop);
|
||||||
});
|
});
|
||||||
|
|
||||||
var lengthOrPercentageProperties = [
|
var lengthOrPercentageProperties = [
|
||||||
'border-top-left-radius',
|
|
||||||
'border-bottom-left-radius',
|
|
||||||
'border-top-right-radius',
|
|
||||||
'border-bottom-right-radius',
|
|
||||||
'top',
|
'top',
|
||||||
'left',
|
'left',
|
||||||
'bottom',
|
'bottom',
|
||||||
|
@ -99,31 +92,26 @@ var lengthOrPercentageProperties = [
|
||||||
'max-height',
|
'max-height',
|
||||||
'line-height',
|
'line-height',
|
||||||
'vertical-align',
|
'vertical-align',
|
||||||
'background-position',
|
|
||||||
'background-size',
|
|
||||||
'font-size',
|
'font-size',
|
||||||
'text-indent',
|
'text-indent',
|
||||||
'transform-origin',
|
|
||||||
'perspective-origin',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
lengthOrPercentageProperties.forEach(function(prop) {
|
lengthOrPercentageProperties.forEach(function(prop) {
|
||||||
test(function() {
|
test(function() {
|
||||||
div.style.setProperty(prop, 'calc(1px + 0%)');
|
div.style.setProperty(prop, 'calc(1px + 0%)');
|
||||||
assert_equals(div.style.getPropertyValue(prop), 'calc(1px + 0%)');
|
assert_equals(div.style.getPropertyValue(prop), 'calc(1px + 0%)');
|
||||||
assert_equals(window.getComputedStyle(div).getPropertyValue(prop), '1px');
|
|
||||||
}, 'calc for ' + prop);
|
}, 'calc for ' + prop);
|
||||||
});
|
});
|
||||||
|
|
||||||
var timeProperties = [
|
var timeProperties = [
|
||||||
'transition-delay',
|
'transition-delay',
|
||||||
|
'transition-duration',
|
||||||
];
|
];
|
||||||
|
|
||||||
timeProperties.forEach(function(prop) {
|
timeProperties.forEach(function(prop) {
|
||||||
test(function() {
|
test(function() {
|
||||||
div.style.setProperty(prop, 'calc(1s)');
|
div.style.setProperty(prop, 'calc(1s)');
|
||||||
assert_equals(div.style.getPropertyValue(prop), '1s');
|
assert_equals(div.style.getPropertyValue(prop), '1s');
|
||||||
assert_equals(window.getComputedStyle(div).getPropertyValue(prop), '1s');
|
|
||||||
}, 'calc for ' + prop);
|
}, 'calc for ' + prop);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -131,22 +119,40 @@ var numberProperties = [
|
||||||
'z-index',
|
'z-index',
|
||||||
'column-count',
|
'column-count',
|
||||||
'opacity',
|
'opacity',
|
||||||
'transition-duration',
|
|
||||||
];
|
];
|
||||||
|
|
||||||
numberProperties.forEach(function(prop) {
|
numberProperties.forEach(function(prop) {
|
||||||
test(function() {
|
test(function() {
|
||||||
div.style.setProperty(prop, 'calc(1)');
|
div.style.setProperty(prop, 'calc(1)');
|
||||||
assert_equals(div.style.getPropertyValue(prop), '1');
|
assert_equals(div.style.getPropertyValue(prop), '1');
|
||||||
assert_equals(window.getComputedStyle(div).getPropertyValue(prop), '1');
|
|
||||||
}, 'calc for ' + prop);
|
}, 'calc for ' + prop);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var otherProperties = [
|
||||||
|
['border-width', 'calc(1px)', '1px 1px 1px 1px'],
|
||||||
|
['border-spacing', 'calc(1px)', '1px 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'],
|
||||||
|
['background-position', 'calc(1px + 0%) calc(2px + 0%)', 'calc(1px + 0%) calc(2px + 0%)'],
|
||||||
|
['border-top-left-radius', 'calc(1px + 0%)', 'calc(1px + 0%) calc(1px + 0%)'],
|
||||||
|
['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%)'],
|
||||||
|
];
|
||||||
|
|
||||||
|
otherProperties.forEach(function(testcase) {
|
||||||
|
test(function() {
|
||||||
|
div.style.setProperty(testcase[0], testcase[1]);
|
||||||
|
assert_equals(div.style.getPropertyValue(testcase[0]), testcase[2]);
|
||||||
|
}, 'calc for ' + testcase[0]);
|
||||||
|
});
|
||||||
|
|
||||||
/* TODO: test these:
|
/* TODO: test these:
|
||||||
counter-increment, counter-reset,
|
counter-increment, counter-reset,
|
||||||
color, box-shadow, clip, text-shadow, transform
|
color, box-shadow, clip, text-shadow, transform
|
||||||
transition-timing-function
|
transition-timing-function
|
||||||
|
angles
|
||||||
*/
|
*/
|
||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue