1use crate::color::AbsoluteColor;
8use crate::context::QuirksMode;
9use crate::custom_properties::CssEnvironment;
10use crate::font_metrics::FontMetrics;
11use crate::logical_geometry::WritingMode;
12use crate::media_queries::MediaType;
13use crate::properties::style_structs::Font;
14use crate::properties::ComputedValues;
15use crate::queries::values::PrefersColorScheme;
16use crate::values::computed::font::GenericFontFamily;
17use crate::values::computed::{CSSPixelLength, Length, LineHeight, NonNegativeLength};
18use crate::values::specified::color::{ColorSchemeFlags, ForcedColors, SystemColor};
19use crate::values::specified::font::{
20 QueryFontMetricsFlags, FONT_MEDIUM_CAP_PX, FONT_MEDIUM_CH_PX, FONT_MEDIUM_EX_PX,
21 FONT_MEDIUM_IC_PX, FONT_MEDIUM_LINE_HEIGHT_PX, FONT_MEDIUM_PX,
22};
23use crate::values::specified::ViewportVariant;
24use crate::values::KeyframesName;
25use app_units::{Au, AU_PER_PX};
26use euclid::default::Size2D as UntypedSize2D;
27use euclid::{Scale, SideOffsets2D, Size2D};
28use malloc_size_of_derive::MallocSizeOf;
29use mime::Mime;
30use parking_lot::RwLock;
31use servo_arc::Arc;
32use std::fmt::Debug;
33use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
34use style_traits::{CSSPixel, DevicePixel};
35
36use crate::device::Device;
37
38pub trait FontMetricsProvider: Debug + Sync {
41 fn query_font_metrics(
43 &self,
44 vertical: bool,
45 font: &Font,
46 base_size: CSSPixelLength,
47 flags: QueryFontMetricsFlags,
48 ) -> FontMetrics;
49 fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length;
51}
52
53#[derive(Debug, MallocSizeOf)]
54pub(super) struct ExtraDeviceData {
55 media_type: MediaType,
57 viewport_size: Size2D<f32, CSSPixel>,
59 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
61 #[ignore_malloc_size_of = "Pure stack type"]
63 quirks_mode: QuirksMode,
64 #[ignore_malloc_size_of = "Pure stack type"]
66 prefers_color_scheme: PrefersColorScheme,
67 #[ignore_malloc_size_of = "Owned by embedder"]
69 font_metrics_provider: Box<dyn FontMetricsProvider>,
70}
71
72impl Device {
73 pub fn new(
75 media_type: MediaType,
76 quirks_mode: QuirksMode,
77 viewport_size: Size2D<f32, CSSPixel>,
78 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
79 font_metrics_provider: Box<dyn FontMetricsProvider>,
80 default_values: Arc<ComputedValues>,
81 prefers_color_scheme: PrefersColorScheme,
82 ) -> Device {
83 let root_style = RwLock::new(Arc::clone(&default_values));
84 Device {
85 root_style,
86 root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()),
87 root_line_height: AtomicU32::new(FONT_MEDIUM_LINE_HEIGHT_PX.to_bits()),
88 root_font_metrics_ex: AtomicU32::new(FONT_MEDIUM_EX_PX.to_bits()),
89 root_font_metrics_cap: AtomicU32::new(FONT_MEDIUM_CAP_PX.to_bits()),
90 root_font_metrics_ch: AtomicU32::new(FONT_MEDIUM_CH_PX.to_bits()),
91 root_font_metrics_ic: AtomicU32::new(FONT_MEDIUM_IC_PX.to_bits()),
92 used_root_font_size: AtomicBool::new(false),
93 used_root_line_height: AtomicBool::new(false),
94 used_root_font_metrics: RwLock::new(false),
95 used_font_metrics: AtomicBool::new(false),
96 used_viewport_size: AtomicBool::new(false),
97 used_dynamic_viewport_size: AtomicBool::new(false),
98 environment: CssEnvironment,
99 default_values,
100 body_text_color: AtomicU32::new(AbsoluteColor::BLACK.to_nscolor()),
101 extra: ExtraDeviceData {
102 media_type,
103 viewport_size,
104 device_pixel_ratio,
105 quirks_mode,
106 prefers_color_scheme,
107 font_metrics_provider,
108 },
109 }
110 }
111
112 pub fn calc_line_height(
116 &self,
117 font: &crate::properties::style_structs::Font,
118 _writing_mode: WritingMode,
119 _element: Option<()>,
120 ) -> NonNegativeLength {
121 (match font.line_height {
122 LineHeight::Normal => CSSPixelLength::new(0.),
124 LineHeight::Number(number) => font.font_size.computed_size() * number.0,
125 LineHeight::Length(length) => length.0,
126 })
127 .into()
128 }
129
130 pub fn quirks_mode(&self) -> QuirksMode {
132 self.extra.quirks_mode
133 }
134
135 pub fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length {
137 self.extra
138 .font_metrics_provider
139 .base_size_for_generic(generic)
140 }
141
142 pub fn animation_name_may_be_referenced(&self, _: &KeyframesName) -> bool {
144 true
146 }
147
148 pub fn viewport_size(&self) -> Size2D<f32, CSSPixel> {
150 self.extra.viewport_size
151 }
152
153 pub fn set_viewport_size(&mut self, viewport_size: Size2D<f32, CSSPixel>) {
159 self.extra.viewport_size = viewport_size;
160 }
161
162 #[inline]
165 pub fn au_viewport_size(&self) -> UntypedSize2D<Au> {
166 Size2D::new(
167 Au::from_f32_px(self.extra.viewport_size.width),
168 Au::from_f32_px(self.extra.viewport_size.height),
169 )
170 }
171
172 pub fn au_viewport_size_for_viewport_unit_resolution(
174 &self,
175 _: ViewportVariant,
176 ) -> UntypedSize2D<Au> {
177 self.used_viewport_size.store(true, Ordering::Relaxed);
178 self.au_viewport_size()
181 }
182
183 pub fn app_units_per_device_pixel(&self) -> i32 {
185 (AU_PER_PX as f32 / self.extra.device_pixel_ratio.0) as i32
186 }
187
188 pub fn device_pixel_ratio_ignoring_full_zoom(&self) -> Scale<f32, CSSPixel, DevicePixel> {
190 self.extra.device_pixel_ratio
191 }
192
193 pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
195 self.extra.device_pixel_ratio
196 }
197
198 pub fn set_device_pixel_ratio(
204 &mut self,
205 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
206 ) {
207 self.extra.device_pixel_ratio = device_pixel_ratio;
208 }
209
210 pub fn scrollbar_inline_size(&self) -> CSSPixelLength {
212 CSSPixelLength::new(0.0)
214 }
215
216 pub fn query_font_metrics(
218 &self,
219 vertical: bool,
220 font: &Font,
221 base_size: CSSPixelLength,
222 flags: QueryFontMetricsFlags,
223 track_usage: bool,
224 ) -> FontMetrics {
225 if track_usage {
226 self.used_font_metrics.store(true, Ordering::Relaxed);
227 }
228 self.extra
229 .font_metrics_provider
230 .query_font_metrics(vertical, font, base_size, flags)
231 }
232
233 pub fn media_type(&self) -> MediaType {
235 self.extra.media_type.clone()
236 }
237
238 pub fn forced_colors(&self) -> ForcedColors {
240 ForcedColors::None
241 }
242
243 pub fn default_background_color(&self) -> AbsoluteColor {
245 AbsoluteColor::WHITE
246 }
247
248 pub fn default_color(&self) -> AbsoluteColor {
250 AbsoluteColor::BLACK
251 }
252
253 pub fn set_color_scheme(&mut self, new_color_scheme: PrefersColorScheme) {
259 self.extra.prefers_color_scheme = new_color_scheme;
260 }
261
262 pub fn color_scheme(&self) -> PrefersColorScheme {
264 self.extra.prefers_color_scheme
265 }
266
267 pub(crate) fn is_dark_color_scheme(&self, _: ColorSchemeFlags) -> bool {
268 false
269 }
270
271 pub(crate) fn system_color(
272 &self,
273 system_color: SystemColor,
274 color_scheme_flags: ColorSchemeFlags,
275 ) -> AbsoluteColor {
276 fn srgb(r: u8, g: u8, b: u8) -> AbsoluteColor {
277 AbsoluteColor::srgb_legacy(r, g, b, 1f32)
278 }
279
280 if self.is_dark_color_scheme(color_scheme_flags) {
283 match system_color {
285 SystemColor::Accentcolor => srgb(10, 132, 255),
286 SystemColor::Accentcolortext => srgb(255, 255, 255),
287 SystemColor::Activetext => srgb(255, 0, 0),
288 SystemColor::Linktext => srgb(158, 158, 255),
289 SystemColor::Visitedtext => srgb(208, 173, 240),
290 SystemColor::Buttonborder
291 | SystemColor::Activeborder
293 | SystemColor::Inactiveborder
294 | SystemColor::Threeddarkshadow
295 | SystemColor::Threedshadow
296 | SystemColor::Windowframe => srgb(255, 255, 255),
297 SystemColor::Buttonface
298 | SystemColor::Buttonhighlight
300 | SystemColor::Buttonshadow
301 | SystemColor::Threedface
302 | SystemColor::Threedhighlight
303 | SystemColor::Threedlightshadow => srgb(107, 107, 107),
304 SystemColor::Buttontext => srgb(245, 245, 245),
305 SystemColor::Canvas
306 | SystemColor::Activecaption
308 | SystemColor::Appworkspace
309 | SystemColor::Background
310 | SystemColor::Inactivecaption
311 | SystemColor::Infobackground
312 | SystemColor::Menu
313 | SystemColor::Scrollbar
314 | SystemColor::Window => srgb(30, 30, 30),
315 SystemColor::Canvastext
316 | SystemColor::Captiontext
318 | SystemColor::Infotext
319 | SystemColor::Menutext
320 | SystemColor::Windowtext => srgb(232, 232, 232),
321 SystemColor::Field => srgb(45, 45, 45),
322 SystemColor::Fieldtext => srgb(240, 240, 240),
323 SystemColor::Graytext
324 | SystemColor::Inactivecaptiontext => srgb(155, 155, 155),
326 SystemColor::Highlight => srgb(38, 79, 120),
327 SystemColor::Highlighttext => srgb(255, 255, 255),
328 SystemColor::Mark => srgb(102, 92, 0),
329 SystemColor::Marktext => srgb(255, 255, 255),
330 SystemColor::Selecteditem => srgb(153, 200, 255),
331 SystemColor::Selecteditemtext => srgb(59, 59, 59),
332 }
333 } else {
334 match system_color {
335 SystemColor::Accentcolor => srgb(0, 102, 204),
336 SystemColor::Accentcolortext => srgb(255, 255, 255),
337 SystemColor::Activetext => srgb(238, 0, 0),
338 SystemColor::Linktext => srgb(0, 0, 238),
339 SystemColor::Visitedtext => srgb(85, 26, 139),
340 SystemColor::Buttonborder
341 | SystemColor::Activeborder
343 | SystemColor::Inactiveborder
344 | SystemColor::Threeddarkshadow
345 | SystemColor::Threedshadow
346 | SystemColor::Windowframe => srgb(169, 169, 169),
347 SystemColor::Buttonface
348 | SystemColor::Buttonhighlight
350 | SystemColor::Buttonshadow
351 | SystemColor::Threedface
352 | SystemColor::Threedhighlight
353 | SystemColor::Threedlightshadow => srgb(220, 220, 220),
354 SystemColor::Buttontext => srgb(0, 0, 0),
355 SystemColor::Canvas
356 | SystemColor::Activecaption
358 | SystemColor::Appworkspace
359 | SystemColor::Background
360 | SystemColor::Inactivecaption
361 | SystemColor::Infobackground
362 | SystemColor::Menu
363 | SystemColor::Scrollbar
364 | SystemColor::Window => srgb(255, 255, 255),
365 SystemColor::Canvastext
366 | SystemColor::Captiontext
368 | SystemColor::Infotext
369 | SystemColor::Menutext
370 | SystemColor::Windowtext => srgb(0, 0, 0),
371 SystemColor::Field => srgb(255, 255, 255),
372 SystemColor::Fieldtext => srgb(0, 0, 0),
373 SystemColor::Graytext
374 | SystemColor::Inactivecaptiontext => srgb(109, 109, 109),
376 SystemColor::Highlight => srgb(0, 65, 198),
377 SystemColor::Highlighttext => srgb(0, 0, 0),
378 SystemColor::Mark => srgb(255, 235, 59),
379 SystemColor::Marktext => srgb(0, 0, 0),
380 SystemColor::Selecteditem => srgb(0, 102, 204),
381 SystemColor::Selecteditemtext => srgb(255, 255, 255),
382 }
383 }
384 }
385
386 pub fn safe_area_insets(&self) -> SideOffsets2D<f32, CSSPixel> {
388 SideOffsets2D::zero()
389 }
390
391 pub fn is_supported_mime_type(&self, mime_type: &str) -> bool {
393 match mime_type.parse::<Mime>() {
394 Ok(m) => {
395 m == mime::IMAGE_BMP
398 || m == mime::IMAGE_GIF
399 || m == mime::IMAGE_PNG
400 || m == mime::IMAGE_JPEG
401 || m == "image/x-icon"
402 || m == "image/webp"
403 },
404 _ => false,
405 }
406 }
407
408 #[inline]
410 pub fn chrome_rules_enabled_for_document(&self) -> bool {
411 false
412 }
413}