diff options
author | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-11-06 13:47:46 +0100 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2017-11-06 16:36:41 +0100 |
commit | 3fa75bbdf6eec7b2f81ae62f60035f4a7c3676e9 (patch) | |
tree | e09f3043a7b4bfb7f0908578c1b81a84b2ed8281 /components/style | |
parent | 001c50bccad658b71a65ddc680d17639c2af3fdf (diff) | |
download | servo-3fa75bbdf6eec7b2f81ae62f60035f4a7c3676e9.tar.gz servo-3fa75bbdf6eec7b2f81ae62f60035f4a7c3676e9.zip |
style: Introduce SourceSizeList.
MozReview-Commit-ID: 9QMF45VcBFB
Diffstat (limited to 'components/style')
-rw-r--r-- | components/style/gecko/media_queries.rs | 37 | ||||
-rw-r--r-- | components/style/servo/media_queries.rs | 36 | ||||
-rw-r--r-- | components/style/values/computed/mod.rs | 32 | ||||
-rw-r--r-- | components/style/values/specified/mod.rs | 1 | ||||
-rw-r--r-- | components/style/values/specified/source_size_list.rs | 79 |
5 files changed, 131 insertions, 54 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/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 }) + } +} |