mirror of
https://github.com/servo/servo.git
synced 2025-08-05 05:30:08 +01:00
Auto merge of #9208 - jmr0:master-img, r=asajeffrey
Use image metadata to lay out images Fixes #7047. cc: @jdm <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/9208) <!-- Reviewable:end -->
This commit is contained in:
commit
46b3eb6535
15 changed files with 269 additions and 63 deletions
|
@ -17,7 +17,7 @@ use gfx_traits::LayerId;
|
|||
use ipc_channel::ipc::{self, IpcSender};
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::image_cache_thread::{ImageCacheChan, ImageCacheThread, ImageResponse, ImageState};
|
||||
use net_traits::image_cache_thread::{UsePlaceholder};
|
||||
use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||
use std::cell::{RefCell, RefMut};
|
||||
use std::collections::HashMap;
|
||||
use std::collections::hash_state::DefaultState;
|
||||
|
@ -155,7 +155,7 @@ impl<'a> LayoutContext<'a> {
|
|||
match sync_rx.recv().unwrap().image_response {
|
||||
ImageResponse::Loaded(image) |
|
||||
ImageResponse::PlaceholderLoaded(image) => Some(image),
|
||||
ImageResponse::None => None,
|
||||
ImageResponse::None | ImageResponse::MetadataLoaded(_) => None,
|
||||
}
|
||||
}
|
||||
// Not yet requested, async mode - request image from the cache
|
||||
|
@ -172,4 +172,51 @@ impl<'a> LayoutContext<'a> {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_or_request_image_or_meta(&self, url: Url, use_placeholder: UsePlaceholder)
|
||||
-> Option<ImageOrMetadataAvailable> {
|
||||
// See if the image is already available
|
||||
let result = self.shared.image_cache_thread.find_image_or_metadata(url.clone(),
|
||||
use_placeholder);
|
||||
|
||||
match result {
|
||||
Ok(image_or_metadata) => Some(image_or_metadata),
|
||||
Err(state) => {
|
||||
// If we are emitting an output file, then we need to block on
|
||||
// image load or we risk emitting an output file missing the image.
|
||||
let is_sync = opts::get().output_file.is_some() ||
|
||||
opts::get().exit_after_load;
|
||||
|
||||
match (state, is_sync) {
|
||||
// Image failed to load, so just return nothing
|
||||
(ImageState::LoadError, _) => None,
|
||||
// Not loaded, test mode - load the image synchronously
|
||||
(_, true) => {
|
||||
let (sync_tx, sync_rx) = ipc::channel().unwrap();
|
||||
self.shared.image_cache_thread.request_image(url,
|
||||
ImageCacheChan(sync_tx),
|
||||
None);
|
||||
match sync_rx.recv().unwrap().image_response {
|
||||
ImageResponse::Loaded(image) |
|
||||
ImageResponse::PlaceholderLoaded(image) =>
|
||||
Some(ImageOrMetadataAvailable::ImageAvailable(image)),
|
||||
ImageResponse::None | ImageResponse::MetadataLoaded(_) =>
|
||||
None,
|
||||
}
|
||||
}
|
||||
// Not yet requested, async mode - request image or metadata from the cache
|
||||
(ImageState::NotRequested, false) => {
|
||||
let sender = self.shared.image_cache_sender.lock().unwrap().clone();
|
||||
self.shared.image_cache_thread.request_image_and_metadata(url, sender, None);
|
||||
None
|
||||
}
|
||||
// Image has been requested, is still pending. Return no image
|
||||
// for this paint loop. When the image loads it will trigger
|
||||
// a reflow and/or repaint.
|
||||
(ImageState::Pending, false) => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -25,8 +25,8 @@ use ipc_channel::ipc::IpcSender;
|
|||
use layout_debug;
|
||||
use model::{self, IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto, specified};
|
||||
use msg::constellation_msg::PipelineId;
|
||||
use net_traits::image::base::Image;
|
||||
use net_traits::image_cache_thread::UsePlaceholder;
|
||||
use net_traits::image::base::{Image, ImageMetadata};
|
||||
use net_traits::image_cache_thread::{ImageOrMetadataAvailable, UsePlaceholder};
|
||||
use rustc_serialize::{Encodable, Encoder};
|
||||
use script::dom::htmlcanvaselement::HTMLCanvasData;
|
||||
use std::borrow::ToOwned;
|
||||
|
@ -344,6 +344,7 @@ pub struct ImageFragmentInfo {
|
|||
/// The image held within this fragment.
|
||||
pub replaced_image_fragment_info: ReplacedImageFragmentInfo,
|
||||
pub image: Option<Arc<Image>>,
|
||||
pub metadata: Option<ImageMetadata>,
|
||||
}
|
||||
|
||||
impl ImageFragmentInfo {
|
||||
|
@ -361,26 +362,39 @@ impl ImageFragmentInfo {
|
|||
.map(Au::from_px)
|
||||
}
|
||||
|
||||
let image = url.and_then(|url| {
|
||||
layout_context.get_or_request_image(url, UsePlaceholder::Yes)
|
||||
let image_or_metadata = url.and_then(|url| {
|
||||
layout_context.get_or_request_image_or_meta(url, UsePlaceholder::Yes)
|
||||
});
|
||||
|
||||
let (image, metadata) = match image_or_metadata {
|
||||
Some(ImageOrMetadataAvailable::ImageAvailable(i)) => {
|
||||
(Some(i.clone()), Some(ImageMetadata { height: i.height, width: i.width } ))
|
||||
}
|
||||
Some(ImageOrMetadataAvailable::MetadataAvailable(m)) => {
|
||||
(None, Some(m))
|
||||
}
|
||||
None => {
|
||||
(None, None)
|
||||
}
|
||||
};
|
||||
|
||||
ImageFragmentInfo {
|
||||
replaced_image_fragment_info: ReplacedImageFragmentInfo::new(node,
|
||||
convert_length(node, &atom!("width")),
|
||||
convert_length(node, &atom!("height"))),
|
||||
image: image,
|
||||
metadata: metadata,
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the original inline-size of the image.
|
||||
pub fn image_inline_size(&mut self) -> Au {
|
||||
match self.image {
|
||||
Some(ref image) => {
|
||||
match self.metadata {
|
||||
Some(ref metadata) => {
|
||||
Au::from_px(if self.replaced_image_fragment_info.writing_mode_is_vertical {
|
||||
image.height
|
||||
metadata.height
|
||||
} else {
|
||||
image.width
|
||||
metadata.width
|
||||
} as i32)
|
||||
}
|
||||
None => Au(0)
|
||||
|
@ -389,12 +403,12 @@ impl ImageFragmentInfo {
|
|||
|
||||
/// Returns the original block-size of the image.
|
||||
pub fn image_block_size(&mut self) -> Au {
|
||||
match self.image {
|
||||
Some(ref image) => {
|
||||
match self.metadata {
|
||||
Some(ref metadata) => {
|
||||
Au::from_px(if self.replaced_image_fragment_info.writing_mode_is_vertical {
|
||||
image.width
|
||||
metadata.width
|
||||
} else {
|
||||
image.height
|
||||
metadata.height
|
||||
} as i32)
|
||||
}
|
||||
None => Au(0)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue