aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2017-11-06 09:37:14 -0600
committerGitHub <noreply@github.com>2017-11-06 09:37:14 -0600
commit0047c77f0374ec773fab1cb0c0b7fcfdbb6472d2 (patch)
treee083c68abe2f68a8a1231eb0c9fe5b9a8e3dc559
parent41a5a8c75faa348ff7301963a7f2f6fab7423750 (diff)
parent3fa75bbdf6eec7b2f81ae62f60035f4a7c3676e9 (diff)
downloadservo-0047c77f0374ec773fab1cb0c0b7fcfdbb6472d2.tar.gz
servo-0047c77f0374ec773fab1cb0c0b7fcfdbb6472d2.zip
Auto merge of #19126 - emilio:source-size-list, r=nox
style: Introduce SourceSizeList. This is part of the work for https://bugzilla.mozilla.org/show_bug.cgi?id=1408308. But this can just land now IMO, before I do the integration bits. <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/19126) <!-- Reviewable:end -->
-rw-r--r--components/style/gecko/media_queries.rs37
-rw-r--r--components/style/media_queries.rs26
-rw-r--r--components/style/servo/media_queries.rs36
-rw-r--r--components/style/values/computed/mod.rs32
-rw-r--r--components/style/values/specified/mod.rs1
-rw-r--r--components/style/values/specified/source_size_list.rs79
6 files changed, 142 insertions, 69 deletions
diff --git a/components/style/gecko/media_queries.rs b/components/style/gecko/media_queries.rs
index 71f46178c5c..1dd6e5aa06c 100644
--- a/components/style/gecko/media_queries.rs
+++ b/components/style/gecko/media_queries.rs
@@ -10,7 +10,6 @@ use context::QuirksMode;
use cssparser::{CssStringWriter, Parser, RGBA, Token, BasicParseErrorKind};
use euclid::ScaleFactor;
use euclid::Size2D;
-use font_metrics::get_metrics_provider_for_product;
use gecko::values::{convert_nscolor_to_rgba, convert_rgba_to_nscolor};
use gecko_bindings::bindings;
use gecko_bindings::structs;
@@ -20,11 +19,9 @@ use gecko_bindings::structs::{nsMediaFeature_ValueType, nsMediaFeature_RangeType
use gecko_bindings::structs::{nsPresContext, RawGeckoPresContextOwned};
use media_queries::MediaType;
use parser::ParserContext;
-use properties::{ComputedValues, StyleBuilder};
+use properties::ComputedValues;
use properties::longhands::font_size;
-use rule_cache::RuleCacheConditions;
use servo_arc::Arc;
-use std::cell::RefCell;
use std::fmt::{self, Write};
use std::sync::atomic::{AtomicBool, AtomicIsize, AtomicUsize, Ordering};
use str::starts_with_ignore_ascii_case;
@@ -722,26 +719,8 @@ impl Expression {
self.feature.mRangeType == nsMediaFeature_RangeType::eMinMaxAllowed,
"Whoops, wrong range");
- let default_values = device.default_computed_values();
-
-
- let provider = get_metrics_provider_for_product();
-
// http://dev.w3.org/csswg/mediaqueries3/#units
// em units are relative to the initial font-size.
- let mut conditions = RuleCacheConditions::default();
- let context = computed::Context {
- is_root_element: false,
- builder: StyleBuilder::for_derived_style(device, default_values, None, None),
- font_metrics_provider: &provider,
- cached_system_font: None,
- in_media_query: true,
- quirks_mode,
- for_smil_animation: false,
- for_non_inherited_property: None,
- rule_cache_conditions: RefCell::new(&mut conditions),
- };
-
let required_value = match self.value {
Some(ref v) => v,
None => {
@@ -750,7 +729,13 @@ impl Expression {
return match *actual_value {
BoolInteger(v) => v,
Integer(v) => v != 0,
- Length(ref l) => l.to_computed_value(&context).px() != 0.,
+ Length(ref l) => {
+ computed::Context::for_media_query_evaluation(
+ device,
+ quirks_mode,
+ |context| l.to_computed_value(&context).px() != 0.,
+ )
+ },
_ => true,
}
}
@@ -759,8 +744,10 @@ impl Expression {
// FIXME(emilio): Handle the possible floating point errors?
let cmp = match (required_value, actual_value) {
(&Length(ref one), &Length(ref other)) => {
- one.to_computed_value(&context).to_i32_au()
- .cmp(&other.to_computed_value(&context).to_i32_au())
+ computed::Context::for_media_query_evaluation(device, quirks_mode, |context| {
+ one.to_computed_value(&context).to_i32_au()
+ .cmp(&other.to_computed_value(&context).to_i32_au())
+ })
}
(&Integer(one), &Integer(ref other)) => one.cmp(other),
(&BoolInteger(one), &BoolInteger(ref other)) => one.cmp(other),
diff --git a/components/style/media_queries.rs b/components/style/media_queries.rs
index b77f7c85f84..42a72ba2d58 100644
--- a/components/style/media_queries.rs
+++ b/components/style/media_queries.rs
@@ -77,17 +77,10 @@ impl MediaQuery {
/// Return a media query that never matches, used for when we fail to parse
/// a given media query.
fn never_matching() -> Self {
- Self::new(Some(Qualifier::Not), MediaQueryType::All, vec![])
- }
-
- /// Trivially constructs a new media query.
- pub fn new(qualifier: Option<Qualifier>,
- media_type: MediaQueryType,
- expressions: Vec<Expression>) -> MediaQuery {
- MediaQuery {
- qualifier: qualifier,
- media_type: media_type,
- expressions: expressions,
+ Self {
+ qualifier: Some(Qualifier::Not),
+ media_type: MediaQueryType::All,
+ expressions: vec![],
}
}
}
@@ -209,9 +202,12 @@ impl MediaQuery {
let media_type = match input.try(|i| i.expect_ident_cloned()) {
Ok(ident) => {
- let result: Result<_, ParseError> = MediaQueryType::parse(&*ident)
- .map_err(|()| input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(ident.clone())));
- result?
+ MediaQueryType::parse(&*ident)
+ .map_err(|()| {
+ input.new_custom_error(
+ SelectorParseErrorKind::UnexpectedIdent(ident.clone())
+ )
+ })?
}
Err(_) => {
// Media type is only optional if qualifier is not specified.
@@ -229,7 +225,7 @@ impl MediaQuery {
// Parse any subsequent expressions
loop {
if input.try(|input| input.expect_ident_matching("and")).is_err() {
- return Ok(MediaQuery::new(qualifier, media_type, expressions))
+ return Ok(MediaQuery { qualifier, media_type, expressions })
}
expressions.push(Expression::parse(context, input)?)
}
diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs
index ecdbf4aa9b3..e5c57b4d703 100644
--- a/components/style/servo/media_queries.rs
+++ b/components/style/servo/media_queries.rs
@@ -8,14 +8,11 @@ use app_units::Au;
use context::QuirksMode;
use cssparser::{Parser, RGBA};
use euclid::{ScaleFactor, Size2D, TypedSize2D};
-use font_metrics::ServoMetricsProvider;
use media_queries::MediaType;
use parser::ParserContext;
-use properties::{ComputedValues, StyleBuilder};
+use properties::ComputedValues;
use properties::longhands::font_size;
-use rule_cache::RuleCacheConditions;
use selectors::parser::SelectorParseErrorKind;
-use std::cell::RefCell;
use std::fmt;
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
use style_traits::{CSSPixel, DevicePixel, ToCss, ParseError};
@@ -252,29 +249,12 @@ pub enum Range<T> {
impl Range<specified::Length> {
fn to_computed_range(&self, device: &Device, quirks_mode: QuirksMode) -> Range<Au> {
- let default_values = device.default_computed_values();
- let mut conditions = RuleCacheConditions::default();
- // http://dev.w3.org/csswg/mediaqueries3/#units
- // em units are relative to the initial font-size.
- let context = computed::Context {
- is_root_element: false,
- builder: StyleBuilder::for_derived_style(device, default_values, None, None),
- // Servo doesn't support font metrics
- // A real provider will be needed here once we do; since
- // ch units can exist in media queries.
- font_metrics_provider: &ServoMetricsProvider,
- in_media_query: true,
- cached_system_font: None,
- quirks_mode,
- for_smil_animation: false,
- for_non_inherited_property: None,
- rule_cache_conditions: RefCell::new(&mut conditions),
- };
-
- match *self {
- Range::Min(ref width) => Range::Min(Au::from(width.to_computed_value(&context))),
- Range::Max(ref width) => Range::Max(Au::from(width.to_computed_value(&context))),
- Range::Eq(ref width) => Range::Eq(Au::from(width.to_computed_value(&context)))
- }
+ computed::Context::for_media_query_evaluation(device, quirks_mode, |context| {
+ match *self {
+ Range::Min(ref width) => Range::Min(Au::from(width.to_computed_value(&context))),
+ Range::Max(ref width) => Range::Max(Au::from(width.to_computed_value(&context))),
+ Range::Eq(ref width) => Range::Eq(Au::from(width.to_computed_value(&context)))
+ }
+ })
}
}
diff --git a/components/style/values/computed/mod.rs b/components/style/values/computed/mod.rs
index e74386bfc42..c6b33d58748 100644
--- a/components/style/values/computed/mod.rs
+++ b/components/style/values/computed/mod.rs
@@ -7,7 +7,7 @@
use {Atom, Namespace};
use context::QuirksMode;
use euclid::Size2D;
-use font_metrics::FontMetricsProvider;
+use font_metrics::{FontMetricsProvider, get_metrics_provider_for_product};
use media_queries::Device;
#[cfg(feature = "gecko")]
use properties;
@@ -136,6 +136,36 @@ pub struct Context<'a> {
}
impl<'a> Context<'a> {
+ /// Creates a suitable context for media query evaluation, in which
+ /// font-relative units compute against the system_font, and executes `f`
+ /// with it.
+ pub fn for_media_query_evaluation<F, R>(
+ device: &Device,
+ quirks_mode: QuirksMode,
+ f: F,
+ ) -> R
+ where
+ F: FnOnce(&Context) -> R
+ {
+ let mut conditions = RuleCacheConditions::default();
+ let default_values = device.default_computed_values();
+ let provider = get_metrics_provider_for_product();
+
+ let context = Context {
+ is_root_element: false,
+ builder: StyleBuilder::for_derived_style(device, default_values, None, None),
+ font_metrics_provider: &provider,
+ cached_system_font: None,
+ in_media_query: true,
+ quirks_mode,
+ for_smil_animation: false,
+ for_non_inherited_property: None,
+ rule_cache_conditions: RefCell::new(&mut conditions),
+ };
+
+ f(&context)
+ }
+
/// Whether the current element is the root element.
pub fn is_root_element(&self) -> bool {
self.is_root_element
diff --git a/components/style/values/specified/mod.rs b/components/style/values/specified/mod.rs
index 004910ae6b1..ffe4d7ba59b 100644
--- a/components/style/values/specified/mod.rs
+++ b/components/style/values/specified/mod.rs
@@ -76,6 +76,7 @@ pub mod length;
pub mod percentage;
pub mod position;
pub mod rect;
+pub mod source_size_list;
pub mod svg;
pub mod table;
pub mod text;
diff --git a/components/style/values/specified/source_size_list.rs b/components/style/values/specified/source_size_list.rs
new file mode 100644
index 00000000000..4a0c068ce78
--- /dev/null
+++ b/components/style/values/specified/source_size_list.rs
@@ -0,0 +1,79 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+//! https://html.spec.whatwg.org/multipage/#source-size-list
+
+use app_units::Au;
+use cssparser::Parser;
+use media_queries::{Device, Expression as MediaExpression};
+use parser::{Parse, ParserContext};
+use selectors::context::QuirksMode;
+use style_traits::ParseError;
+use values::computed::{self, ToComputedValue};
+use values::specified::Length;
+
+/// A value for a `<source-size>`:
+///
+/// https://html.spec.whatwg.org/multipage/#source-size
+pub struct SourceSize {
+ condition: MediaExpression,
+ value: Length,
+}
+
+impl Parse for SourceSize {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ let condition = MediaExpression::parse(context, input)?;
+ let value = Length::parse_non_negative(context, input)?;
+
+ Ok(Self { condition, value })
+ }
+}
+
+/// A value for a `<source-size-list>`:
+///
+/// https://html.spec.whatwg.org/multipage/#source-size-list
+pub struct SourceSizeList {
+ source_sizes: Vec<SourceSize>,
+ value: Length,
+}
+
+impl SourceSizeList {
+ /// Evaluate this <source-size-list> to get the final viewport length.
+ pub fn evaluate(&self, device: &Device, quirks_mode: QuirksMode) -> Au {
+ let matching_source_size = self.source_sizes.iter().find(|source_size| {
+ source_size.condition.matches(device, quirks_mode)
+ });
+
+ computed::Context::for_media_query_evaluation(device, quirks_mode, |context| {
+ match matching_source_size {
+ Some(source_size) => {
+ source_size.value.to_computed_value(context)
+ }
+ None => {
+ self.value.to_computed_value(context)
+ }
+ }
+ }).into()
+ }
+}
+
+impl Parse for SourceSizeList {
+ fn parse<'i, 't>(
+ context: &ParserContext,
+ input: &mut Parser<'i, 't>,
+ ) -> Result<Self, ParseError<'i>> {
+ let source_sizes = input.try(|input| {
+ input.parse_comma_separated(|input| {
+ SourceSize::parse(context, input)
+ })
+ }).unwrap_or(vec![]);
+
+ let value = Length::parse_non_negative(context, input)?;
+
+ Ok(Self { source_sizes, value })
+ }
+}