mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-02-24 03:19:06 +00:00
Bug 1765999 - Move some of the media query code to a more generic queries module. r=hiro
No behavior change, just moving and renaming files. The code in the "queries" module will be shared between @media and @container. @media has some other code that container queries doesn't need like MediaList / MediaType / etc. That remains in the media_queries module. Differential Revision: https://phabricator.services.mozilla.com/D144435
This commit is contained in:
parent
63420746b0
commit
e097b4be55
@ -6,8 +6,7 @@
|
|||||||
|
|
||||||
use crate::gecko_bindings::bindings;
|
use crate::gecko_bindings::bindings;
|
||||||
use crate::gecko_bindings::structs;
|
use crate::gecko_bindings::structs;
|
||||||
use crate::media_queries::media_feature::{AllowsRanges, ParsingRequirements};
|
use crate::queries::feature::{AllowsRanges, Evaluator, ParsingRequirements, QueryFeatureDescription};
|
||||||
use crate::media_queries::media_feature::{Evaluator, MediaFeatureDescription};
|
|
||||||
use crate::media_queries::{Device, MediaType};
|
use crate::media_queries::{Device, MediaType};
|
||||||
use crate::values::computed::{Context, CSSPixelLength, Ratio, Resolution};
|
use crate::values::computed::{Context, CSSPixelLength, Ratio, Resolution};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
@ -583,7 +582,7 @@ macro_rules! bool_pref_feature {
|
|||||||
/// to support new types in these entries and (2) ensuring that either
|
/// to support new types in these entries and (2) ensuring that either
|
||||||
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
|
/// nsPresContext::MediaFeatureValuesChanged is called when the value that
|
||||||
/// would be returned by the evaluator function could change.
|
/// would be returned by the evaluator function could change.
|
||||||
pub static MEDIA_FEATURES: [MediaFeatureDescription; 60] = [
|
pub static MEDIA_FEATURES: [QueryFeatureDescription; 60] = [
|
||||||
feature!(
|
feature!(
|
||||||
atom!("width"),
|
atom!("width"),
|
||||||
AllowsRanges::Yes,
|
AllowsRanges::Yes,
|
||||||
|
@ -103,10 +103,11 @@ pub mod invalidation;
|
|||||||
#[allow(missing_docs)] // TODO.
|
#[allow(missing_docs)] // TODO.
|
||||||
pub mod logical_geometry;
|
pub mod logical_geometry;
|
||||||
pub mod matching;
|
pub mod matching;
|
||||||
#[macro_use]
|
|
||||||
pub mod media_queries;
|
pub mod media_queries;
|
||||||
pub mod parallel;
|
pub mod parallel;
|
||||||
pub mod parser;
|
pub mod parser;
|
||||||
|
#[macro_use]
|
||||||
|
pub mod queries;
|
||||||
pub mod rule_cache;
|
pub mod rule_cache;
|
||||||
pub mod rule_collector;
|
pub mod rule_collector;
|
||||||
pub mod rule_tree;
|
pub mod rule_tree;
|
||||||
|
@ -6,7 +6,7 @@
|
|||||||
//!
|
//!
|
||||||
//! https://drafts.csswg.org/mediaqueries/#typedef-media-query
|
//! https://drafts.csswg.org/mediaqueries/#typedef-media-query
|
||||||
|
|
||||||
use super::media_condition::MediaCondition;
|
use crate::queries::QueryCondition;
|
||||||
use crate::parser::ParserContext;
|
use crate::parser::ParserContext;
|
||||||
use crate::str::string_as_ascii_lowercase;
|
use crate::str::string_as_ascii_lowercase;
|
||||||
use crate::values::CustomIdent;
|
use crate::values::CustomIdent;
|
||||||
@ -66,7 +66,7 @@ pub struct MediaQuery {
|
|||||||
pub media_type: MediaQueryType,
|
pub media_type: MediaQueryType,
|
||||||
/// The condition that this media query contains. This cannot have `or`
|
/// The condition that this media query contains. This cannot have `or`
|
||||||
/// in the first level.
|
/// in the first level.
|
||||||
pub condition: Option<MediaCondition>,
|
pub condition: Option<QueryCondition>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for MediaQuery {
|
impl ToCss for MediaQuery {
|
||||||
@ -134,9 +134,9 @@ impl MediaQuery {
|
|||||||
.unwrap_or_default();
|
.unwrap_or_default();
|
||||||
|
|
||||||
let condition = if explicit_media_type.is_none() {
|
let condition = if explicit_media_type.is_none() {
|
||||||
Some(MediaCondition::parse(context, input)?)
|
Some(QueryCondition::parse(context, input)?)
|
||||||
} else if input.try_parse(|i| i.expect_ident_matching("and")).is_ok() {
|
} else if input.try_parse(|i| i.expect_ident_matching("and")).is_ok() {
|
||||||
Some(MediaCondition::parse_disallow_or(context, input)?)
|
Some(QueryCondition::parse_disallow_or(context, input)?)
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -6,15 +6,9 @@
|
|||||||
//!
|
//!
|
||||||
//! [mq]: https://drafts.csswg.org/mediaqueries/
|
//! [mq]: https://drafts.csswg.org/mediaqueries/
|
||||||
|
|
||||||
mod media_condition;
|
|
||||||
mod media_list;
|
mod media_list;
|
||||||
mod media_query;
|
mod media_query;
|
||||||
#[macro_use]
|
|
||||||
pub mod media_feature;
|
|
||||||
pub mod media_feature_expression;
|
|
||||||
|
|
||||||
pub use self::media_condition::MediaCondition;
|
|
||||||
pub use self::media_feature_expression::MediaFeatureExpression;
|
|
||||||
pub use self::media_list::MediaList;
|
pub use self::media_list::MediaList;
|
||||||
pub use self::media_query::{MediaQuery, MediaQueryType, MediaType, Qualifier};
|
pub use self::media_query::{MediaQuery, MediaQueryType, MediaType, Qualifier};
|
||||||
|
|
||||||
|
@ -2,11 +2,12 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! A media query condition:
|
//! A query condition:
|
||||||
//!
|
//!
|
||||||
//! https://drafts.csswg.org/mediaqueries-4/#typedef-media-condition
|
//! https://drafts.csswg.org/mediaqueries-4/#typedef-media-condition
|
||||||
|
//! https://drafts.csswg.org/css-contain-3/#typedef-container-condition
|
||||||
|
|
||||||
use super::MediaFeatureExpression;
|
use super::QueryFeatureExpression;
|
||||||
use crate::parser::ParserContext;
|
use crate::parser::ParserContext;
|
||||||
use crate::values::computed;
|
use crate::values::computed;
|
||||||
use cssparser::{Parser, Token};
|
use cssparser::{Parser, Token};
|
||||||
@ -28,38 +29,38 @@ enum AllowOr {
|
|||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a media condition.
|
/// Represents a condition.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||||
pub enum MediaCondition {
|
pub enum QueryCondition {
|
||||||
/// A simple media feature expression, implicitly parenthesized.
|
/// A simple feature expression, implicitly parenthesized.
|
||||||
Feature(MediaFeatureExpression),
|
Feature(QueryFeatureExpression),
|
||||||
/// A negation of a condition.
|
/// A negation of a condition.
|
||||||
Not(Box<MediaCondition>),
|
Not(Box<QueryCondition>),
|
||||||
/// A set of joint operations.
|
/// A set of joint operations.
|
||||||
Operation(Box<[MediaCondition]>, Operator),
|
Operation(Box<[QueryCondition]>, Operator),
|
||||||
/// A condition wrapped in parenthesis.
|
/// A condition wrapped in parenthesis.
|
||||||
InParens(Box<MediaCondition>),
|
InParens(Box<QueryCondition>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for MediaCondition {
|
impl ToCss for QueryCondition {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
where
|
||||||
W: fmt::Write,
|
W: fmt::Write,
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
// NOTE(emilio): MediaFeatureExpression already includes the
|
// NOTE(emilio): QueryFeatureExpression already includes the
|
||||||
// parenthesis.
|
// parenthesis.
|
||||||
MediaCondition::Feature(ref f) => f.to_css(dest),
|
QueryCondition::Feature(ref f) => f.to_css(dest),
|
||||||
MediaCondition::Not(ref c) => {
|
QueryCondition::Not(ref c) => {
|
||||||
dest.write_str("not ")?;
|
dest.write_str("not ")?;
|
||||||
c.to_css(dest)
|
c.to_css(dest)
|
||||||
},
|
},
|
||||||
MediaCondition::InParens(ref c) => {
|
QueryCondition::InParens(ref c) => {
|
||||||
dest.write_char('(')?;
|
dest.write_char('(')?;
|
||||||
c.to_css(dest)?;
|
c.to_css(dest)?;
|
||||||
dest.write_char(')')
|
dest.write_char(')')
|
||||||
},
|
},
|
||||||
MediaCondition::Operation(ref list, op) => {
|
QueryCondition::Operation(ref list, op) => {
|
||||||
let mut iter = list.iter();
|
let mut iter = list.iter();
|
||||||
iter.next().unwrap().to_css(dest)?;
|
iter.next().unwrap().to_css(dest)?;
|
||||||
for item in iter {
|
for item in iter {
|
||||||
@ -74,8 +75,8 @@ impl ToCss for MediaCondition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaCondition {
|
impl QueryCondition {
|
||||||
/// Parse a single media condition.
|
/// Parse a single condition.
|
||||||
pub fn parse<'i, 't>(
|
pub fn parse<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
@ -83,9 +84,9 @@ impl MediaCondition {
|
|||||||
Self::parse_internal(context, input, AllowOr::Yes)
|
Self::parse_internal(context, input, AllowOr::Yes)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a single media condition, disallowing `or` expressions.
|
/// Parse a single condition, disallowing `or` expressions.
|
||||||
///
|
///
|
||||||
/// To be used from the legacy media query syntax.
|
/// To be used from the legacy query syntax.
|
||||||
pub fn parse_disallow_or<'i, 't>(
|
pub fn parse_disallow_or<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
@ -109,7 +110,7 @@ impl MediaCondition {
|
|||||||
|
|
||||||
if is_negation {
|
if is_negation {
|
||||||
let inner_condition = Self::parse_in_parens(context, input)?;
|
let inner_condition = Self::parse_in_parens(context, input)?;
|
||||||
return Ok(MediaCondition::Not(Box::new(inner_condition)));
|
return Ok(QueryCondition::Not(Box::new(inner_condition)));
|
||||||
}
|
}
|
||||||
|
|
||||||
// ParenthesisBlock.
|
// ParenthesisBlock.
|
||||||
@ -134,7 +135,7 @@ impl MediaCondition {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
if input.try_parse(|i| i.expect_ident_matching(delim)).is_err() {
|
if input.try_parse(|i| i.expect_ident_matching(delim)).is_err() {
|
||||||
return Ok(MediaCondition::Operation(
|
return Ok(QueryCondition::Operation(
|
||||||
conditions.into_boxed_slice(),
|
conditions.into_boxed_slice(),
|
||||||
operator,
|
operator,
|
||||||
));
|
));
|
||||||
@ -144,7 +145,7 @@ impl MediaCondition {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a media condition in parentheses.
|
/// Parse a condition in parentheses.
|
||||||
pub fn parse_in_parens<'i, 't>(
|
pub fn parse_in_parens<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
@ -160,20 +161,20 @@ impl MediaCondition {
|
|||||||
input.parse_nested_block(|input| {
|
input.parse_nested_block(|input| {
|
||||||
// Base case.
|
// Base case.
|
||||||
if let Ok(inner) = input.try_parse(|i| Self::parse(context, i)) {
|
if let Ok(inner) = input.try_parse(|i| Self::parse(context, i)) {
|
||||||
return Ok(MediaCondition::InParens(Box::new(inner)));
|
return Ok(QueryCondition::InParens(Box::new(inner)));
|
||||||
}
|
}
|
||||||
let expr = MediaFeatureExpression::parse_in_parenthesis_block(context, input)?;
|
let expr = QueryFeatureExpression::parse_in_parenthesis_block(context, input)?;
|
||||||
Ok(MediaCondition::Feature(expr))
|
Ok(QueryCondition::Feature(expr))
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether this condition matches the device and quirks mode.
|
/// Whether this condition matches the device and quirks mode.
|
||||||
pub fn matches(&self, context: &computed::Context) -> bool {
|
pub fn matches(&self, context: &computed::Context) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
MediaCondition::Feature(ref f) => f.matches(context),
|
QueryCondition::Feature(ref f) => f.matches(context),
|
||||||
MediaCondition::InParens(ref c) => c.matches(context),
|
QueryCondition::InParens(ref c) => c.matches(context),
|
||||||
MediaCondition::Not(ref c) => !c.matches(context),
|
QueryCondition::Not(ref c) => !c.matches(context),
|
||||||
MediaCondition::Operation(ref conditions, op) => {
|
QueryCondition::Operation(ref conditions, op) => {
|
||||||
let mut iter = conditions.iter();
|
let mut iter = conditions.iter();
|
||||||
match op {
|
match op {
|
||||||
Operator::And => iter.all(|c| c.matches(context)),
|
Operator::And => iter.all(|c| c.matches(context)),
|
@ -2,7 +2,7 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! Media features.
|
//! Query features.
|
||||||
|
|
||||||
use crate::parser::ParserContext;
|
use crate::parser::ParserContext;
|
||||||
use crate::values::computed::{self, CSSPixelLength, Resolution, Ratio};
|
use crate::values::computed::{self, CSSPixelLength, Resolution, Ratio};
|
||||||
@ -14,7 +14,7 @@ use style_traits::ParseError;
|
|||||||
/// A generic discriminant for an enum value.
|
/// A generic discriminant for an enum value.
|
||||||
pub type KeywordDiscriminant = u8;
|
pub type KeywordDiscriminant = u8;
|
||||||
|
|
||||||
type MediaFeatureGetter<T> = fn(device: &computed::Context) -> T;
|
type QueryFeatureGetter<T> = fn(device: &computed::Context) -> T;
|
||||||
|
|
||||||
/// Serializes a given discriminant.
|
/// Serializes a given discriminant.
|
||||||
///
|
///
|
||||||
@ -28,19 +28,19 @@ pub type KeywordParser = for<'a, 'i, 't> fn(
|
|||||||
input: &'a mut Parser<'i, 't>,
|
input: &'a mut Parser<'i, 't>,
|
||||||
) -> Result<KeywordDiscriminant, ParseError<'i>>;
|
) -> Result<KeywordDiscriminant, ParseError<'i>>;
|
||||||
|
|
||||||
/// An evaluator for a given media feature.
|
/// An evaluator for a given feature.
|
||||||
///
|
///
|
||||||
/// This determines the kind of values that get parsed, too.
|
/// This determines the kind of values that get parsed, too.
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub enum Evaluator {
|
pub enum Evaluator {
|
||||||
Length(MediaFeatureGetter<CSSPixelLength>),
|
Length(QueryFeatureGetter<CSSPixelLength>),
|
||||||
Integer(MediaFeatureGetter<u32>),
|
Integer(QueryFeatureGetter<u32>),
|
||||||
Float(MediaFeatureGetter<f32>),
|
Float(QueryFeatureGetter<f32>),
|
||||||
BoolInteger(MediaFeatureGetter<bool>),
|
BoolInteger(QueryFeatureGetter<bool>),
|
||||||
/// A non-negative number ratio, such as the one from device-pixel-ratio.
|
/// A non-negative number ratio, such as the one from device-pixel-ratio.
|
||||||
NumberRatio(MediaFeatureGetter<Ratio>),
|
NumberRatio(QueryFeatureGetter<Ratio>),
|
||||||
/// A resolution.
|
/// A resolution.
|
||||||
Resolution(MediaFeatureGetter<Resolution>),
|
Resolution(QueryFeatureGetter<Resolution>),
|
||||||
/// A keyword value.
|
/// A keyword value.
|
||||||
Enumerated {
|
Enumerated {
|
||||||
/// The parser to get a discriminant given a string.
|
/// The parser to get a discriminant given a string.
|
||||||
@ -67,14 +67,14 @@ macro_rules! keyword_evaluator {
|
|||||||
context: &$crate::parser::ParserContext,
|
context: &$crate::parser::ParserContext,
|
||||||
input: &mut $crate::cssparser::Parser<'i, 't>,
|
input: &mut $crate::cssparser::Parser<'i, 't>,
|
||||||
) -> Result<
|
) -> Result<
|
||||||
$crate::media_queries::media_feature::KeywordDiscriminant,
|
$crate::queries::feature::KeywordDiscriminant,
|
||||||
::style_traits::ParseError<'i>,
|
::style_traits::ParseError<'i>,
|
||||||
> {
|
> {
|
||||||
let kw = <$keyword_type as $crate::parser::Parse>::parse(context, input)?;
|
let kw = <$keyword_type as $crate::parser::Parse>::parse(context, input)?;
|
||||||
Ok(kw as $crate::media_queries::media_feature::KeywordDiscriminant)
|
Ok(kw as $crate::queries::feature::KeywordDiscriminant)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn __serialize(kw: $crate::media_queries::media_feature::KeywordDiscriminant) -> String {
|
fn __serialize(kw: $crate::queries::feature::KeywordDiscriminant) -> String {
|
||||||
// This unwrap is ok because the only discriminants that get
|
// This unwrap is ok because the only discriminants that get
|
||||||
// back to us is the ones that `parse` produces.
|
// back to us is the ones that `parse` produces.
|
||||||
let value: $keyword_type = ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap();
|
let value: $keyword_type = ::num_traits::cast::FromPrimitive::from_u8(kw).unwrap();
|
||||||
@ -83,7 +83,7 @@ macro_rules! keyword_evaluator {
|
|||||||
|
|
||||||
fn __evaluate(
|
fn __evaluate(
|
||||||
context: &$crate::values::computed::Context,
|
context: &$crate::values::computed::Context,
|
||||||
value: Option<$crate::media_queries::media_feature::KeywordDiscriminant>,
|
value: Option<$crate::queries::feature::KeywordDiscriminant>,
|
||||||
) -> bool {
|
) -> bool {
|
||||||
// This unwrap is ok because the only discriminants that get
|
// This unwrap is ok because the only discriminants that get
|
||||||
// back to us is the ones that `parse` produces.
|
// back to us is the ones that `parse` produces.
|
||||||
@ -92,7 +92,7 @@ macro_rules! keyword_evaluator {
|
|||||||
$actual_evaluator(context, value)
|
$actual_evaluator(context, value)
|
||||||
}
|
}
|
||||||
|
|
||||||
$crate::media_queries::media_feature::Evaluator::Enumerated {
|
$crate::queries::feature::Evaluator::Enumerated {
|
||||||
parser: __parse,
|
parser: __parse,
|
||||||
serializer: __serialize,
|
serializer: __serialize,
|
||||||
evaluator: __evaluate,
|
evaluator: __evaluate,
|
||||||
@ -111,7 +111,7 @@ bitflags! {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Whether a media feature allows ranges or not.
|
/// Whether a feature allows ranges or not.
|
||||||
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
|
||||||
#[allow(missing_docs)]
|
#[allow(missing_docs)]
|
||||||
pub enum AllowsRanges {
|
pub enum AllowsRanges {
|
||||||
@ -119,9 +119,9 @@ pub enum AllowsRanges {
|
|||||||
No,
|
No,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A description of a media feature.
|
/// A description of a feature.
|
||||||
pub struct MediaFeatureDescription {
|
pub struct QueryFeatureDescription {
|
||||||
/// The media feature name, in ascii lowercase.
|
/// The feature name, in ascii lowercase.
|
||||||
pub name: Atom,
|
pub name: Atom,
|
||||||
/// Whether min- / max- prefixes are allowed or not.
|
/// Whether min- / max- prefixes are allowed or not.
|
||||||
pub allows_ranges: AllowsRanges,
|
pub allows_ranges: AllowsRanges,
|
||||||
@ -133,18 +133,18 @@ pub struct MediaFeatureDescription {
|
|||||||
pub requirements: ParsingRequirements,
|
pub requirements: ParsingRequirements,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaFeatureDescription {
|
impl QueryFeatureDescription {
|
||||||
/// Whether this media feature allows ranges.
|
/// Whether this feature allows ranges.
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn allows_ranges(&self) -> bool {
|
pub fn allows_ranges(&self) -> bool {
|
||||||
self.allows_ranges == AllowsRanges::Yes
|
self.allows_ranges == AllowsRanges::Yes
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A simple helper to construct a `MediaFeatureDescription`.
|
/// A simple helper to construct a `QueryFeatureDescription`.
|
||||||
macro_rules! feature {
|
macro_rules! feature {
|
||||||
($name:expr, $allows_ranges:expr, $evaluator:expr, $reqs:expr,) => {
|
($name:expr, $allows_ranges:expr, $evaluator:expr, $reqs:expr,) => {
|
||||||
$crate::media_queries::media_feature::MediaFeatureDescription {
|
$crate::queries::feature::QueryFeatureDescription {
|
||||||
name: $name,
|
name: $name,
|
||||||
allows_ranges: $allows_ranges,
|
allows_ranges: $allows_ranges,
|
||||||
evaluator: $evaluator,
|
evaluator: $evaluator,
|
||||||
@ -153,9 +153,9 @@ macro_rules! feature {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Debug for MediaFeatureDescription {
|
impl fmt::Debug for QueryFeatureDescription {
|
||||||
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("QueryFeatureDescription")
|
||||||
.field("name", &self.name)
|
.field("name", &self.name)
|
||||||
.field("allows_ranges", &self.allows_ranges)
|
.field("allows_ranges", &self.allows_ranges)
|
||||||
.field("requirements", &self.requirements)
|
.field("requirements", &self.requirements)
|
@ -2,11 +2,11 @@
|
|||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! Parsing for media feature expressions, like `(foo: bar)` or
|
//! Parsing for query feature expressions, like `(foo: bar)` or
|
||||||
//! `(width >= 400px)`.
|
//! `(width >= 400px)`.
|
||||||
|
|
||||||
use super::media_feature::{Evaluator, MediaFeatureDescription};
|
use super::feature::{Evaluator, QueryFeatureDescription};
|
||||||
use super::media_feature::{KeywordDiscriminant, ParsingRequirements};
|
use super::feature::{KeywordDiscriminant, ParsingRequirements};
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::gecko::media_features::MEDIA_FEATURES;
|
use crate::gecko::media_features::MEDIA_FEATURES;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
@ -22,7 +22,7 @@ use std::cmp::{Ordering, PartialOrd};
|
|||||||
use std::fmt::{self, Write};
|
use std::fmt::{self, Write};
|
||||||
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
use style_traits::{CssWriter, ParseError, StyleParseErrorKind, ToCss};
|
||||||
|
|
||||||
/// The kind of matching that should be performed on a media feature value.
|
/// The kind of matching that should be performed on a feature value.
|
||||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
|
||||||
pub enum Range {
|
pub enum Range {
|
||||||
/// At least the specified value.
|
/// At least the specified value.
|
||||||
@ -31,7 +31,7 @@ pub enum Range {
|
|||||||
Max,
|
Max,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The operator that was specified in this media feature.
|
/// The operator that was specified in this feature.
|
||||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
|
||||||
pub enum Operator {
|
pub enum Operator {
|
||||||
/// =
|
/// =
|
||||||
@ -63,8 +63,7 @@ impl ToCss for Operator {
|
|||||||
|
|
||||||
/// Either a `Range` or an `Operator`.
|
/// Either a `Range` or an `Operator`.
|
||||||
///
|
///
|
||||||
/// Ranged media features are not allowed with operations (that'd make no
|
/// Ranged features are not allowed with operations (that'd make no sense).
|
||||||
/// sense).
|
|
||||||
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
|
#[derive(Clone, Copy, Debug, Eq, MallocSizeOf, PartialEq, ToShmem)]
|
||||||
pub enum RangeOrOperator {
|
pub enum RangeOrOperator {
|
||||||
/// A `Range`.
|
/// A `Range`.
|
||||||
@ -121,16 +120,16 @@ impl RangeOrOperator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A feature expression contains a reference to the media feature, the value
|
/// A feature expression contains a reference to the feature, the value the
|
||||||
/// the media query contained, and the range to evaluate.
|
/// query contained, and the range to evaluate.
|
||||||
#[derive(Clone, Debug, MallocSizeOf, ToShmem, PartialEq)]
|
#[derive(Clone, Debug, MallocSizeOf, ToShmem, PartialEq)]
|
||||||
pub struct MediaFeatureExpression {
|
pub struct QueryFeatureExpression {
|
||||||
feature_index: usize,
|
feature_index: usize,
|
||||||
value: Option<MediaExpressionValue>,
|
value: Option<QueryExpressionValue>,
|
||||||
range_or_operator: Option<RangeOrOperator>,
|
range_or_operator: Option<RangeOrOperator>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ToCss for MediaFeatureExpression {
|
impl ToCss for QueryFeatureExpression {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>) -> fmt::Result
|
||||||
where
|
where
|
||||||
W: fmt::Write,
|
W: fmt::Write,
|
||||||
@ -243,10 +242,10 @@ fn disabled_by_pref(feature: &Atom, context: &ParserContext) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaFeatureExpression {
|
impl QueryFeatureExpression {
|
||||||
fn new(
|
fn new(
|
||||||
feature_index: usize,
|
feature_index: usize,
|
||||||
value: Option<MediaExpressionValue>,
|
value: Option<QueryExpressionValue>,
|
||||||
range_or_operator: Option<RangeOrOperator>,
|
range_or_operator: Option<RangeOrOperator>,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
debug_assert!(feature_index < MEDIA_FEATURES.len());
|
debug_assert!(feature_index < MEDIA_FEATURES.len());
|
||||||
@ -257,11 +256,11 @@ impl MediaFeatureExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn feature(&self) -> &'static MediaFeatureDescription {
|
fn feature(&self) -> &'static QueryFeatureDescription {
|
||||||
&MEDIA_FEATURES[self.feature_index]
|
&MEDIA_FEATURES[self.feature_index]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a media expression of the form:
|
/// Parse a feature expression of the form:
|
||||||
///
|
///
|
||||||
/// ```
|
/// ```
|
||||||
/// (media-feature: media-value)
|
/// (media-feature: media-value)
|
||||||
@ -274,8 +273,7 @@ impl MediaFeatureExpression {
|
|||||||
input.parse_nested_block(|input| Self::parse_in_parenthesis_block(context, input))
|
input.parse_nested_block(|input| Self::parse_in_parenthesis_block(context, input))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Parse a media feature expression where we've already consumed the
|
/// Parse a feature expression where we've already consumed the parenthesis.
|
||||||
/// parenthesis.
|
|
||||||
pub fn parse_in_parenthesis_block<'i, 't>(
|
pub fn parse_in_parenthesis_block<'i, 't>(
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
@ -332,9 +330,8 @@ impl MediaFeatureExpression {
|
|||||||
let operator = input.try_parse(consume_operation_or_colon);
|
let operator = input.try_parse(consume_operation_or_colon);
|
||||||
let operator = match operator {
|
let operator = match operator {
|
||||||
Err(..) => {
|
Err(..) => {
|
||||||
// If there's no colon, this is a media query of the
|
// If there's no colon, this is a query of the form
|
||||||
// form '(<feature>)', that is, there's no value
|
// '(<feature>)', that is, there's no value specified.
|
||||||
// specified.
|
|
||||||
//
|
//
|
||||||
// Gecko doesn't allow ranged expressions without a
|
// Gecko doesn't allow ranged expressions without a
|
||||||
// value, so just reject them here too.
|
// value, so just reject them here too.
|
||||||
@ -370,7 +367,7 @@ impl MediaFeatureExpression {
|
|||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
let value = MediaExpressionValue::parse(feature, context, input).map_err(|err| {
|
let value = QueryExpressionValue::parse(feature, context, input).map_err(|err| {
|
||||||
err.location
|
err.location
|
||||||
.new_custom_error(StyleParseErrorKind::MediaQueryExpectedFeatureValue)
|
.new_custom_error(StyleParseErrorKind::MediaQueryExpectedFeatureValue)
|
||||||
})?;
|
})?;
|
||||||
@ -378,15 +375,15 @@ impl MediaFeatureExpression {
|
|||||||
Ok(Self::new(feature_index, Some(value), range_or_operator))
|
Ok(Self::new(feature_index, Some(value), range_or_operator))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns whether this media query evaluates to true for the given device.
|
/// Returns whether this query evaluates to true for the given device.
|
||||||
pub fn matches(&self, context: &computed::Context) -> bool {
|
pub fn matches(&self, context: &computed::Context) -> bool {
|
||||||
let value = self.value.as_ref();
|
let value = self.value.as_ref();
|
||||||
|
|
||||||
macro_rules! expect {
|
macro_rules! expect {
|
||||||
($variant:ident) => {
|
($variant:ident) => {
|
||||||
value.map(|value| match *value {
|
value.map(|value| match *value {
|
||||||
MediaExpressionValue::$variant(ref v) => v,
|
QueryExpressionValue::$variant(ref v) => v,
|
||||||
_ => unreachable!("Unexpected MediaExpressionValue"),
|
_ => unreachable!("Unexpected QueryExpressionValue"),
|
||||||
})
|
})
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -442,7 +439,7 @@ impl MediaFeatureExpression {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A value found or expected in a media expression.
|
/// A value found or expected in a expression.
|
||||||
///
|
///
|
||||||
/// FIXME(emilio): How should calc() serialize in the Number / Integer /
|
/// FIXME(emilio): How should calc() serialize in the Number / Integer /
|
||||||
/// BoolInteger / NumberRatio case, as computed or as specified value?
|
/// BoolInteger / NumberRatio case, as computed or as specified value?
|
||||||
@ -451,7 +448,7 @@ impl MediaFeatureExpression {
|
|||||||
///
|
///
|
||||||
/// See: https://github.com/w3c/csswg-drafts/issues/1968
|
/// See: https://github.com/w3c/csswg-drafts/issues/1968
|
||||||
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToShmem)]
|
||||||
pub enum MediaExpressionValue {
|
pub enum QueryExpressionValue {
|
||||||
/// A length.
|
/// A length.
|
||||||
Length(Length),
|
Length(Length),
|
||||||
/// A (non-negative) integer.
|
/// A (non-negative) integer.
|
||||||
@ -470,19 +467,19 @@ pub enum MediaExpressionValue {
|
|||||||
Enumerated(KeywordDiscriminant),
|
Enumerated(KeywordDiscriminant),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MediaExpressionValue {
|
impl QueryExpressionValue {
|
||||||
fn to_css<W>(&self, dest: &mut CssWriter<W>, for_expr: &MediaFeatureExpression) -> fmt::Result
|
fn to_css<W>(&self, dest: &mut CssWriter<W>, for_expr: &QueryFeatureExpression) -> fmt::Result
|
||||||
where
|
where
|
||||||
W: fmt::Write,
|
W: fmt::Write,
|
||||||
{
|
{
|
||||||
match *self {
|
match *self {
|
||||||
MediaExpressionValue::Length(ref l) => l.to_css(dest),
|
QueryExpressionValue::Length(ref l) => l.to_css(dest),
|
||||||
MediaExpressionValue::Integer(v) => v.to_css(dest),
|
QueryExpressionValue::Integer(v) => v.to_css(dest),
|
||||||
MediaExpressionValue::Float(v) => v.to_css(dest),
|
QueryExpressionValue::Float(v) => v.to_css(dest),
|
||||||
MediaExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }),
|
QueryExpressionValue::BoolInteger(v) => dest.write_str(if v { "1" } else { "0" }),
|
||||||
MediaExpressionValue::NumberRatio(ratio) => ratio.to_css(dest),
|
QueryExpressionValue::NumberRatio(ratio) => ratio.to_css(dest),
|
||||||
MediaExpressionValue::Resolution(ref r) => r.to_css(dest),
|
QueryExpressionValue::Resolution(ref r) => r.to_css(dest),
|
||||||
MediaExpressionValue::Enumerated(value) => match for_expr.feature().evaluator {
|
QueryExpressionValue::Enumerated(value) => match for_expr.feature().evaluator {
|
||||||
Evaluator::Enumerated { serializer, .. } => dest.write_str(&*serializer(value)),
|
Evaluator::Enumerated { serializer, .. } => dest.write_str(&*serializer(value)),
|
||||||
_ => unreachable!(),
|
_ => unreachable!(),
|
||||||
},
|
},
|
||||||
@ -490,18 +487,18 @@ impl MediaExpressionValue {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn parse<'i, 't>(
|
fn parse<'i, 't>(
|
||||||
for_feature: &MediaFeatureDescription,
|
for_feature: &QueryFeatureDescription,
|
||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<MediaExpressionValue, ParseError<'i>> {
|
) -> Result<QueryExpressionValue, ParseError<'i>> {
|
||||||
Ok(match for_feature.evaluator {
|
Ok(match for_feature.evaluator {
|
||||||
Evaluator::Length(..) => {
|
Evaluator::Length(..) => {
|
||||||
let length = Length::parse_non_negative(context, input)?;
|
let length = Length::parse_non_negative(context, input)?;
|
||||||
MediaExpressionValue::Length(length)
|
QueryExpressionValue::Length(length)
|
||||||
},
|
},
|
||||||
Evaluator::Integer(..) => {
|
Evaluator::Integer(..) => {
|
||||||
let integer = Integer::parse_non_negative(context, input)?;
|
let integer = Integer::parse_non_negative(context, input)?;
|
||||||
MediaExpressionValue::Integer(integer.value() as u32)
|
QueryExpressionValue::Integer(integer.value() as u32)
|
||||||
},
|
},
|
||||||
Evaluator::BoolInteger(..) => {
|
Evaluator::BoolInteger(..) => {
|
||||||
let integer = Integer::parse_non_negative(context, input)?;
|
let integer = Integer::parse_non_negative(context, input)?;
|
||||||
@ -509,22 +506,22 @@ impl MediaExpressionValue {
|
|||||||
if value > 1 {
|
if value > 1 {
|
||||||
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
return Err(input.new_custom_error(StyleParseErrorKind::UnspecifiedError));
|
||||||
}
|
}
|
||||||
MediaExpressionValue::BoolInteger(value == 1)
|
QueryExpressionValue::BoolInteger(value == 1)
|
||||||
},
|
},
|
||||||
Evaluator::Float(..) => {
|
Evaluator::Float(..) => {
|
||||||
let number = Number::parse(context, input)?;
|
let number = Number::parse(context, input)?;
|
||||||
MediaExpressionValue::Float(number.get())
|
QueryExpressionValue::Float(number.get())
|
||||||
},
|
},
|
||||||
Evaluator::NumberRatio(..) => {
|
Evaluator::NumberRatio(..) => {
|
||||||
use crate::values::specified::Ratio as SpecifiedRatio;
|
use crate::values::specified::Ratio as SpecifiedRatio;
|
||||||
let ratio = SpecifiedRatio::parse(context, input)?;
|
let ratio = SpecifiedRatio::parse(context, input)?;
|
||||||
MediaExpressionValue::NumberRatio(Ratio::new(ratio.0.get(), ratio.1.get()))
|
QueryExpressionValue::NumberRatio(Ratio::new(ratio.0.get(), ratio.1.get()))
|
||||||
},
|
},
|
||||||
Evaluator::Resolution(..) => {
|
Evaluator::Resolution(..) => {
|
||||||
MediaExpressionValue::Resolution(Resolution::parse(context, input)?)
|
QueryExpressionValue::Resolution(Resolution::parse(context, input)?)
|
||||||
},
|
},
|
||||||
Evaluator::Enumerated { parser, .. } => {
|
Evaluator::Enumerated { parser, .. } => {
|
||||||
MediaExpressionValue::Enumerated(parser(context, input)?)
|
QueryExpressionValue::Enumerated(parser(context, input)?)
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
17
servo/components/style/queries/mod.rs
Normal file
17
servo/components/style/queries/mod.rs
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
/* 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 https://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
//! Code shared between [media queries][mq] and [container queries][cq].
|
||||||
|
//!
|
||||||
|
//! [mq]: https://drafts.csswg.org/mediaqueries/
|
||||||
|
//! [cq]: https://drafts.csswg.org/css-contain-3/#container-rule
|
||||||
|
|
||||||
|
mod condition;
|
||||||
|
|
||||||
|
#[macro_use]
|
||||||
|
pub mod feature;
|
||||||
|
pub mod feature_expression;
|
||||||
|
|
||||||
|
pub use self::condition::QueryCondition;
|
||||||
|
pub use self::feature_expression::QueryFeatureExpression;
|
@ -6,7 +6,7 @@
|
|||||||
//!
|
//!
|
||||||
//! [container]: https://drafts.csswg.org/css-contain-3/#container-rule
|
//! [container]: https://drafts.csswg.org/css-contain-3/#container-rule
|
||||||
|
|
||||||
use crate::media_queries::MediaCondition;
|
use crate::queries::QueryCondition;
|
||||||
use crate::shared_lock::{
|
use crate::shared_lock::{
|
||||||
DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard,
|
DeepCloneParams, DeepCloneWithLock, Locked, SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard,
|
||||||
};
|
};
|
||||||
@ -76,4 +76,4 @@ impl ToCssWithGuard for ContainerRule {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// TODO: Factor out the media query code to work with containers.
|
/// TODO: Factor out the media query code to work with containers.
|
||||||
pub type ContainerCondition = MediaCondition;
|
pub type ContainerCondition = QueryCondition;
|
||||||
|
@ -6,8 +6,9 @@
|
|||||||
|
|
||||||
#[cfg(feature = "gecko")]
|
#[cfg(feature = "gecko")]
|
||||||
use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
use crate::gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||||
use crate::media_queries::{Device, MediaCondition};
|
use crate::media_queries::Device;
|
||||||
use crate::parser::{Parse, ParserContext};
|
use crate::parser::{Parse, ParserContext};
|
||||||
|
use crate::queries::QueryCondition;
|
||||||
use crate::values::computed::{self, ToComputedValue};
|
use crate::values::computed::{self, ToComputedValue};
|
||||||
use crate::values::specified::{Length, NoCalcLength, ViewportPercentageLength};
|
use crate::values::specified::{Length, NoCalcLength, ViewportPercentageLength};
|
||||||
use app_units::Au;
|
use app_units::Au;
|
||||||
@ -20,7 +21,7 @@ use style_traits::ParseError;
|
|||||||
/// https://html.spec.whatwg.org/multipage/#source-size
|
/// https://html.spec.whatwg.org/multipage/#source-size
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct SourceSize {
|
pub struct SourceSize {
|
||||||
condition: MediaCondition,
|
condition: QueryCondition,
|
||||||
value: Length,
|
value: Length,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -29,9 +30,8 @@ impl Parse for SourceSize {
|
|||||||
context: &ParserContext,
|
context: &ParserContext,
|
||||||
input: &mut Parser<'i, 't>,
|
input: &mut Parser<'i, 't>,
|
||||||
) -> Result<Self, ParseError<'i>> {
|
) -> Result<Self, ParseError<'i>> {
|
||||||
let condition = MediaCondition::parse(context, input)?;
|
let condition = QueryCondition::parse(context, input)?;
|
||||||
let value = Length::parse_non_negative(context, input)?;
|
let value = Length::parse_non_negative(context, input)?;
|
||||||
|
|
||||||
Ok(Self { condition, value })
|
Ok(Self { condition, value })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user