1use std::sync::Arc;
6
7use log::debug;
8use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
9use malloc_size_of_derive::MallocSizeOf;
10use paint_api::CrossProcessPaintApi;
11use pixels::{CorsStatus, ImageMetadata, RasterImage};
12use profile_traits::mem::Report;
13use resvg::usvg::{Font, fontdb};
14use serde::{Deserialize, Serialize};
15use servo_base::cross_process_instant::CrossProcessInstant;
16use servo_base::id::{PipelineId, WebViewId};
17use servo_url::{ImmutableOrigin, ServoUrl};
18use uuid::Uuid;
19use webrender_api::ImageKey;
20use webrender_api::units::DeviceIntSize;
21
22use crate::FetchResponseMsg;
23use crate::request::CorsSettings;
24
25pub trait FontResolver: Sync + Send + MallocSizeOf {
31 fn resolve(&self, font: &Font, database: &mut Arc<fontdb::Database>) -> Option<fontdb::ID>;
35 fn resolve_fallback(
37 &self,
38 char: char,
39 excluded: &[fontdb::ID],
40 database: &mut Arc<fontdb::Database>,
41 ) -> Option<fontdb::ID>;
42}
43
44pub type VectorImageId = PendingImageId;
45
46#[derive(Clone, Debug, MallocSizeOf)]
50pub enum Image {
51 Raster(#[conditional_malloc_size_of] Arc<RasterImage>),
52 Vector(VectorImage),
53}
54
55#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
56pub struct VectorImage {
57 pub id: VectorImageId,
58 pub svg_id: Option<Uuid>,
59 pub metadata: ImageMetadata,
60 pub cors_status: CorsStatus,
61 pub load_time: Option<CrossProcessInstant>,
62}
63
64impl Image {
65 pub fn metadata(&self) -> ImageMetadata {
66 match self {
67 Image::Vector(image, ..) => image.metadata,
68 Image::Raster(image) => image.metadata,
69 }
70 }
71
72 pub fn cors_status(&self) -> CorsStatus {
73 match self {
74 Image::Vector(image) => image.cors_status,
75 Image::Raster(image) => image.cors_status,
76 }
77 }
78
79 pub fn as_raster_image(&self) -> Option<Arc<RasterImage>> {
80 match self {
81 Image::Raster(image) => Some(image.clone()),
82 Image::Vector(..) => None,
83 }
84 }
85
86 pub fn load_time(&self) -> Option<CrossProcessInstant> {
87 match self {
88 Image::Raster(image) => image.load_time,
89 Image::Vector(image) => image.load_time,
90 }
91 }
92}
93
94#[derive(Clone, Debug, MallocSizeOf)]
96pub enum ImageOrMetadataAvailable {
97 ImageAvailable { image: Image, url: ServoUrl },
98 MetadataAvailable(ImageMetadata, PendingImageId),
99}
100
101#[derive(Clone, Debug, MallocSizeOf)]
103pub enum RasterizationResult {
104 Image(RasterImage),
106 PendingRasterization,
108 InvalidSvgParameters,
110}
111
112pub type ImageCacheResponseCallback = Box<dyn Fn(ImageCacheResponseMessage) + Send + 'static>;
113
114#[derive(MallocSizeOf)]
119pub struct ImageLoadListener {
120 pipeline_id: PipelineId,
121 pub id: PendingImageId,
122 #[ignore_malloc_size_of = "Difficult to measure FnOnce"]
123 callback: ImageCacheResponseCallback,
124}
125
126impl ImageLoadListener {
127 pub fn new(
128 callback: ImageCacheResponseCallback,
129 pipeline_id: PipelineId,
130 id: PendingImageId,
131 ) -> ImageLoadListener {
132 ImageLoadListener {
133 pipeline_id,
134 callback,
135 id,
136 }
137 }
138
139 pub fn respond(&self, response: ImageResponse) {
140 debug!("Notifying listener");
141 (self.callback)(ImageCacheResponseMessage::NotifyPendingImageLoadStatus(
142 PendingImageResponse {
143 pipeline_id: self.pipeline_id,
144 response,
145 id: self.id,
146 },
147 ));
148 }
149}
150
151#[derive(Clone, Debug, MallocSizeOf)]
153pub enum ImageResponse {
154 Loaded(Image, ServoUrl),
156 MetadataLoaded(ImageMetadata),
158 FailedToLoadOrDecode,
160}
161
162#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
164pub struct PendingImageId(pub u64);
165
166#[derive(Clone, Debug)]
167pub struct PendingImageResponse {
168 pub pipeline_id: PipelineId,
169 pub response: ImageResponse,
170 pub id: PendingImageId,
171}
172
173#[derive(Clone, Debug, Deserialize, Serialize)]
174pub struct RasterizationCompleteResponse {
175 pub pipeline_id: PipelineId,
176 pub image_id: PendingImageId,
177 pub requested_size: DeviceIntSize,
178}
179
180#[derive(Clone, Debug)]
181pub enum ImageCacheResponseMessage {
182 NotifyPendingImageLoadStatus(PendingImageResponse),
183 VectorImageRasterizationComplete(RasterizationCompleteResponse),
184}
185
186pub enum ImageCacheResult {
191 Available(ImageOrMetadataAvailable),
192 FailedToLoadOrDecode,
193 Pending(PendingImageId),
194 ReadyForRequest(PendingImageId),
195}
196
197pub trait ImageCacheFactory: Sync + Send {
201 fn create(
202 &self,
203 webview_id: WebViewId,
204 pipeline_id: PipelineId,
205 paint_api: &CrossProcessPaintApi,
206 font_resolver: Arc<dyn FontResolver>,
207 ) -> Arc<dyn ImageCache>;
208}
209
210pub trait ImageCache: Sync + Send {
213 fn memory_reports(&self, prefix: &str, ops: &mut MallocSizeOfOps) -> Vec<Report>;
214
215 #[cfg(feature = "test-util")]
216 fn number_of_rasterize_tasks(&self) -> usize;
218
219 fn get_image_key(&self) -> Option<ImageKey>;
223
224 fn get_image(
226 &self,
227 url: ServoUrl,
228 origin: ImmutableOrigin,
229 cors_setting: Option<CorsSettings>,
230 ) -> Option<Image>;
231
232 fn get_cached_image_status(
234 &self,
235 url: ServoUrl,
236 origin: &ImmutableOrigin,
237 cors_setting: Option<CorsSettings>,
238 ) -> ImageCacheResult;
239
240 fn rasterize_vector_image(
246 &self,
247 image_id: VectorImageId,
248 size: DeviceIntSize,
249 svg_id: Option<Uuid>,
250 ) -> RasterizationResult;
251
252 fn add_rasterization_complete_listener(
257 &self,
258 pipeline_id: PipelineId,
259 image_id: VectorImageId,
260 size: DeviceIntSize,
261 callback: ImageCacheResponseCallback,
262 );
263
264 fn evict_rasterized_image(&self, svg_id: &Uuid);
266
267 fn evict_completed_image(
269 &self,
270 url: &ServoUrl,
271 origin: &ImmutableOrigin,
272 cors_setting: &Option<CorsSettings>,
273 );
274
275 fn get_broken_image_icon(&self) -> Option<Arc<RasterImage>>;
278
279 fn add_listener(&self, listener: ImageLoadListener);
282
283 fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
285
286 fn dispatch_fill_key_cache_with_batch_of_keys(&self, image_keys: Vec<ImageKey>);
288
289 fn clear(&self);
291}