diff options
Diffstat (limited to 'components/style/servo/media_queries.rs')
-rw-r--r-- | components/style/servo/media_queries.rs | 167 |
1 files changed, 44 insertions, 123 deletions
diff --git a/components/style/servo/media_queries.rs b/components/style/servo/media_queries.rs index ba31cfcaf4b..98b1ec7ae6f 100644 --- a/components/style/servo/media_queries.rs +++ b/components/style/servo/media_queries.rs @@ -5,19 +5,18 @@ //! Servo's media-query device and expression representation. use app_units::Au; -use context::QuirksMode; -use cssparser::{Parser, RGBA}; +use cssparser::RGBA; use euclid::{Size2D, TypedScale, TypedSize2D}; use media_queries::MediaType; -use parser::ParserContext; +use media_queries::media_feature::{AllowsRanges, ParsingRequirements}; +use media_queries::media_feature::{MediaFeatureDescription, Evaluator}; +use media_queries::media_feature_expression::RangeOrOperator; use properties::ComputedValues; -use selectors::parser::SelectorParseErrorKind; -use std::fmt::{self, Write}; use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering}; -use style_traits::{CSSPixel, CssWriter, DevicePixel, ParseError, ToCss}; +use style_traits::{CSSPixel, DevicePixel}; use style_traits::viewport::ViewportConstraints; -use values::{specified, KeyframesName}; -use values::computed::{self, ToComputedValue}; +use values::KeyframesName; +use values::computed::CSSPixelLength; use values::computed::font::FontSize; /// A device is a structure that represents the current media a given document @@ -155,125 +154,47 @@ impl Device { } } -/// A expression kind servo understands and parses. -/// -/// Only `pub` for unit testing, please don't use it directly! -#[derive(Clone, Debug, PartialEq)] -#[cfg_attr(feature = "servo", derive(MallocSizeOf))] -pub enum ExpressionKind { - /// <http://dev.w3.org/csswg/mediaqueries-3/#width> - Width(Range<specified::Length>), +/// https://drafts.csswg.org/mediaqueries-4/#width +fn eval_width( + device: &Device, + value: Option<CSSPixelLength>, + range_or_operator: Option<RangeOrOperator>, +) -> bool { + RangeOrOperator::evaluate( + range_or_operator, + value.map(Au::from), + device.au_viewport_size().width, + ) } -/// A single expression a per: -/// -/// <http://dev.w3.org/csswg/mediaqueries-3/#media1> -#[derive(Clone, Debug, PartialEq)] -#[cfg_attr(feature = "servo", derive(MallocSizeOf))] -pub struct MediaFeatureExpression(pub ExpressionKind); - -impl MediaFeatureExpression { - /// The kind of expression we're, just for unit testing. - /// - /// Eventually this will become servo-only. - pub fn kind_for_testing(&self) -> &ExpressionKind { - &self.0 - } - - /// Parse a media expression of the form: - /// - /// ``` - /// media-feature: media-value - /// ``` - /// - /// Only supports width ranges for now. - pub fn parse<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result<Self, ParseError<'i>> { - input.expect_parenthesis_block()?; - input.parse_nested_block(|input| { - Self::parse_in_parenthesis_block(context, input) - }) - } - - /// Parse a media range expression where we've already consumed the - /// parenthesis. - pub fn parse_in_parenthesis_block<'i, 't>( - context: &ParserContext, - input: &mut Parser<'i, 't>, - ) -> Result<Self, ParseError<'i>> { - let name = input.expect_ident_cloned()?; - input.expect_colon()?; - // TODO: Handle other media features - Ok(MediaFeatureExpression(match_ignore_ascii_case! { &name, - "min-width" => { - ExpressionKind::Width(Range::Min(specified::Length::parse_non_negative(context, input)?)) - }, - "max-width" => { - ExpressionKind::Width(Range::Max(specified::Length::parse_non_negative(context, input)?)) - }, - "width" => { - ExpressionKind::Width(Range::Eq(specified::Length::parse_non_negative(context, input)?)) - }, - _ => return Err(input.new_custom_error(SelectorParseErrorKind::UnexpectedIdent(name.clone()))) - })) - } - - /// Evaluate this expression and return whether it matches the current - /// device. - pub fn matches(&self, device: &Device, quirks_mode: QuirksMode) -> bool { - let viewport_size = device.au_viewport_size(); - let value = viewport_size.width; - match self.0 { - ExpressionKind::Width(ref range) => { - match range.to_computed_range(device, quirks_mode) { - Range::Min(ref width) => value >= *width, - Range::Max(ref width) => value <= *width, - Range::Eq(ref width) => value == *width, - } - }, - } - } +#[derive(Clone, Copy, Debug, FromPrimitive, Parse, ToCss)] +#[repr(u8)] +enum Scan { + Progressive, + Interlace, } -impl ToCss for MediaFeatureExpression { - fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result - where - W: Write, - { - let (s, l) = match self.0 { - ExpressionKind::Width(Range::Min(ref l)) => ("(min-width: ", l), - ExpressionKind::Width(Range::Max(ref l)) => ("(max-width: ", l), - ExpressionKind::Width(Range::Eq(ref l)) => ("(width: ", l), - }; - dest.write_str(s)?; - l.to_css(dest)?; - dest.write_char(')') - } +/// https://drafts.csswg.org/mediaqueries-4/#scan +fn eval_scan(_: &Device, _: Option<Scan>) -> bool { + // Since we doesn't support the 'tv' media type, the 'scan' feature never + // matches. + false } -/// An enumeration that represents a ranged value. -/// -/// Only public for testing, implementation details of `MediaFeatureExpression` -/// may change for Stylo. -#[derive(Clone, Copy, Debug, Eq, PartialEq)] -#[cfg_attr(feature = "servo", derive(MallocSizeOf))] -pub enum Range<T> { - /// At least the inner value. - Min(T), - /// At most the inner value. - Max(T), - /// Exactly the inner value. - Eq(T), -} - -impl Range<specified::Length> { - fn to_computed_range(&self, device: &Device, quirks_mode: QuirksMode) -> Range<Au> { - 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))), - }) - } +lazy_static! { + /// A list with all the media features that Servo supports. + pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 2] = [ + feature!( + atom!("width"), + AllowsRanges::Yes, + Evaluator::Length(eval_width), + ParsingRequirements::empty(), + ), + feature!( + atom!("scan"), + AllowsRanges::No, + keyword_evaluator!(eval_scan, Scan), + ParsingRequirements::empty(), + ), + ]; } |