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 fn resolve_fallback(
36 &self,
37 char: char,
38 excluded: &[fontdb::ID],
39 database: &mut Arc<fontdb::Database>,
40 ) -> Option<fontdb::ID>;
41}
42
43pub type VectorImageId = PendingImageId;
44
45#[derive(Clone, Debug, MallocSizeOf)]
49pub enum Image {
50 Raster(#[conditional_malloc_size_of] Arc<RasterImage>),
51 Vector(VectorImage),
52}
53
54#[derive(Clone, Debug, Deserialize, MallocSizeOf, Serialize)]
55pub struct VectorImage {
56 pub id: VectorImageId,
57 pub svg_id: Option<Uuid>,
58 pub metadata: ImageMetadata,
59 pub cors_status: CorsStatus,
60}
61
62impl Image {
63 pub fn metadata(&self) -> ImageMetadata {
64 match self {
65 Image::Vector(image, ..) => image.metadata,
66 Image::Raster(image) => image.metadata,
67 }
68 }
69
70 pub fn cors_status(&self) -> CorsStatus {
71 match self {
72 Image::Vector(image) => image.cors_status,
73 Image::Raster(image) => image.cors_status,
74 }
75 }
76
77 pub fn as_raster_image(&self) -> Option<Arc<RasterImage>> {
78 match self {
79 Image::Raster(image) => Some(image.clone()),
80 Image::Vector(..) => None,
81 }
82 }
83}
84
85#[derive(Clone, Debug, MallocSizeOf)]
87pub enum ImageOrMetadataAvailable {
88 ImageAvailable { image: Image, url: ServoUrl },
89 MetadataAvailable(ImageMetadata, PendingImageId),
90}
91
92pub type ImageCacheResponseCallback = Box<dyn Fn(ImageCacheResponseMessage) + Send + 'static>;
93
94#[derive(MallocSizeOf)]
99pub struct ImageLoadListener {
100 pipeline_id: PipelineId,
101 pub id: PendingImageId,
102 #[ignore_malloc_size_of = "Difficult to measure FnOnce"]
103 callback: ImageCacheResponseCallback,
104}
105
106impl ImageLoadListener {
107 pub fn new(
108 callback: ImageCacheResponseCallback,
109 pipeline_id: PipelineId,
110 id: PendingImageId,
111 ) -> ImageLoadListener {
112 ImageLoadListener {
113 pipeline_id,
114 callback,
115 id,
116 }
117 }
118
119 pub fn respond(&self, response: ImageResponse) {
120 debug!("Notifying listener");
121 (self.callback)(ImageCacheResponseMessage::NotifyPendingImageLoadStatus(
122 PendingImageResponse {
123 pipeline_id: self.pipeline_id,
124 response,
125 id: self.id,
126 },
127 ));
128 }
129}
130
131#[derive(Clone, Debug, MallocSizeOf)]
133pub enum ImageResponse {
134 Loaded(Image, ServoUrl),
136 MetadataLoaded(ImageMetadata),
138 FailedToLoadOrDecode,
140}
141
142#[derive(Clone, Copy, Debug, Deserialize, Eq, Hash, MallocSizeOf, PartialEq, Serialize)]
144pub struct PendingImageId(pub u64);
145
146#[derive(Clone, Debug)]
147pub struct PendingImageResponse {
148 pub pipeline_id: PipelineId,
149 pub response: ImageResponse,
150 pub id: PendingImageId,
151}
152
153#[derive(Clone, Debug, Deserialize, Serialize)]
154pub struct RasterizationCompleteResponse {
155 pub pipeline_id: PipelineId,
156 pub image_id: PendingImageId,
157 pub requested_size: DeviceIntSize,
158}
159
160#[derive(Clone, Debug)]
161pub enum ImageCacheResponseMessage {
162 NotifyPendingImageLoadStatus(PendingImageResponse),
163 VectorImageRasterizationComplete(RasterizationCompleteResponse),
164}
165
166pub enum ImageCacheResult {
171 Available(ImageOrMetadataAvailable),
172 FailedToLoadOrDecode,
173 Pending(PendingImageId),
174 ReadyForRequest(PendingImageId),
175}
176
177pub trait ImageCacheFactory: Sync + Send {
181 fn create(
182 &self,
183 webview_id: WebViewId,
184 pipeline_id: PipelineId,
185 paint_api: &CrossProcessPaintApi,
186 font_resolver: Arc<dyn FontResolver>,
187 ) -> Arc<dyn ImageCache>;
188}
189
190pub trait ImageCache: Sync + Send {
193 fn memory_reports(&self, prefix: &str, ops: &mut MallocSizeOfOps) -> Vec<Report>;
194
195 #[cfg(feature = "test-util")]
196 fn number_of_rasterize_tasks(&self) -> usize;
198
199 fn get_image_key(&self) -> Option<ImageKey>;
203
204 fn get_image(
206 &self,
207 url: ServoUrl,
208 origin: ImmutableOrigin,
209 cors_setting: Option<CorsSettings>,
210 ) -> Option<Image>;
211
212 fn get_cached_image_status(
214 &self,
215 url: ServoUrl,
216 origin: ImmutableOrigin,
217 cors_setting: Option<CorsSettings>,
218 ) -> ImageCacheResult;
219
220 fn rasterize_vector_image(
225 &self,
226 image_id: VectorImageId,
227 size: DeviceIntSize,
228 svg_id: Option<Uuid>,
229 ) -> Option<RasterImage>;
230
231 fn add_rasterization_complete_listener(
236 &self,
237 pipeline_id: PipelineId,
238 image_id: VectorImageId,
239 size: DeviceIntSize,
240 callback: ImageCacheResponseCallback,
241 );
242
243 fn evict_rasterized_image(&self, svg_id: &Uuid);
245
246 fn evict_completed_image(
248 &self,
249 url: &ServoUrl,
250 origin: &ImmutableOrigin,
251 cors_setting: &Option<CorsSettings>,
252 );
253
254 fn get_broken_image_icon(&self) -> Option<Arc<RasterImage>>;
257
258 fn add_listener(&self, listener: ImageLoadListener);
261
262 fn notify_pending_response(&self, id: PendingImageId, action: FetchResponseMsg);
264
265 fn dispatch_fill_key_cache_with_batch_of_keys(&self, image_keys: Vec<ImageKey>);
267
268 fn clear(&self);
270}