1use std::sync::Arc;
6
7use base::id::{PipelineId, WebViewId};
8use compositing_traits::CrossProcessCompositorApi;
9use log::debug;
10use malloc_size_of::MallocSizeOfOps;
11use malloc_size_of_derive::MallocSizeOf;
12use pixels::{CorsStatus, ImageMetadata, RasterImage};
13use profile_traits::mem::Report;
14use serde::{Deserialize, Serialize};
15use servo_url::{ImmutableOrigin, ServoUrl};
16use webrender_api::ImageKey;
17use webrender_api::units::DeviceIntSize;
18
19use crate::FetchResponseMsg;
20use crate::request::CorsSettings;
21
22pub type VectorImageId = PendingImageId;
27
28#[derive(Clone, Debug, MallocSizeOf)]
32pub enum Image {
33 Raster(#[conditional_malloc_size_of] Arc<RasterImage>),
34 Vector(VectorImage),
35}
36
37#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
38pub struct VectorImage {
39 pub id: VectorImageId,
40 pub metadata: ImageMetadata,
41 pub cors_status: CorsStatus,
42}
43
44impl Image {
45 pub fn metadata(&self) -> ImageMetadata {
46 match self {
47 Image::Vector(image, ..) => image.metadata,
48 Image::Raster(image) => image.metadata,
49 }
50 }
51
52 pub fn cors_status(&self) -> CorsStatus {
53 match self {
54 Image::Vector(image) => image.cors_status,
55 Image::Raster(image) => image.cors_status,
56 }
57 }
58
59 pub fn as_raster_image(&self) -> Option<Arc<RasterImage>> {
60 match self {
61 Image::Raster(image) => Some(image.clone()),
62 Image::Vector(..) => None,
63 }
64 }
65}
66
67#[derive(Clone, Debug, MallocSizeOf)]
69pub enum ImageOrMetadataAvailable {
70 ImageAvailable { image: Image, url: ServoUrl },
71 MetadataAvailable(ImageMetadata, PendingImageId),
72}
73
74pub type ImageCacheResponseCallback = Box<dyn Fn(ImageCacheResponseMessage) + Send + 'static>;
75
76#[derive(MallocSizeOf)]
81pub struct ImageLoadListener {
82 pipeline_id: PipelineId,
83 pub id: PendingImageId,
84 #[ignore_malloc_size_of = "Difficult to measure FnOnce"]
85 callback: ImageCacheResponseCallback,
86}
87
88impl ImageLoadListener {
89 pub fn new(
90 callback: ImageCacheResponseCallback,
91 pipeline_id: PipelineId,
92 id: PendingImageId,
93 ) -> ImageLoadListener {
94 ImageLoadListener {
95 pipeline_id,
96 callback,
97 id,
98 }
99 }
100
101 pub fn respond(&self, response: ImageResponse) {
102 debug!("Notifying listener");
103 (self.callback)(ImageCacheResponseMessage::NotifyPendingImageLoadStatus(
104 PendingImageResponse {
105 pipeline_id: self.pipeline_id,
106 response,
107 id: self.id,
108 },
109 ));
110 }
111}
112
113#[derive(Clone, Debug, MallocSizeOf)]
115pub enum ImageResponse {
116 Loaded(Image, ServoUrl),
118 MetadataLoaded(ImageMetadata),
120 FailedToLoadOrDecode,
122}
123
124#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
126pub struct PendingImageId(pub u64);
127
128#[derive(Clone, Debug)]
129pub struct PendingImageResponse {
130 pub pipeline_id: PipelineId,
131 pub response: ImageResponse,
132 pub id: PendingImageId,
133}
134
135#[derive(Clone, Debug, Deserialize, Serialize)]
136pub struct RasterizationCompleteResponse {
137 pub pipeline_id: PipelineId,
138 pub image_id: PendingImageId,
139 pub requested_size: DeviceIntSize,
140}
141
142#[derive(Clone, Debug)]
143pub enum ImageCacheResponseMessage {
144 NotifyPendingImageLoadStatus(PendingImageResponse),
145 VectorImageRasterizationComplete(RasterizationCompleteResponse),
146}
147
148pub enum ImageCacheResult {
153 Available(ImageOrMetadataAvailable),
154 FailedToLoadOrDecode,
155 Pending(PendingImageId),
156 ReadyForRequest(PendingImageId),
157}
158
159pub trait ImageCacheFactory: Sync + Send {
163 fn create(
164 &self,
165 webview_id: WebViewId,
166 pipeline_id: PipelineId,
167 compositor_api: &CrossProcessCompositorApi,
168 ) -> Arc<dyn ImageCache>;
169}
170
171pub trait ImageCache: Sync + Send {
174 fn memory_report(&self, prefix: &str, ops: &mut MallocSizeOfOps) -> Report;
175
176 fn get_image_key(&self) -> Option<ImageKey>;
180
181 fn get_image(
183 &self,
184 url: ServoUrl,
185 origin: ImmutableOrigin,
186 cors_setting: Option<CorsSettings>,
187 ) -> Option<Image>;
188
189 fn get_cached_image_status(
190 &self,
191 url: ServoUrl,
192 origin: ImmutableOrigin,
193 cors_setting: Option<CorsSettings>,
194 ) -> ImageCacheResult;
195
196 fn rasterize_vector_image(
201 &self,
202 image_id: VectorImageId,
203 size: DeviceIntSize,
204 ) -> Option<RasterImage>;
205
206 fn add_rasterization_complete_listener(
211 &self,
212 pipeline_id: PipelineId,
213 image_id: VectorImageId,
214 size: DeviceIntSize,
215 callback: ImageCacheResponseCallback,
216 );
217
218 fn get_broken_image_icon(&self) -> Option<Arc<RasterImage>>;
221
222 fn add_listener(&self, listener: ImageLoadListener);
225
226 fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
228
229 fn fill_key_cache_with_batch_of_keys(&self, image_keys: Vec<ImageKey>);
231}