mirror of
https://github.com/servo/servo.git
synced 2025-06-09 09:03:23 +00:00
auto merge of #5154 : luniv/servo/viewpoint-percent-lengths, r=SimonSapin
Spec: http://dev.w3.org/csswg/css-values-3/#viewport-relative-lengths
This commit is contained in:
commit
a557b51c28
7 changed files with 254 additions and 117 deletions
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
#![allow(unsafe_blocks)]
|
#![allow(unsafe_blocks)]
|
||||||
|
|
||||||
|
use context::SharedLayoutContext;
|
||||||
use css::node_style::StyledNode;
|
use css::node_style::StyledNode;
|
||||||
use incremental::{self, RestyleDamage};
|
use incremental::{self, RestyleDamage};
|
||||||
use data::{LayoutDataAccess, LayoutDataWrapper};
|
use data::{LayoutDataAccess, LayoutDataWrapper};
|
||||||
|
@ -391,6 +392,7 @@ pub trait MatchMethods {
|
||||||
-> StyleSharingResult;
|
-> StyleSharingResult;
|
||||||
|
|
||||||
unsafe fn cascade_node(&self,
|
unsafe fn cascade_node(&self,
|
||||||
|
layout_context: &SharedLayoutContext,
|
||||||
parent: Option<LayoutNode>,
|
parent: Option<LayoutNode>,
|
||||||
applicable_declarations: &ApplicableDeclarations,
|
applicable_declarations: &ApplicableDeclarations,
|
||||||
applicable_declarations_cache: &mut ApplicableDeclarationsCache);
|
applicable_declarations_cache: &mut ApplicableDeclarationsCache);
|
||||||
|
@ -398,6 +400,7 @@ pub trait MatchMethods {
|
||||||
|
|
||||||
trait PrivateMatchMethods {
|
trait PrivateMatchMethods {
|
||||||
fn cascade_node_pseudo_element(&self,
|
fn cascade_node_pseudo_element(&self,
|
||||||
|
layout_context: &SharedLayoutContext,
|
||||||
parent_style: Option<&Arc<ComputedValues>>,
|
parent_style: Option<&Arc<ComputedValues>>,
|
||||||
applicable_declarations: &[DeclarationBlock],
|
applicable_declarations: &[DeclarationBlock],
|
||||||
style: &mut Option<Arc<ComputedValues>>,
|
style: &mut Option<Arc<ComputedValues>>,
|
||||||
|
@ -414,6 +417,7 @@ trait PrivateMatchMethods {
|
||||||
|
|
||||||
impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
fn cascade_node_pseudo_element(&self,
|
fn cascade_node_pseudo_element(&self,
|
||||||
|
layout_context: &SharedLayoutContext,
|
||||||
parent_style: Option<&Arc<ComputedValues>>,
|
parent_style: Option<&Arc<ComputedValues>>,
|
||||||
applicable_declarations: &[DeclarationBlock],
|
applicable_declarations: &[DeclarationBlock],
|
||||||
style: &mut Option<Arc<ComputedValues>>,
|
style: &mut Option<Arc<ComputedValues>>,
|
||||||
|
@ -430,7 +434,8 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
None => None,
|
None => None,
|
||||||
Some(ref style) => Some(&**style),
|
Some(ref style) => Some(&**style),
|
||||||
};
|
};
|
||||||
let (the_style, is_cacheable) = cascade(applicable_declarations,
|
let (the_style, is_cacheable) = cascade(layout_context.screen_size,
|
||||||
|
applicable_declarations,
|
||||||
shareable,
|
shareable,
|
||||||
Some(&***parent_style),
|
Some(&***parent_style),
|
||||||
cached_computed_values);
|
cached_computed_values);
|
||||||
|
@ -438,7 +443,8 @@ impl<'ln> PrivateMatchMethods for LayoutNode<'ln> {
|
||||||
this_style = Arc::new(the_style);
|
this_style = Arc::new(the_style);
|
||||||
}
|
}
|
||||||
None => {
|
None => {
|
||||||
let (the_style, is_cacheable) = cascade(applicable_declarations,
|
let (the_style, is_cacheable) = cascade(layout_context.screen_size,
|
||||||
|
applicable_declarations,
|
||||||
shareable,
|
shareable,
|
||||||
None,
|
None,
|
||||||
None);
|
None);
|
||||||
|
@ -602,6 +608,7 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe fn cascade_node(&self,
|
unsafe fn cascade_node(&self,
|
||||||
|
layout_context: &SharedLayoutContext,
|
||||||
parent: Option<LayoutNode>,
|
parent: Option<LayoutNode>,
|
||||||
applicable_declarations: &ApplicableDeclarations,
|
applicable_declarations: &ApplicableDeclarations,
|
||||||
applicable_declarations_cache: &mut ApplicableDeclarationsCache) {
|
applicable_declarations_cache: &mut ApplicableDeclarationsCache) {
|
||||||
|
@ -635,26 +642,29 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let mut damage = self.cascade_node_pseudo_element(
|
let mut damage = self.cascade_node_pseudo_element(
|
||||||
|
layout_context,
|
||||||
parent_style,
|
parent_style,
|
||||||
applicable_declarations.normal.as_slice(),
|
applicable_declarations.normal.as_slice(),
|
||||||
&mut layout_data.shared_data.style,
|
&mut layout_data.shared_data.style,
|
||||||
applicable_declarations_cache,
|
applicable_declarations_cache,
|
||||||
applicable_declarations.normal_shareable);
|
applicable_declarations.normal_shareable);
|
||||||
if applicable_declarations.before.len() > 0 {
|
if applicable_declarations.before.len() > 0 {
|
||||||
damage = damage | self.cascade_node_pseudo_element(
|
damage = damage | self.cascade_node_pseudo_element(
|
||||||
Some(layout_data.shared_data.style.as_ref().unwrap()),
|
layout_context,
|
||||||
&*applicable_declarations.before,
|
Some(layout_data.shared_data.style.as_ref().unwrap()),
|
||||||
&mut layout_data.data.before_style,
|
&*applicable_declarations.before,
|
||||||
applicable_declarations_cache,
|
&mut layout_data.data.before_style,
|
||||||
false);
|
applicable_declarations_cache,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
if applicable_declarations.after.len() > 0 {
|
if applicable_declarations.after.len() > 0 {
|
||||||
damage = damage | self.cascade_node_pseudo_element(
|
damage = damage | self.cascade_node_pseudo_element(
|
||||||
Some(layout_data.shared_data.style.as_ref().unwrap()),
|
layout_context,
|
||||||
&*applicable_declarations.after,
|
Some(layout_data.shared_data.style.as_ref().unwrap()),
|
||||||
&mut layout_data.data.after_style,
|
&*applicable_declarations.after,
|
||||||
applicable_declarations_cache,
|
&mut layout_data.data.after_style,
|
||||||
false);
|
applicable_declarations_cache,
|
||||||
|
false);
|
||||||
}
|
}
|
||||||
layout_data.data.restyle_damage = damage;
|
layout_data.data.restyle_damage = damage;
|
||||||
}
|
}
|
||||||
|
|
|
@ -176,7 +176,8 @@ impl<'a> PreorderDomTraversal for RecalcStyleForNode<'a> {
|
||||||
|
|
||||||
// Perform the CSS cascade.
|
// Perform the CSS cascade.
|
||||||
unsafe {
|
unsafe {
|
||||||
node.cascade_node(parent_opt,
|
node.cascade_node(self.layout_context.shared,
|
||||||
|
parent_opt,
|
||||||
&applicable_declarations,
|
&applicable_declarations,
|
||||||
self.layout_context.applicable_declarations_cache());
|
self.layout_context.applicable_declarations_cache());
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ impl PresentationalHintSynthesis for Stylist {
|
||||||
*shareable = false
|
*shareable = false
|
||||||
}
|
}
|
||||||
LengthOrPercentageOrAuto::Length(length) => {
|
LengthOrPercentageOrAuto::Length(length) => {
|
||||||
let width_value = specified::LengthOrPercentageOrAuto::Length(specified::Length::Au(length));
|
let width_value = specified::LengthOrPercentageOrAuto::Length(specified::Length::Absolute(length));
|
||||||
matching_rules_list.vec_push(from_declaration(
|
matching_rules_list.vec_push(from_declaration(
|
||||||
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
PropertyDeclaration::Width(SpecifiedValue(width_value))));
|
||||||
*shareable = false
|
*shareable = false
|
||||||
|
@ -160,9 +160,9 @@ impl PresentationalHintSynthesis for Stylist {
|
||||||
// FIXME(pcwalton): More use of atoms, please!
|
// FIXME(pcwalton): More use of atoms, please!
|
||||||
let value = match element.get_attr(&ns!(""), &atom!("type")) {
|
let value = match element.get_attr(&ns!(""), &atom!("type")) {
|
||||||
Some("text") | Some("password") => {
|
Some("text") | Some("password") => {
|
||||||
specified::Length::ServoCharacterWidth(value)
|
specified::Length::ServoCharacterWidth(specified::CharacterWidth(value))
|
||||||
}
|
}
|
||||||
_ => specified::Length::Au(Au::from_px(value as int)),
|
_ => specified::Length::Absolute(Au::from_px(value as int)),
|
||||||
};
|
};
|
||||||
matching_rules_list.vec_push(from_declaration(
|
matching_rules_list.vec_push(from_declaration(
|
||||||
PropertyDeclaration::Width(SpecifiedValue(
|
PropertyDeclaration::Width(SpecifiedValue(
|
||||||
|
@ -180,7 +180,7 @@ impl PresentationalHintSynthesis for Stylist {
|
||||||
// scrollbar size into consideration (but we don't have a scrollbar yet!)
|
// scrollbar size into consideration (but we don't have a scrollbar yet!)
|
||||||
//
|
//
|
||||||
// https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-width
|
// https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-width
|
||||||
let value = specified::Length::ServoCharacterWidth(value);
|
let value = specified::Length::ServoCharacterWidth(specified::CharacterWidth(value));
|
||||||
matching_rules_list.vec_push(from_declaration(
|
matching_rules_list.vec_push(from_declaration(
|
||||||
PropertyDeclaration::Width(SpecifiedValue(
|
PropertyDeclaration::Width(SpecifiedValue(
|
||||||
specified::LengthOrPercentageOrAuto::Length(value)))));
|
specified::LengthOrPercentageOrAuto::Length(value)))));
|
||||||
|
@ -193,7 +193,7 @@ impl PresentationalHintSynthesis for Stylist {
|
||||||
// TODO(mttr) This should take scrollbar size into consideration.
|
// TODO(mttr) This should take scrollbar size into consideration.
|
||||||
//
|
//
|
||||||
// https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-height
|
// https://html.spec.whatwg.org/multipage/rendering.html#textarea-effective-height
|
||||||
let value = specified::Length::Em(value as CSSFloat);
|
let value = specified::Length::FontRelative(specified::FontRelativeLength::Em(value as CSSFloat));
|
||||||
matching_rules_list.vec_push(from_declaration(
|
matching_rules_list.vec_push(from_declaration(
|
||||||
PropertyDeclaration::Height(SpecifiedValue(
|
PropertyDeclaration::Height(SpecifiedValue(
|
||||||
longhands::height::SpecifiedValue(
|
longhands::height::SpecifiedValue(
|
||||||
|
@ -241,7 +241,7 @@ impl PresentationalHintSynthesis for Stylist {
|
||||||
match element.get_unsigned_integer_attribute(UnsignedIntegerAttribute::Border) {
|
match element.get_unsigned_integer_attribute(UnsignedIntegerAttribute::Border) {
|
||||||
None => {}
|
None => {}
|
||||||
Some(length) => {
|
Some(length) => {
|
||||||
let width_value = specified::Length::Au(Au::from_px(length as int));
|
let width_value = specified::Length::Absolute(Au::from_px(length as int));
|
||||||
matching_rules_list.vec_push(from_declaration(
|
matching_rules_list.vec_push(from_declaration(
|
||||||
PropertyDeclaration::BorderTopWidth(SpecifiedValue(
|
PropertyDeclaration::BorderTopWidth(SpecifiedValue(
|
||||||
longhands::border_top_width::SpecifiedValue(width_value)))));
|
longhands::border_top_width::SpecifiedValue(width_value)))));
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
use cssparser::{Token, Parser, Delimiter};
|
use cssparser::{Token, Parser, Delimiter};
|
||||||
|
|
||||||
use geom::size::TypedSize2D;
|
use geom::size::{Size2D, TypedSize2D};
|
||||||
use properties::longhands;
|
use properties::longhands;
|
||||||
use util::geometry::{Au, ViewportPx};
|
use util::geometry::{Au, ViewportPx};
|
||||||
use values::specified;
|
use values::specified;
|
||||||
|
@ -23,6 +23,31 @@ pub enum Range<T> {
|
||||||
//Eq(T), // FIXME: Implement parsing support for equality then re-enable this.
|
//Eq(T), // FIXME: Implement parsing support for equality then re-enable this.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl Range<specified::Length> {
|
||||||
|
fn to_computed_range(&self, viewport_size: Size2D<Au>) -> Range<Au> {
|
||||||
|
let compute_width = |width| {
|
||||||
|
match width {
|
||||||
|
&specified::Length::Absolute(value) => value,
|
||||||
|
&specified::Length::FontRelative(value) => {
|
||||||
|
// http://dev.w3.org/csswg/mediaqueries3/ - Section 6
|
||||||
|
// em units are relative to the initial font-size.
|
||||||
|
let initial_font_size = longhands::font_size::get_initial_value();
|
||||||
|
value.to_computed_value(initial_font_size, initial_font_size)
|
||||||
|
}
|
||||||
|
&specified::Length::ViewportPercentage(value) =>
|
||||||
|
value.to_computed_value(viewport_size),
|
||||||
|
_ => unreachable!()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
match *self {
|
||||||
|
Range::Min(ref width) => Range::Min(compute_width(width)),
|
||||||
|
Range::Max(ref width) => Range::Max(compute_width(width)),
|
||||||
|
//Range::Eq(ref width) => Range::Eq(compute_width(width))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: Ord> Range<T> {
|
impl<T: Ord> Range<T> {
|
||||||
fn evaluate(&self, value: T) -> bool {
|
fn evaluate(&self, value: T) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
|
@ -33,9 +58,9 @@ impl<T: Ord> Range<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Debug)]
|
#[derive(PartialEq, Copy, Debug)]
|
||||||
pub enum Expression {
|
pub enum Expression {
|
||||||
Width(Range<Au>),
|
Width(Range<specified::Length>),
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Copy, Debug)]
|
#[derive(PartialEq, Eq, Copy, Debug)]
|
||||||
|
@ -91,17 +116,6 @@ impl Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn parse_non_negative_length(input: &mut Parser) -> Result<Au, ()> {
|
|
||||||
let length = try!(specified::Length::parse_non_negative(input));
|
|
||||||
|
|
||||||
// http://dev.w3.org/csswg/mediaqueries3/ - Section 6
|
|
||||||
// em units are relative to the initial font-size.
|
|
||||||
let initial_font_size = longhands::font_size::get_initial_value();
|
|
||||||
Ok(length.to_computed_value_with_font_size(initial_font_size, initial_font_size))
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
impl Expression {
|
impl Expression {
|
||||||
fn parse(input: &mut Parser) -> Result<Expression, ()> {
|
fn parse(input: &mut Parser) -> Result<Expression, ()> {
|
||||||
try!(input.expect_parenthesis_block());
|
try!(input.expect_parenthesis_block());
|
||||||
|
@ -111,10 +125,10 @@ impl Expression {
|
||||||
// TODO: Handle other media features
|
// TODO: Handle other media features
|
||||||
match_ignore_ascii_case! { name,
|
match_ignore_ascii_case! { name,
|
||||||
"min-width" => {
|
"min-width" => {
|
||||||
Ok(Expression::Width(Range::Min(try!(parse_non_negative_length(input)))))
|
Ok(Expression::Width(Range::Min(try!(specified::Length::parse_non_negative(input)))))
|
||||||
},
|
},
|
||||||
"max-width" => {
|
"max-width" => {
|
||||||
Ok(Expression::Width(Range::Max(try!(parse_non_negative_length(input)))))
|
Ok(Expression::Width(Range::Max(try!(specified::Length::parse_non_negative(input)))))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
|
@ -186,6 +200,9 @@ pub fn parse_media_query_list(input: &mut Parser) -> MediaQueryList {
|
||||||
|
|
||||||
impl MediaQueryList {
|
impl MediaQueryList {
|
||||||
pub fn evaluate(&self, device: &Device) -> bool {
|
pub fn evaluate(&self, device: &Device) -> bool {
|
||||||
|
let viewport_size = Size2D(Au::from_frac32_px(device.viewport_size.width.get()),
|
||||||
|
Au::from_frac32_px(device.viewport_size.height.get()));
|
||||||
|
|
||||||
// Check if any queries match (OR condition)
|
// Check if any queries match (OR condition)
|
||||||
self.media_queries.iter().any(|mq| {
|
self.media_queries.iter().any(|mq| {
|
||||||
// Check if media matches. Unknown media never matches.
|
// Check if media matches. Unknown media never matches.
|
||||||
|
@ -198,8 +215,8 @@ impl MediaQueryList {
|
||||||
// Check if all conditions match (AND condition)
|
// Check if all conditions match (AND condition)
|
||||||
let query_match = media_match && mq.expressions.iter().all(|expression| {
|
let query_match = media_match && mq.expressions.iter().all(|expression| {
|
||||||
match expression {
|
match expression {
|
||||||
&Expression::Width(value) => value.evaluate(
|
&Expression::Width(value) =>
|
||||||
Au::from_frac_px(device.viewport_size.to_untyped().width as f64)),
|
value.to_computed_range(viewport_size).evaluate(viewport_size.width),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -220,6 +237,7 @@ mod tests {
|
||||||
use stylesheets::Origin;
|
use stylesheets::Origin;
|
||||||
use super::*;
|
use super::*;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
use values::specified;
|
||||||
use std::borrow::ToOwned;
|
use std::borrow::ToOwned;
|
||||||
|
|
||||||
fn test_media_rule<F>(css: &str, callback: F) where F: Fn(&MediaQueryList, &str) {
|
fn test_media_rule<F>(css: &str, callback: F) where F: Fn(&MediaQueryList, &str) {
|
||||||
|
@ -385,7 +403,7 @@ mod tests {
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
match q.expressions[0] {
|
match q.expressions[0] {
|
||||||
Expression::Width(Range::Min(w)) => assert!(w == Au::from_px(100)),
|
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -397,7 +415,7 @@ mod tests {
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
match q.expressions[0] {
|
match q.expressions[0] {
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(43)),
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -412,7 +430,7 @@ mod tests {
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
match q.expressions[0] {
|
match q.expressions[0] {
|
||||||
Expression::Width(Range::Min(w)) => assert!(w == Au::from_px(100)),
|
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -424,7 +442,7 @@ mod tests {
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Print), css.to_owned());
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
match q.expressions[0] {
|
match q.expressions[0] {
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(43)),
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(43))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -436,7 +454,7 @@ mod tests {
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Unknown), css.to_owned());
|
||||||
assert!(q.expressions.len() == 1, css.to_owned());
|
assert!(q.expressions.len() == 1, css.to_owned());
|
||||||
match q.expressions[0] {
|
match q.expressions[0] {
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(52)),
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(52))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -451,11 +469,11 @@ mod tests {
|
||||||
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
assert!(q.media_type == MediaQueryType::All, css.to_owned());
|
||||||
assert!(q.expressions.len() == 2, css.to_owned());
|
assert!(q.expressions.len() == 2, css.to_owned());
|
||||||
match q.expressions[0] {
|
match q.expressions[0] {
|
||||||
Expression::Width(Range::Min(w)) => assert!(w == Au::from_px(100)),
|
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
match q.expressions[1] {
|
match q.expressions[1] {
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(200)),
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(200))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -467,11 +485,11 @@ mod tests {
|
||||||
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
assert!(q.media_type == MediaQueryType::MediaType(MediaType::Screen), css.to_owned());
|
||||||
assert!(q.expressions.len() == 2, css.to_owned());
|
assert!(q.expressions.len() == 2, css.to_owned());
|
||||||
match q.expressions[0] {
|
match q.expressions[0] {
|
||||||
Expression::Width(Range::Min(w)) => assert!(w == Au::from_px(100)),
|
Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(100))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
match q.expressions[1] {
|
match q.expressions[1] {
|
||||||
Expression::Width(Range::Max(w)) => assert!(w == Au::from_px(200)),
|
Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(200))),
|
||||||
_ => panic!("wrong expression type"),
|
_ => panic!("wrong expression type"),
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -19,8 +19,9 @@ use cssparser::{Parser, Color, RGBA, AtRuleParser, DeclarationParser,
|
||||||
DeclarationListParser, parse_important, ToCss};
|
DeclarationListParser, parse_important, ToCss};
|
||||||
use geom::num::Zero;
|
use geom::num::Zero;
|
||||||
use geom::SideOffsets2D;
|
use geom::SideOffsets2D;
|
||||||
|
use geom::size::Size2D;
|
||||||
|
|
||||||
use values::specified::BorderStyle;
|
use values::specified::{Length, BorderStyle};
|
||||||
use values::computed::{self, ToComputedValue};
|
use values::computed::{self, ToComputedValue};
|
||||||
use selectors::matching::DeclarationBlock;
|
use selectors::matching::DeclarationBlock;
|
||||||
use parser::{ParserContext, log_css_error};
|
use parser::{ParserContext, log_css_error};
|
||||||
|
@ -566,7 +567,7 @@ pub mod longhands {
|
||||||
SpecifiedValue::Number(value) => computed_value::T::Number(value),
|
SpecifiedValue::Number(value) => computed_value::T::Number(value),
|
||||||
SpecifiedValue::Percentage(value) => {
|
SpecifiedValue::Percentage(value) => {
|
||||||
computed_value::T::Length(
|
computed_value::T::Length(
|
||||||
specified::Length::Em(value).to_computed_value(context))
|
specified::Length::FontRelative(specified::FontRelativeLength::Em(value)).to_computed_value(context))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1475,21 +1476,21 @@ pub mod longhands {
|
||||||
input.try(specified::LengthOrPercentage::parse_non_negative)
|
input.try(specified::LengthOrPercentage::parse_non_negative)
|
||||||
.map(|value| match value {
|
.map(|value| match value {
|
||||||
specified::LengthOrPercentage::Length(value) => value,
|
specified::LengthOrPercentage::Length(value) => value,
|
||||||
specified::LengthOrPercentage::Percentage(value) => specified::Length::Em(value)
|
specified::LengthOrPercentage::Percentage(value) => specified::Length::FontRelative(specified::FontRelativeLength::Em(value))
|
||||||
})
|
})
|
||||||
.or_else(|()| {
|
.or_else(|()| {
|
||||||
match_ignore_ascii_case! { try!(input.expect_ident()),
|
match_ignore_ascii_case! { try!(input.expect_ident()),
|
||||||
"xx-small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 5)),
|
"xx-small" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 3 / 5)),
|
||||||
"x-small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 4)),
|
"x-small" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 3 / 4)),
|
||||||
"small" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 8 / 9)),
|
"small" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 8 / 9)),
|
||||||
"medium" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX))),
|
"medium" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX))),
|
||||||
"large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 6 / 5)),
|
"large" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 6 / 5)),
|
||||||
"x-large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 3 / 2)),
|
"x-large" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 3 / 2)),
|
||||||
"xx-large" => Ok(specified::Length::Au(Au::from_px(MEDIUM_PX) * 2)),
|
"xx-large" => Ok(specified::Length::Absolute(Au::from_px(MEDIUM_PX) * 2)),
|
||||||
|
|
||||||
// https://github.com/servo/servo/issues/3423#issuecomment-56321664
|
// https://github.com/servo/servo/issues/3423#issuecomment-56321664
|
||||||
"smaller" => Ok(specified::Length::Em(0.85)),
|
"smaller" => Ok(specified::Length::FontRelative(specified::FontRelativeLength::Em(0.85))),
|
||||||
"larger" => Ok(specified::Length::Em(1.2))
|
"larger" => Ok(specified::Length::FontRelative(specified::FontRelativeLength::Em(1.2)))
|
||||||
|
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
|
@ -2038,7 +2039,7 @@ pub mod longhands {
|
||||||
|
|
||||||
pub fn parse_one_box_shadow(input: &mut Parser) -> Result<SpecifiedBoxShadow, ()> {
|
pub fn parse_one_box_shadow(input: &mut Parser) -> Result<SpecifiedBoxShadow, ()> {
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
let mut lengths = [specified::Length::Au(Au(0)); 4];
|
let mut lengths = [specified::Length::Absolute(Au(0)); 4];
|
||||||
let mut lengths_parsed = false;
|
let mut lengths_parsed = false;
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
let mut inset = false;
|
let mut inset = false;
|
||||||
|
@ -2208,10 +2209,10 @@ pub mod longhands {
|
||||||
}));
|
}));
|
||||||
if sides.len() == 4 {
|
if sides.len() == 4 {
|
||||||
Ok(Some(SpecifiedClipRect {
|
Ok(Some(SpecifiedClipRect {
|
||||||
top: sides[0].unwrap_or(Length::Au(Au(0))),
|
top: sides[0].unwrap_or(Length::Absolute(Au(0))),
|
||||||
right: sides[1],
|
right: sides[1],
|
||||||
bottom: sides[2],
|
bottom: sides[2],
|
||||||
left: sides[3].unwrap_or(Length::Au(Au(0))),
|
left: sides[3].unwrap_or(Length::Absolute(Au(0))),
|
||||||
}))
|
}))
|
||||||
} else {
|
} else {
|
||||||
Err(())
|
Err(())
|
||||||
|
@ -2317,7 +2318,7 @@ pub mod longhands {
|
||||||
|
|
||||||
fn parse_one_text_shadow(input: &mut Parser) -> Result<SpecifiedTextShadow,()> {
|
fn parse_one_text_shadow(input: &mut Parser) -> Result<SpecifiedTextShadow,()> {
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
let mut lengths = [specified::Length::Au(Au(0)); 3];
|
let mut lengths = [specified::Length::Absolute(Au(0)); 3];
|
||||||
let mut lengths_parsed = false;
|
let mut lengths_parsed = false;
|
||||||
let mut color = None;
|
let mut color = None;
|
||||||
|
|
||||||
|
@ -2855,7 +2856,7 @@ pub mod shorthands {
|
||||||
fn parse_one_set_of_border_radii(mut input: &mut Parser)
|
fn parse_one_set_of_border_radii(mut input: &mut Parser)
|
||||||
-> Result<[LengthOrPercentage; 4], ()> {
|
-> Result<[LengthOrPercentage; 4], ()> {
|
||||||
let mut count = 0;
|
let mut count = 0;
|
||||||
let mut values = [LengthOrPercentage::Length(Length::Au(Au(0))); 4];
|
let mut values = [LengthOrPercentage::Length(Length::Absolute(Au(0))); 4];
|
||||||
while count < 4 {
|
while count < 4 {
|
||||||
if let Ok(value) = input.try(LengthOrPercentage::parse) {
|
if let Ok(value) = input.try(LengthOrPercentage::parse) {
|
||||||
values[count] = value;
|
values[count] = value;
|
||||||
|
@ -3699,6 +3700,8 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock<
|
||||||
/// Performs the CSS cascade, computing new styles for an element from its parent style and
|
/// Performs the CSS cascade, computing new styles for an element from its parent style and
|
||||||
/// optionally a cached related style. The arguments are:
|
/// optionally a cached related style. The arguments are:
|
||||||
///
|
///
|
||||||
|
/// * `viewport_size`: The size of the initial viewport.
|
||||||
|
///
|
||||||
/// * `applicable_declarations`: The list of CSS rules that matched.
|
/// * `applicable_declarations`: The list of CSS rules that matched.
|
||||||
///
|
///
|
||||||
/// * `shareable`: Whether the `ComputedValues` structure to be constructed should be considered
|
/// * `shareable`: Whether the `ComputedValues` structure to be constructed should be considered
|
||||||
|
@ -3712,7 +3715,8 @@ fn cascade_with_cached_declarations(applicable_declarations: &[DeclarationBlock<
|
||||||
/// this is ignored.
|
/// this is ignored.
|
||||||
///
|
///
|
||||||
/// Returns the computed values and a boolean indicating whether the result is cacheable.
|
/// Returns the computed values and a boolean indicating whether the result is cacheable.
|
||||||
pub fn cascade(applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>],
|
pub fn cascade(viewport_size: Size2D<Au>,
|
||||||
|
applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclaration>>],
|
||||||
shareable: bool,
|
shareable: bool,
|
||||||
parent_style: Option< &ComputedValues >,
|
parent_style: Option< &ComputedValues >,
|
||||||
cached_style: Option< &ComputedValues >)
|
cached_style: Option< &ComputedValues >)
|
||||||
|
@ -3727,6 +3731,7 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclarati
|
||||||
let inherited_font_style = inherited_style.get_font();
|
let inherited_font_style = inherited_style.get_font();
|
||||||
computed::Context {
|
computed::Context {
|
||||||
is_root_element: is_root_element,
|
is_root_element: is_root_element,
|
||||||
|
viewport_size: viewport_size,
|
||||||
inherited_font_weight: inherited_font_style.font_weight,
|
inherited_font_weight: inherited_font_style.font_weight,
|
||||||
inherited_font_size: inherited_font_style.font_size,
|
inherited_font_size: inherited_font_style.font_size,
|
||||||
inherited_height: inherited_style.get_box().height,
|
inherited_height: inherited_style.get_box().height,
|
||||||
|
@ -3769,9 +3774,12 @@ pub fn cascade(applicable_declarations: &[DeclarationBlock<Vec<PropertyDeclarati
|
||||||
PropertyDeclaration::FontSize(ref value) => {
|
PropertyDeclaration::FontSize(ref value) => {
|
||||||
context.font_size = match *value {
|
context.font_size = match *value {
|
||||||
DeclaredValue::SpecifiedValue(ref specified_value) => {
|
DeclaredValue::SpecifiedValue(ref specified_value) => {
|
||||||
specified_value.0.to_computed_value_with_font_size(
|
match specified_value.0 {
|
||||||
context.inherited_font_size, context.root_font_size
|
Length::FontRelative(value) => value.to_computed_value(context.inherited_font_size,
|
||||||
)
|
context.root_font_size),
|
||||||
|
Length::ServoCharacterWidth(value) => value.to_computed_value(context.inherited_font_size),
|
||||||
|
_ => specified_value.0.to_computed_value(&context)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
DeclaredValue::Initial => longhands::font_size::get_initial_value(),
|
DeclaredValue::Initial => longhands::font_size::get_initial_value(),
|
||||||
DeclaredValue::Inherit => context.inherited_font_size,
|
DeclaredValue::Inherit => context.inherited_font_size,
|
||||||
|
|
|
@ -52,11 +52,14 @@ pub type CSSFloat = f64;
|
||||||
|
|
||||||
pub mod specified {
|
pub mod specified {
|
||||||
use std::ascii::AsciiExt;
|
use std::ascii::AsciiExt;
|
||||||
|
use std::cmp;
|
||||||
use std::f64::consts::PI;
|
use std::f64::consts::PI;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use std::fmt::{Formatter, Debug};
|
use std::fmt::{Formatter, Debug};
|
||||||
|
use std::num::{NumCast, ToPrimitive};
|
||||||
use url::Url;
|
use url::Url;
|
||||||
use cssparser::{self, Token, Parser, ToCss, CssStringWriter};
|
use cssparser::{self, Token, Parser, ToCss, CssStringWriter};
|
||||||
|
use geom::size::Size2D;
|
||||||
use parser::ParserContext;
|
use parser::ParserContext;
|
||||||
use text_writer::{self, TextWriter};
|
use text_writer::{self, TextWriter};
|
||||||
use util::geometry::Au;
|
use util::geometry::Au;
|
||||||
|
@ -114,17 +117,114 @@ pub mod specified {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Copy)]
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
pub enum Length {
|
pub enum FontRelativeLength {
|
||||||
Au(Au), // application units
|
|
||||||
Em(CSSFloat),
|
Em(CSSFloat),
|
||||||
Ex(CSSFloat),
|
Ex(CSSFloat),
|
||||||
Rem(CSSFloat),
|
Rem(CSSFloat)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for FontRelativeLength {
|
||||||
|
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for FontRelativeLength {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
|
||||||
|
match self {
|
||||||
|
&FontRelativeLength::Em(length) => write!(dest, "{}em", length),
|
||||||
|
&FontRelativeLength::Ex(length) => write!(dest, "{}ex", length),
|
||||||
|
&FontRelativeLength::Rem(length) => write!(dest, "{}rem", length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FontRelativeLength {
|
||||||
|
pub fn to_computed_value(&self,
|
||||||
|
reference_font_size: Au,
|
||||||
|
root_font_size: Au)
|
||||||
|
-> Au
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
&FontRelativeLength::Em(length) => reference_font_size.scale_by(length),
|
||||||
|
&FontRelativeLength::Ex(length) => {
|
||||||
|
let x_height = 0.5; // TODO: find that from the font
|
||||||
|
reference_font_size.scale_by(length * x_height)
|
||||||
|
},
|
||||||
|
&FontRelativeLength::Rem(length) => root_font_size.scale_by(length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
|
pub enum ViewportPercentageLength {
|
||||||
|
Vw(CSSFloat),
|
||||||
|
Vh(CSSFloat),
|
||||||
|
Vmin(CSSFloat),
|
||||||
|
Vmax(CSSFloat)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Debug for ViewportPercentageLength {
|
||||||
|
#[inline] fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { self.fmt_to_css(f) }
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ToCss for ViewportPercentageLength {
|
||||||
|
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
|
||||||
|
match self {
|
||||||
|
&ViewportPercentageLength::Vw(length) => write!(dest, "{}vw", length),
|
||||||
|
&ViewportPercentageLength::Vh(length) => write!(dest, "{}vh", length),
|
||||||
|
&ViewportPercentageLength::Vmin(length) => write!(dest, "{}vmin", length),
|
||||||
|
&ViewportPercentageLength::Vmax(length) => write!(dest, "{}vmax", length)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ViewportPercentageLength {
|
||||||
|
pub fn to_computed_value(&self, viewport_size: Size2D<Au>) -> Au {
|
||||||
|
macro_rules! to_unit {
|
||||||
|
($viewport_dimension:expr) => {
|
||||||
|
$viewport_dimension.to_f64().unwrap() / 100.0
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let value = match self {
|
||||||
|
&ViewportPercentageLength::Vw(length) =>
|
||||||
|
length * to_unit!(viewport_size.width),
|
||||||
|
&ViewportPercentageLength::Vh(length) =>
|
||||||
|
length * to_unit!(viewport_size.height),
|
||||||
|
&ViewportPercentageLength::Vmin(length) =>
|
||||||
|
length * to_unit!(cmp::min(viewport_size.width, viewport_size.height)),
|
||||||
|
&ViewportPercentageLength::Vmax(length) =>
|
||||||
|
length * to_unit!(cmp::max(viewport_size.width, viewport_size.height)),
|
||||||
|
};
|
||||||
|
NumCast::from(value).unwrap()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
|
pub struct CharacterWidth(pub i32);
|
||||||
|
|
||||||
|
impl CharacterWidth {
|
||||||
|
pub fn to_computed_value(&self, reference_font_size: Au) -> Au {
|
||||||
|
// This applies the *converting a character width to pixels* algorithm as specified
|
||||||
|
// in HTML5 § 14.5.4.
|
||||||
|
//
|
||||||
|
// TODO(pcwalton): Find these from the font.
|
||||||
|
let average_advance = reference_font_size.scale_by(0.5);
|
||||||
|
let max_advance = reference_font_size;
|
||||||
|
average_advance.scale_by(self.0 as CSSFloat - 1.0) + max_advance
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, PartialEq, Copy)]
|
||||||
|
pub enum Length {
|
||||||
|
Absolute(Au), // application units
|
||||||
|
FontRelative(FontRelativeLength),
|
||||||
|
ViewportPercentage(ViewportPercentageLength),
|
||||||
|
|
||||||
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
|
/// HTML5 "character width", as defined in HTML5 § 14.5.4.
|
||||||
///
|
///
|
||||||
/// 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(i32),
|
ServoCharacterWidth(CharacterWidth),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for Length {
|
impl fmt::Debug for Length {
|
||||||
|
@ -134,41 +234,15 @@ pub mod specified {
|
||||||
impl ToCss for Length {
|
impl ToCss for Length {
|
||||||
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
|
fn to_css<W>(&self, dest: &mut W) -> text_writer::Result where W: TextWriter {
|
||||||
match self {
|
match self {
|
||||||
&Length::Au(length) => write!(dest, "{}px", length.to_subpx()),
|
&Length::Absolute(length) => write!(dest, "{}px", length.to_subpx()),
|
||||||
&Length::Em(length) => write!(dest, "{}em", length),
|
&Length::FontRelative(length) => length.to_css(dest),
|
||||||
&Length::Ex(length) => write!(dest, "{}ex", length),
|
&Length::ViewportPercentage(length) => length.to_css(dest),
|
||||||
&Length::Rem(length) => write!(dest, "{}rem", length),
|
|
||||||
&Length::ServoCharacterWidth(_)
|
&Length::ServoCharacterWidth(_)
|
||||||
=> panic!("internal CSS values should never be serialized"),
|
=> panic!("internal CSS values should never be serialized"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Length {
|
|
||||||
pub fn to_computed_value_with_font_size(&self, reference_font_size: Au, root_font_size: Au)
|
|
||||||
-> Au {
|
|
||||||
match *self {
|
|
||||||
Length::Au(value) => value,
|
|
||||||
Length::Em(value) => reference_font_size.scale_by(value),
|
|
||||||
Length::Ex(value) => {
|
|
||||||
let x_height = 0.5; // TODO: find that from the font
|
|
||||||
reference_font_size.scale_by(value * x_height)
|
|
||||||
},
|
|
||||||
Length::Rem(value) => root_font_size.scale_by(value),
|
|
||||||
Length::ServoCharacterWidth(value) => {
|
|
||||||
// This applies the *converting a character width to pixels* algorithm as specified
|
|
||||||
// in HTML5 § 14.5.4.
|
|
||||||
//
|
|
||||||
// TODO(pcwalton): Find these from the font.
|
|
||||||
let average_advance = reference_font_size.scale_by(0.5);
|
|
||||||
let max_advance = reference_font_size;
|
|
||||||
average_advance.scale_by(value as CSSFloat - 1.0) + max_advance
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const AU_PER_PX: CSSFloat = 60.;
|
const AU_PER_PX: CSSFloat = 60.;
|
||||||
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;
|
||||||
|
@ -182,7 +256,7 @@ pub mod specified {
|
||||||
Token::Dimension(ref value, ref unit) if negative_ok || value.value >= 0. => {
|
Token::Dimension(ref value, ref unit) if negative_ok || value.value >= 0. => {
|
||||||
Length::parse_dimension(value.value, unit)
|
Length::parse_dimension(value.value, unit)
|
||||||
}
|
}
|
||||||
Token::Number(ref value) if value.value == 0. => Ok(Length::Au(Au(0))),
|
Token::Number(ref value) if value.value == 0. => Ok(Length::Absolute(Au(0))),
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,20 +270,26 @@ pub mod specified {
|
||||||
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
pub fn parse_dimension(value: CSSFloat, unit: &str) -> Result<Length, ()> {
|
||||||
match_ignore_ascii_case! { unit,
|
match_ignore_ascii_case! { unit,
|
||||||
"px" => Ok(Length::from_px(value)),
|
"px" => Ok(Length::from_px(value)),
|
||||||
"in" => Ok(Length::Au(Au((value * AU_PER_IN) as i32))),
|
"in" => Ok(Length::Absolute(Au((value * AU_PER_IN) as i32))),
|
||||||
"cm" => Ok(Length::Au(Au((value * AU_PER_CM) as i32))),
|
"cm" => Ok(Length::Absolute(Au((value * AU_PER_CM) as i32))),
|
||||||
"mm" => Ok(Length::Au(Au((value * AU_PER_MM) as i32))),
|
"mm" => Ok(Length::Absolute(Au((value * AU_PER_MM) as i32))),
|
||||||
"pt" => Ok(Length::Au(Au((value * AU_PER_PT) as i32))),
|
"pt" => Ok(Length::Absolute(Au((value * AU_PER_PT) as i32))),
|
||||||
"pc" => Ok(Length::Au(Au((value * AU_PER_PC) as i32))),
|
"pc" => Ok(Length::Absolute(Au((value * AU_PER_PC) as i32))),
|
||||||
"em" => Ok(Length::Em(value)),
|
// font-relative
|
||||||
"ex" => Ok(Length::Ex(value)),
|
"em" => Ok(Length::FontRelative(FontRelativeLength::Em(value))),
|
||||||
"rem" => Ok(Length::Rem(value))
|
"ex" => Ok(Length::FontRelative(FontRelativeLength::Ex(value))),
|
||||||
|
"rem" => Ok(Length::FontRelative(FontRelativeLength::Rem(value))),
|
||||||
|
// viewport percentages
|
||||||
|
"vw" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vw(value))),
|
||||||
|
"vh" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vh(value))),
|
||||||
|
"vmin" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vmin(value))),
|
||||||
|
"vmax" => Ok(Length::ViewportPercentage(ViewportPercentageLength::Vmax(value)))
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn from_px(px_value: CSSFloat) -> Length {
|
pub fn from_px(px_value: CSSFloat) -> Length {
|
||||||
Length::Au(Au((px_value * AU_PER_PX) as i32))
|
Length::Absolute(Au((px_value * AU_PER_PX) as i32))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,7 +325,7 @@ pub mod specified {
|
||||||
Ok(LengthOrPercentage::Percentage(value.unit_value))
|
Ok(LengthOrPercentage::Percentage(value.unit_value))
|
||||||
}
|
}
|
||||||
Token::Number(ref value) if value.value == 0. => {
|
Token::Number(ref value) if value.value == 0. => {
|
||||||
Ok(LengthOrPercentage::Length(Length::Au(Au(0))))
|
Ok(LengthOrPercentage::Length(Length::Absolute(Au(0))))
|
||||||
}
|
}
|
||||||
_ => Err(())
|
_ => Err(())
|
||||||
}
|
}
|
||||||
|
@ -294,7 +374,7 @@ pub mod specified {
|
||||||
Ok(LengthOrPercentageOrAuto::Percentage(value.unit_value))
|
Ok(LengthOrPercentageOrAuto::Percentage(value.unit_value))
|
||||||
}
|
}
|
||||||
Token::Number(ref value) if value.value == 0. => {
|
Token::Number(ref value) if value.value == 0. => {
|
||||||
Ok(LengthOrPercentageOrAuto::Length(Length::Au(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)
|
||||||
|
@ -345,7 +425,7 @@ pub mod specified {
|
||||||
Ok(LengthOrPercentageOrNone::Percentage(value.unit_value))
|
Ok(LengthOrPercentageOrNone::Percentage(value.unit_value))
|
||||||
}
|
}
|
||||||
Token::Number(ref value) if value.value == 0. => {
|
Token::Number(ref value) if value.value == 0. => {
|
||||||
Ok(LengthOrPercentageOrNone::Length(Length::Au(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") => {
|
||||||
Ok(LengthOrPercentageOrNone::None)
|
Ok(LengthOrPercentageOrNone::None)
|
||||||
|
@ -386,7 +466,7 @@ pub mod specified {
|
||||||
Ok(PositionComponent::Percentage(value.unit_value))
|
Ok(PositionComponent::Percentage(value.unit_value))
|
||||||
}
|
}
|
||||||
Token::Number(ref value) if value.value == 0. => {
|
Token::Number(ref value) if value.value == 0. => {
|
||||||
Ok(PositionComponent::Length(Length::Au(Au(0))))
|
Ok(PositionComponent::Length(Length::Absolute(Au(0))))
|
||||||
}
|
}
|
||||||
Token::Ident(value) => {
|
Token::Ident(value) => {
|
||||||
match_ignore_ascii_case! { value,
|
match_ignore_ascii_case! { value,
|
||||||
|
@ -673,6 +753,7 @@ pub mod computed {
|
||||||
use super::specified::{AngleOrCorner};
|
use super::specified::{AngleOrCorner};
|
||||||
use super::{specified, CSSFloat};
|
use super::{specified, CSSFloat};
|
||||||
pub use cssparser::Color as CSSColor;
|
pub use cssparser::Color as CSSColor;
|
||||||
|
use geom::size::Size2D;
|
||||||
use properties::longhands;
|
use properties::longhands;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
@ -699,6 +780,7 @@ pub mod computed {
|
||||||
pub border_bottom_present: bool,
|
pub border_bottom_present: bool,
|
||||||
pub border_left_present: bool,
|
pub border_left_present: bool,
|
||||||
pub is_root_element: bool,
|
pub is_root_element: bool,
|
||||||
|
pub viewport_size: Size2D<Au>
|
||||||
// TODO, as needed: viewport size, etc.
|
// TODO, as needed: viewport size, etc.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -736,7 +818,15 @@ pub mod computed {
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn to_computed_value(&self, context: &Context) -> Au {
|
fn to_computed_value(&self, context: &Context) -> Au {
|
||||||
self.to_computed_value_with_font_size(context.font_size, context.root_font_size)
|
match self {
|
||||||
|
&specified::Length::Absolute(length) => length,
|
||||||
|
&specified::Length::FontRelative(length) =>
|
||||||
|
length.to_computed_value(context.font_size, context.root_font_size),
|
||||||
|
&specified::Length::ViewportPercentage(length) =>
|
||||||
|
length.to_computed_value(context.viewport_size),
|
||||||
|
&specified::Length::ServoCharacterWidth(length) =>
|
||||||
|
length.to_computed_value(context.font_size)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -136,6 +136,7 @@ struct Reftest {
|
||||||
is_flaky: bool,
|
is_flaky: bool,
|
||||||
experimental: bool,
|
experimental: bool,
|
||||||
fragment_identifier: Option<String>,
|
fragment_identifier: Option<String>,
|
||||||
|
resolution: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
struct TestLine<'a> {
|
struct TestLine<'a> {
|
||||||
|
@ -195,6 +196,7 @@ fn parse_lists(file: &Path, servo_args: &[String], render_mode: RenderMode, id_o
|
||||||
let mut flakiness = RenderMode::empty();
|
let mut flakiness = RenderMode::empty();
|
||||||
let mut experimental = false;
|
let mut experimental = false;
|
||||||
let mut fragment_identifier = None;
|
let mut fragment_identifier = None;
|
||||||
|
let mut resolution = None;
|
||||||
for condition in conditions_list {
|
for condition in conditions_list {
|
||||||
match condition {
|
match condition {
|
||||||
"flaky_cpu" => flakiness.insert(CPU_RENDERING),
|
"flaky_cpu" => flakiness.insert(CPU_RENDERING),
|
||||||
|
@ -207,6 +209,9 @@ fn parse_lists(file: &Path, servo_args: &[String], render_mode: RenderMode, id_o
|
||||||
if condition.starts_with("fragment=") {
|
if condition.starts_with("fragment=") {
|
||||||
fragment_identifier = Some(condition.slice_from("fragment=".len()).to_string());
|
fragment_identifier = Some(condition.slice_from("fragment=".len()).to_string());
|
||||||
}
|
}
|
||||||
|
if condition.starts_with("resolution=") {
|
||||||
|
resolution = Some(condition.slice_from("resolution=".len()).to_string());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let reftest = Reftest {
|
let reftest = Reftest {
|
||||||
|
@ -219,6 +224,7 @@ fn parse_lists(file: &Path, servo_args: &[String], render_mode: RenderMode, id_o
|
||||||
is_flaky: render_mode.intersects(flakiness),
|
is_flaky: render_mode.intersects(flakiness),
|
||||||
experimental: experimental,
|
experimental: experimental,
|
||||||
fragment_identifier: fragment_identifier,
|
fragment_identifier: fragment_identifier,
|
||||||
|
resolution: resolution,
|
||||||
};
|
};
|
||||||
|
|
||||||
tests.push(make_test(reftest));
|
tests.push(make_test(reftest));
|
||||||
|
@ -265,6 +271,10 @@ fn capture(reftest: &Reftest, side: usize) -> (u32, u32, Vec<u8>) {
|
||||||
if reftest.experimental {
|
if reftest.experimental {
|
||||||
command.arg("--experimental");
|
command.arg("--experimental");
|
||||||
}
|
}
|
||||||
|
if let Some(ref resolution) = reftest.resolution {
|
||||||
|
command.arg("--resolution");
|
||||||
|
command.arg(resolution);
|
||||||
|
}
|
||||||
let retval = match command.status() {
|
let retval = match command.status() {
|
||||||
Ok(status) => status,
|
Ok(status) => status,
|
||||||
Err(e) => panic!("failed to execute process: {}", e),
|
Err(e) => panic!("failed to execute process: {}", e),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue