mirror of
https://github.com/servo/servo.git
synced 2025-08-03 12:40:06 +01:00
implement update_source_set, select_image_source
This commit is contained in:
parent
8eb2a53e20
commit
8d06da8afd
6 changed files with 289 additions and 99 deletions
|
@ -47,6 +47,7 @@ use dom::bindings::root::{Dom, DomRoot};
|
||||||
use dom::bindings::str::{DOMString, USVString};
|
use dom::bindings::str::{DOMString, USVString};
|
||||||
use dom::bindings::utils::WindowProxyHandler;
|
use dom::bindings::utils::WindowProxyHandler;
|
||||||
use dom::document::PendingRestyle;
|
use dom::document::PendingRestyle;
|
||||||
|
use dom::htmlimageelement::SourceSet;
|
||||||
use encoding_rs::{Decoder, Encoding};
|
use encoding_rs::{Decoder, Encoding};
|
||||||
use euclid::{Transform2D, Transform3D, Point2D, Vector2D, Rect, TypedSize2D, TypedScale};
|
use euclid::{Transform2D, Transform3D, Point2D, Vector2D, Rect, TypedSize2D, TypedScale};
|
||||||
use euclid::Length as EuclidLength;
|
use euclid::Length as EuclidLength;
|
||||||
|
@ -425,6 +426,7 @@ unsafe_no_jsmanaged_fields!(ScriptToConstellationChan);
|
||||||
unsafe_no_jsmanaged_fields!(InteractiveMetrics);
|
unsafe_no_jsmanaged_fields!(InteractiveMetrics);
|
||||||
unsafe_no_jsmanaged_fields!(InteractiveWindow);
|
unsafe_no_jsmanaged_fields!(InteractiveWindow);
|
||||||
unsafe_no_jsmanaged_fields!(CanvasId);
|
unsafe_no_jsmanaged_fields!(CanvasId);
|
||||||
|
unsafe_no_jsmanaged_fields!(SourceSet);
|
||||||
|
|
||||||
unsafe impl<'a> JSTraceable for &'a str {
|
unsafe impl<'a> JSTraceable for &'a str {
|
||||||
#[inline]
|
#[inline]
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
use app_units::{Au, AU_PER_PX};
|
use app_units::{Au, AU_PER_PX};
|
||||||
|
use cssparser::{Parser, ParserInput};
|
||||||
use document_loader::{LoadType, LoadBlocker};
|
use document_loader::{LoadType, LoadBlocker};
|
||||||
use dom::activation::Activatable;
|
use dom::activation::Activatable;
|
||||||
use dom::attr::Attr;
|
use dom::attr::Attr;
|
||||||
|
@ -12,6 +13,7 @@ use dom::bindings::codegen::Bindings::ElementBinding::ElementBinding::ElementMet
|
||||||
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
|
use dom::bindings::codegen::Bindings::HTMLImageElementBinding;
|
||||||
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
|
use dom::bindings::codegen::Bindings::HTMLImageElementBinding::HTMLImageElementMethods;
|
||||||
use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
use dom::bindings::codegen::Bindings::MouseEventBinding::MouseEventMethods;
|
||||||
|
use dom::bindings::codegen::Bindings::NodeBinding::NodeBinding::NodeMethods;
|
||||||
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
use dom::bindings::codegen::Bindings::WindowBinding::WindowMethods;
|
||||||
use dom::bindings::error::Fallible;
|
use dom::bindings::error::Fallible;
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
|
@ -28,6 +30,8 @@ use dom::htmlareaelement::HTMLAreaElement;
|
||||||
use dom::htmlelement::HTMLElement;
|
use dom::htmlelement::HTMLElement;
|
||||||
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
use dom::htmlformelement::{FormControl, HTMLFormElement};
|
||||||
use dom::htmlmapelement::HTMLMapElement;
|
use dom::htmlmapelement::HTMLMapElement;
|
||||||
|
use dom::htmlpictureelement::HTMLPictureElement;
|
||||||
|
use dom::htmlsourceelement::HTMLSourceElement;
|
||||||
use dom::mouseevent::MouseEvent;
|
use dom::mouseevent::MouseEvent;
|
||||||
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
|
use dom::node::{Node, NodeDamage, document_from_node, window_from_node};
|
||||||
use dom::progressevent::ProgressEvent;
|
use dom::progressevent::ProgressEvent;
|
||||||
|
@ -40,6 +44,7 @@ use html5ever::{LocalName, Prefix};
|
||||||
use ipc_channel::ipc;
|
use ipc_channel::ipc;
|
||||||
use ipc_channel::router::ROUTER;
|
use ipc_channel::router::ROUTER;
|
||||||
use microtask::{Microtask, MicrotaskRunnable};
|
use microtask::{Microtask, MicrotaskRunnable};
|
||||||
|
use mime::{Mime, TopLevel};
|
||||||
use net_traits::{FetchResponseListener, FetchMetadata, NetworkError, FetchResponseMsg};
|
use net_traits::{FetchResponseListener, FetchMetadata, NetworkError, FetchResponseMsg};
|
||||||
use net_traits::image::base::{Image, ImageMetadata};
|
use net_traits::image::base::{Image, ImageMetadata};
|
||||||
use net_traits::image_cache::{CanRequestImages, ImageCache, ImageOrMetadataAvailable};
|
use net_traits::image_cache::{CanRequestImages, ImageCache, ImageOrMetadataAvailable};
|
||||||
|
@ -53,26 +58,49 @@ use servo_url::ServoUrl;
|
||||||
use servo_url::origin::ImmutableOrigin;
|
use servo_url::origin::ImmutableOrigin;
|
||||||
use std::cell::{Cell, RefMut};
|
use std::cell::{Cell, RefMut};
|
||||||
use std::char;
|
use std::char;
|
||||||
|
use std::collections::HashSet;
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
use std::i32;
|
use std::i32;
|
||||||
use std::sync::{Arc, Mutex};
|
use std::sync::{Arc, Mutex};
|
||||||
use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_double, parse_unsigned_integer};
|
use style::attr::{AttrValue, LengthOrPercentageOrAuto, parse_double, parse_length, parse_unsigned_integer};
|
||||||
|
use style::context::QuirksMode;
|
||||||
|
use style::media_queries::MediaList;
|
||||||
|
use style::parser::ParserContext;
|
||||||
use style::str::is_ascii_digit;
|
use style::str::is_ascii_digit;
|
||||||
|
use style::stylesheets::{CssRuleType, Origin};
|
||||||
|
use style::values::specified::{AbsoluteLength, source_size_list::SourceSizeList};
|
||||||
|
use style::values::specified::length::{Length, NoCalcLength};
|
||||||
|
use style_traits::ParsingMode;
|
||||||
use task_source::{TaskSource, TaskSourceName};
|
use task_source::{TaskSource, TaskSourceName};
|
||||||
|
|
||||||
|
|
||||||
enum ParseState {
|
enum ParseState {
|
||||||
InDescriptor,
|
InDescriptor,
|
||||||
InParens,
|
InParens,
|
||||||
AfterDescriptor,
|
AfterDescriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
pub struct SourceSet {
|
||||||
|
image_sources: Vec<ImageSource>,
|
||||||
|
source_size: SourceSizeList,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl SourceSet {
|
||||||
|
fn new() -> SourceSet {
|
||||||
|
SourceSet {
|
||||||
|
image_sources: Vec::new(),
|
||||||
|
source_size: SourceSizeList::empty(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct ImageSource {
|
pub struct ImageSource {
|
||||||
pub url: String,
|
pub url: String,
|
||||||
pub descriptor: Descriptor,
|
pub descriptor: Descriptor,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, PartialEq)]
|
#[derive(Clone, Debug, PartialEq)]
|
||||||
pub struct Descriptor {
|
pub struct Descriptor {
|
||||||
pub wid: Option<u32>,
|
pub wid: Option<u32>,
|
||||||
pub den: Option<f64>,
|
pub den: Option<f64>,
|
||||||
|
@ -112,6 +140,8 @@ pub struct HTMLImageElement {
|
||||||
pending_request: DomRefCell<ImageRequest>,
|
pending_request: DomRefCell<ImageRequest>,
|
||||||
form_owner: MutNullableDom<HTMLFormElement>,
|
form_owner: MutNullableDom<HTMLFormElement>,
|
||||||
generation: Cell<u32>,
|
generation: Cell<u32>,
|
||||||
|
#[ignore_malloc_size_of = "SourceSet"]
|
||||||
|
source_set: DomRefCell<SourceSet>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl HTMLImageElement {
|
impl HTMLImageElement {
|
||||||
|
@ -356,20 +386,233 @@ impl HTMLImageElement {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#update-the-source-set>
|
/// <https://html.spec.whatwg.org/multipage/#update-the-source-set>
|
||||||
fn update_source_set(&self) -> Vec<DOMString> {
|
fn update_source_set(&self) {
|
||||||
|
// Step 1
|
||||||
|
*self.source_set.borrow_mut() = SourceSet::new();
|
||||||
|
|
||||||
|
// Step 2
|
||||||
let elem = self.upcast::<Element>();
|
let elem = self.upcast::<Element>();
|
||||||
// TODO: follow the algorithm
|
let parent = elem.upcast::<Node>().GetParentElement();
|
||||||
let src = elem.get_string_attribute(&local_name!("src"));
|
let nodes;
|
||||||
if src.is_empty() {
|
let elements = match parent.as_ref() {
|
||||||
return vec![]
|
Some(p) => {
|
||||||
|
if p.is::<HTMLPictureElement>() {
|
||||||
|
nodes = p.upcast::<Node>().children();
|
||||||
|
nodes.filter_map(DomRoot::downcast::<Element>)
|
||||||
|
.map(|n| DomRoot::from_ref(&*n)).collect()
|
||||||
|
} else {
|
||||||
|
vec![DomRoot::from_ref(&*elem)]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => {
|
||||||
|
vec![DomRoot::from_ref(&*elem)]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 3
|
||||||
|
let width = match elem.get_attribute(&ns!(), &local_name!("width")) {
|
||||||
|
Some(x) => {
|
||||||
|
match parse_length(&x.value()) {
|
||||||
|
LengthOrPercentageOrAuto::Length(x) =>{
|
||||||
|
let abs_length = AbsoluteLength::Px(x.to_f32_px());
|
||||||
|
Some(Length::NoCalc(NoCalcLength::Absolute(abs_length)))
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => None
|
||||||
|
};
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
for element in &elements {
|
||||||
|
// Step 4.1
|
||||||
|
if *element == DomRoot::from_ref(&*elem) {
|
||||||
|
let mut source_set = SourceSet::new();
|
||||||
|
// Step 4.1.1
|
||||||
|
if let Some(x) = element.get_attribute(&ns!(), &local_name!("srcset")) {
|
||||||
|
source_set.image_sources = parse_a_srcset_attribute(&x.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.1.2
|
||||||
|
if let Some(x) = element.get_attribute(&ns!(), &local_name!("sizes")) {
|
||||||
|
source_set.source_size =
|
||||||
|
parse_a_sizes_attribute(DOMString::from_string(x.value().to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.1.3
|
||||||
|
let src_attribute = element.get_string_attribute(&local_name!("src"));
|
||||||
|
let is_src_empty = src_attribute.is_empty();
|
||||||
|
let no_density_source_of_1 = source_set.image_sources.iter()
|
||||||
|
.all(|source| source.descriptor.den != Some(1.));
|
||||||
|
let no_width_descriptor = source_set.image_sources.iter()
|
||||||
|
.all(|source| source.descriptor.wid.is_none());
|
||||||
|
if !is_src_empty && no_density_source_of_1 && no_width_descriptor {
|
||||||
|
source_set.image_sources.push(ImageSource {
|
||||||
|
url: src_attribute.to_string(),
|
||||||
|
descriptor: Descriptor { wid: None, den: None }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.1.4
|
||||||
|
self.normalise_source_densities(&mut source_set, width);
|
||||||
|
|
||||||
|
// Step 4.1.5
|
||||||
|
*self.source_set.borrow_mut() = source_set;
|
||||||
|
|
||||||
|
// Step 4.1.6
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Step 4.2
|
||||||
|
if !element.is::<HTMLSourceElement>() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.3 - 4.4
|
||||||
|
let mut source_set = SourceSet::new();
|
||||||
|
match element.get_attribute(&ns!(), &local_name!("srcset")) {
|
||||||
|
Some(x) => {
|
||||||
|
source_set.image_sources = parse_a_srcset_attribute(&x.value());
|
||||||
|
}
|
||||||
|
_ => continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.5
|
||||||
|
if source_set.image_sources.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.6
|
||||||
|
if let Some(x) = element.get_attribute(&ns!(), &local_name!("media")) {
|
||||||
|
if !self.matches_environment(x.value().to_string()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.7
|
||||||
|
if let Some(x) = element.get_attribute(&ns!(), &local_name!("sizes")) {
|
||||||
|
source_set.source_size =
|
||||||
|
parse_a_sizes_attribute(DOMString::from_string(x.value().to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.8
|
||||||
|
if let Some(x) = element.get_attribute(&ns!(), &local_name!("type")) {
|
||||||
|
// TODO Handle unsupported mime type
|
||||||
|
let mime = x.value().parse::<Mime>();
|
||||||
|
match mime {
|
||||||
|
Ok(m) =>
|
||||||
|
match m {
|
||||||
|
Mime(TopLevel::Image, _, _) => (),
|
||||||
|
_ => continue
|
||||||
|
},
|
||||||
|
_ => continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4.9
|
||||||
|
self.normalise_source_densities(&mut source_set, width);
|
||||||
|
|
||||||
|
// Step 4.10
|
||||||
|
*self.source_set.borrow_mut() = source_set;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
vec![src]
|
}
|
||||||
|
|
||||||
|
fn evaluate_source_size_list(&self, source_size_list: &mut SourceSizeList, width: Option<Length>) -> Au {
|
||||||
|
let document = document_from_node(self);
|
||||||
|
let device = document.device();
|
||||||
|
if !device.is_some() {
|
||||||
|
return Au(1);
|
||||||
|
}
|
||||||
|
let quirks_mode = document.quirks_mode();
|
||||||
|
source_size_list.set_fallback_value(width);
|
||||||
|
source_size_list.evaluate(&device.unwrap(), quirks_mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// https://html.spec.whatwg.org/multipage/#matches-the-environment
|
||||||
|
fn matches_environment(&self, media_query: String) -> bool {
|
||||||
|
let document = document_from_node(self);
|
||||||
|
let device = document.device();
|
||||||
|
if !device.is_some() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let quirks_mode = document.quirks_mode();
|
||||||
|
let document_url = &document.url();
|
||||||
|
let context = ParserContext::new(
|
||||||
|
Origin::Author,
|
||||||
|
document_url,
|
||||||
|
Some(CssRuleType::Style),
|
||||||
|
ParsingMode::all(),
|
||||||
|
quirks_mode,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
let mut parserInput = ParserInput::new(&media_query);
|
||||||
|
let mut parser = Parser::new(&mut parserInput);
|
||||||
|
let media_list = MediaList::parse(&context, &mut parser);
|
||||||
|
media_list.evaluate(&device.unwrap(), quirks_mode)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <https://html.spec.whatwg.org/multipage/#normalise-the-source-densities>
|
||||||
|
fn normalise_source_densities(&self, source_set: &mut SourceSet, width: Option<Length>) {
|
||||||
|
// Step 1
|
||||||
|
let mut source_size = &mut source_set.source_size;
|
||||||
|
|
||||||
|
// Find source_size_length for Step 2.2
|
||||||
|
let source_size_length = self.evaluate_source_size_list(&mut source_size, width);
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
for imgsource in &mut source_set.image_sources {
|
||||||
|
// Step 2.1
|
||||||
|
if imgsource.descriptor.den.is_some() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// Step 2.2
|
||||||
|
if imgsource.descriptor.wid.is_some() {
|
||||||
|
let wid = imgsource.descriptor.wid.unwrap();
|
||||||
|
imgsource.descriptor.den = Some(wid as f64 / source_size_length.to_f64_px());
|
||||||
|
} else {
|
||||||
|
//Step 2.3
|
||||||
|
imgsource.descriptor.den = Some(1 as f64);
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <https://html.spec.whatwg.org/multipage/#select-an-image-source>
|
/// <https://html.spec.whatwg.org/multipage/#select-an-image-source>
|
||||||
fn select_image_source(&self) -> Option<DOMString> {
|
fn select_image_source(&self) -> Option<(DOMString, f32)> {
|
||||||
// TODO: select an image source from source set
|
// Step 1, 3
|
||||||
self.update_source_set().first().cloned()
|
self.update_source_set();
|
||||||
|
let source_set = &*self.source_set.borrow_mut();
|
||||||
|
let len = source_set.image_sources.len();
|
||||||
|
|
||||||
|
// Step 2
|
||||||
|
if len == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 4
|
||||||
|
let mut repeat_indices = HashSet::new();
|
||||||
|
for outer_index in 0..len {
|
||||||
|
if repeat_indices.contains(&outer_index) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
let imgsource = &source_set.image_sources[outer_index];
|
||||||
|
let pixel_density = imgsource.descriptor.den.unwrap();
|
||||||
|
for inner_index in (outer_index + 1)..len {
|
||||||
|
let imgsource2 = &source_set.image_sources[inner_index];
|
||||||
|
if pixel_density == imgsource2.descriptor.den.unwrap() {
|
||||||
|
repeat_indices.insert(inner_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let img_sources = &mut vec![];
|
||||||
|
for outer_index in 0..len {
|
||||||
|
if !repeat_indices.contains(&outer_index) {
|
||||||
|
img_sources.push(&source_set.image_sources[outer_index]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO Step 5 - select source based on pixel density
|
||||||
|
let selected_source = img_sources.remove(0).clone();
|
||||||
|
Some((DOMString::from_string(selected_source.url), selected_source.descriptor.den.unwrap() as f32))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init_image_request(&self,
|
fn init_image_request(&self,
|
||||||
|
@ -439,7 +682,7 @@ impl HTMLImageElement {
|
||||||
Some(src) => {
|
Some(src) => {
|
||||||
// Step 8.
|
// Step 8.
|
||||||
// TODO: Handle pixel density.
|
// TODO: Handle pixel density.
|
||||||
src
|
src.0
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
// Step 9.
|
// Step 9.
|
||||||
|
@ -619,6 +862,7 @@ impl HTMLImageElement {
|
||||||
}),
|
}),
|
||||||
form_owner: Default::default(),
|
form_owner: Default::default(),
|
||||||
generation: Default::default(),
|
generation: Default::default(),
|
||||||
|
source_set: DomRefCell::new(SourceSet::new()),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -745,6 +989,22 @@ impl LayoutHTMLImageElementHelpers for LayoutDom<HTMLImageElement> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//https://html.spec.whatwg.org/multipage/#parse-a-sizes-attribute
|
||||||
|
pub fn parse_a_sizes_attribute(value: DOMString) -> SourceSizeList {
|
||||||
|
let mut input = ParserInput::new(&value);
|
||||||
|
let mut parser = Parser::new(&mut input);
|
||||||
|
let url = ServoUrl::parse("about:blank").unwrap();
|
||||||
|
let context = ParserContext::new(
|
||||||
|
Origin::Author,
|
||||||
|
&url,
|
||||||
|
Some(CssRuleType::Style),
|
||||||
|
ParsingMode::empty(),
|
||||||
|
QuirksMode::NoQuirks,
|
||||||
|
None,
|
||||||
|
);
|
||||||
|
SourceSizeList::parse(&context, &mut parser)
|
||||||
|
}
|
||||||
|
|
||||||
impl HTMLImageElementMethods for HTMLImageElement {
|
impl HTMLImageElementMethods for HTMLImageElement {
|
||||||
// https://html.spec.whatwg.org/multipage/#dom-img-alt
|
// https://html.spec.whatwg.org/multipage/#dom-img-alt
|
||||||
make_getter!(Alt, "alt");
|
make_getter!(Alt, "alt");
|
||||||
|
|
|
@ -18,6 +18,7 @@ use values::specified::{Length, NoCalcLength, ViewportPercentageLength};
|
||||||
/// A value for a `<source-size>`:
|
/// A value for a `<source-size>`:
|
||||||
///
|
///
|
||||||
/// https://html.spec.whatwg.org/multipage/#source-size
|
/// https://html.spec.whatwg.org/multipage/#source-size
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SourceSize {
|
pub struct SourceSize {
|
||||||
condition: MediaCondition,
|
condition: MediaCondition,
|
||||||
value: Length,
|
value: Length,
|
||||||
|
@ -38,6 +39,7 @@ impl Parse for SourceSize {
|
||||||
/// A value for a `<source-size-list>`:
|
/// A value for a `<source-size-list>`:
|
||||||
///
|
///
|
||||||
/// https://html.spec.whatwg.org/multipage/#source-size-list
|
/// https://html.spec.whatwg.org/multipage/#source-size-list
|
||||||
|
#[derive(Debug)]
|
||||||
pub struct SourceSizeList {
|
pub struct SourceSizeList {
|
||||||
source_sizes: Vec<SourceSize>,
|
source_sizes: Vec<SourceSize>,
|
||||||
value: Option<Length>,
|
value: Option<Length>,
|
||||||
|
@ -52,6 +54,11 @@ impl SourceSizeList {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Set content of `value`, which can be used as fall-back during evaluate.
|
||||||
|
pub fn set_fallback_value(&mut self, width: Option<Length>) {
|
||||||
|
self.value = width;
|
||||||
|
}
|
||||||
|
|
||||||
/// Evaluate this <source-size-list> to get the final viewport length.
|
/// Evaluate this <source-size-list> to get the final viewport length.
|
||||||
pub fn evaluate(&self, device: &Device, quirks_mode: QuirksMode) -> Au {
|
pub fn evaluate(&self, device: &Device, quirks_mode: QuirksMode) -> Au {
|
||||||
let matching_source_size = self.source_sizes
|
let matching_source_size = self.source_sizes
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
[adoption.html]
|
[adoption.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
expected: TIMEOUT
|
|
||||||
[img (src only)]
|
[img (src only)]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
@ -11,13 +10,13 @@
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[img (srcset 1 cand)]
|
[img (srcset 1 cand)]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[img (srcset 1 cand), parent is picture]
|
[img (srcset 1 cand), parent is picture]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[img (srcset 1 cand), previous sibling is source]
|
[img (srcset 1 cand), previous sibling is source]
|
||||||
expected: TIMEOUT
|
expected: FAIL
|
||||||
|
|
||||||
[adopt a cloned img in template]
|
[adopt a cloned img in template]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
|
@ -3,9 +3,6 @@
|
||||||
[<img srcset="//[">]
|
[<img srcset="//[">]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<img srcset="//[" src="/images/red.png">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img srcset="//[, /images/red.png">]
|
[<img srcset="//[, /images/red.png">]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
|
@ -1,107 +1,32 @@
|
||||||
[update-the-source-set.html]
|
[update-the-source-set.html]
|
||||||
type: testharness
|
type: testharness
|
||||||
[<img srcset="data:,b" src="data:,a" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b" data-expect="data:,b"><!-- srcset after src -->]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 1x" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 1.0x" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 1e0x" data-expect="data:,b">]
|
[<img src="data:,a" srcset="data:,b 1e0x" data-expect="data:,b">]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 10000w" sizes="1px" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 10000w, data:,c 10000x" sizes="1px" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 10000x, data:,c 10000w" sizes="1px" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 1w" sizes="10000px" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 1w, data:,c 0.0001x" sizes="10000px" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img src="data:,a" srcset="data:,b 0.0001x, data:,c 1w" sizes="10000px" data-expect="data:,b">]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<img srcset="data:,a" data-expect="data:,a">]
|
[<img srcset="data:,a" data-expect="data:,a">]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" media=""><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" media="all"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" media="all and (min-width:0)"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" media="not all and (max-width:0)"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" media="all, !"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" media=", all"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type=""><img src="data:,a" data-expect="data:,b"></picture>]
|
[<picture><source srcset="data:,b" type=""><img src="data:,a" data-expect="data:,b"></picture>]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type=" "><img src="data:,a" data-expect="data:,b"></picture>]
|
[<picture><source srcset="data:,b" type=" "><img src="data:,a" data-expect="data:,b"></picture>]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/gif"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type=" image/gif"><img src="data:,a" data-expect="data:,b"></picture>]
|
[<picture><source srcset="data:,b" type=" image/gif"><img src="data:,a" data-expect="data:,b"></picture>]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/gif "><img src="data:,a" data-expect="data:,b"></picture>]
|
[<picture><source srcset="data:,b" type="image/gif "><img src="data:,a" data-expect="data:,b"></picture>]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/gif;"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/gif;encodings"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/gif;encodings="><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/gif;encodings=foobar"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/png"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/jpeg"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/svg+xml"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b" type="image/x-icon"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><source srcset="data:,b"><img data-expect="data:,b"></picture>]
|
[<picture><source srcset="data:,b"><img data-expect="data:,b"></picture>]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<picture><svg></svg><source srcset="data:,b"><img src="data:,a" data-expect="data:,b"></picture>]
|
|
||||||
expected: FAIL
|
|
||||||
|
|
||||||
[<picture><svg><!--<font face> tag breaks out of svg--><font face=""></font><source srcset="data:,b"></source></svg><img src="data:,a" data-expect="data:,b"></picture>]
|
[<picture><svg><!--<font face> tag breaks out of svg--><font face=""></font><source srcset="data:,b"></source></svg><img src="data:,a" data-expect="data:,b"></picture>]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
[<picture><svg><!--<font face> tag breaks out of svg--></svg><font face=""></font><source srcset="data:,b"><img src="data:,a" data-expect="data:,b"></picture>]
|
[<picture><source srcset="data:,b" type="image/*"><img src="data:,a" data-expect="data:,a"></picture>]
|
||||||
|
expected: FAIL
|
||||||
|
|
||||||
|
[<picture><source srcset="data:,b" type="image/foobarbaz"><img src="data:,a" data-expect="data:,a"></picture>]
|
||||||
expected: FAIL
|
expected: FAIL
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue