mirror of
https://github.com/servo/servo.git
synced 2025-07-08 16:03:40 +01:00
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 -->
This commit is contained in:
commit
0047c77f03
6 changed files with 142 additions and 69 deletions
|
@ -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),
|
||||
|
|
|
@ -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)?)
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
79
components/style/values/specified/source_size_list.rs
Normal file
79
components/style/values/specified/source_size_list.rs
Normal file
|
@ -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 })
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue