mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Auto merge of #7496 - servo:calc_, r=SimonSapin
Implement CSS3 Calc This is #7185 with one commit added to make it build merged with master, which got support for the `ch` unit in the meantime. <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7496) <!-- Reviewable:end -->
This commit is contained in:
commit
a547ae6826
21 changed files with 873 additions and 63 deletions
|
@ -327,7 +327,12 @@ impl CandidateBSizeIterator {
|
||||||
(LengthOrPercentageOrAuto::Percentage(percent), Some(block_container_block_size)) => {
|
(LengthOrPercentageOrAuto::Percentage(percent), Some(block_container_block_size)) => {
|
||||||
MaybeAuto::Specified(block_container_block_size.scale_by(percent))
|
MaybeAuto::Specified(block_container_block_size.scale_by(percent))
|
||||||
}
|
}
|
||||||
(LengthOrPercentageOrAuto::Percentage(_), None) | (LengthOrPercentageOrAuto::Auto, _) => MaybeAuto::Auto,
|
(LengthOrPercentageOrAuto::Calc(calc), Some(block_container_block_size)) => {
|
||||||
|
MaybeAuto::Specified(calc.length() + block_container_block_size.scale_by(calc.percentage()))
|
||||||
|
}
|
||||||
|
(LengthOrPercentageOrAuto::Percentage(_), None) |
|
||||||
|
(LengthOrPercentageOrAuto::Auto, _) |
|
||||||
|
(LengthOrPercentageOrAuto::Calc(_), _) => MaybeAuto::Auto,
|
||||||
(LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length),
|
(LengthOrPercentageOrAuto::Length(length), _) => MaybeAuto::Specified(length),
|
||||||
};
|
};
|
||||||
let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) {
|
let max_block_size = match (fragment.style.max_block_size(), block_container_block_size) {
|
||||||
|
@ -342,6 +347,10 @@ impl CandidateBSizeIterator {
|
||||||
(LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => {
|
(LengthOrPercentage::Percentage(percent), Some(block_container_block_size)) => {
|
||||||
block_container_block_size.scale_by(percent)
|
block_container_block_size.scale_by(percent)
|
||||||
}
|
}
|
||||||
|
(LengthOrPercentage::Calc(calc), Some(block_container_block_size)) => {
|
||||||
|
calc.length() + block_container_block_size.scale_by(calc.percentage())
|
||||||
|
}
|
||||||
|
(LengthOrPercentage::Calc(calc), None) => calc.length(),
|
||||||
(LengthOrPercentage::Percentage(_), None) => Au(0),
|
(LengthOrPercentage::Percentage(_), None) => Au(0),
|
||||||
(LengthOrPercentage::Length(length), _) => length,
|
(LengthOrPercentage::Length(length), _) => length,
|
||||||
};
|
};
|
||||||
|
@ -1128,13 +1137,15 @@ impl BlockFlow {
|
||||||
let content_block_size = self.fragment.style().content_block_size();
|
let content_block_size = self.fragment.style().content_block_size();
|
||||||
|
|
||||||
match (content_block_size, containing_block_size) {
|
match (content_block_size, containing_block_size) {
|
||||||
|
(LengthOrPercentageOrAuto::Calc(calc), Some(container_size)) => {
|
||||||
|
Some(container_size.scale_by(calc.percentage()) + calc.length())
|
||||||
|
}
|
||||||
(LengthOrPercentageOrAuto::Length(length), _) => Some(length),
|
(LengthOrPercentageOrAuto::Length(length), _) => Some(length),
|
||||||
(LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => {
|
(LengthOrPercentageOrAuto::Percentage(percent), Some(container_size)) => {
|
||||||
Some(container_size.scale_by(percent))
|
Some(container_size.scale_by(percent))
|
||||||
}
|
}
|
||||||
(LengthOrPercentageOrAuto::Percentage(_), None) => {
|
(LengthOrPercentageOrAuto::Percentage(_), None) |
|
||||||
None
|
(LengthOrPercentageOrAuto::Calc(_), None) |
|
||||||
}
|
|
||||||
(LengthOrPercentageOrAuto::Auto, None) => {
|
(LengthOrPercentageOrAuto::Auto, None) => {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
|
@ -1959,6 +1959,8 @@ fn position_to_offset(position: LengthOrPercentage, Au(total_length): Au) -> f32
|
||||||
fmin(1.0, (length as f32) / (total_length as f32))
|
fmin(1.0, (length as f32) / (total_length as f32))
|
||||||
}
|
}
|
||||||
LengthOrPercentage::Percentage(percentage) => percentage as f32,
|
LengthOrPercentage::Percentage(percentage) => percentage as f32,
|
||||||
|
LengthOrPercentage::Calc(calc) =>
|
||||||
|
fmin(1.0, calc.percentage() + (calc.length().0 as f32) / (total_length as f32)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -167,6 +167,7 @@ impl FlexFlow {
|
||||||
}
|
}
|
||||||
(LengthOrPercentageOrAuto::Percentage(_), None) |
|
(LengthOrPercentageOrAuto::Percentage(_), None) |
|
||||||
(LengthOrPercentageOrAuto::Auto, _) => None,
|
(LengthOrPercentageOrAuto::Auto, _) => None,
|
||||||
|
(LengthOrPercentageOrAuto::Calc(_), _) => None,
|
||||||
(LengthOrPercentageOrAuto::Length(length), _) => Some(length),
|
(LengthOrPercentageOrAuto::Length(length), _) => Some(length),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -463,6 +463,10 @@ impl ReplacedImageFragmentInfo {
|
||||||
MaybeAuto::Specified(container_size.scale_by(pc))
|
MaybeAuto::Specified(container_size.scale_by(pc))
|
||||||
}
|
}
|
||||||
(LengthOrPercentageOrAuto::Percentage(_), _, None) => MaybeAuto::Auto,
|
(LengthOrPercentageOrAuto::Percentage(_), _, None) => MaybeAuto::Auto,
|
||||||
|
(LengthOrPercentageOrAuto::Calc(calc), _, Some(container_size)) => {
|
||||||
|
MaybeAuto::Specified(calc.length() + container_size.scale_by(calc.percentage()))
|
||||||
|
}
|
||||||
|
(LengthOrPercentageOrAuto::Calc(_), _, None) => MaybeAuto::Auto,
|
||||||
(LengthOrPercentageOrAuto::Auto, Some(dom_length), _) => MaybeAuto::Specified(dom_length),
|
(LengthOrPercentageOrAuto::Auto, Some(dom_length), _) => MaybeAuto::Specified(dom_length),
|
||||||
(LengthOrPercentageOrAuto::Auto, None, _) => MaybeAuto::Auto,
|
(LengthOrPercentageOrAuto::Auto, None, _) => MaybeAuto::Auto,
|
||||||
}
|
}
|
||||||
|
@ -616,6 +620,10 @@ impl IframeFragmentInfo {
|
||||||
let computed_size = match (content_size, containing_size) {
|
let computed_size = match (content_size, containing_size) {
|
||||||
(LengthOrPercentageOrAuto::Length(length), _) => length,
|
(LengthOrPercentageOrAuto::Length(length), _) => length,
|
||||||
(LengthOrPercentageOrAuto::Percentage(pc), Some(container_size)) => container_size.scale_by(pc),
|
(LengthOrPercentageOrAuto::Percentage(pc), Some(container_size)) => container_size.scale_by(pc),
|
||||||
|
(LengthOrPercentageOrAuto::Calc(calc), Some(container_size)) => {
|
||||||
|
container_size.scale_by(calc.percentage()) + calc.length()
|
||||||
|
},
|
||||||
|
(LengthOrPercentageOrAuto::Calc(calc), None) => calc.length(),
|
||||||
(LengthOrPercentageOrAuto::Percentage(_), None) => default_size,
|
(LengthOrPercentageOrAuto::Percentage(_), None) => default_size,
|
||||||
(LengthOrPercentageOrAuto::Auto, _) => default_size,
|
(LengthOrPercentageOrAuto::Auto, _) => default_size,
|
||||||
};
|
};
|
||||||
|
@ -1285,6 +1293,7 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
(Some(dom_inline_size), _) => dom_inline_size,
|
(Some(dom_inline_size), _) => dom_inline_size,
|
||||||
(None, LengthOrPercentageOrAuto::Length(length)) => length,
|
(None, LengthOrPercentageOrAuto::Length(length)) => length,
|
||||||
|
(None, LengthOrPercentageOrAuto::Calc(calc)) => calc.length(),
|
||||||
};
|
};
|
||||||
result.union_block(&IntrinsicISizes {
|
result.union_block(&IntrinsicISizes {
|
||||||
minimum_inline_size: image_inline_size,
|
minimum_inline_size: image_inline_size,
|
||||||
|
|
|
@ -988,6 +988,11 @@ impl InlineFlow {
|
||||||
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) => {
|
||||||
|
let line_height = fragment.calculate_line_height(layout_context);
|
||||||
|
let percent_offset = line_height.scale_by(calc.percentage());
|
||||||
|
offset_from_baseline = offset_from_baseline - percent_offset - calc.length()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
(offset_from_baseline - ascent, largest_size_updated)
|
(offset_from_baseline - ascent, largest_size_updated)
|
||||||
|
|
|
@ -379,6 +379,9 @@ impl MaybeAuto {
|
||||||
LengthOrPercentageOrAuto::Percentage(percent) => {
|
LengthOrPercentageOrAuto::Percentage(percent) => {
|
||||||
MaybeAuto::Specified(containing_length.scale_by(percent))
|
MaybeAuto::Specified(containing_length.scale_by(percent))
|
||||||
}
|
}
|
||||||
|
LengthOrPercentageOrAuto::Calc(calc) => {
|
||||||
|
MaybeAuto::Specified(calc.length() + containing_length.scale_by(calc.percentage()))
|
||||||
|
}
|
||||||
LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(length)
|
LengthOrPercentageOrAuto::Length(length) => MaybeAuto::Specified(length)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,7 +419,9 @@ pub fn specified_or_none(length: LengthOrPercentageOrNone, containing_length: Au
|
||||||
pub fn specified(length: LengthOrPercentage, containing_length: Au) -> Au {
|
pub fn specified(length: LengthOrPercentage, containing_length: Au) -> Au {
|
||||||
match length {
|
match length {
|
||||||
LengthOrPercentage::Length(length) => length,
|
LengthOrPercentage::Length(length) => length,
|
||||||
LengthOrPercentage::Percentage(p) => containing_length.scale_by(p)
|
LengthOrPercentage::Percentage(p) => containing_length.scale_by(p),
|
||||||
|
LengthOrPercentage::Calc(calc) =>
|
||||||
|
containing_length.scale_by(calc.percentage()) + calc.length(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -267,11 +267,13 @@ impl Flow for TableFlow {
|
||||||
self.column_intrinsic_inline_sizes.push(ColumnIntrinsicInlineSize {
|
self.column_intrinsic_inline_sizes.push(ColumnIntrinsicInlineSize {
|
||||||
minimum_length: match *specified_inline_size {
|
minimum_length: match *specified_inline_size {
|
||||||
LengthOrPercentageOrAuto::Auto |
|
LengthOrPercentageOrAuto::Auto |
|
||||||
|
LengthOrPercentageOrAuto::Calc(_) |
|
||||||
LengthOrPercentageOrAuto::Percentage(_) => Au(0),
|
LengthOrPercentageOrAuto::Percentage(_) => Au(0),
|
||||||
LengthOrPercentageOrAuto::Length(length) => length,
|
LengthOrPercentageOrAuto::Length(length) => length,
|
||||||
},
|
},
|
||||||
percentage: match *specified_inline_size {
|
percentage: match *specified_inline_size {
|
||||||
LengthOrPercentageOrAuto::Auto |
|
LengthOrPercentageOrAuto::Auto |
|
||||||
|
LengthOrPercentageOrAuto::Calc(_) |
|
||||||
LengthOrPercentageOrAuto::Length(_) => 0.0,
|
LengthOrPercentageOrAuto::Length(_) => 0.0,
|
||||||
LengthOrPercentageOrAuto::Percentage(percentage) => percentage,
|
LengthOrPercentageOrAuto::Percentage(percentage) => percentage,
|
||||||
},
|
},
|
||||||
|
|
|
@ -280,6 +280,7 @@ impl Flow for TableRowFlow {
|
||||||
let child_column_inline_size = ColumnIntrinsicInlineSize {
|
let child_column_inline_size = ColumnIntrinsicInlineSize {
|
||||||
minimum_length: match child_specified_inline_size {
|
minimum_length: match child_specified_inline_size {
|
||||||
LengthOrPercentageOrAuto::Auto |
|
LengthOrPercentageOrAuto::Auto |
|
||||||
|
LengthOrPercentageOrAuto::Calc(_) |
|
||||||
LengthOrPercentageOrAuto::Percentage(_) => {
|
LengthOrPercentageOrAuto::Percentage(_) => {
|
||||||
child_base.intrinsic_inline_sizes.minimum_inline_size
|
child_base.intrinsic_inline_sizes.minimum_inline_size
|
||||||
}
|
}
|
||||||
|
@ -287,6 +288,7 @@ impl Flow for TableRowFlow {
|
||||||
},
|
},
|
||||||
percentage: match child_specified_inline_size {
|
percentage: match child_specified_inline_size {
|
||||||
LengthOrPercentageOrAuto::Auto |
|
LengthOrPercentageOrAuto::Auto |
|
||||||
|
LengthOrPercentageOrAuto::Calc(_) |
|
||||||
LengthOrPercentageOrAuto::Length(_) => 0.0,
|
LengthOrPercentageOrAuto::Length(_) => 0.0,
|
||||||
LengthOrPercentageOrAuto::Percentage(percentage) => percentage,
|
LengthOrPercentageOrAuto::Percentage(percentage) => percentage,
|
||||||
},
|
},
|
||||||
|
@ -294,6 +296,7 @@ impl Flow for TableRowFlow {
|
||||||
constrained: match child_specified_inline_size {
|
constrained: match child_specified_inline_size {
|
||||||
LengthOrPercentageOrAuto::Length(_) => true,
|
LengthOrPercentageOrAuto::Length(_) => true,
|
||||||
LengthOrPercentageOrAuto::Auto |
|
LengthOrPercentageOrAuto::Auto |
|
||||||
|
LengthOrPercentageOrAuto::Calc(_) |
|
||||||
LengthOrPercentageOrAuto::Percentage(_) => false,
|
LengthOrPercentageOrAuto::Percentage(_) => false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
@ -365,7 +365,8 @@ impl RawLayoutElementHelpers for Element {
|
||||||
match width {
|
match width {
|
||||||
LengthOrPercentageOrAuto::Auto => {}
|
LengthOrPercentageOrAuto::Auto => {}
|
||||||
LengthOrPercentageOrAuto::Percentage(percentage) => {
|
LengthOrPercentageOrAuto::Percentage(percentage) => {
|
||||||
let width_value = specified::LengthOrPercentageOrAuto::Percentage(percentage);
|
let width_value =
|
||||||
|
specified::LengthOrPercentageOrAuto::Percentage(specified::Percentage(percentage));
|
||||||
hints.push(from_declaration(
|
hints.push(from_declaration(
|
||||||
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
||||||
}
|
}
|
||||||
|
@ -388,7 +389,8 @@ impl RawLayoutElementHelpers for Element {
|
||||||
match height {
|
match height {
|
||||||
LengthOrPercentageOrAuto::Auto => {}
|
LengthOrPercentageOrAuto::Auto => {}
|
||||||
LengthOrPercentageOrAuto::Percentage(percentage) => {
|
LengthOrPercentageOrAuto::Percentage(percentage) => {
|
||||||
let height_value = specified::LengthOrPercentageOrAuto::Percentage(percentage);
|
let height_value =
|
||||||
|
specified::LengthOrPercentageOrAuto::Percentage(specified::Percentage(percentage));
|
||||||
hints.push(from_declaration(
|
hints.push(from_declaration(
|
||||||
PropertyDeclaration::Height(SpecifiedValue(height_value))));
|
PropertyDeclaration::Height(SpecifiedValue(height_value))));
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
|
|
||||||
#![feature(arc_unique)]
|
#![feature(arc_unique)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
|
#![feature(box_patterns)]
|
||||||
#![feature(core_intrinsics)]
|
#![feature(core_intrinsics)]
|
||||||
#![feature(custom_attribute)]
|
#![feature(custom_attribute)]
|
||||||
#![feature(custom_derive)]
|
#![feature(custom_derive)]
|
||||||
|
|
|
@ -760,7 +760,7 @@ pub mod longhands {
|
||||||
pub mod computed_value {
|
pub mod computed_value {
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
use values::CSSFloat;
|
use values::{CSSFloat, computed};
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
#[derive(PartialEq, Copy, Clone, HeapSizeOf)]
|
#[derive(PartialEq, Copy, Clone, HeapSizeOf)]
|
||||||
pub enum T {
|
pub enum T {
|
||||||
|
@ -769,6 +769,7 @@ pub mod longhands {
|
||||||
% endfor
|
% endfor
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
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 {
|
||||||
|
@ -778,6 +779,7 @@ pub mod longhands {
|
||||||
% endfor
|
% endfor
|
||||||
&T::Length(length) => write!(f, "{:?}", length),
|
&T::Length(length) => write!(f, "{:?}", length),
|
||||||
&T::Percentage(number) => write!(f, "{}%", number),
|
&T::Percentage(number) => write!(f, "{}%", number),
|
||||||
|
&T::Calc(calc) => write!(f, "{:?}", calc)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -789,6 +791,7 @@ pub mod longhands {
|
||||||
% endfor
|
% endfor
|
||||||
T::Length(value) => value.to_css(dest),
|
T::Length(value) => value.to_css(dest),
|
||||||
T::Percentage(percentage) => write!(dest, "{}%", percentage * 100.),
|
T::Percentage(percentage) => write!(dest, "{}%", percentage * 100.),
|
||||||
|
T::Calc(calc) => calc.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -809,12 +812,12 @@ pub mod longhands {
|
||||||
% endfor
|
% endfor
|
||||||
SpecifiedValue::LengthOrPercentage(value) => {
|
SpecifiedValue::LengthOrPercentage(value) => {
|
||||||
match value.to_computed_value(context) {
|
match value.to_computed_value(context) {
|
||||||
computed::LengthOrPercentage::Length(value) => {
|
computed::LengthOrPercentage::Length(value) =>
|
||||||
computed_value::T::Length(value)
|
computed_value::T::Length(value),
|
||||||
}
|
computed::LengthOrPercentage::Percentage(value) =>
|
||||||
computed::LengthOrPercentage::Percentage(value) => {
|
computed_value::T::Percentage(value),
|
||||||
computed_value::T::Percentage(value)
|
computed::LengthOrPercentage::Calc(value) =>
|
||||||
}
|
computed_value::T::Calc(value),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1910,10 +1913,12 @@ 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, ()> {
|
||||||
input.try(specified::LengthOrPercentage::parse_non_negative)
|
input.try(specified::LengthOrPercentage::parse_non_negative)
|
||||||
.map(|value| match value {
|
.and_then(|value| match value {
|
||||||
specified::LengthOrPercentage::Length(value) => value,
|
specified::LengthOrPercentage::Length(value) => Ok(value),
|
||||||
specified::LengthOrPercentage::Percentage(value) =>
|
specified::LengthOrPercentage::Percentage(value) =>
|
||||||
specified::Length::FontRelative(specified::FontRelativeLength::Em(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(|()| {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
|
@ -3984,6 +3989,7 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn parse_origin(_: &ParserContext, input: &mut Parser) -> Result<OriginParseResult,()> {
|
pub fn parse_origin(_: &ParserContext, input: &mut Parser) -> Result<OriginParseResult,()> {
|
||||||
|
use values::specified::{LengthOrPercentage, Percentage};
|
||||||
let (mut horizontal, mut vertical, mut depth) = (None, None, None);
|
let (mut horizontal, mut vertical, mut depth) = (None, None, None);
|
||||||
loop {
|
loop {
|
||||||
if let Err(_) = input.try(|input| {
|
if let Err(_) = input.try(|input| {
|
||||||
|
@ -3992,37 +3998,37 @@ pub mod longhands {
|
||||||
token,
|
token,
|
||||||
"left" => {
|
"left" => {
|
||||||
if horizontal.is_none() {
|
if horizontal.is_none() {
|
||||||
horizontal = Some(specified::LengthOrPercentage::Percentage(0.0))
|
horizontal = Some(LengthOrPercentage::Percentage(Percentage(0.0)))
|
||||||
} else {
|
} else {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"center" => {
|
"center" => {
|
||||||
if horizontal.is_none() {
|
if horizontal.is_none() {
|
||||||
horizontal = Some(specified::LengthOrPercentage::Percentage(0.5))
|
horizontal = Some(LengthOrPercentage::Percentage(Percentage(0.5)))
|
||||||
} else if vertical.is_none() {
|
} else if vertical.is_none() {
|
||||||
vertical = Some(specified::LengthOrPercentage::Percentage(0.5))
|
vertical = Some(LengthOrPercentage::Percentage(Percentage(0.5)))
|
||||||
} else {
|
} else {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"right" => {
|
"right" => {
|
||||||
if horizontal.is_none() {
|
if horizontal.is_none() {
|
||||||
horizontal = Some(specified::LengthOrPercentage::Percentage(1.0))
|
horizontal = Some(LengthOrPercentage::Percentage(Percentage(1.0)))
|
||||||
} else {
|
} else {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"top" => {
|
"top" => {
|
||||||
if vertical.is_none() {
|
if vertical.is_none() {
|
||||||
vertical = Some(specified::LengthOrPercentage::Percentage(0.0))
|
vertical = Some(LengthOrPercentage::Percentage(Percentage(0.0)))
|
||||||
} else {
|
} else {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"bottom" => {
|
"bottom" => {
|
||||||
if vertical.is_none() {
|
if vertical.is_none() {
|
||||||
vertical = Some(specified::LengthOrPercentage::Percentage(1.0))
|
vertical = Some(LengthOrPercentage::Percentage(Percentage(1.0)))
|
||||||
} else {
|
} else {
|
||||||
return Err(())
|
return Err(())
|
||||||
}
|
}
|
||||||
|
@ -4031,13 +4037,13 @@ pub mod longhands {
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}) {
|
}) {
|
||||||
match specified::LengthOrPercentage::parse(input) {
|
match LengthOrPercentage::parse(input) {
|
||||||
Ok(value) => {
|
Ok(value) => {
|
||||||
if horizontal.is_none() {
|
if horizontal.is_none() {
|
||||||
horizontal = Some(value);
|
horizontal = Some(value);
|
||||||
} else if vertical.is_none() {
|
} else if vertical.is_none() {
|
||||||
vertical = Some(value);
|
vertical = Some(value);
|
||||||
} else if let specified::LengthOrPercentage::Length(length) = value {
|
} else if let LengthOrPercentage::Length(length) = value {
|
||||||
depth = Some(length);
|
depth = Some(length);
|
||||||
} else {
|
} else {
|
||||||
break;
|
break;
|
||||||
|
@ -4065,7 +4071,7 @@ pub mod longhands {
|
||||||
|
|
||||||
<%self:longhand name="transform-origin">
|
<%self:longhand name="transform-origin">
|
||||||
use values::computed::Context;
|
use values::computed::Context;
|
||||||
use values::specified::{Length, LengthOrPercentage};
|
use values::specified::{Length, LengthOrPercentage, Percentage};
|
||||||
|
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -4121,8 +4127,8 @@ pub mod longhands {
|
||||||
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
pub fn parse(context: &ParserContext, input: &mut Parser) -> Result<SpecifiedValue,()> {
|
||||||
let result = try!(super::parse_origin(context, input));
|
let result = try!(super::parse_origin(context, input));
|
||||||
Ok(SpecifiedValue {
|
Ok(SpecifiedValue {
|
||||||
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(0.5)),
|
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
|
||||||
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(0.5)),
|
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
|
||||||
depth: result.depth.unwrap_or(Length::Absolute(Au(0))),
|
depth: result.depth.unwrap_or(Length::Absolute(Au(0))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -4147,7 +4153,7 @@ pub mod longhands {
|
||||||
|
|
||||||
<%self:longhand name="perspective-origin">
|
<%self:longhand name="perspective-origin">
|
||||||
use values::computed::Context;
|
use values::computed::Context;
|
||||||
use values::specified::LengthOrPercentage;
|
use values::specified::{LengthOrPercentage, Percentage};
|
||||||
|
|
||||||
use cssparser::ToCss;
|
use cssparser::ToCss;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
@ -4197,8 +4203,8 @@ pub mod longhands {
|
||||||
match result.depth {
|
match result.depth {
|
||||||
Some(_) => Err(()),
|
Some(_) => Err(()),
|
||||||
None => Ok(SpecifiedValue {
|
None => Ok(SpecifiedValue {
|
||||||
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(0.5)),
|
horizontal: result.horizontal.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
|
||||||
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(0.5)),
|
vertical: result.vertical.unwrap_or(LengthOrPercentage::Percentage(Percentage(0.5))),
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -358,19 +358,359 @@ pub mod specified {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct CalcSumNode {
|
||||||
|
products: Vec<CalcProductNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct CalcProductNode {
|
||||||
|
values: Vec<CalcValueNode>
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum CalcValueNode {
|
||||||
|
Length(Length),
|
||||||
|
Percentage(CSSFloat),
|
||||||
|
Number(CSSFloat),
|
||||||
|
Sum(Box<CalcSumNode>),
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
struct SimplifiedSumNode {
|
||||||
|
values: Vec<SimplifiedValueNode>,
|
||||||
|
}
|
||||||
|
impl<'a> Mul<CSSFloat> for &'a SimplifiedSumNode {
|
||||||
|
type Output = SimplifiedSumNode;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, scalar: CSSFloat) -> SimplifiedSumNode {
|
||||||
|
SimplifiedSumNode {
|
||||||
|
values: self.values.iter().map(|p| p * scalar).collect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug)]
|
||||||
|
enum SimplifiedValueNode {
|
||||||
|
Length(Length),
|
||||||
|
Percentage(CSSFloat),
|
||||||
|
Number(CSSFloat),
|
||||||
|
Sum(Box<SimplifiedSumNode>),
|
||||||
|
}
|
||||||
|
impl<'a> Mul<CSSFloat> for &'a SimplifiedValueNode {
|
||||||
|
type Output = SimplifiedValueNode;
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn mul(self, scalar: CSSFloat) -> SimplifiedValueNode {
|
||||||
|
match self {
|
||||||
|
&SimplifiedValueNode::Length(l) => SimplifiedValueNode::Length(l * scalar),
|
||||||
|
&SimplifiedValueNode::Percentage(p) => SimplifiedValueNode::Percentage(p * scalar),
|
||||||
|
&SimplifiedValueNode::Number(n) => SimplifiedValueNode::Number(n * scalar),
|
||||||
|
&SimplifiedValueNode::Sum(box ref s) => {
|
||||||
|
let sum = s * scalar;
|
||||||
|
SimplifiedValueNode::Sum(box sum)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
|
pub struct Calc {
|
||||||
|
pub absolute: Option<Au>,
|
||||||
|
pub vw: Option<ViewportPercentageLength>,
|
||||||
|
pub vh: Option<ViewportPercentageLength>,
|
||||||
|
pub vmin: Option<ViewportPercentageLength>,
|
||||||
|
pub vmax: Option<ViewportPercentageLength>,
|
||||||
|
pub em: Option<FontRelativeLength>,
|
||||||
|
pub ex: Option<FontRelativeLength>,
|
||||||
|
pub ch: Option<FontRelativeLength>,
|
||||||
|
pub rem: Option<FontRelativeLength>,
|
||||||
|
pub percentage: Option<Percentage>,
|
||||||
|
}
|
||||||
|
impl Calc {
|
||||||
|
fn parse_sum(input: &mut Parser) -> Result<CalcSumNode, ()> {
|
||||||
|
let mut products = Vec::new();
|
||||||
|
products.push(try!(Calc::parse_product(input)));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
match input.next() {
|
||||||
|
Ok(Token::Delim('+')) => {
|
||||||
|
products.push(try!(Calc::parse_product(input)));
|
||||||
|
}
|
||||||
|
Ok(Token::Delim('-')) => {
|
||||||
|
let mut right = try!(Calc::parse_product(input));
|
||||||
|
right.values.push(CalcValueNode::Number(-1.));
|
||||||
|
products.push(right);
|
||||||
|
}
|
||||||
|
Ok(_) => return Err(()),
|
||||||
|
_ => break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(CalcSumNode { products: products })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_product(input: &mut Parser) -> Result<CalcProductNode, ()> {
|
||||||
|
let mut values = Vec::new();
|
||||||
|
values.push(try!(Calc::parse_value(input)));
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let position = input.position();
|
||||||
|
match input.next() {
|
||||||
|
Ok(Token::Delim('*')) => {
|
||||||
|
values.push(try!(Calc::parse_value(input)));
|
||||||
|
}
|
||||||
|
Ok(Token::Delim('/')) => {
|
||||||
|
if let Ok(Token::Number(ref value)) = input.next() {
|
||||||
|
if value.value == 0. {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
values.push(CalcValueNode::Number(1. / value.value));
|
||||||
|
} else {
|
||||||
|
return Err(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
input.reset(position);
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(CalcProductNode { values: values })
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_value(input: &mut Parser) -> Result<CalcValueNode, ()> {
|
||||||
|
match input.next() {
|
||||||
|
Ok(Token::Number(ref value)) => Ok(CalcValueNode::Number(value.value)),
|
||||||
|
Ok(Token::Dimension(ref value, ref unit)) =>
|
||||||
|
Length::parse_dimension(value.value, unit).map(CalcValueNode::Length),
|
||||||
|
Ok(Token::Percentage(ref value)) =>
|
||||||
|
Ok(CalcValueNode::Percentage(value.unit_value)),
|
||||||
|
Ok(Token::ParenthesisBlock) => {
|
||||||
|
let result = try!(input.parse_nested_block(Calc::parse_sum));
|
||||||
|
Ok(CalcValueNode::Sum(box result))
|
||||||
|
},
|
||||||
|
_ => Err(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplify_value_to_number(node: &CalcValueNode) -> Option<CSSFloat> {
|
||||||
|
match node {
|
||||||
|
&CalcValueNode::Number(number) => Some(number),
|
||||||
|
&CalcValueNode::Sum(box ref sum) => Calc::simplify_sum_to_number(sum),
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplify_sum_to_number(node: &CalcSumNode) -> Option<CSSFloat> {
|
||||||
|
let mut sum = 0.;
|
||||||
|
for ref product in &node.products {
|
||||||
|
match Calc::simplify_product_to_number(product) {
|
||||||
|
Some(number) => sum += number,
|
||||||
|
_ => return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(sum)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplify_product_to_number(node: &CalcProductNode) -> Option<CSSFloat> {
|
||||||
|
let mut product = 1.;
|
||||||
|
for ref value in &node.values {
|
||||||
|
match Calc::simplify_value_to_number(value) {
|
||||||
|
Some(number) => product *= number,
|
||||||
|
_ => return None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(product)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplify_products_in_sum(node: &CalcSumNode) -> Result<SimplifiedValueNode, ()> {
|
||||||
|
let mut simplified = Vec::new();
|
||||||
|
for product in &node.products {
|
||||||
|
match try!(Calc::simplify_product(product)) {
|
||||||
|
SimplifiedValueNode::Sum(box sum) => simplified.push_all(&sum.values),
|
||||||
|
val => simplified.push(val),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if simplified.len() == 1 {
|
||||||
|
Ok(simplified[0].clone())
|
||||||
|
} else {
|
||||||
|
Ok(SimplifiedValueNode::Sum(box SimplifiedSumNode { values: simplified } ))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn simplify_product(node: &CalcProductNode) -> Result<SimplifiedValueNode, ()> {
|
||||||
|
let mut multiplier = 1.;
|
||||||
|
let mut node_with_unit = None;
|
||||||
|
for node in &node.values {
|
||||||
|
match Calc::simplify_value_to_number(&node) {
|
||||||
|
Some(number) => multiplier *= number,
|
||||||
|
_ if node_with_unit.is_none() => {
|
||||||
|
node_with_unit = Some(match node {
|
||||||
|
&CalcValueNode::Sum(box ref sum) =>
|
||||||
|
try!(Calc::simplify_products_in_sum(sum)),
|
||||||
|
&CalcValueNode::Length(l) => SimplifiedValueNode::Length(l),
|
||||||
|
&CalcValueNode::Percentage(p) => SimplifiedValueNode::Percentage(p),
|
||||||
|
_ => unreachable!("Numbers should have been handled by simplify_value_to_nubmer")
|
||||||
|
})
|
||||||
|
},
|
||||||
|
_ => return Err(()),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
match node_with_unit {
|
||||||
|
None => Ok(SimplifiedValueNode::Number(multiplier)),
|
||||||
|
Some(ref value) => Ok(value * multiplier)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn parse(input: &mut Parser) -> Result<Calc, ()> {
|
||||||
|
let ast = try!(Calc::parse_sum(input));
|
||||||
|
|
||||||
|
let mut simplified = Vec::new();
|
||||||
|
for ref node in ast.products {
|
||||||
|
match try!(Calc::simplify_product(node)) {
|
||||||
|
SimplifiedValueNode::Sum(sum) => simplified.push_all(&sum.values),
|
||||||
|
value => simplified.push(value),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut absolute = None;
|
||||||
|
let mut vw = None;
|
||||||
|
let mut vh = None;
|
||||||
|
let mut vmax = None;
|
||||||
|
let mut vmin = None;
|
||||||
|
let mut em = None;
|
||||||
|
let mut ex = None;
|
||||||
|
let mut ch = None;
|
||||||
|
let mut rem = None;
|
||||||
|
let mut percentage = None;
|
||||||
|
let mut number = None;
|
||||||
|
|
||||||
|
for value in simplified {
|
||||||
|
match value {
|
||||||
|
SimplifiedValueNode::Percentage(p) =>
|
||||||
|
percentage = Some(percentage.unwrap_or(0.) + p),
|
||||||
|
SimplifiedValueNode::Length(Length::Absolute(Au(au))) =>
|
||||||
|
absolute = Some(absolute.unwrap_or(0) + au),
|
||||||
|
SimplifiedValueNode::Length(Length::ViewportPercentage(v)) =>
|
||||||
|
match v {
|
||||||
|
ViewportPercentageLength::Vw(val) =>
|
||||||
|
vw = Some(vw.unwrap_or(0.) + val),
|
||||||
|
ViewportPercentageLength::Vh(val) =>
|
||||||
|
vh = Some(vh.unwrap_or(0.) + val),
|
||||||
|
ViewportPercentageLength::Vmin(val) =>
|
||||||
|
vmin = Some(vmin.unwrap_or(0.) + val),
|
||||||
|
ViewportPercentageLength::Vmax(val) =>
|
||||||
|
vmax = Some(vmax.unwrap_or(0.) + val),
|
||||||
|
},
|
||||||
|
SimplifiedValueNode::Length(Length::FontRelative(f)) =>
|
||||||
|
match f {
|
||||||
|
FontRelativeLength::Em(val) =>
|
||||||
|
em = Some(em.unwrap_or(0.) + val),
|
||||||
|
FontRelativeLength::Ex(val) =>
|
||||||
|
ex = Some(ex.unwrap_or(0.) + val),
|
||||||
|
FontRelativeLength::Ch(val) =>
|
||||||
|
ch = Some(ch.unwrap_or(0.) + val),
|
||||||
|
FontRelativeLength::Rem(val) =>
|
||||||
|
rem = Some(rem.unwrap_or(0.) + val),
|
||||||
|
},
|
||||||
|
SimplifiedValueNode::Number(val) => number = Some(number.unwrap_or(0.) + val),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(Calc {
|
||||||
|
absolute: absolute.map(Au),
|
||||||
|
vw: vw.map(ViewportPercentageLength::Vw),
|
||||||
|
vh: vh.map(ViewportPercentageLength::Vh),
|
||||||
|
vmax: vmax.map(ViewportPercentageLength::Vmax),
|
||||||
|
vmin: vmin.map(ViewportPercentageLength::Vmin),
|
||||||
|
em: em.map(FontRelativeLength::Em),
|
||||||
|
ex: ex.map(FontRelativeLength::Ex),
|
||||||
|
ch: ch.map(FontRelativeLength::Ch),
|
||||||
|
rem: rem.map(FontRelativeLength::Rem),
|
||||||
|
percentage: percentage.map(Percentage),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for Calc {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
|
||||||
|
macro_rules! count {
|
||||||
|
( $( $val:ident ),* ) => {
|
||||||
|
{
|
||||||
|
let mut count = 0;
|
||||||
|
$(
|
||||||
|
if let Some(_) = self.$val {
|
||||||
|
count += 1;
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
count
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! serialize {
|
||||||
|
( $( $val:ident ),* ) => {
|
||||||
|
{
|
||||||
|
let mut first_value = true;
|
||||||
|
$(
|
||||||
|
if let Some(val) = self.$val {
|
||||||
|
if !first_value {
|
||||||
|
try!(write!(dest, " + "));
|
||||||
|
} else {
|
||||||
|
first_value = false;
|
||||||
|
}
|
||||||
|
try!(val.to_css(dest));
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
let count = count!(ch, em, ex, absolute, rem, vh, vmax, vmin, vw, percentage);
|
||||||
|
assert!(count > 0);
|
||||||
|
|
||||||
|
if count > 1 {
|
||||||
|
try!(write!(dest, "calc("));
|
||||||
|
}
|
||||||
|
|
||||||
|
serialize!(ch, em, ex, absolute, rem, vh, vmax, vmin, vw, percentage);
|
||||||
|
|
||||||
|
if count > 1 {
|
||||||
|
try!(write!(dest, ")"));
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
|
pub struct Percentage(pub CSSFloat); // [0 .. 100%] maps to [0.0 .. 1.0]
|
||||||
|
|
||||||
|
impl ToCss for Percentage {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
write!(dest, "{}%", self.0 * 100.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
Percentage(Percentage),
|
||||||
|
Calc(Calc),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for LengthOrPercentage {
|
impl ToCss for LengthOrPercentage {
|
||||||
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 {
|
||||||
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
||||||
&LengthOrPercentage::Percentage(percentage)
|
&LengthOrPercentage::Percentage(percentage) => percentage.to_css(dest),
|
||||||
=> write!(dest, "{}%", percentage * 100.),
|
&LengthOrPercentage::Calc(calc) => calc.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -386,9 +726,13 @@ pub mod specified {
|
||||||
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
|
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
|
||||||
Length::parse_dimension(value.value, unit).map(LengthOrPercentage::Length),
|
Length::parse_dimension(value.value, unit).map(LengthOrPercentage::Length),
|
||||||
Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
|
Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
|
||||||
Ok(LengthOrPercentage::Percentage(value.unit_value)),
|
Ok(LengthOrPercentage::Percentage(Percentage(value.unit_value))),
|
||||||
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") => {
|
||||||
|
let calc = try!(input.parse_nested_block(Calc::parse));
|
||||||
|
Ok(LengthOrPercentage::Calc(calc))
|
||||||
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,17 +750,18 @@ pub mod specified {
|
||||||
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
pub enum LengthOrPercentageOrAuto {
|
pub enum LengthOrPercentageOrAuto {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
Percentage(Percentage),
|
||||||
Auto,
|
Auto,
|
||||||
|
Calc(Calc),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for LengthOrPercentageOrAuto {
|
impl ToCss for LengthOrPercentageOrAuto {
|
||||||
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 {
|
||||||
&LengthOrPercentageOrAuto::Length(length) => length.to_css(dest),
|
&LengthOrPercentageOrAuto::Length(length) => length.to_css(dest),
|
||||||
&LengthOrPercentageOrAuto::Percentage(percentage)
|
&LengthOrPercentageOrAuto::Percentage(percentage) => percentage.to_css(dest),
|
||||||
=> write!(dest, "{}%", percentage * 100.),
|
|
||||||
&LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
|
&LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
|
||||||
|
&LengthOrPercentageOrAuto::Calc(calc) => calc.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -429,11 +774,15 @@ pub mod specified {
|
||||||
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
|
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
|
||||||
Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrAuto::Length),
|
Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrAuto::Length),
|
||||||
Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
|
Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
|
||||||
Ok(LengthOrPercentageOrAuto::Percentage(value.unit_value)),
|
Ok(LengthOrPercentageOrAuto::Percentage(Percentage(value.unit_value))),
|
||||||
Token::Number(ref value) if value.value == 0. =>
|
Token::Number(ref value) if value.value == 0. =>
|
||||||
Ok(LengthOrPercentageOrAuto::Length(Length::Absolute(Au(0)))),
|
Ok(LengthOrPercentageOrAuto::Length(Length::Absolute(Au(0)))),
|
||||||
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") => {
|
||||||
|
let calc = try!(input.parse_nested_block(Calc::parse));
|
||||||
|
Ok(LengthOrPercentageOrAuto::Calc(calc))
|
||||||
|
},
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -450,7 +799,7 @@ pub mod specified {
|
||||||
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
pub enum LengthOrPercentageOrNone {
|
pub enum LengthOrPercentageOrNone {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
Percentage(Percentage),
|
||||||
None,
|
None,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -458,8 +807,7 @@ pub mod specified {
|
||||||
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 {
|
||||||
&LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
|
&LengthOrPercentageOrNone::Length(length) => length.to_css(dest),
|
||||||
&LengthOrPercentageOrNone::Percentage(percentage) =>
|
&LengthOrPercentageOrNone::Percentage(percentage) => percentage.to_css(dest),
|
||||||
write!(dest, "{}%", percentage * 100.),
|
|
||||||
&LengthOrPercentageOrNone::None => dest.write_str("none"),
|
&LengthOrPercentageOrNone::None => dest.write_str("none"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -472,7 +820,7 @@ pub mod specified {
|
||||||
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
|
Token::Dimension(ref value, ref unit) if context.is_ok(value.value) =>
|
||||||
Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrNone::Length),
|
Length::parse_dimension(value.value, unit).map(LengthOrPercentageOrNone::Length),
|
||||||
Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
|
Token::Percentage(ref value) if context.is_ok(value.unit_value) =>
|
||||||
Ok(LengthOrPercentageOrNone::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::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
Token::Ident(ref value) if value.eq_ignore_ascii_case("none") =>
|
||||||
|
@ -534,7 +882,7 @@ pub mod specified {
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
pub enum PositionComponent {
|
pub enum PositionComponent {
|
||||||
Length(Length),
|
Length(Length),
|
||||||
Percentage(CSSFloat), // [0 .. 100%] maps to [0.0 .. 1.0]
|
Percentage(Percentage),
|
||||||
Center,
|
Center,
|
||||||
Left,
|
Left,
|
||||||
Right,
|
Right,
|
||||||
|
@ -549,7 +897,7 @@ pub mod specified {
|
||||||
.map(PositionComponent::Length)
|
.map(PositionComponent::Length)
|
||||||
}
|
}
|
||||||
Token::Percentage(ref value) => {
|
Token::Percentage(ref value) => {
|
||||||
Ok(PositionComponent::Percentage(value.unit_value))
|
Ok(PositionComponent::Percentage(Percentage(value.unit_value)))
|
||||||
}
|
}
|
||||||
Token::Number(ref value) if value.value == 0. => {
|
Token::Number(ref value) if value.value == 0. => {
|
||||||
Ok(PositionComponent::Length(Length::Absolute(Au(0))))
|
Ok(PositionComponent::Length(Length::Absolute(Au(0))))
|
||||||
|
@ -572,11 +920,11 @@ pub mod specified {
|
||||||
match self {
|
match self {
|
||||||
PositionComponent::Length(x) => LengthOrPercentage::Length(x),
|
PositionComponent::Length(x) => LengthOrPercentage::Length(x),
|
||||||
PositionComponent::Percentage(x) => LengthOrPercentage::Percentage(x),
|
PositionComponent::Percentage(x) => LengthOrPercentage::Percentage(x),
|
||||||
PositionComponent::Center => LengthOrPercentage::Percentage(0.5),
|
PositionComponent::Center => LengthOrPercentage::Percentage(Percentage(0.5)),
|
||||||
PositionComponent::Left |
|
PositionComponent::Left |
|
||||||
PositionComponent::Top => LengthOrPercentage::Percentage(0.0),
|
PositionComponent::Top => LengthOrPercentage::Percentage(Percentage(0.0)),
|
||||||
PositionComponent::Right |
|
PositionComponent::Right |
|
||||||
PositionComponent::Bottom => LengthOrPercentage::Percentage(1.0),
|
PositionComponent::Bottom => LengthOrPercentage::Percentage(Percentage(1.0)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -943,10 +1291,66 @@ pub mod computed {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Copy, Debug, HeapSizeOf)]
|
||||||
|
pub struct Calc {
|
||||||
|
length: Option<Au>,
|
||||||
|
percentage: Option<CSSFloat>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Calc {
|
||||||
|
pub fn length(&self) -> Au {
|
||||||
|
self.length.unwrap_or(Au(0))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn percentage(&self) -> CSSFloat {
|
||||||
|
self.percentage.unwrap_or(0.)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ::cssparser::ToCss for Calc {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> fmt::Result where W: fmt::Write {
|
||||||
|
match (self.length, self.percentage) {
|
||||||
|
(None, Some(p)) => write!(dest, "{}%", p * 100.),
|
||||||
|
(Some(l), None) => write!(dest, "{}px", Au::to_px(l)),
|
||||||
|
(Some(l), Some(p)) => write!(dest, "calc({}px + {}%)", Au::to_px(l), p * 100.),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToComputedValue for specified::Calc {
|
||||||
|
type ComputedValue = Calc;
|
||||||
|
|
||||||
|
fn to_computed_value(&self, context: &Context) -> Calc {
|
||||||
|
let mut length = None;
|
||||||
|
|
||||||
|
if let Some(absolute) = self.absolute {
|
||||||
|
length = Some(length.unwrap_or(Au(0)) + absolute);
|
||||||
|
}
|
||||||
|
|
||||||
|
for val in &[self.vw, self.vh, self.vmin, self.vmax] {
|
||||||
|
if let Some(val) = *val {
|
||||||
|
length = Some(length.unwrap_or(Au(0)) +
|
||||||
|
val.to_computed_value(context.viewport_size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for val in &[self.ch, self.em, self.ex, self.rem] {
|
||||||
|
if let Some(val) = *val {
|
||||||
|
length = Some(length.unwrap_or(Au(0)) +
|
||||||
|
val.to_computed_value(context.font_size, context.root_font_size));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Calc { length: length, percentage: self.percentage.map(|p| p.0) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(PartialEq, Clone, Copy, HeapSizeOf)]
|
#[derive(PartialEq, Clone, Copy, HeapSizeOf)]
|
||||||
pub enum LengthOrPercentage {
|
pub enum LengthOrPercentage {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
|
Calc(Calc),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LengthOrPercentage {
|
impl LengthOrPercentage {
|
||||||
|
@ -960,6 +1364,7 @@ pub mod computed {
|
||||||
match self {
|
match self {
|
||||||
&LengthOrPercentage::Length(length) => write!(f, "{:?}", length),
|
&LengthOrPercentage::Length(length) => write!(f, "{:?}", length),
|
||||||
&LengthOrPercentage::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
|
&LengthOrPercentage::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
|
||||||
|
&LengthOrPercentage::Calc(calc) => write!(f, "{:?}", calc),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -973,7 +1378,10 @@ pub mod computed {
|
||||||
LengthOrPercentage::Length(value.to_computed_value(context))
|
LengthOrPercentage::Length(value.to_computed_value(context))
|
||||||
}
|
}
|
||||||
specified::LengthOrPercentage::Percentage(value) => {
|
specified::LengthOrPercentage::Percentage(value) => {
|
||||||
LengthOrPercentage::Percentage(value)
|
LengthOrPercentage::Percentage(value.0)
|
||||||
|
}
|
||||||
|
specified::LengthOrPercentage::Calc(calc) => {
|
||||||
|
LengthOrPercentage::Calc(calc.to_computed_value(context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -985,6 +1393,7 @@ pub mod computed {
|
||||||
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
&LengthOrPercentage::Length(length) => length.to_css(dest),
|
||||||
&LengthOrPercentage::Percentage(percentage)
|
&LengthOrPercentage::Percentage(percentage)
|
||||||
=> write!(dest, "{}%", percentage * 100.),
|
=> write!(dest, "{}%", percentage * 100.),
|
||||||
|
&LengthOrPercentage::Calc(calc) => calc.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -994,6 +1403,7 @@ pub mod computed {
|
||||||
Length(Au),
|
Length(Au),
|
||||||
Percentage(CSSFloat),
|
Percentage(CSSFloat),
|
||||||
Auto,
|
Auto,
|
||||||
|
Calc(Calc),
|
||||||
}
|
}
|
||||||
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 {
|
||||||
|
@ -1001,6 +1411,7 @@ pub mod computed {
|
||||||
&LengthOrPercentageOrAuto::Length(length) => write!(f, "{:?}", length),
|
&LengthOrPercentageOrAuto::Length(length) => write!(f, "{:?}", length),
|
||||||
&LengthOrPercentageOrAuto::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
|
&LengthOrPercentageOrAuto::Percentage(percentage) => write!(f, "{}%", percentage * 100.),
|
||||||
&LengthOrPercentageOrAuto::Auto => write!(f, "auto"),
|
&LengthOrPercentageOrAuto::Auto => write!(f, "auto"),
|
||||||
|
&LengthOrPercentageOrAuto::Calc(calc) => write!(f, "{:?}", calc),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1015,11 +1426,14 @@ pub mod computed {
|
||||||
LengthOrPercentageOrAuto::Length(value.to_computed_value(context))
|
LengthOrPercentageOrAuto::Length(value.to_computed_value(context))
|
||||||
}
|
}
|
||||||
specified::LengthOrPercentageOrAuto::Percentage(value) => {
|
specified::LengthOrPercentageOrAuto::Percentage(value) => {
|
||||||
LengthOrPercentageOrAuto::Percentage(value)
|
LengthOrPercentageOrAuto::Percentage(value.0)
|
||||||
}
|
}
|
||||||
specified::LengthOrPercentageOrAuto::Auto => {
|
specified::LengthOrPercentageOrAuto::Auto => {
|
||||||
LengthOrPercentageOrAuto::Auto
|
LengthOrPercentageOrAuto::Auto
|
||||||
}
|
}
|
||||||
|
specified::LengthOrPercentageOrAuto::Calc(calc) => {
|
||||||
|
LengthOrPercentageOrAuto::Calc(calc.to_computed_value(context))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1031,6 +1445,7 @@ pub mod computed {
|
||||||
&LengthOrPercentageOrAuto::Percentage(percentage)
|
&LengthOrPercentageOrAuto::Percentage(percentage)
|
||||||
=> write!(dest, "{}%", percentage * 100.),
|
=> write!(dest, "{}%", percentage * 100.),
|
||||||
&LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
|
&LengthOrPercentageOrAuto::Auto => dest.write_str("auto"),
|
||||||
|
&LengthOrPercentageOrAuto::Calc(calc) => calc.to_css(dest),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1061,7 +1476,7 @@ pub mod computed {
|
||||||
LengthOrPercentageOrNone::Length(value.to_computed_value(context))
|
LengthOrPercentageOrNone::Length(value.to_computed_value(context))
|
||||||
}
|
}
|
||||||
specified::LengthOrPercentageOrNone::Percentage(value) => {
|
specified::LengthOrPercentageOrNone::Percentage(value) => {
|
||||||
LengthOrPercentageOrNone::Percentage(value)
|
LengthOrPercentageOrNone::Percentage(value.0)
|
||||||
}
|
}
|
||||||
specified::LengthOrPercentageOrNone::None => {
|
specified::LengthOrPercentageOrNone::None => {
|
||||||
LengthOrPercentageOrNone::None
|
LengthOrPercentageOrNone::None
|
||||||
|
|
|
@ -9,7 +9,8 @@ use parser::{ParserContext, log_css_error};
|
||||||
use properties::longhands;
|
use properties::longhands;
|
||||||
use stylesheets::Origin;
|
use stylesheets::Origin;
|
||||||
use util::geometry::{Au, PagePx, ViewportPx};
|
use util::geometry::{Au, PagePx, ViewportPx};
|
||||||
use values::specified::{AllowedNumericType, Length, LengthOrPercentageOrAuto};
|
use values::computed::{Context, ToComputedValue};
|
||||||
|
use values::specified::{AllowedNumericType, LengthOrPercentageOrAuto};
|
||||||
|
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use std::collections::hash_map::{Entry, HashMap};
|
use std::collections::hash_map::{Entry, HashMap};
|
||||||
|
@ -420,23 +421,42 @@ impl ViewportConstraints {
|
||||||
let initial_viewport = Size2D::new(Au::from_f32_px(initial_viewport.width.get()),
|
let initial_viewport = Size2D::new(Au::from_f32_px(initial_viewport.width.get()),
|
||||||
Au::from_f32_px(initial_viewport.height.get()));
|
Au::from_f32_px(initial_viewport.height.get()));
|
||||||
|
|
||||||
|
|
||||||
|
let context = Context {
|
||||||
|
is_root_element: false,
|
||||||
|
viewport_size: initial_viewport,
|
||||||
|
inherited_font_weight: longhands::font_weight::get_initial_value(),
|
||||||
|
inherited_font_size: longhands::font_size::get_initial_value(),
|
||||||
|
inherited_text_decorations_in_effect: longhands::_servo_text_decorations_in_effect::get_initial_value(),
|
||||||
|
font_size: longhands::font_size::get_initial_value(),
|
||||||
|
root_font_size: longhands::font_size::get_initial_value(),
|
||||||
|
display: longhands::display::get_initial_value(),
|
||||||
|
color: longhands::color::get_initial_value(),
|
||||||
|
text_decoration: longhands::text_decoration::get_initial_value(),
|
||||||
|
overflow_x: longhands::overflow_x::get_initial_value(),
|
||||||
|
overflow_y: longhands::overflow_y::get_initial_value(),
|
||||||
|
positioned: false,
|
||||||
|
floated: false,
|
||||||
|
border_top_present: false,
|
||||||
|
border_right_present: false,
|
||||||
|
border_bottom_present: false,
|
||||||
|
border_left_present: false,
|
||||||
|
outline_style_present: false,
|
||||||
|
};
|
||||||
|
|
||||||
macro_rules! to_pixel_length {
|
macro_rules! to_pixel_length {
|
||||||
($value:ident, $dimension:ident) => {
|
($value:ident, $dimension:ident) => {
|
||||||
if let Some($value) = $value {
|
if let Some($value) = $value {
|
||||||
match $value {
|
match $value {
|
||||||
LengthOrPercentageOrAuto::Length(ref value) => Some(match value {
|
LengthOrPercentageOrAuto::Length(value) =>
|
||||||
&Length::Absolute(length) => length,
|
Some(value.to_computed_value(&context)),
|
||||||
&Length::FontRelative(length) => {
|
|
||||||
let initial_font_size = longhands::font_size::get_initial_value();
|
|
||||||
length.to_computed_value(initial_font_size, initial_font_size)
|
|
||||||
}
|
|
||||||
&Length::ViewportPercentage(length) =>
|
|
||||||
length.to_computed_value(initial_viewport),
|
|
||||||
_ => unreachable!()
|
|
||||||
}),
|
|
||||||
LengthOrPercentageOrAuto::Percentage(value) =>
|
LengthOrPercentageOrAuto::Percentage(value) =>
|
||||||
Some(initial_viewport.$dimension.scale_by(value)),
|
Some(initial_viewport.$dimension.scale_by(value.0)),
|
||||||
LengthOrPercentageOrAuto::Auto => None,
|
LengthOrPercentageOrAuto::Auto => None,
|
||||||
|
LengthOrPercentageOrAuto::Calc(calc) => {
|
||||||
|
let calc = calc.to_computed_value(&context);
|
||||||
|
Some(initial_viewport.$dimension.scale_by(calc.percentage()) + calc.length())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
|
|
|
@ -82,6 +82,7 @@ flaky_cpu == append_style_a.html append_style_b.html
|
||||||
== box_sizing_border_box_a.html box_sizing_border_box_ref.html
|
== box_sizing_border_box_a.html box_sizing_border_box_ref.html
|
||||||
== box_sizing_sanity_check_a.html box_sizing_sanity_check_ref.html
|
== box_sizing_sanity_check_a.html box_sizing_sanity_check_ref.html
|
||||||
== br.html br-ref.html
|
== br.html br-ref.html
|
||||||
|
== calc-basic.html calc-basic-ref.html
|
||||||
== canvas_as_block_element_a.html canvas_as_block_element_ref.html
|
== canvas_as_block_element_a.html canvas_as_block_element_ref.html
|
||||||
== canvas_linear_gradient_a.html canvas_linear_gradient_ref.html
|
== canvas_linear_gradient_a.html canvas_linear_gradient_ref.html
|
||||||
== canvas_radial_gradient_a.html canvas_radial_gradient_ref.html
|
== canvas_radial_gradient_a.html canvas_radial_gradient_ref.html
|
||||||
|
|
19
tests/ref/calc-basic-ref.html
Normal file
19
tests/ref/calc-basic-ref.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<div id="outer">
|
||||||
|
<div id="inner">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
#outer {
|
||||||
|
height: 100px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inner {
|
||||||
|
height: 100%;
|
||||||
|
width: 110px;
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
19
tests/ref/calc-basic.html
Normal file
19
tests/ref/calc-basic.html
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<div id="outer">
|
||||||
|
<div id="inner">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<style>
|
||||||
|
#outer {
|
||||||
|
height: 100px;
|
||||||
|
width: 200px;
|
||||||
|
}
|
||||||
|
|
||||||
|
#inner {
|
||||||
|
height: 100%;
|
||||||
|
width: calc(50px + 30%);
|
||||||
|
background-color: green;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<title>font-size (issues #1435, #3417)</title>
|
<title>font-size (issues #1435, #3417)</title>
|
||||||
|
<style>p { margin: .5em }</style>
|
||||||
<body style="font-size: 20px">
|
<body style="font-size: 20px">
|
||||||
<p style="font-size: 24pt">24pt is 32px.
|
<p style="font-size: 24pt">24pt is 32px.
|
||||||
<p style="font-size: 2em">2em is 40px.
|
<p style="font-size: 2em">2em is 40px.
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<title>font-size (issues #1435, #3417)</title>
|
<title>font-size (issues #1435, #3417)</title>
|
||||||
|
<style>p { margin: .5em }</style>
|
||||||
<body>
|
<body>
|
||||||
<p style="font-size: 32px">24pt is 32px.
|
<p style="font-size: 32px">24pt is 32px.
|
||||||
<p style="font-size: 40px">2em is 40px.
|
<p style="font-size: 40px">2em is 40px.
|
||||||
|
|
|
@ -299,6 +299,12 @@
|
||||||
"url": "/_mozilla/mozilla/body_listener.html"
|
"url": "/_mozilla/mozilla/body_listener.html"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
|
"mozilla/calc.html": [
|
||||||
|
{
|
||||||
|
"path": "mozilla/calc.html",
|
||||||
|
"url": "/_mozilla/mozilla/calc.html"
|
||||||
|
}
|
||||||
|
],
|
||||||
"mozilla/caption.html": [
|
"mozilla/caption.html": [
|
||||||
{
|
{
|
||||||
"path": "mozilla/caption.html",
|
"path": "mozilla/caption.html",
|
||||||
|
|
128
tests/wpt/mozilla/meta/mozilla/calc.html.ini
Normal file
128
tests/wpt/mozilla/meta/mozilla/calc.html.ini
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
[calc.html]
|
||||||
|
type: testharness
|
||||||
|
[calc(1px + 1pt + 1pc + 1in + 1cm + 1mm)]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[calc(0px + 0pt + 0pc + 0in + 0cm + 0mm + 0rem + 0em + 0ex + 0% + 0vw + 0vh + 0vmin + 0vmax)]
|
||||||
|
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]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[calc for column-gap]
|
||||||
|
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]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[calc for opacity]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[calc for transition-duration]
|
||||||
|
expected: FAIL
|
||||||
|
|
153
tests/wpt/mozilla/tests/mozilla/calc.html
Normal file
153
tests/wpt/mozilla/tests/mozilla/calc.html
Normal file
|
@ -0,0 +1,153 @@
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<script src="/resources/testharness.js"></script>
|
||||||
|
<script src="/resources/testharnessreport.js"></script>
|
||||||
|
<style>
|
||||||
|
#outer {
|
||||||
|
width: 1000px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="outer">FOO<div id="inner"></div></div>
|
||||||
|
<script>
|
||||||
|
|
||||||
|
var div = document.getElementById('inner');
|
||||||
|
|
||||||
|
var widthTests = [
|
||||||
|
['calc(10px)', '10px', '10px'],
|
||||||
|
|
||||||
|
// Basic Arithmetic
|
||||||
|
['calc(10px + 10px)', '20px', '20px'],
|
||||||
|
['calc(10px - 5px)', '5px', '5px'],
|
||||||
|
['calc(2 * 10px)', '20px', '20px'],
|
||||||
|
['calc(10px / 2)', '5px', '5px'],
|
||||||
|
|
||||||
|
// Parse ok
|
||||||
|
['calc(20px/2)', '10px', '10px'],
|
||||||
|
['calc(10px*2)', '20px', '20px'],
|
||||||
|
|
||||||
|
// Parse errors - value left over from previous test
|
||||||
|
['calc(10px-10px)', '20px', '20px'],
|
||||||
|
['calc(5px+5px)', '20px', '20px'],
|
||||||
|
|
||||||
|
// Combining units
|
||||||
|
['calc(10px + 10em)', 'calc(10em + 10px)', '170px'],
|
||||||
|
['calc(10px + 10em - 10px)', 'calc(10em + 0px)', '160px'],
|
||||||
|
|
||||||
|
// Fold absolute units
|
||||||
|
['calc(1px + 1pt + 1pc + 1in + 1cm + 1mm)', '155.88333333333333px', '155.88333333333333px'],
|
||||||
|
|
||||||
|
// Alphabetical order
|
||||||
|
['calc(0px + 0pt + 0pc + 0in + 0cm + 0mm + 0rem + 0em + 0ex + 0% + 0vw + 0vh + 0vmin + 0vmax)',
|
||||||
|
'calc(0em + 0ex + 0px + 0rem + 0vh + 0vmax + 0vmin + 0vw + 0%)',
|
||||||
|
'0px'],
|
||||||
|
|
||||||
|
// Simplification
|
||||||
|
['calc((2 - 1) * 10px)', '10px', '10px'],
|
||||||
|
['calc(((3 - 1) * (8 + 4)) * 10px)', '240px', '240px'],
|
||||||
|
['calc(5 * (20px / 2 + 7 * (3em + 12px/4 + (8 - 2) * 2rem)))', 'calc(105em + 155px + 420rem)', '8555px'],
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
widthTests.forEach(function(item) {
|
||||||
|
test(function() {
|
||||||
|
div.style.setProperty('width', item[0]);
|
||||||
|
assert_equals(div.style.getPropertyValue('width'), item[1]);
|
||||||
|
assert_equals(window.getComputedStyle(div).getPropertyValue('width'), item[2]);
|
||||||
|
}, item[0]);
|
||||||
|
});
|
||||||
|
|
||||||
|
var lengthProperties = [
|
||||||
|
'border-width',
|
||||||
|
'border-top-width',
|
||||||
|
'border-left-width',
|
||||||
|
'border-right-width',
|
||||||
|
'border-bottom-width',
|
||||||
|
'outline-width',
|
||||||
|
'outline-offset',
|
||||||
|
'letter-spacing',
|
||||||
|
'word-spacing',
|
||||||
|
'border-spacing',
|
||||||
|
'column-width',
|
||||||
|
'column-gap',
|
||||||
|
'perspective',
|
||||||
|
];
|
||||||
|
|
||||||
|
lengthProperties.forEach(function(prop) {
|
||||||
|
test(function() {
|
||||||
|
div.style.setProperty(prop, 'calc(1px)');
|
||||||
|
assert_equals(div.style.getPropertyValue(prop), '1px');
|
||||||
|
assert_equals(window.getComputedStyle(div).getPropertyValue(prop), '1px');
|
||||||
|
}, 'calc for ' + prop);
|
||||||
|
});
|
||||||
|
|
||||||
|
var lengthOrPercentageProperties = [
|
||||||
|
'border-top-left-radius',
|
||||||
|
'border-bottom-left-radius',
|
||||||
|
'border-top-right-radius',
|
||||||
|
'border-bottom-right-radius',
|
||||||
|
'top',
|
||||||
|
'left',
|
||||||
|
'bottom',
|
||||||
|
'right',
|
||||||
|
'width',
|
||||||
|
'height',
|
||||||
|
'min-width',
|
||||||
|
'min-height',
|
||||||
|
'max-width',
|
||||||
|
'max-height',
|
||||||
|
'line-height',
|
||||||
|
'vertical-align',
|
||||||
|
'background-position',
|
||||||
|
'background-size',
|
||||||
|
'font-size',
|
||||||
|
'text-indent',
|
||||||
|
'transform-origin',
|
||||||
|
'perspective-origin',
|
||||||
|
];
|
||||||
|
|
||||||
|
lengthOrPercentageProperties.forEach(function(prop) {
|
||||||
|
test(function() {
|
||||||
|
div.style.setProperty(prop, 'calc(1px + 0%)');
|
||||||
|
assert_equals(div.style.getPropertyValue(prop), 'calc(1px + 0%)');
|
||||||
|
assert_equals(window.getComputedStyle(div).getPropertyValue(prop), '1px');
|
||||||
|
}, 'calc for ' + prop);
|
||||||
|
});
|
||||||
|
|
||||||
|
var timeProperties = [
|
||||||
|
'transition-delay',
|
||||||
|
];
|
||||||
|
|
||||||
|
timeProperties.forEach(function(prop) {
|
||||||
|
test(function() {
|
||||||
|
div.style.setProperty(prop, 'calc(1s)');
|
||||||
|
assert_equals(div.style.getPropertyValue(prop), '1s');
|
||||||
|
assert_equals(window.getComputedStyle(div).getPropertyValue(prop), '1s');
|
||||||
|
}, 'calc for ' + prop);
|
||||||
|
});
|
||||||
|
|
||||||
|
var numberProperties = [
|
||||||
|
'z-index',
|
||||||
|
'column-count',
|
||||||
|
'opacity',
|
||||||
|
'transition-duration',
|
||||||
|
];
|
||||||
|
|
||||||
|
numberProperties.forEach(function(prop) {
|
||||||
|
test(function() {
|
||||||
|
div.style.setProperty(prop, 'calc(1)');
|
||||||
|
assert_equals(div.style.getPropertyValue(prop), '1');
|
||||||
|
assert_equals(window.getComputedStyle(div).getPropertyValue(prop), '1');
|
||||||
|
}, 'calc for ' + prop);
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
/* TODO: test these:
|
||||||
|
counter-increment, counter-reset,
|
||||||
|
color, box-shadow, clip, text-shadow, transform
|
||||||
|
transition-timing-function
|
||||||
|
*/
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue