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
101pub type ImageCacheResponseCallback = Box<dyn Fn(ImageCacheResponseMessage) + Send + 'static>;
102
103#[derive(MallocSizeOf)]
108pub struct ImageLoadListener {
109 pipeline_id: PipelineId,
110 pub id: PendingImageId,
111 #[ignore_malloc_size_of = "Difficult to measure FnOnce"]
112 callback: ImageCacheResponseCallback,
113}
114
115impl ImageLoadListener {
116 pub fn new(
117 callback: ImageCacheResponseCallback,
118 pipeline_id: PipelineId,
119 id: PendingImageId,
120 ) -> ImageLoadListener {
121 ImageLoadListener {
122 pipeline_id,
123 callback,
124 id,
125 }
126 }
127
128 pub fn respond(&self, response: ImageResponse) {
129 debug!("Notifying listener");
130 (self.callback)(ImageCacheResponseMessage::NotifyPendingImageLoadStatus(
131 PendingImageResponse {
132 pipeline_id: self.pipeline_id,
133 response,
134 id: self.id,
135 },
136 ));
137 }
138}
139
140#[derive(Clone, Debug, MallocSizeOf)]
142pub enum ImageResponse {
143 Loaded(Image, ServoUrl),
145 MetadataLoaded(ImageMetadata),
147 FailedToLoadOrDecode,
149}
150
151#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
153pub struct PendingImageId(pub u64);
154
155#[derive(Clone, Debug)]
156pub struct PendingImageResponse {
157 pub pipeline_id: PipelineId,
158 pub response: ImageResponse,
159 pub id: PendingImageId,
160}
161
162#[derive(Clone, Debug, Deserialize, Serialize)]
163pub struct RasterizationCompleteResponse {
164 pub pipeline_id: PipelineId,
165 pub image_id: PendingImageId,
166 pub requested_size: DeviceIntSize,
167}
168
169#[derive(Clone, Debug)]
170pub enum ImageCacheResponseMessage {
171 NotifyPendingImageLoadStatus(PendingImageResponse),
172 VectorImageRasterizationComplete(RasterizationCompleteResponse),
173}
174
175pub enum ImageCacheResult {
180 Available(ImageOrMetadataAvailable),
181 FailedToLoadOrDecode,
182 Pending(PendingImageId),
183 ReadyForRequest(PendingImageId),
184}
185
186pub trait ImageCacheFactory: Sync + Send {
190 fn create(
191 &self,
192 webview_id: WebViewId,
193 pipeline_id: PipelineId,
194 paint_api: &CrossProcessPaintApi,
195 font_resolver: Arc<dyn FontResolver>,
196 ) -> Arc<dyn ImageCache>;
197}
198
199pub trait ImageCache: Sync + Send {
202 fn memory_reports(&self, prefix: &str, ops: &mut MallocSizeOfOps) -> Vec<Report>;
203
204 #[cfg(feature = "test-util")]
205 fn number_of_rasterize_tasks(&self) -> usize;
207
208 fn get_image_key(&self) -> Option<ImageKey>;
212
213 fn get_image(
215 &self,
216 url: ServoUrl,
217 origin: ImmutableOrigin,
218 cors_setting: Option<CorsSettings>,
219 ) -> Option<Image>;
220
221 fn get_cached_image_status(
223 &self,
224 url: ServoUrl,
225 origin: &ImmutableOrigin,
226 cors_setting: Option<CorsSettings>,
227 ) -> ImageCacheResult;
228
229 fn rasterize_vector_image(
234 &self,
235 image_id: VectorImageId,
236 size: DeviceIntSize,
237 svg_id: Option<Uuid>,
238 ) -> Option<RasterImage>;
239
240 fn add_rasterization_complete_listener(
245 &self,
246 pipeline_id: PipelineId,
247 image_id: VectorImageId,
248 size: DeviceIntSize,
249 callback: ImageCacheResponseCallback,
250 );
251
252 fn evict_rasterized_image(&self, svg_id: &Uuid);
254
255 fn evict_completed_image(
257 &self,
258 url: &ServoUrl,
259 origin: &ImmutableOrigin,
260 cors_setting: &Option<CorsSettings>,
261 );
262
263 fn get_broken_image_icon(&self) -> Option<Arc<RasterImage>>;
266
267 fn add_listener(&self, listener: ImageLoadListener);
270
271 fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
273
274 fn dispatch_fill_key_cache_with_batch_of_keys(&self, image_keys: Vec<ImageKey>);
276
277 fn clear(&self);
279}