diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs
index b71e6b845cdb..a58c0f120112 100644
--- a/components/script/dom/htmlimageelement.rs
+++ b/components/script/dom/htmlimageelement.rs
@@ -3,6 +3,8 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use app_units::Au;
+use core::ops::Deref;
+use cssparser::Parser;
use dom::attr::Attr;
use dom::attr::AttrValue;
use dom::bindings::cell::DOMRefCell;
@@ -31,7 +33,11 @@ use script_runtime::{CommonScriptMsg, ScriptChan};
use script_thread::Runnable;
use std::sync::Arc;
use string_cache::Atom;
+use style::media_queries::MediaQuery;
+use style::values::CSSFloat;
+use style::values::specified::{Length, ViewportPercentageLength};
use url::Url;
+use util;
use util::str::{DOMString, LengthOrPercentageOrAuto};
#[derive(JSTraceable, HeapSizeOf)]
@@ -49,6 +55,11 @@ struct ImageRequest {
image: Option>,
metadata: Option,
}
+#[allow(dead_code)]
+pub struct Size {
+ pub query: Option,
+ pub length: Length,
+}
#[dom_struct]
pub struct HTMLImageElement {
htmlelement: HTMLElement,
@@ -398,3 +409,61 @@ fn image_dimension_setter(element: &Element, attr: Atom, value: u32) {
let value = AttrValue::Dimension(DOMString::from(value.to_string()), dim);
element.set_attribute(&attr, value);
}
+
+
+pub fn parse_a_sizes_attribute(input: DOMString, width: Option) -> Vec {
+ let mut sizes = Vec::::new();
+ let unparsed_sizes = input.deref().split(',').collect::>();
+
+ for unparsed_size in &unparsed_sizes {
+ let temp = *unparsed_size;
+ let whitespace = temp.chars().rev().take_while(|c| util::str::char_is_whitespace(*c)).count();
+ let trimmed: String = unparsed_size.chars().take(temp.chars().count() - whitespace).collect();
+ // TODO: do we need to throw/assert
+ if trimmed.is_empty() {
+ warn!("parse error while parsing sizes attribute");
+ continue;
+ }
+ let length = Parser::new(&trimmed).try(Length::parse_non_negative);
+ match length {
+ Ok(len) => sizes.push(Size {
+ length: len,
+ query: None
+ }),
+ Err(_) => {
+ println!("Starts with media expression and not length");
+ let mut media_query_parser = Parser::new(&trimmed);
+ let media_query = media_query_parser.try(MediaQuery::parse);
+ match media_query {
+ Ok(query) => {
+ let length = media_query_parser.try(Length::parse_non_negative);
+ if length.is_ok() {
+ sizes.push (Size {
+ length: length.unwrap(),
+ query: Some(query)
+ })
+ }
+ },
+ Err(_) => {
+ println!("Could not convert to MediaQuery/Length");
+ continue;
+ },
+ }
+ },
+ }
+ }
+ if sizes.len() == 0 {
+ let size = match width {
+ Some(w) => Size {
+ length: Length::from_px(w as f32),
+ query: None
+ },
+ None => Size {
+ length: Length::ViewportPercentage(ViewportPercentageLength::Vw(100 as f32)),
+ query: None
+ },
+ };
+ sizes.push(size);
+ }
+ sizes
+}
diff --git a/components/servo/Cargo.lock b/components/servo/Cargo.lock
index adba235f7f4c..81b4aa558855 100644
--- a/components/servo/Cargo.lock
+++ b/components/servo/Cargo.lock
@@ -1850,9 +1850,17 @@ dependencies = [
name = "script_tests"
version = "0.0.1"
dependencies = [
+ "app_units 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)",
+ "cssparser 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)",
+ "euclid 0.6.6 (registry+https://github.com/rust-lang/crates.io-index)",
"msg 0.0.1",
"plugins 0.0.1",
+ "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
"script 0.0.1",
+ "selectors 0.5.7 (registry+https://github.com/rust-lang/crates.io-index)",
+ "string_cache 0.2.14 (registry+https://github.com/rust-lang/crates.io-index)",
+ "style 0.0.1",
+ "style_traits 0.0.1",
"url 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)",
"util 0.0.1",
]
diff --git a/components/style/media_queries.rs b/components/style/media_queries.rs
index b19b4d81c7ec..1f05f775de14 100644
--- a/components/style/media_queries.rs
+++ b/components/style/media_queries.rs
@@ -140,7 +140,7 @@ impl Expression {
}
impl MediaQuery {
- fn parse(input: &mut Parser) -> Result {
+ pub fn parse(input: &mut Parser) -> Result {
let mut expressions = vec![];
let qualifier = if input.try(|input| input.expect_ident_matching("only")).is_ok() {
diff --git a/tests/unit/script/Cargo.toml b/tests/unit/script/Cargo.toml
index 171ffb6920e8..004dfb8088a7 100644
--- a/tests/unit/script/Cargo.toml
+++ b/tests/unit/script/Cargo.toml
@@ -12,5 +12,13 @@ doctest = false
msg = {path = "../../../components/msg"}
plugins = {path = "../../../components/plugins"}
script = {path = "../../../components/script"}
+style = {path = "../../../components/style"}
+style_traits = {path = "../../../components/style_traits"}
util = {path = "../../../components/util"}
+app_units = {version = "0.2.3", features = ["plugins"]}
+cssparser = {version = "0.5.4", features = ["heap_size"]}
+euclid = {version = "0.6.4", features = ["plugins"]}
+selectors = {version = "0.5", features = ["heap_size"]}
+string_cache = {version = "0.2", features = ["heap_size"]}
url = {version = "1.0.0", features = ["heap_size"]}
+rustc-serialize = "0.3"
diff --git a/tests/unit/script/lib.rs b/tests/unit/script/lib.rs
index 2dbbd16ea7ac..03b603c6f012 100644
--- a/tests/unit/script/lib.rs
+++ b/tests/unit/script/lib.rs
@@ -5,8 +5,88 @@
#![feature(plugin)]
#![plugin(plugins)]
+use app_units::Au;
+use cssparser::{Parser, SourcePosition};
+use script::dom::htmlimageelement::{parse_a_sizes_attribute, Size};
+use style::media_queries::*;
+use style::values::specified;
+use util::str::DOMString;
+
+#[test]
+fn some_parse_sizes_test() {
+ let result = parse_a_sizes_attribute(DOMString::from("(min-width: 900px) 1000px,
+ (max-width: 900px) and (min-width: 400px) 50em,
+ 100vw "),
+ None);
+ assert_eq!(result.len(), 3);
+}
+
+#[test]
+fn some_parse_sizes_1_test() {
+ let mut result = parse_a_sizes_attribute(DOMString::from("(min-width: 900px) 1000px,
+ (max-width: 900px) and (min-width: 400px) 50em,
+ 100vw "),
+ None);
+ result.pop();
+ let mut component_secondlast = result.pop();
+ if component_secondlast.is_some() {
+ let component_query = component_secondlast.unwrap().query;
+ if component_query.is_some() {
+ let component_query_expr = component_query.unwrap().expressions;
+ assert_eq!(component_query_expr.len() , 2);
+ }
+ }
+}
+
+#[test]
+fn some_parse_sizes_2_test() {
+ let mut result = parse_a_sizes_attribute(DOMString::from("(min-width: 900px) 1000px,
+ (max-width: 900px) and (min-width: 400px) 50em,
+ 100vw "),
+ None);
+ result.pop();
+ result.pop();
+ let mut component_first = result.pop();
+ if component_first.is_some() {
+ let component_query = component_first.unwrap().query;
+ if component_query.is_some() {
+ let component_query_expr = component_query.unwrap().expressions;
+ match component_query_expr[0] {
+ Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(900))),
+ _ => panic!("wrong expression type"),
+ }
+ }
+ }
+}
+
+#[test]
+fn some_parse_sizes_3_test() {
+ let mut result = parse_a_sizes_attribute(DOMString::from("(min-width: 900px) 1000px,
+ (max-width: 900px) and (min-width: 400px) 50em ,
+ 100vw "),
+ None);
+ result.pop();
+ let mut component_secondlast = result.pop();
+ if component_secondlast.is_some() {
+ let component_query = component_secondlast.unwrap().query;
+ if component_query.is_some() {
+ let component_query_expr = component_query.unwrap().expressions;
+ match component_query_expr[0] {
+ Expression::Width(Range::Max(w)) => assert!(w == specified::Length::Absolute(Au::from_px(900))),
+ _ => panic!("wrong expression type"),
+ }
+ match component_query_expr[1] {
+ Expression::Width(Range::Min(w)) => assert!(w == specified::Length::Absolute(Au::from_px(400))),
+ _ => panic!("wrong expression type"),
+ }
+ }
+ }
+}
+extern crate app_units;
+extern crate cssparser;
extern crate msg;
extern crate script;
+extern crate style;
extern crate url;
extern crate util;