diff --git a/components/layout/fragment.rs b/components/layout/fragment.rs index 33a6ac3dd3b..486a344989b 100644 --- a/components/layout/fragment.rs +++ b/components/layout/fragment.rs @@ -401,6 +401,11 @@ pub struct ImageFragmentInfo { pub metadata: Option, } +enum ImageOrMetadata { + Image(Arc), + Metadata(ImageMetadata), +} + impl ImageFragmentInfo { /// Creates a new image fragment from the given URL and local image cache. /// @@ -412,14 +417,29 @@ impl ImageFragmentInfo { node: &N, layout_context: &LayoutContext, ) -> ImageFragmentInfo { - let image_or_metadata = url.and_then(|url| { - layout_context.get_or_request_image_or_meta(node.opaque(), url, UsePlaceholder::Yes) - }); + // First use any image data present in the element... + let image_or_metadata = node.image_data().and_then(|(image, metadata)| { + match (image, metadata) { + (Some(image), _) => Some(ImageOrMetadata::Image(image)), + (None, Some(metadata)) => Some(ImageOrMetadata::Metadata(metadata)), + _ => None, + } + }).or_else(|| url.and_then(|url| { + // Otherwise query the image cache for anything known about the associated source URL. + layout_context.get_or_request_image_or_meta( + node.opaque(), + url, + UsePlaceholder::Yes + ).map(|result| match result { + ImageOrMetadataAvailable::ImageAvailable(i, _) => ImageOrMetadata::Image(i), + ImageOrMetadataAvailable::MetadataAvailable(m) => ImageOrMetadata::Metadata(m), + }) + })); let current_pixel_density = density.unwrap_or(1f64); let (image, metadata) = match image_or_metadata { - Some(ImageOrMetadataAvailable::ImageAvailable(i, _)) => { + Some(ImageOrMetadata::Image(i)) => { let height = (i.height as f64 / current_pixel_density) as u32; let width = (i.width as f64 / current_pixel_density) as u32; ( @@ -434,7 +454,7 @@ impl ImageFragmentInfo { }), ) }, - Some(ImageOrMetadataAvailable::MetadataAvailable(m)) => { + Some(ImageOrMetadata::Metadata(m)) => { ( None, Some(ImageMetadata { diff --git a/components/layout_thread/dom_wrapper.rs b/components/layout_thread/dom_wrapper.rs index 3c3495ee6fe..bd760204884 100644 --- a/components/layout_thread/dom_wrapper.rs +++ b/components/layout_thread/dom_wrapper.rs @@ -36,6 +36,7 @@ use html5ever::{LocalName, Namespace}; use layout::data::StyleAndLayoutData; use layout::wrapper::GetRawData; use msg::constellation_msg::{BrowsingContextId, PipelineId}; +use net_traits::image::base::{Image, ImageMetadata}; use range::Range; use script::layout_exports::{CharacterDataTypeId, ElementTypeId, HTMLElementTypeId, NodeTypeId}; use script::layout_exports::{Document, Element, Node, Text}; @@ -59,6 +60,7 @@ use std::fmt::Debug; use std::hash::{Hash, Hasher}; use std::marker::PhantomData; use std::ptr::NonNull; +use std::sync::Arc as StdArc; use std::sync::atomic::Ordering; use style::CaseSensitivityExt; use style::applicable_declarations::ApplicableDeclarationBlock; @@ -1048,6 +1050,11 @@ impl<'ln> ThreadSafeLayoutNode for ServoThreadSafeLayoutNode<'ln> { this.image_density() } + fn image_data(&self) -> Option<(Option>, Option)> { + let this = unsafe { self.get_jsmanaged() }; + this.image_data() + } + fn canvas_data(&self) -> Option { let this = unsafe { self.get_jsmanaged() }; this.canvas_data() diff --git a/components/script/dom/htmlimageelement.rs b/components/script/dom/htmlimageelement.rs index ca9243beb1b..b31c5e886af 100644 --- a/components/script/dom/htmlimageelement.rs +++ b/components/script/dom/htmlimageelement.rs @@ -1328,6 +1328,9 @@ pub trait LayoutHTMLImageElementHelpers { #[allow(unsafe_code)] unsafe fn image_density(&self) -> Option; + #[allow(unsafe_code)] + unsafe fn image_data(&self) -> (Option>, Option); + fn get_width(&self) -> LengthOrPercentageOrAuto; fn get_height(&self) -> LengthOrPercentageOrAuto; } @@ -1351,6 +1354,14 @@ impl LayoutHTMLImageElementHelpers for LayoutDom { .clone() } + #[allow(unsafe_code)] + unsafe fn image_data(&self) -> (Option>, Option) { + let current_request = (*self.unsafe_get()) + .current_request + .borrow_for_layout(); + (current_request.image.clone(), current_request.metadata.clone()) + } + #[allow(unsafe_code)] unsafe fn image_density(&self) -> Option { (*self.unsafe_get()) diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index 1a5a23f4ef6..8024f2a04a7 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -62,6 +62,7 @@ use js::jsapi::{JSContext, JSObject, JSRuntime}; use libc::{self, c_void, uintptr_t}; use malloc_size_of::{MallocSizeOf, MallocSizeOfOps}; use msg::constellation_msg::{BrowsingContextId, PipelineId}; +use net_traits::image::base::{Image, ImageMetadata}; use ref_slice::ref_slice; use script_layout_interface::{HTMLCanvasData, HTMLMediaData, LayoutElementType, LayoutNodeType}; use script_layout_interface::{OpaqueStyleAndLayoutData, SVGSVGData, TrustedNodeAddress}; @@ -81,6 +82,7 @@ use std::default::Default; use std::iter; use std::mem; use std::ops::Range; +use std::sync::Arc as StdArc; use style::context::QuirksMode; use style::dom::OpaqueNode; use style::selector_parser::{SelectorImpl, SelectorParser}; @@ -1086,6 +1088,7 @@ pub trait LayoutNodeHelpers { fn selection(&self) -> Option>; fn image_url(&self) -> Option; fn image_density(&self) -> Option; + fn image_data(&self) -> Option<(Option>, Option)>; fn canvas_data(&self) -> Option; fn media_data(&self) -> Option; fn svg_data(&self) -> Option; @@ -1233,6 +1236,13 @@ impl LayoutNodeHelpers for LayoutDom { } } + #[allow(unsafe_code)] + fn image_data(&self) -> Option<(Option>, Option)> { + unsafe { + self.downcast::().map(|e| e.image_data()) + } + } + #[allow(unsafe_code)] fn image_density(&self) -> Option { unsafe { diff --git a/components/script_layout_interface/wrapper_traits.rs b/components/script_layout_interface/wrapper_traits.rs index 9df6a7b44f4..6bce47ec845 100644 --- a/components/script_layout_interface/wrapper_traits.rs +++ b/components/script_layout_interface/wrapper_traits.rs @@ -13,10 +13,12 @@ use atomic_refcell::AtomicRef; use gfx_traits::{ByteIndex, FragmentType, combine_id_with_fragment_type}; use html5ever::{Namespace, LocalName}; use msg::constellation_msg::{BrowsingContextId, PipelineId}; +use net_traits::image::base::{Image, ImageMetadata}; use range::Range; use servo_arc::Arc; use servo_url::ServoUrl; use std::fmt::Debug; +use std::sync::Arc as StdArc; use style::attr::AttrValue; use style::context::SharedStyleContext; use style::data::ElementData; @@ -276,6 +278,9 @@ pub trait ThreadSafeLayoutNode: /// If this is an image element, returns its current-pixel-density. If this is not an image element, fails. fn image_density(&self) -> Option; + /// If this is an image element, returns its image data. Otherwise, returns `None`. + fn image_data(&self) -> Option<(Option>, Option)>; + fn canvas_data(&self) -> Option; fn svg_data(&self) -> Option; diff --git a/tests/wpt/metadata/MANIFEST.json b/tests/wpt/metadata/MANIFEST.json index 545cc63b1f1..55f9f591b44 100644 --- a/tests/wpt/metadata/MANIFEST.json +++ b/tests/wpt/metadata/MANIFEST.json @@ -188281,6 +188281,18 @@ {} ] ], + "html/semantics/embedded-content/the-img-element/available-images.html": [ + [ + "/html/semantics/embedded-content/the-img-element/available-images.html", + [ + [ + "/html/semantics/embedded-content/the-img-element/available-images-ref.html", + "==" + ] + ], + {} + ] + ], "html/semantics/embedded-content/the-img-element/document-adopt-base-url.html": [ [ "/html/semantics/embedded-content/the-img-element/document-adopt-base-url.html", @@ -292044,6 +292056,11 @@ {} ] ], + "html/semantics/embedded-content/the-img-element/available-images-ref.html": [ + [ + {} + ] + ], "html/semantics/embedded-content/the-img-element/brokenimg.jpg": [ [ {} @@ -614985,6 +615002,14 @@ "15e02bcf51535d45a702b0977f919eff8ce5ba9c", "testharness" ], + "html/semantics/embedded-content/the-img-element/available-images-ref.html": [ + "8061abae50899a2befe286723d8bd5c285b356ab", + "support" + ], + "html/semantics/embedded-content/the-img-element/available-images.html": [ + "779ff978689e4f5565b8d45d383efa75ac78b8b2", + "reftest" + ], "html/semantics/embedded-content/the-img-element/brokenimg.jpg": [ "ccff177ae9b5066a7085f7e967ab869e665975cc", "support" diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/available-images-ref.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/available-images-ref.html new file mode 100644 index 00000000000..8061abae508 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/available-images-ref.html @@ -0,0 +1,2 @@ + + diff --git a/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/available-images.html b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/available-images.html new file mode 100644 index 00000000000..779ff978689 --- /dev/null +++ b/tests/wpt/web-platform-tests/html/semantics/embedded-content/the-img-element/available-images.html @@ -0,0 +1,17 @@ + + +Ensure images from available images list are rendered + + + +
+