Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Merged
merged 1 commit into from Oct 13, 2018
Merged
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

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

  • Loading branch information
jdm committed Oct 13, 2018
commit 49d2ea4f74d94cc5c72b5dcc724d9e5ddf6fc4d6
@@ -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 {
@@ -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()
@@ -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())
@@ -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 {
@@ -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>;
{}
]
],
"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",
{}
]
],
"html/semantics/embedded-content/the-img-element/available-images-ref.html": [
[
{}
]
],
"html/semantics/embedded-content/the-img-element/brokenimg.jpg": [
[
{}
"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"
@@ -0,0 +1,2 @@
<!doctype html>
<img src="3.jpg">
@@ -0,0 +1,17 @@
<!doctype html>
<html class="reftest-wait">
<title>Ensure images from available images list are rendered</title>
<meta charset="utf-8">
<link rel="match" href="available-images-ref.html">
<link rel="help" href="https://html.spec.whatwg.org/multipage/#the-img-element">
<div id="log"></div>
<script>
var i = new Image();
i.onload = function() {
var i2 = new Image();
i2.src = "3.jpg";
document.body.appendChild(i2);
document.documentElement.classList.remove("reftest-wait");

This comment has been minimized.

@emilio

emilio Oct 13, 2018

Member

FWIW I don't know how useful this test will be in the future. If Servo doesn't have a way to wait for image decoding or something of the sort (on top of reftest-wait) it may eventually need one to avoid displaying the placeholders in reftests and such...

But in any case I guess the test doesn't really harm.

};
i.src = "3.jpg";
</script>
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.