Make layout use available image data before querying the image cache.

This commit is contained in:
Josh Matthews 2018-10-12 12:35:12 -04:00
parent 5f463d3c97
commit 49d2ea4f74
8 changed files with 102 additions and 5 deletions

View file

@ -401,6 +401,11 @@ pub struct ImageFragmentInfo {
pub metadata: Option<ImageMetadata>,
}
enum ImageOrMetadata {
Image(Arc<Image>),
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 {

View file

@ -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<StdArc<Image>>, Option<ImageMetadata>)> {
let this = unsafe { self.get_jsmanaged() };
this.image_data()
}
fn canvas_data(&self) -> Option<HTMLCanvasData> {
let this = unsafe { self.get_jsmanaged() };
this.canvas_data()

View file

@ -1328,6 +1328,9 @@ pub trait LayoutHTMLImageElementHelpers {
#[allow(unsafe_code)]
unsafe fn image_density(&self) -> Option<f64>;
#[allow(unsafe_code)]
unsafe fn image_data(&self) -> (Option<Arc<Image>>, Option<ImageMetadata>);
fn get_width(&self) -> LengthOrPercentageOrAuto;
fn get_height(&self) -> LengthOrPercentageOrAuto;
}
@ -1351,6 +1354,14 @@ impl LayoutHTMLImageElementHelpers for LayoutDom<HTMLImageElement> {
.clone()
}
#[allow(unsafe_code)]
unsafe fn image_data(&self) -> (Option<Arc<Image>>, Option<ImageMetadata>) {
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<f64> {
(*self.unsafe_get())

View file

@ -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<Range<usize>>;
fn image_url(&self) -> Option<ServoUrl>;
fn image_density(&self) -> Option<f64>;
fn image_data(&self) -> Option<(Option<StdArc<Image>>, Option<ImageMetadata>)>;
fn canvas_data(&self) -> Option<HTMLCanvasData>;
fn media_data(&self) -> Option<HTMLMediaData>;
fn svg_data(&self) -> Option<SVGSVGData>;
@ -1233,6 +1236,13 @@ impl LayoutNodeHelpers for LayoutDom<Node> {
}
}
#[allow(unsafe_code)]
fn image_data(&self) -> Option<(Option<StdArc<Image>>, Option<ImageMetadata>)> {
unsafe {
self.downcast::<HTMLImageElement>().map(|e| e.image_data())
}
}
#[allow(unsafe_code)]
fn image_density(&self) -> Option<f64> {
unsafe {

View file

@ -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<f64>;
/// If this is an image element, returns its image data. Otherwise, returns `None`.
fn image_data(&self) -> Option<(Option<StdArc<Image>>, Option<ImageMetadata>)>;
fn canvas_data(&self) -> Option<HTMLCanvasData>;
fn svg_data(&self) -> Option<SVGSVGData>;