diff --git a/components/net/image_cache_thread.rs b/components/net/image_cache_thread.rs index 660ba87cb4e5..c70352037055 100644 --- a/components/net/image_cache_thread.rs +++ b/components/net/image_cache_thread.rs @@ -394,6 +394,9 @@ impl ImageCache { let result = self.get_image_or_meta_if_available(url, use_placeholder); consumer.send(result).unwrap(); } + ImageCacheCommand::StoreDecodeImage(url, image_vector) => { + self.store_decode_image(url, image_vector); + } }; None @@ -588,6 +591,18 @@ impl ImageCache { } } } + + fn store_decode_image(&mut self, + ref_url: Url, + loaded_bytes: Vec) { + let (cache_result, load_key, pending_load) = self.pending_loads.get_cached(Arc::new(ref_url)); + assert!(cache_result == CacheResult::Miss); + let action: ResponseAction = ResponseAction::ResponseComplete(Ok(())); + self.progress_sender.send(ResourceLoadInfo { + action: action, + key: load_key, + }); + } } /// Create a new image cache. diff --git a/components/net_traits/image_cache_thread.rs b/components/net_traits/image_cache_thread.rs index 0011cab8e9f5..623c44ccb43c 100644 --- a/components/net_traits/image_cache_thread.rs +++ b/components/net_traits/image_cache_thread.rs @@ -92,6 +92,10 @@ pub enum ImageCacheCommand { /// state and but its metadata has been made available, it will be sent as a response. GetImageOrMetadataIfAvailable(Url, UsePlaceholder, IpcSender>), + /// Instruct the cache to store this data as a newly-complete network request and continue + /// decoding the result into pixel data + StoreDecodeImage(Url, Vec), + /// Clients must wait for a response before shutting down the ResourceThread Exit(IpcSender<()>), } @@ -157,6 +161,14 @@ impl ImageCacheThread { receiver.recv().unwrap() } + /// Decode the given image bytes and cache the result for the given URL. + pub fn store_complete_image_bytes(&self, + url: Url, + image_data: Vec) { + let msg = ImageCacheCommand::StoreDecodeImage(url, image_data); + self.chan.send(msg).unwrap(); + } + /// Shutdown the image cache thread. pub fn exit(&self) { let (response_chan, response_port) = ipc::channel().unwrap(); diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index c0a9e9603857..0397d5f2dede 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -29,9 +29,12 @@ use net_traits::image_cache_thread::{ImageResponder, ImageResponse}; use script_runtime::ScriptThreadEventCategory::UpdateReplacedElement; use script_runtime::{CommonScriptMsg, ScriptChan}; use script_thread::Runnable; +use std::collections::LinkedList; use std::sync::Arc; use string_cache::Atom; +use style::values::specified::Length; use url::Url; +use util; use util::str::{DOMString, LengthOrPercentageOrAuto}; #[derive(JSTraceable, HeapSizeOf)] @@ -43,6 +46,13 @@ enum State { Broken, } #[derive(JSTraceable, HeapSizeOf)] +#[allow(dead_code)] +enum ParseState { + InDescriptor, + InParens, + AfterDescriptor, +} +#[derive(JSTraceable, HeapSizeOf)] struct ImageRequest { state: State, url: Option, @@ -247,6 +257,11 @@ impl HTMLImageElementMethods for HTMLImageElement { // https://html.spec.whatwg.org/multipage/#dom-img-src make_setter!(SetSrc, "src"); + // https://html.spec.whatwg.org/multipage/#dom-img-srcset + //make_getter!(Srcset, "srcset"); + // https://html.spec.whatwg.org/multipage/#dom-img-srcset + //make_setter!(SetsrcSet, "srcset"); + // https://html.spec.whatwg.org/multipage/#dom-img-crossOrigin make_enumerated_getter!(CrossOrigin, "crossorigin", "anonymous", ("use-credentials")); // https://html.spec.whatwg.org/multipage/#dom-img-crossOrigin @@ -398,3 +413,119 @@ 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); } + + +struct ImageSource { + candidate: String, + length: Length, +} + +fn collect_sequence_characters<'a, P>(s: &'a str, predicate: P) + -> (&'a str, &'a str) + where P: Fn(char) -> bool { + for (i, c) in s.chars().enumerate() { + if !predicate(c) { + return (&s[0..i], &s[i..]); + } + } + return (s, ""); +} + +fn parse_a_srcset_attribute(input: String) -> Vec { + let position = &input; + let candidate: Vec = Vec::new(); + let(spaces, position) = collect_sequence_characters(position, |c| c ==',' || util::str::char_is_whitespace(c)); + println!("{} {}", spaces, position); + let x = spaces.find(','); + match x { + Some(val) => println!("Parse Error"), + None => println!("No commas"), + } + if position == "" { + //Does something need to be asserted here? The algorithm says abort the steps is this condition exists + return candidate; + } + let (url, spaces) = collect_sequence_characters(position, |c| !util::str::char_is_whitespace(c)); + let comma_count = url.chars().rev().take_while(|c| *c == ',').count(); + let url: String = url.chars().take(url.chars().count() - comma_count).collect(); + if comma_count > 1 { + println!("Parse Error (trailing commas)") + } + + let mut descriptor = LinkedList::::new(); + // Descriptor Tokeniser: whitespace + let (space, position) = collect_sequence_characters(position, |c| util::str::char_is_whitespace(c)); + let mut current_descriptor = String::new(); + let mut state = ParseState::InDescriptor; + for (i, c) in position.chars().enumerate() { + match state { + ParseState::InDescriptor => { + match c { + ' ' => { + if current_descriptor != "" { + descriptor.push_back(current_descriptor.clone()); + state = ParseState::AfterDescriptor; + } + }, + ',' => { position.chars().enumerate(); + if current_descriptor != "" { + descriptor.push_back(current_descriptor.clone()); + state = ParseState::AfterDescriptor; + } + } + '(' => { + current_descriptor.push(c); + state = ParseState::InParens; + } + //Matching EOF + /*'' => { if current_descriptor != "" { + descriptor.push_back(current_descriptor.clone()); + state = ParseState::AfterDescriptor; + } + } + */ + _ => { + current_descriptor.push(c); + } + } + } + ParseState::InParens =>{ + match c { + '(' => { + current_descriptor.push(c); + state = ParseState::InDescriptor; + } + //Matching EOF + /*'' => { if current_descriptor != "" { + descriptor.push_back(current_descriptor.clone()); + state = ParseState::AfterDescriptor; + } + } + */ + _ => { + current_descriptor.push(c); + } + } + } + ParseState::AfterDescriptor => { + match c { + ' ' => { + state = ParseState::AfterDescriptor; + } + //Matching EOF + /*'' => { if current_descriptor != "" { + descriptor.push_back(current_descriptor.clone()); + state = ParseState::AfterDescriptor; + } + } + */ + _ => { + state = ParseState::InDescriptor; + } + } + } + } + } + return candidate; +} + diff --git a/components/script/dom/webidls/HTMLImageElement.webidl b/components/script/dom/webidls/HTMLImageElement.webidl index 69bd2f7d4c1e..a10718a0690f 100644 --- a/components/script/dom/webidls/HTMLImageElement.webidl +++ b/components/script/dom/webidls/HTMLImageElement.webidl @@ -8,7 +8,7 @@ interface HTMLImageElement : HTMLElement { attribute DOMString alt; attribute DOMString src; - // attribute DOMString srcset; + // attribute DOMString srcset; attribute DOMString crossOrigin; attribute DOMString useMap; attribute boolean isMap;