mirror of
https://github.com/servo/servo.git
synced 2025-08-04 05:00:08 +01:00
Address some code nits
Signed-off-by: Martin Robinson <mrobinson@igalia.com>
This commit is contained in:
parent
2ab511f19c
commit
cbb2d18bc0
11 changed files with 166 additions and 148 deletions
|
@ -16,8 +16,9 @@ use malloc_size_of::{MallocSizeOf as MallocSizeOfTrait, MallocSizeOfOps};
|
|||
use malloc_size_of_derive::MallocSizeOf;
|
||||
use mime::Mime;
|
||||
use net_traits::image_cache::{
|
||||
Image, ImageCache, ImageCacheMessage, ImageCacheResult, ImageLoadListener,
|
||||
ImageOrMetadataAvailable, ImageResponse, PendingImageId, UsePlaceholder, VectorImage,
|
||||
Image, ImageCache, ImageCacheResponseMessage, ImageCacheResult, ImageLoadListener,
|
||||
ImageOrMetadataAvailable, ImageResponse, PendingImageId, RasterizationCompleteResponse,
|
||||
UsePlaceholder, VectorImage,
|
||||
};
|
||||
use net_traits::request::CorsSettings;
|
||||
use net_traits::{FetchMetadata, FetchResponseMsg, FilteredMetadata, NetworkError};
|
||||
|
@ -397,41 +398,39 @@ impl PendingLoad {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(MallocSizeOf)]
|
||||
#[derive(Default, MallocSizeOf)]
|
||||
struct RasterizationTask {
|
||||
listeners: Vec<(PipelineId, IpcSender<ImageCacheMessage>)>,
|
||||
listeners: Vec<(PipelineId, IpcSender<ImageCacheResponseMessage>)>,
|
||||
result: Option<RasterImage>,
|
||||
}
|
||||
|
||||
// ======================================================================
|
||||
// Image cache implementation.
|
||||
// ======================================================================
|
||||
/// ## Image cache implementation.
|
||||
#[derive(MallocSizeOf)]
|
||||
struct ImageCacheStore {
|
||||
// Images that are loading over network, or decoding.
|
||||
/// Images that are loading over network, or decoding.
|
||||
pending_loads: AllPendingLoads,
|
||||
|
||||
// Images that have finished loading (successful or not)
|
||||
/// Images that have finished loading (successful or not)
|
||||
completed_loads: HashMap<ImageKey, CompletedLoad>,
|
||||
|
||||
// Vector (e.g. SVG) images that have been sucessfully loaded and parsed
|
||||
// but are yet to be rasterized. Since the same SVG data can be used for
|
||||
// rasterizing at different sizes, we use this hasmap to share the data.
|
||||
/// Vector (e.g. SVG) images that have been sucessfully loaded and parsed
|
||||
/// but are yet to be rasterized. Since the same SVG data can be used for
|
||||
/// rasterizing at different sizes, we use this hasmap to share the data.
|
||||
vector_images: HashMap<PendingImageId, VectorImageData>,
|
||||
|
||||
// Vector images for which rasterization at a particular size has started
|
||||
// or completed. If completed, the `result` member of `RasterizationTask`
|
||||
// contains the rasterized image.
|
||||
/// Vector images for which rasterization at a particular size has started
|
||||
/// or completed. If completed, the `result` member of `RasterizationTask`
|
||||
/// contains the rasterized image.
|
||||
rasterized_vector_images: HashMap<(PendingImageId, DeviceIntSize), RasterizationTask>,
|
||||
|
||||
// The placeholder image used when an image fails to load
|
||||
/// The placeholder image used when an image fails to load
|
||||
#[conditional_malloc_size_of]
|
||||
placeholder_image: Arc<RasterImage>,
|
||||
|
||||
// The URL used for the placeholder image
|
||||
/// The URL used for the placeholder image
|
||||
placeholder_url: ServoUrl,
|
||||
|
||||
// Cross-process compositor API instance.
|
||||
/// Cross-process compositor API instance.
|
||||
#[ignore_malloc_size_of = "Channel from another crate"]
|
||||
compositor_api: CrossProcessCompositorApi,
|
||||
}
|
||||
|
@ -683,39 +682,38 @@ impl ImageCache for ImageCacheImpl {
|
|||
&self,
|
||||
pipeline_id: PipelineId,
|
||||
image_id: PendingImageId,
|
||||
size: DeviceIntSize,
|
||||
sender: IpcSender<ImageCacheMessage>,
|
||||
requested_size: DeviceIntSize,
|
||||
sender: IpcSender<ImageCacheResponseMessage>,
|
||||
) {
|
||||
let key = (image_id, size);
|
||||
let completed = {
|
||||
let mut store = self.store.lock().unwrap();
|
||||
let key = (image_id, requested_size);
|
||||
if !store.vector_images.contains_key(&image_id) {
|
||||
warn!("Unknown image requested for rasterization for key {key:?}");
|
||||
return;
|
||||
};
|
||||
|
||||
match store.rasterized_vector_images.entry(key) {
|
||||
Occupied(mut entry) => {
|
||||
let task = entry.get_mut();
|
||||
if task.result.is_some() {
|
||||
true
|
||||
} else {
|
||||
task.listeners.push((pipeline_id, sender.clone()));
|
||||
false
|
||||
}
|
||||
},
|
||||
Vacant(_) => {
|
||||
warn!("Image rasterization task not found in the cache for key {key:?}");
|
||||
return;
|
||||
let Some(task) = store.rasterized_vector_images.get_mut(&key) else {
|
||||
warn!("Image rasterization task not found in the cache for key {key:?}");
|
||||
return;
|
||||
};
|
||||
|
||||
match task.result {
|
||||
Some(_) => true,
|
||||
None => {
|
||||
task.listeners.push((pipeline_id, sender.clone()));
|
||||
false
|
||||
},
|
||||
}
|
||||
};
|
||||
|
||||
if completed {
|
||||
let _ = sender.send(ImageCacheMessage::VectorImageRasterizationCompleted(
|
||||
pipeline_id,
|
||||
image_id,
|
||||
size,
|
||||
let _ = sender.send(ImageCacheResponseMessage::VectorImageRasterizationComplete(
|
||||
RasterizationCompleteResponse {
|
||||
pipeline_id,
|
||||
image_id,
|
||||
requested_size,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
@ -723,7 +721,7 @@ impl ImageCache for ImageCacheImpl {
|
|||
fn rasterize_vector_image(
|
||||
&self,
|
||||
image_id: PendingImageId,
|
||||
size: DeviceIntSize,
|
||||
requested_size: DeviceIntSize,
|
||||
) -> Option<RasterImage> {
|
||||
let mut store = self.store.lock().unwrap();
|
||||
let Some(vector_image) = store.vector_images.get(&image_id).cloned() else {
|
||||
|
@ -731,44 +729,48 @@ impl ImageCache for ImageCacheImpl {
|
|||
return None;
|
||||
};
|
||||
|
||||
match store.rasterized_vector_images.entry((image_id, size)) {
|
||||
Occupied(occupied_entry) => {
|
||||
return occupied_entry.get().result.clone();
|
||||
},
|
||||
Vacant(entry) => entry.insert(RasterizationTask {
|
||||
listeners: vec![],
|
||||
result: None,
|
||||
}),
|
||||
};
|
||||
// This early return relies on the fact that the result of image rasterization cannot
|
||||
// ever be `None`. If that were the case we would need to check whether the entry
|
||||
// in the `HashMap` was `Occupied` or not.
|
||||
let entry = store
|
||||
.rasterized_vector_images
|
||||
.entry((image_id, requested_size))
|
||||
.or_default();
|
||||
if let Some(result) = entry.result.as_ref() {
|
||||
return Some(result.clone());
|
||||
}
|
||||
|
||||
let store = self.store.clone();
|
||||
self.thread_pool.spawn(move || {
|
||||
let natural_size = vector_image.svg_tree.size().to_int_size();
|
||||
let requested_size = {
|
||||
let width = size.width.try_into().unwrap_or(0);
|
||||
let height = size.height.try_into().unwrap_or(0);
|
||||
let tinyskia_requested_size = {
|
||||
let width = requested_size.width.try_into().unwrap_or(0);
|
||||
let height = requested_size.height.try_into().unwrap_or(0);
|
||||
tiny_skia::IntSize::from_wh(width, height).unwrap_or(natural_size)
|
||||
};
|
||||
let transform = tiny_skia::Transform::from_scale(
|
||||
requested_size.width() as f32 / natural_size.width() as f32,
|
||||
requested_size.height() as f32 / natural_size.height() as f32,
|
||||
tinyskia_requested_size.width() as f32 / natural_size.width() as f32,
|
||||
tinyskia_requested_size.height() as f32 / natural_size.height() as f32,
|
||||
);
|
||||
let mut pixmap =
|
||||
tiny_skia::Pixmap::new(requested_size.width(), requested_size.height()).unwrap();
|
||||
let mut pixmap = tiny_skia::Pixmap::new(
|
||||
tinyskia_requested_size.width(),
|
||||
tinyskia_requested_size.height(),
|
||||
)
|
||||
.unwrap();
|
||||
resvg::render(&vector_image.svg_tree, transform, &mut pixmap.as_mut());
|
||||
|
||||
let bytes = pixmap.take();
|
||||
let frame = ImageFrame {
|
||||
delay: None,
|
||||
byte_range: 0..bytes.len(),
|
||||
width: requested_size.width(),
|
||||
height: requested_size.height(),
|
||||
width: tinyskia_requested_size.width(),
|
||||
height: tinyskia_requested_size.height(),
|
||||
};
|
||||
|
||||
let mut rasterized_image = RasterImage {
|
||||
metadata: ImageMetadata {
|
||||
width: requested_size.width(),
|
||||
height: requested_size.height(),
|
||||
width: tinyskia_requested_size.width(),
|
||||
height: tinyskia_requested_size.height(),
|
||||
},
|
||||
format: PixelFormat::RGBA8,
|
||||
frames: vec![frame],
|
||||
|
@ -780,19 +782,23 @@ impl ImageCache for ImageCacheImpl {
|
|||
let listeners = {
|
||||
let mut store = store.lock().unwrap();
|
||||
set_webrender_image_key(&store.compositor_api, &mut rasterized_image);
|
||||
if let Some(task) = store.rasterized_vector_images.get_mut(&(image_id, size)) {
|
||||
task.result = Some(rasterized_image);
|
||||
std::mem::take(&mut task.listeners)
|
||||
} else {
|
||||
Vec::new()
|
||||
}
|
||||
store
|
||||
.rasterized_vector_images
|
||||
.get_mut(&(image_id, requested_size))
|
||||
.map(|task| {
|
||||
task.result = Some(rasterized_image);
|
||||
std::mem::take(&mut task.listeners)
|
||||
})
|
||||
.unwrap_or_default()
|
||||
};
|
||||
|
||||
for (pipeline_id, sender) in listeners {
|
||||
let _ = sender.send(ImageCacheMessage::VectorImageRasterizationCompleted(
|
||||
pipeline_id,
|
||||
image_id,
|
||||
size,
|
||||
let _ = sender.send(ImageCacheResponseMessage::VectorImageRasterizationComplete(
|
||||
RasterizationCompleteResponse {
|
||||
pipeline_id,
|
||||
image_id,
|
||||
requested_size,
|
||||
},
|
||||
));
|
||||
}
|
||||
});
|
||||
|
|
|
@ -7,6 +7,7 @@ use std::rc::Rc;
|
|||
|
||||
use dom_struct::dom_struct;
|
||||
use js::rust::{HandleObject, MutableHandleValue};
|
||||
use net_traits::image_cache::Image;
|
||||
|
||||
use crate::dom::bindings::cell::DomRefCell;
|
||||
use crate::dom::bindings::codegen::Bindings::DataTransferBinding::DataTransferMethods;
|
||||
|
@ -155,10 +156,9 @@ impl DataTransferMethods<crate::DomTypeHolder> for DataTransfer {
|
|||
|
||||
// Step 3
|
||||
if let Some(image) = image.downcast::<HTMLImageElement>() {
|
||||
if let Some(image) = image.image_data().and_then(|image| image.as_raster_image()) {
|
||||
data_store.set_bitmap(Some(image), x, y);
|
||||
} else {
|
||||
warn!("Vector images are not yet supported in setDragImage");
|
||||
match image.image_data().as_ref().and_then(Image::as_raster_image) {
|
||||
Some(image) => data_store.set_bitmap(Some(image), x, y),
|
||||
None => warn!("Vector images are not yet supported in setDragImage"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -341,14 +341,12 @@ impl HTMLImageElement {
|
|||
is_placeholder,
|
||||
}) => {
|
||||
if is_placeholder {
|
||||
let image = image
|
||||
.as_raster_image()
|
||||
.expect("Only raster images are supported as placeholders currently");
|
||||
|
||||
self.process_image_response(
|
||||
ImageResponse::PlaceholderLoaded(image, url),
|
||||
can_gc,
|
||||
)
|
||||
if let Some(raster_image) = image.as_raster_image() {
|
||||
self.process_image_response(
|
||||
ImageResponse::PlaceholderLoaded(raster_image, url),
|
||||
can_gc,
|
||||
)
|
||||
}
|
||||
} else {
|
||||
self.process_image_response(ImageResponse::Loaded(image, url), can_gc)
|
||||
}
|
||||
|
|
|
@ -262,11 +262,10 @@ impl HTMLVideoElement {
|
|||
match response {
|
||||
ImageResponse::Loaded(image, url) => {
|
||||
debug!("Loaded poster image for video element: {:?}", url);
|
||||
if let Some(image) = image.as_raster_image() {
|
||||
self.htmlmediaelement.process_poster_image_loaded(image);
|
||||
} else {
|
||||
warn!("Vector images are not yet supported in video poster");
|
||||
};
|
||||
match image.as_raster_image() {
|
||||
Some(image) => self.htmlmediaelement.process_poster_image_loaded(image),
|
||||
None => warn!("Vector images are not yet supported in video poster"),
|
||||
}
|
||||
LoadBlocker::terminate(&self.load_blocker, can_gc);
|
||||
},
|
||||
ImageResponse::MetadataLoaded(..) => {},
|
||||
|
|
|
@ -21,8 +21,8 @@ use js::jsval::JSVal;
|
|||
use js::rust::{HandleObject, MutableHandleValue};
|
||||
use net_traits::http_status::HttpStatus;
|
||||
use net_traits::image_cache::{
|
||||
ImageCache, ImageCacheMessage, ImageCacheResult, ImageLoadListener, ImageOrMetadataAvailable,
|
||||
ImageResponse, PendingImageId, UsePlaceholder,
|
||||
ImageCache, ImageCacheResponseMessage, ImageCacheResult, ImageLoadListener,
|
||||
ImageOrMetadataAvailable, ImageResponse, PendingImageId, UsePlaceholder,
|
||||
};
|
||||
use net_traits::request::{RequestBuilder, RequestId};
|
||||
use net_traits::{
|
||||
|
@ -929,7 +929,7 @@ impl Notification {
|
|||
pending_image_id: PendingImageId,
|
||||
resource_type: ResourceType,
|
||||
) {
|
||||
let (sender, receiver) = ipc::channel::<ImageCacheMessage>().expect("ipc channel failure");
|
||||
let (sender, receiver) = ipc::channel().expect("ipc channel failure");
|
||||
|
||||
let global: &GlobalScope = &self.global();
|
||||
|
||||
|
@ -945,7 +945,7 @@ impl Notification {
|
|||
task_source.queue(task!(handle_response: move || {
|
||||
let this = trusted_this.root();
|
||||
if let Ok(response) = response {
|
||||
let ImageCacheMessage::NotifyPendingImageLoadStatus(status) = response else {
|
||||
let ImageCacheResponseMessage::NotifyPendingImageLoadStatus(status) = response else {
|
||||
warn!("Received unexpected message from image cache: {response:?}");
|
||||
return;
|
||||
};
|
||||
|
|
|
@ -609,23 +609,29 @@ impl WebGLRenderingContext {
|
|||
};
|
||||
let cors_setting = cors_setting_for_element(image.upcast());
|
||||
|
||||
let img =
|
||||
match canvas_utils::request_image_from_cache(&window, img_url, cors_setting) {
|
||||
ImageResponse::Loaded(image, _) => {
|
||||
if let Some(image) = image.as_raster_image() {
|
||||
image
|
||||
} else {
|
||||
// Related https://github.com/KhronosGroup/WebGL/issues/1503?
|
||||
let img = match canvas_utils::request_image_from_cache(
|
||||
&window,
|
||||
img_url,
|
||||
cors_setting,
|
||||
) {
|
||||
ImageResponse::Loaded(image, _) => {
|
||||
match image.as_raster_image() {
|
||||
Some(image) => image,
|
||||
None => {
|
||||
// Vector images are not currently supported here and there are some open questions
|
||||
// in the specification about how to handle them:
|
||||
// See https://github.com/KhronosGroup/WebGL/issues/1503.
|
||||
warn!(
|
||||
"Vector images as are not yet supported as WebGL texture source"
|
||||
);
|
||||
return Ok(None);
|
||||
}
|
||||
},
|
||||
ImageResponse::PlaceholderLoaded(_, _) |
|
||||
ImageResponse::None |
|
||||
ImageResponse::MetadataLoaded(_) => return Ok(None),
|
||||
};
|
||||
},
|
||||
}
|
||||
},
|
||||
ImageResponse::PlaceholderLoaded(_, _) |
|
||||
ImageResponse::None |
|
||||
ImageResponse::MetadataLoaded(_) => return Ok(None),
|
||||
};
|
||||
|
||||
let size = Size2D::new(img.metadata.width, img.metadata.height);
|
||||
|
||||
|
|
|
@ -55,8 +55,8 @@ use malloc_size_of::MallocSizeOf;
|
|||
use media::WindowGLContext;
|
||||
use net_traits::ResourceThreads;
|
||||
use net_traits::image_cache::{
|
||||
ImageCache, ImageCacheMessage, ImageLoadListener, ImageResponse, PendingImageId,
|
||||
PendingImageResponse,
|
||||
ImageCache, ImageCacheResponseMessage, ImageLoadListener, ImageResponse, PendingImageId,
|
||||
PendingImageResponse, RasterizationCompleteResponse,
|
||||
};
|
||||
use net_traits::storage_thread::StorageType;
|
||||
use num_traits::ToPrimitive;
|
||||
|
@ -243,7 +243,7 @@ pub(crate) struct Window {
|
|||
#[no_trace]
|
||||
image_cache: Arc<dyn ImageCache>,
|
||||
#[no_trace]
|
||||
image_cache_sender: IpcSender<ImageCacheMessage>,
|
||||
image_cache_sender: IpcSender<ImageCacheResponseMessage>,
|
||||
window_proxy: MutNullableDom<WindowProxy>,
|
||||
document: MutNullableDom<Document>,
|
||||
location: MutNullableDom<Location>,
|
||||
|
@ -346,13 +346,13 @@ pub(crate) struct Window {
|
|||
pending_image_callbacks: DomRefCell<HashMap<PendingImageId, Vec<PendingImageCallback>>>,
|
||||
|
||||
/// All of the elements that have an outstanding image request that was
|
||||
/// initiated by layout during a reflow. They are stored in the script thread
|
||||
/// initiated by layout during a reflow. They are stored in the [`ScriptThread`]
|
||||
/// to ensure that the element can be marked dirty when the image data becomes
|
||||
/// available at some point in the future.
|
||||
pending_layout_images: DomRefCell<HashMapTracedValues<PendingImageId, Vec<Dom<Node>>>>,
|
||||
|
||||
/// Vector images for which layout has intiated rasterization at a specific size
|
||||
/// and whose results are not yet available. They are stored in the script thread
|
||||
/// and whose results are not yet available. They are stored in the [`ScriptThread`]
|
||||
/// so that the element can be marked dirty once the rasterization is completed.
|
||||
pending_images_for_rasterization:
|
||||
DomRefCell<HashMapTracedValues<PendingImageRasterizationKey, Vec<Dom<Node>>>>,
|
||||
|
@ -577,7 +577,7 @@ impl Window {
|
|||
&self,
|
||||
id: PendingImageId,
|
||||
callback: impl Fn(PendingImageResponse) + 'static,
|
||||
) -> IpcSender<ImageCacheMessage> {
|
||||
) -> IpcSender<ImageCacheResponseMessage> {
|
||||
self.pending_image_callbacks
|
||||
.borrow_mut()
|
||||
.entry(id)
|
||||
|
@ -608,11 +608,10 @@ impl Window {
|
|||
|
||||
pub(crate) fn handle_image_rasterization_complete_notification(
|
||||
&self,
|
||||
image_id: PendingImageId,
|
||||
size: DeviceIntSize,
|
||||
response: RasterizationCompleteResponse,
|
||||
) {
|
||||
let mut images = self.pending_images_for_rasterization.borrow_mut();
|
||||
let nodes = images.entry((image_id, size));
|
||||
let nodes = images.entry((response.image_id, response.requested_size));
|
||||
let nodes = match nodes {
|
||||
Entry::Occupied(nodes) => nodes,
|
||||
Entry::Vacant(_) => return,
|
||||
|
@ -3054,7 +3053,7 @@ impl Window {
|
|||
script_chan: Sender<MainThreadScriptMsg>,
|
||||
layout: Box<dyn Layout>,
|
||||
font_context: Arc<FontContext>,
|
||||
image_cache_sender: IpcSender<ImageCacheMessage>,
|
||||
image_cache_sender: IpcSender<ImageCacheResponseMessage>,
|
||||
image_cache: Arc<dyn ImageCache>,
|
||||
resource_threads: ResourceThreads,
|
||||
#[cfg(feature = "bluetooth")] bluetooth_thread: IpcSender<BluetoothRequest>,
|
||||
|
|
|
@ -16,7 +16,7 @@ use crossbeam_channel::{Receiver, SendError, Sender, select};
|
|||
use devtools_traits::{DevtoolScriptControlMsg, ScriptToDevtoolsControlMsg};
|
||||
use ipc_channel::ipc::IpcSender;
|
||||
use net_traits::FetchResponseMsg;
|
||||
use net_traits::image_cache::ImageCacheMessage;
|
||||
use net_traits::image_cache::ImageCacheResponseMessage;
|
||||
use profile_traits::mem::{self as profile_mem, OpaqueSender, ReportsChan};
|
||||
use profile_traits::time::{self as profile_time};
|
||||
use script_traits::{Painter, ScriptThreadMessage};
|
||||
|
@ -40,7 +40,7 @@ pub(crate) enum MixedMessage {
|
|||
FromConstellation(ScriptThreadMessage),
|
||||
FromScript(MainThreadScriptMsg),
|
||||
FromDevtools(DevtoolScriptControlMsg),
|
||||
FromImageCache(ImageCacheMessage),
|
||||
FromImageCache(ImageCacheResponseMessage),
|
||||
#[cfg(feature = "webgpu")]
|
||||
FromWebGPUServer(WebGPUMsg),
|
||||
TimerFired,
|
||||
|
@ -105,11 +105,11 @@ impl MixedMessage {
|
|||
MainThreadScriptMsg::WakeUp => None,
|
||||
},
|
||||
MixedMessage::FromImageCache(response) => match response {
|
||||
ImageCacheMessage::NotifyPendingImageLoadStatus(response) => {
|
||||
ImageCacheResponseMessage::NotifyPendingImageLoadStatus(response) => {
|
||||
Some(response.pipeline_id)
|
||||
},
|
||||
ImageCacheMessage::VectorImageRasterizationCompleted(pipeline_id, ..) => {
|
||||
Some(*pipeline_id)
|
||||
ImageCacheResponseMessage::VectorImageRasterizationComplete(response) => {
|
||||
Some(response.pipeline_id)
|
||||
},
|
||||
},
|
||||
MixedMessage::FromDevtools(_) | MixedMessage::TimerFired => None,
|
||||
|
@ -333,7 +333,7 @@ pub(crate) struct ScriptThreadSenders {
|
|||
/// messages on this channel are routed to crossbeam [`Sender`] on the router thread, which
|
||||
/// in turn sends messages to [`ScriptThreadReceivers::image_cache_receiver`].
|
||||
#[no_trace]
|
||||
pub(crate) image_cache_sender: IpcSender<ImageCacheMessage>,
|
||||
pub(crate) image_cache_sender: IpcSender<ImageCacheResponseMessage>,
|
||||
|
||||
/// For providing contact with the time profiler.
|
||||
#[no_trace]
|
||||
|
@ -362,7 +362,7 @@ pub(crate) struct ScriptThreadReceivers {
|
|||
|
||||
/// The [`Receiver`] which receives incoming messages from the `ImageCache`.
|
||||
#[no_trace]
|
||||
pub(crate) image_cache_receiver: Receiver<ImageCacheMessage>,
|
||||
pub(crate) image_cache_receiver: Receiver<ImageCacheResponseMessage>,
|
||||
|
||||
/// For receiving commands from an optional devtools server. Will be ignored if no such server
|
||||
/// exists. When devtools are not active this will be [`crossbeam_channel::never()`].
|
||||
|
|
|
@ -71,7 +71,7 @@ use js::jsval::UndefinedValue;
|
|||
use js::rust::ParentRuntime;
|
||||
use media::WindowGLContext;
|
||||
use metrics::MAX_TASK_NS;
|
||||
use net_traits::image_cache::{ImageCache, ImageCacheMessage};
|
||||
use net_traits::image_cache::{ImageCache, ImageCacheResponseMessage};
|
||||
use net_traits::request::{Referrer, RequestId};
|
||||
use net_traits::response::ResponseInit;
|
||||
use net_traits::storage_thread::StorageType;
|
||||
|
@ -2095,9 +2095,9 @@ impl ScriptThread {
|
|||
}
|
||||
}
|
||||
|
||||
fn handle_msg_from_image_cache(&self, response: ImageCacheMessage) {
|
||||
fn handle_msg_from_image_cache(&self, response: ImageCacheResponseMessage) {
|
||||
match response {
|
||||
ImageCacheMessage::NotifyPendingImageLoadStatus(pending_image_response) => {
|
||||
ImageCacheResponseMessage::NotifyPendingImageLoadStatus(pending_image_response) => {
|
||||
let window = self
|
||||
.documents
|
||||
.borrow()
|
||||
|
@ -2106,10 +2106,10 @@ impl ScriptThread {
|
|||
window.pending_image_notification(pending_image_response);
|
||||
}
|
||||
},
|
||||
ImageCacheMessage::VectorImageRasterizationCompleted(pipeline_id, image_id, size) => {
|
||||
let window = self.documents.borrow().find_window(pipeline_id);
|
||||
ImageCacheResponseMessage::VectorImageRasterizationComplete(response) => {
|
||||
let window = self.documents.borrow().find_window(response.pipeline_id);
|
||||
if let Some(ref window) = window {
|
||||
window.handle_image_rasterization_complete_notification(image_id, size);
|
||||
window.handle_image_rasterization_complete_notification(response);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
|
|
@ -24,9 +24,10 @@ use crate::request::CorsSettings;
|
|||
// ======================================================================
|
||||
|
||||
pub type VectorImageId = PendingImageId;
|
||||
|
||||
// Represents either a raster image for which the pixel data is available
|
||||
// or a vector image for which only the natural dimensions are available
|
||||
// and thus require an further rasterization step.
|
||||
// and thus requires a further rasterization step to render.
|
||||
#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
|
||||
pub enum Image {
|
||||
Raster(#[conditional_malloc_size_of] Arc<RasterImage>),
|
||||
|
@ -82,12 +83,12 @@ pub enum ImageOrMetadataAvailable {
|
|||
pub struct ImageLoadListener {
|
||||
pipeline_id: PipelineId,
|
||||
pub id: PendingImageId,
|
||||
sender: IpcSender<ImageCacheMessage>,
|
||||
sender: IpcSender<ImageCacheResponseMessage>,
|
||||
}
|
||||
|
||||
impl ImageLoadListener {
|
||||
pub fn new(
|
||||
sender: IpcSender<ImageCacheMessage>,
|
||||
sender: IpcSender<ImageCacheResponseMessage>,
|
||||
pipeline_id: PipelineId,
|
||||
id: PendingImageId,
|
||||
) -> ImageLoadListener {
|
||||
|
@ -103,14 +104,15 @@ impl ImageLoadListener {
|
|||
// This send can fail if thread waiting for this notification has panicked.
|
||||
// That's not a case that's worth warning about.
|
||||
// TODO(#15501): are there cases in which we should perform cleanup?
|
||||
let msg = PendingImageResponse {
|
||||
pipeline_id: self.pipeline_id,
|
||||
response,
|
||||
id: self.id,
|
||||
};
|
||||
let _ = self
|
||||
.sender
|
||||
.send(ImageCacheMessage::NotifyPendingImageLoadStatus(msg));
|
||||
.send(ImageCacheResponseMessage::NotifyPendingImageLoadStatus(
|
||||
PendingImageResponse {
|
||||
pipeline_id: self.pipeline_id,
|
||||
response,
|
||||
id: self.id,
|
||||
},
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -139,9 +141,16 @@ pub struct PendingImageResponse {
|
|||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum ImageCacheMessage {
|
||||
pub struct RasterizationCompleteResponse {
|
||||
pub pipeline_id: PipelineId,
|
||||
pub image_id: PendingImageId,
|
||||
pub requested_size: DeviceIntSize,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Serialize)]
|
||||
pub enum ImageCacheResponseMessage {
|
||||
NotifyPendingImageLoadStatus(PendingImageResponse),
|
||||
VectorImageRasterizationCompleted(PipelineId, PendingImageId, DeviceIntSize),
|
||||
VectorImageRasterizationComplete(RasterizationCompleteResponse),
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, PartialEq, Serialize)]
|
||||
|
@ -184,26 +193,26 @@ pub trait ImageCache: Sync + Send {
|
|||
use_placeholder: UsePlaceholder,
|
||||
) -> ImageCacheResult;
|
||||
|
||||
// Returns `Some` if the given `image_id` has already been rasterized at the given `size`.
|
||||
// Otherwise, triggers a new job to perform the rasterization. If a notification
|
||||
// is needed after rasterization is completed, the `add_rasterization_complete_listener`
|
||||
// API below can be used to add a listener.
|
||||
/// Returns `Some` if the given `image_id` has already been rasterized at the given `size`.
|
||||
/// Otherwise, triggers a new job to perform the rasterization. If a notification
|
||||
/// is needed after rasterization is completed, the `add_rasterization_complete_listener`
|
||||
/// API below can be used to add a listener.
|
||||
fn rasterize_vector_image(
|
||||
&self,
|
||||
image_id: VectorImageId,
|
||||
size: DeviceIntSize,
|
||||
) -> Option<RasterImage>;
|
||||
|
||||
// Adds a new listener to be notified once the given `image_id` has been rasterized at
|
||||
// the given `size`. The listener will receive a `VectorImageRasterizationCompleted`
|
||||
// message on the given `sender`, even if the listener is called after rasterization
|
||||
// at has already completed.
|
||||
/// Adds a new listener to be notified once the given `image_id` has been rasterized at
|
||||
/// the given `size`. The listener will receive a `VectorImageRasterizationComplete`
|
||||
/// message on the given `sender`, even if the listener is called after rasterization
|
||||
/// at has already completed.
|
||||
fn add_rasterization_complete_listener(
|
||||
&self,
|
||||
pipeline_id: PipelineId,
|
||||
image_id: VectorImageId,
|
||||
size: DeviceIntSize,
|
||||
sender: IpcSender<ImageCacheMessage>,
|
||||
sender: IpcSender<ImageCacheResponseMessage>,
|
||||
);
|
||||
|
||||
/// Add a new listener for the given pending image id. If the image is already present,
|
||||
|
|
|
@ -154,8 +154,9 @@ pub struct PendingImage {
|
|||
pub origin: ImmutableOrigin,
|
||||
}
|
||||
|
||||
// A vector image that is fully loaded (i.e has a parsed SVG tree) but not yet
|
||||
// rasterized to the size needed by layout.
|
||||
/// A data structure to tarck vector image that are fully loaded (i.e has a parsed SVG
|
||||
/// tree) but not yet rasterized to the size needed by layout. The rasterization is
|
||||
/// happening in the image cache.
|
||||
#[derive(Debug)]
|
||||
pub struct PendingRasterizationImage {
|
||||
pub node: UntrustedNodeAddress,
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue