mirror of
https://github.com/servo/servo.git
synced 2025-07-23 07:13:52 +01:00
stylo: Integrate Servo SourceSizeList in ResponsiveImageSelector.
This needs to dumb down the parsing in order to match what we do in Gecko and pass more tests. The remaining tests are just because of calc() in media queries and "or" media expressions. Bug: 1408308 Reviewed-by: Manishearth MozReview-Commit-ID: CXGdYVbojBL
This commit is contained in:
parent
bc58e18761
commit
a76cb65751
3 changed files with 131 additions and 15 deletions
|
@ -23,7 +23,7 @@
|
|||
//! [cssparser]: ../cssparser/index.html
|
||||
//! [selectors]: ../selectors/index.html
|
||||
|
||||
#![deny(warnings)]
|
||||
// #![deny(warnings)]
|
||||
#![deny(missing_docs)]
|
||||
|
||||
// FIXME(bholley): We need to blanket-allow unsafe code in order to make the
|
||||
|
|
|
@ -5,18 +5,22 @@
|
|||
//! https://html.spec.whatwg.org/multipage/#source-size-list
|
||||
|
||||
use app_units::Au;
|
||||
use cssparser::Parser;
|
||||
use cssparser::{Delimiter, Parser, Token};
|
||||
#[cfg(feature = "gecko")]
|
||||
use gecko_bindings::sugar::ownership::{HasBoxFFI, HasFFI, HasSimpleFFI};
|
||||
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;
|
||||
use values::specified::{Length, NoCalcLength, ViewportPercentageLength};
|
||||
|
||||
/// A value for a `<source-size>`:
|
||||
///
|
||||
/// https://html.spec.whatwg.org/multipage/#source-size
|
||||
pub struct SourceSize {
|
||||
// FIXME(emilio): This should be a `MediaCondition`, and support `and` and
|
||||
// `or`.
|
||||
condition: MediaExpression,
|
||||
value: Length,
|
||||
}
|
||||
|
@ -38,10 +42,18 @@ impl Parse for SourceSize {
|
|||
/// https://html.spec.whatwg.org/multipage/#source-size-list
|
||||
pub struct SourceSizeList {
|
||||
source_sizes: Vec<SourceSize>,
|
||||
value: Length,
|
||||
value: Option<Length>,
|
||||
}
|
||||
|
||||
impl SourceSizeList {
|
||||
/// Create an empty `SourceSizeList`, which can be used as a fall-back.
|
||||
pub fn empty() -> Self {
|
||||
Self {
|
||||
source_sizes: vec![],
|
||||
value: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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| {
|
||||
|
@ -54,26 +66,80 @@ impl SourceSizeList {
|
|||
source_size.value.to_computed_value(context)
|
||||
}
|
||||
None => {
|
||||
self.value.to_computed_value(context)
|
||||
match self.value {
|
||||
Some(ref v) => v.to_computed_value(context),
|
||||
None => {
|
||||
Length::NoCalc(NoCalcLength::ViewportPercentage(
|
||||
ViewportPercentageLength::Vw(100.)
|
||||
)).to_computed_value(context)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}).into()
|
||||
}
|
||||
}
|
||||
|
||||
impl Parse for SourceSizeList {
|
||||
enum SourceSizeOrLength {
|
||||
SourceSize(SourceSize),
|
||||
Length(Length),
|
||||
}
|
||||
|
||||
impl Parse for SourceSizeOrLength {
|
||||
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![]);
|
||||
if let Ok(size) = input.try(|input| SourceSize::parse(context, input)) {
|
||||
return Ok(SourceSizeOrLength::SourceSize(size));
|
||||
}
|
||||
|
||||
let value = Length::parse_non_negative(context, input)?;
|
||||
|
||||
Ok(Self { source_sizes, value })
|
||||
let length = Length::parse_non_negative(context, input)?;
|
||||
Ok(SourceSizeOrLength::Length(length))
|
||||
}
|
||||
}
|
||||
|
||||
impl SourceSizeList {
|
||||
/// NOTE(emilio): This doesn't match the grammar in the spec, see:
|
||||
///
|
||||
/// https://html.spec.whatwg.org/multipage/#parsing-a-sizes-attribute
|
||||
pub fn parse<'i, 't>(
|
||||
context: &ParserContext,
|
||||
input: &mut Parser<'i, 't>,
|
||||
) -> Self {
|
||||
let mut source_sizes = vec![];
|
||||
|
||||
loop {
|
||||
let result = input.parse_until_before(Delimiter::Comma, |input| {
|
||||
SourceSizeOrLength::parse(context, input)
|
||||
});
|
||||
|
||||
match result {
|
||||
Ok(SourceSizeOrLength::Length(value)) => {
|
||||
return Self { source_sizes, value: Some(value) }
|
||||
}
|
||||
Ok(SourceSizeOrLength::SourceSize(source_size)) => {
|
||||
source_sizes.push(source_size);
|
||||
}
|
||||
Err(..) => {}
|
||||
}
|
||||
|
||||
match input.next() {
|
||||
Ok(&Token::Comma) => {},
|
||||
Err(..) => break,
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
|
||||
SourceSizeList { source_sizes, value: None }
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "gecko")]
|
||||
unsafe impl HasFFI for SourceSizeList {
|
||||
type FFIType = ::gecko_bindings::structs::RawServoSourceSizeList;
|
||||
}
|
||||
#[cfg(feature = "gecko")]
|
||||
unsafe impl HasSimpleFFI for SourceSizeList {}
|
||||
#[cfg(feature = "gecko")]
|
||||
unsafe impl HasBoxFFI for SourceSizeList {}
|
||||
|
|
|
@ -44,6 +44,7 @@ use style::gecko_bindings::bindings::{RawServoMediaRule, RawServoMediaRuleBorrow
|
|||
use style::gecko_bindings::bindings::{RawServoNamespaceRule, RawServoNamespaceRuleBorrowed};
|
||||
use style::gecko_bindings::bindings::{RawServoPageRule, RawServoPageRuleBorrowed};
|
||||
use style::gecko_bindings::bindings::{RawServoSelectorListBorrowed, RawServoSelectorListOwned};
|
||||
use style::gecko_bindings::bindings::{RawServoSourceSizeListBorrowedOrNull, RawServoSourceSizeListOwned};
|
||||
use style::gecko_bindings::bindings::{RawServoStyleSetBorrowed, RawServoStyleSetBorrowedOrNull, RawServoStyleSetOwned};
|
||||
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsBorrowed, ServoComputedDataBorrowed};
|
||||
use style::gecko_bindings::bindings::{RawServoStyleSheetContentsStrong, ServoStyleContextBorrowed};
|
||||
|
@ -95,6 +96,7 @@ use style::gecko_bindings::structs::OriginFlags_UserAgent;
|
|||
use style::gecko_bindings::structs::RawGeckoGfxMatrix4x4;
|
||||
use style::gecko_bindings::structs::RawGeckoPresContextOwned;
|
||||
use style::gecko_bindings::structs::RawServoSelectorList;
|
||||
use style::gecko_bindings::structs::RawServoSourceSizeList;
|
||||
use style::gecko_bindings::structs::SeenPtrs;
|
||||
use style::gecko_bindings::structs::ServoElementSnapshotTable;
|
||||
use style::gecko_bindings::structs::ServoStyleSetSizes;
|
||||
|
@ -147,6 +149,7 @@ use style::values::computed::{Context, ToComputedValue};
|
|||
use style::values::distance::ComputeSquaredDistance;
|
||||
use style::values::specified;
|
||||
use style::values::specified::gecko::IntersectionObserverRootMargin;
|
||||
use style::values::specified::source_size_list::SourceSizeList;
|
||||
use style_traits::{ParsingMode, ToCss};
|
||||
use super::error_reporter::ErrorReporter;
|
||||
use super::stylesheet_loader::StylesheetLoader;
|
||||
|
@ -4515,7 +4518,7 @@ pub unsafe extern "C" fn Servo_SelectorList_Parse(
|
|||
|
||||
debug_assert!(!selector_list.is_null());
|
||||
|
||||
let input = ::std::str::from_utf8_unchecked(&**selector_list);
|
||||
let input = (*selector_list).as_str_unchecked();
|
||||
let selector_list = match SelectorParser::parse_author_origin_no_namespace(&input) {
|
||||
Ok(selector_list) => selector_list,
|
||||
Err(..) => return ptr::null_mut(),
|
||||
|
@ -4627,3 +4630,50 @@ pub extern "C" fn Servo_ParseIntersectionObserverRootMargin(
|
|||
Err(..) => false,
|
||||
}
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_SourceSizeList_Parse(
|
||||
value: *const nsACString,
|
||||
) -> *mut RawServoSourceSizeList {
|
||||
let value = (*value).as_str_unchecked();
|
||||
let mut input = ParserInput::new(value);
|
||||
let mut parser = Parser::new(&mut input);
|
||||
|
||||
let context = ParserContext::new(
|
||||
Origin::Author,
|
||||
dummy_url_data(),
|
||||
Some(CssRuleType::Style),
|
||||
ParsingMode::DEFAULT,
|
||||
QuirksMode::NoQuirks,
|
||||
);
|
||||
|
||||
// NB: Intentionally not calling parse_entirely.
|
||||
let list = SourceSizeList::parse(&context, &mut parser);
|
||||
Box::into_raw(Box::new(list)) as *mut _
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_SourceSizeList_Evaluate(
|
||||
raw_data: RawServoStyleSetBorrowed,
|
||||
list: RawServoSourceSizeListBorrowedOrNull,
|
||||
) -> i32 {
|
||||
let doc_data = PerDocumentStyleData::from_ffi(raw_data).borrow();
|
||||
let device = doc_data.stylist.device();
|
||||
let quirks_mode = doc_data.stylist.quirks_mode();
|
||||
|
||||
let result = match list {
|
||||
Some(list) => {
|
||||
SourceSizeList::from_ffi(list).evaluate(device, quirks_mode)
|
||||
}
|
||||
None => {
|
||||
SourceSizeList::empty().evaluate(device, quirks_mode)
|
||||
}
|
||||
};
|
||||
|
||||
result.0
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn Servo_SourceSizeList_Drop(list: RawServoSourceSizeListOwned) {
|
||||
let _ = list.into_box::<SourceSizeList>();
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue