1use std::sync::Arc;
6
7use log::debug;
8use malloc_size_of::MallocSizeOfOps;
9use malloc_size_of_derive::MallocSizeOf;
10use paint_api::CrossProcessPaintApi;
11use pixels::{CorsStatus, ImageMetadata, RasterImage};
12use profile_traits::mem::Report;
13use serde::{Deserialize, Serialize};
14use servo_base::id::{PipelineId, WebViewId};
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 svg_id: Option<String>,
41 pub metadata: ImageMetadata,
42 pub cors_status: CorsStatus,
43}
44
45impl Image {
46 pub fn metadata(&self) -> ImageMetadata {
47 match self {
48 Image::Vector(image, ..) => image.metadata,
49 Image::Raster(image) => image.metadata,
50 }
51 }
52
53 pub fn cors_status(&self) -> CorsStatus {
54 match self {
55 Image::Vector(image) => image.cors_status,
56 Image::Raster(image) => image.cors_status,
57 }
58 }
59
60 pub fn as_raster_image(&self) -> Option<Arc<RasterImage>> {
61 match self {
62 Image::Raster(image) => Some(image.clone()),
63 Image::Vector(..) => None,
64 }
65 }
66}
67
68#[derive(Clone, Debug, MallocSizeOf)]
70pub enum ImageOrMetadataAvailable {
71 ImageAvailable { image: Image, url: ServoUrl },
72 MetadataAvailable(ImageMetadata, PendingImageId),
73}
74
75pub type ImageCacheResponseCallback = Box<dyn Fn(ImageCacheResponseMessage) + Send + 'static>;
76
77#[derive(MallocSizeOf)]
82pub struct ImageLoadListener {
83 pipeline_id: PipelineId,
84 pub id: PendingImageId,
85 #[ignore_malloc_size_of = "Difficult to measure FnOnce"]
86 callback: ImageCacheResponseCallback,
87}
88
89impl ImageLoadListener {
90 pub fn new(
91 callback: ImageCacheResponseCallback,
92 pipeline_id: PipelineId,
93 id: PendingImageId,
94 ) -> ImageLoadListener {
95 ImageLoadListener {
96 pipeline_id,
97 callback,
98 id,
99 }
100 }
101
102 pub fn respond(&self, response: ImageResponse) {
103 debug!("Notifying listener");
104 (self.callback)(ImageCacheResponseMessage::NotifyPendingImageLoadStatus(
105 PendingImageResponse {
106 pipeline_id: self.pipeline_id,
107 response,
108 id: self.id,
109 },
110 ));
111 }
112}
113
114#[derive(Clone, Debug, MallocSizeOf)]
116pub enum ImageResponse {
117 Loaded(Image, ServoUrl),
119 MetadataLoaded(ImageMetadata),
121 FailedToLoadOrDecode,
123}
124
125#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
127pub struct PendingImageId(pub u64);
128
129#[derive(Clone, Debug)]
130pub struct PendingImageResponse {
131 pub pipeline_id: PipelineId,
132 pub response: ImageResponse,
133 pub id: PendingImageId,
134}
135
136#[derive(Clone, Debug, Deserialize, Serialize)]
137pub struct RasterizationCompleteResponse {
138 pub pipeline_id: PipelineId,
139 pub image_id: PendingImageId,
140 pub requested_size: DeviceIntSize,
141}
142
143#[derive(Clone, Debug)]
144pub enum ImageCacheResponseMessage {
145 NotifyPendingImageLoadStatus(PendingImageResponse),
146 VectorImageRasterizationComplete(RasterizationCompleteResponse),
147}
148
149pub enum ImageCacheResult {
154 Available(ImageOrMetadataAvailable),
155 FailedToLoadOrDecode,
156 Pending(PendingImageId),
157 ReadyForRequest(PendingImageId),
158}
159
160pub trait ImageCacheFactory: Sync + Send {
164 fn create(
165 &self,
166 webview_id: WebViewId,
167 pipeline_id: PipelineId,
168 paint_api: &CrossProcessPaintApi,
169 ) -> Arc<dyn ImageCache>;
170}
171
172pub trait ImageCache: Sync + Send {
175 fn memory_reports(&self, prefix: &str, ops: &mut MallocSizeOfOps) -> Vec<Report>;
176
177 #[cfg(feature = "test-util")]
178 fn number_of_rasterize_tasks(&self) -> usize;
180
181 fn get_image_key(&self) -> Option<ImageKey>;
185
186 fn get_image(
188 &self,
189 url: ServoUrl,
190 origin: ImmutableOrigin,
191 cors_setting: Option<CorsSettings>,
192 ) -> Option<Image>;
193
194 fn get_cached_image_status(
195 &self,
196 url: ServoUrl,
197 origin: ImmutableOrigin,
198 cors_setting: Option<CorsSettings>,
199 ) -> ImageCacheResult;
200
201 fn rasterize_vector_image(
206 &self,
207 image_id: VectorImageId,
208 size: DeviceIntSize,
209 svg_id: Option<String>,
210 ) -> Option<RasterImage>;
211
212 fn add_rasterization_complete_listener(
217 &self,
218 pipeline_id: PipelineId,
219 image_id: VectorImageId,
220 size: DeviceIntSize,
221 callback: ImageCacheResponseCallback,
222 );
223
224 fn evict_rasterized_image(&self, svg_id: &str);
226
227 fn evict_completed_image(
229 &self,
230 url: &ServoUrl,
231 origin: &ImmutableOrigin,
232 cors_setting: &Option<CorsSettings>,
233 );
234
235 fn get_broken_image_icon(&self) -> Option<Arc<RasterImage>>;
238
239 fn add_listener(&self, listener: ImageLoadListener);
242
243 fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
245
246 fn fill_key_cache_with_batch_of_keys(&self, image_keys: Vec<ImageKey>);
248
249 fn clear(&self);
251}