mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
Port servo to the new media query system.
Port `width`, and also add the `scan` media feature so I don't need to add ugliness just to workaround the unused keyword_evaluator macro.
This commit is contained in:
parent
8ae1322fb3
commit
935b5393a9
3 changed files with 57 additions and 134 deletions
|
@ -16,17 +16,6 @@ use media_queries::media_feature::{MediaFeatureDescription, Evaluator};
|
||||||
use media_queries::media_feature::{AllowsRanges, ParsingRequirements};
|
use media_queries::media_feature::{AllowsRanges, ParsingRequirements};
|
||||||
use media_queries::media_feature_expression::{AspectRatio, RangeOrOperator};
|
use media_queries::media_feature_expression::{AspectRatio, RangeOrOperator};
|
||||||
|
|
||||||
macro_rules! feature {
|
|
||||||
($name:expr, $allows_ranges:expr, $evaluator:expr, $reqs:expr,) => {
|
|
||||||
MediaFeatureDescription {
|
|
||||||
name: $name,
|
|
||||||
allows_ranges: $allows_ranges,
|
|
||||||
evaluator: $evaluator,
|
|
||||||
requirements: $reqs,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn viewport_size(device: &Device) -> Size2D<Au> {
|
fn viewport_size(device: &Device) -> Size2D<Au> {
|
||||||
let pc = device.pres_context();
|
let pc = device.pres_context();
|
||||||
if pc.mIsRootPaginatedDocument() != 0 {
|
if pc.mIsRootPaginatedDocument() != 0 {
|
||||||
|
|
|
@ -161,6 +161,18 @@ impl MediaFeatureDescription {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// A simple helper to construct a `MediaFeatureDescription`.
|
||||||
|
macro_rules! feature {
|
||||||
|
($name:expr, $allows_ranges:expr, $evaluator:expr, $reqs:expr,) => {
|
||||||
|
$crate::media_queries::media_feature::MediaFeatureDescription {
|
||||||
|
name: $name,
|
||||||
|
allows_ranges: $allows_ranges,
|
||||||
|
evaluator: $evaluator,
|
||||||
|
requirements: $reqs,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl fmt::Debug for MediaFeatureDescription {
|
impl fmt::Debug for MediaFeatureDescription {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
f.debug_struct("MediaFeatureExpression")
|
f.debug_struct("MediaFeatureExpression")
|
||||||
|
|
|
@ -5,21 +5,21 @@
|
||||||
//! Servo's media-query device and expression representation.
|
//! Servo's media-query device and expression representation.
|
||||||
|
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
use context::QuirksMode;
|
use cssparser::RGBA;
|
||||||
use cssparser::{Parser, RGBA};
|
|
||||||
use euclid::{Size2D, TypedScale, TypedSize2D};
|
use euclid::{Size2D, TypedScale, TypedSize2D};
|
||||||
use media_queries::MediaType;
|
use media_queries::MediaType;
|
||||||
use parser::ParserContext;
|
|
||||||
use properties::ComputedValues;
|
use properties::ComputedValues;
|
||||||
use selectors::parser::SelectorParseErrorKind;
|
|
||||||
use std::fmt::{self, Write};
|
|
||||||
use std::sync::atomic::{AtomicBool, AtomicIsize, Ordering};
|
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 style_traits::viewport::ViewportConstraints;
|
||||||
use values::{specified, KeyframesName};
|
use values::KeyframesName;
|
||||||
use values::computed::{self, ToComputedValue};
|
use values::computed::CSSPixelLength;
|
||||||
use values::computed::font::FontSize;
|
use values::computed::font::FontSize;
|
||||||
|
|
||||||
|
use media_queries::media_feature::{MediaFeatureDescription, Evaluator};
|
||||||
|
use media_queries::media_feature::{AllowsRanges, ParsingRequirements};
|
||||||
|
use media_queries::media_feature_expression::RangeOrOperator;
|
||||||
|
|
||||||
/// A device is a structure that represents the current media a given document
|
/// A device is a structure that represents the current media a given document
|
||||||
/// is displayed in.
|
/// is displayed in.
|
||||||
///
|
///
|
||||||
|
@ -155,125 +155,47 @@ impl Device {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A expression kind servo understands and parses.
|
/// https://drafts.csswg.org/mediaqueries-4/#width
|
||||||
///
|
fn eval_width(
|
||||||
/// Only `pub` for unit testing, please don't use it directly!
|
device: &Device,
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
value: Option<CSSPixelLength>,
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
range_or_operator: Option<RangeOrOperator>,
|
||||||
pub enum ExpressionKind {
|
) -> bool {
|
||||||
/// <http://dev.w3.org/csswg/mediaqueries-3/#width>
|
RangeOrOperator::evaluate(
|
||||||
Width(Range<specified::Length>),
|
range_or_operator,
|
||||||
|
value.map(Au::from),
|
||||||
|
device.au_viewport_size().width,
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A single expression a per:
|
#[derive(Debug, Copy, Clone, FromPrimitive, ToCss, Parse)]
|
||||||
///
|
#[repr(u8)]
|
||||||
/// <http://dev.w3.org/csswg/mediaqueries-3/#media1>
|
enum Scan {
|
||||||
#[derive(Clone, Debug, PartialEq)]
|
Progressive,
|
||||||
#[cfg_attr(feature = "servo", derive(MallocSizeOf))]
|
Interlace,
|
||||||
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:
|
/// 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
|
||||||
/// media-feature: media-value
|
// matches.
|
||||||
/// ```
|
false
|
||||||
///
|
|
||||||
/// 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
|
lazy_static! {
|
||||||
/// parenthesis.
|
/// A list with all the media features that Servo supports.
|
||||||
pub fn parse_in_parenthesis_block<'i, 't>(
|
pub static ref MEDIA_FEATURES: [MediaFeatureDescription; 2] = [
|
||||||
context: &ParserContext,
|
feature!(
|
||||||
input: &mut Parser<'i, 't>,
|
atom!("width"),
|
||||||
) -> Result<Self, ParseError<'i>> {
|
AllowsRanges::Yes,
|
||||||
let name = input.expect_ident_cloned()?;
|
Evaluator::Length(eval_width),
|
||||||
input.expect_colon()?;
|
ParsingRequirements::empty(),
|
||||||
// TODO: Handle other media features
|
),
|
||||||
Ok(MediaFeatureExpression(match_ignore_ascii_case! { &name,
|
feature!(
|
||||||
"min-width" => {
|
atom!("scan"),
|
||||||
ExpressionKind::Width(Range::Min(specified::Length::parse_non_negative(context, input)?))
|
AllowsRanges::No,
|
||||||
},
|
keyword_evaluator!(eval_scan, Scan),
|
||||||
"max-width" => {
|
ParsingRequirements::empty(),
|
||||||
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,
|
|
||||||
}
|
|
||||||
},
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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(')')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 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))),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue