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 resvg::usvg::{Font, fontdb};
14use serde::{Deserialize, Serialize};
15use servo_base::id::{PipelineId, WebViewId};
16use servo_url::{ImmutableOrigin, ServoUrl};
17use uuid::Uuid;
18use webrender_api::ImageKey;
19use webrender_api::units::DeviceIntSize;
20
21use crate::FetchResponseMsg;
22use crate::request::CorsSettings;
23
24pub trait FontResolver: Sync + Send {
30 fn resolve(&self, font: &Font, database: &mut Arc<fontdb::Database>) -> Option<fontdb::ID>;
34}
35
36pub type VectorImageId = PendingImageId;
37
38#[derive(Clone, Debug, MallocSizeOf)]
42pub enum Image {
43 Raster(#[conditional_malloc_size_of] Arc<RasterImage>),
44 Vector(VectorImage),
45}
46
47#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
48pub struct VectorImage {
49 pub id: VectorImageId,
50 pub svg_id: Option<Uuid>,
51 pub metadata: ImageMetadata,
52 pub cors_status: CorsStatus,
53}
54
55impl Image {
56 pub fn metadata(&self) -> ImageMetadata {
57 match self {
58 Image::Vector(image, ..) => image.metadata,
59 Image::Raster(image) => image.metadata,
60 }
61 }
62
63 pub fn cors_status(&self) -> CorsStatus {
64 match self {
65 Image::Vector(image) => image.cors_status,
66 Image::Raster(image) => image.cors_status,
67 }
68 }
69
70 pub fn as_raster_image(&self) -> Option<Arc<RasterImage>> {
71 match self {
72 Image::Raster(image) => Some(image.clone()),
73 Image::Vector(..) => None,
74 }
75 }
76}
77
78#[derive(Clone, Debug, MallocSizeOf)]
80pub enum ImageOrMetadataAvailable {
81 ImageAvailable { image: Image, url: ServoUrl },
82 MetadataAvailable(ImageMetadata, PendingImageId),
83}
84
85pub type ImageCacheResponseCallback = Box<dyn Fn(ImageCacheResponseMessage) + Send + 'static>;
86
87#[derive(MallocSizeOf)]
92pub struct ImageLoadListener {
93 pipeline_id: PipelineId,
94 pub id: PendingImageId,
95 #[ignore_malloc_size_of = "Difficult to measure FnOnce"]
96 callback: ImageCacheResponseCallback,
97}
98
99impl ImageLoadListener {
100 pub fn new(
101 callback: ImageCacheResponseCallback,
102 pipeline_id: PipelineId,
103 id: PendingImageId,
104 ) -> ImageLoadListener {
105 ImageLoadListener {
106 pipeline_id,
107 callback,
108 id,
109 }
110 }
111
112 pub fn respond(&self, response: ImageResponse) {
113 debug!("Notifying listener");
114 (self.callback)(ImageCacheResponseMessage::NotifyPendingImageLoadStatus(
115 PendingImageResponse {
116 pipeline_id: self.pipeline_id,
117 response,
118 id: self.id,
119 },
120 ));
121 }
122}
123
124#[derive(Clone, Debug, MallocSizeOf)]
126pub enum ImageResponse {
127 Loaded(Image, ServoUrl),
129 MetadataLoaded(ImageMetadata),
131 FailedToLoadOrDecode,
133}
134
135#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
137pub struct PendingImageId(pub u64);
138
139#[derive(Clone, Debug)]
140pub struct PendingImageResponse {
141 pub pipeline_id: PipelineId,
142 pub response: ImageResponse,
143 pub id: PendingImageId,
144}
145
146#[derive(Clone, Debug, Deserialize, Serialize)]
147pub struct RasterizationCompleteResponse {
148 pub pipeline_id: PipelineId,
149 pub image_id: PendingImageId,
150 pub requested_size: DeviceIntSize,
151}
152
153#[derive(Clone, Debug)]
154pub enum ImageCacheResponseMessage {
155 NotifyPendingImageLoadStatus(PendingImageResponse),
156 VectorImageRasterizationComplete(RasterizationCompleteResponse),
157}
158
159pub enum ImageCacheResult {
164 Available(ImageOrMetadataAvailable),
165 FailedToLoadOrDecode,
166 Pending(PendingImageId),
167 ReadyForRequest(PendingImageId),
168}
169
170pub trait ImageCacheFactory: Sync + Send {
174 fn create(
175 &self,
176 webview_id: WebViewId,
177 pipeline_id: PipelineId,
178 paint_api: &CrossProcessPaintApi,
179 font_resolver: Arc<dyn FontResolver>,
180 ) -> Arc<dyn ImageCache>;
181}
182
183pub trait ImageCache: Sync + Send {
186 fn memory_reports(&self, prefix: &str, ops: &mut MallocSizeOfOps) -> Vec<Report>;
187
188 #[cfg(feature = "test-util")]
189 fn number_of_rasterize_tasks(&self) -> usize;
191
192 fn get_image_key(&self) -> Option<ImageKey>;
196
197 fn get_image(
199 &self,
200 url: ServoUrl,
201 origin: ImmutableOrigin,
202 cors_setting: Option<CorsSettings>,
203 ) -> Option<Image>;
204
205 fn get_cached_image_status(
207 &self,
208 url: ServoUrl,
209 origin: ImmutableOrigin,
210 cors_setting: Option<CorsSettings>,
211 ) -> ImageCacheResult;
212
213 fn rasterize_vector_image(
218 &self,
219 image_id: VectorImageId,
220 size: DeviceIntSize,
221 svg_id: Option<Uuid>,
222 ) -> Option<RasterImage>;
223
224 fn add_rasterization_complete_listener(
229 &self,
230 pipeline_id: PipelineId,
231 image_id: VectorImageId,
232 size: DeviceIntSize,
233 callback: ImageCacheResponseCallback,
234 );
235
236 fn evict_rasterized_image(&self, svg_id: &Uuid);
238
239 fn evict_completed_image(
241 &self,
242 url: &ServoUrl,
243 origin: &ImmutableOrigin,
244 cors_setting: &Option<CorsSettings>,
245 );
246
247 fn get_broken_image_icon(&self) -> Option<Arc<RasterImage>>;
250
251 fn add_listener(&self, listener: ImageLoadListener);
254
255 fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
257
258 fn dispatch_fill_key_cache_with_batch_of_keys(&self, image_keys: Vec<ImageKey>);
260
261 fn clear(&self);
263}