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::ComputedValues;
14use crate::properties::style_structs::Font;
15use crate::queries::values::PrefersColorScheme;
16use crate::servo::media_features::PointerCapabilities;
17use crate::values::KeyframesName;
18use crate::values::computed::font::GenericFontFamily;
19use crate::values::computed::{
20 CSSPixelLength, Length, LineHeight, LinkParameters, NonNegativeLength,
21};
22use crate::values::specified::ViewportVariant;
23use crate::values::specified::color::{ColorSchemeFlags, ForcedColors, SystemColor};
24use crate::values::specified::font::{
25 FONT_MEDIUM_CAP_PX, FONT_MEDIUM_CH_PX, FONT_MEDIUM_EX_PX, FONT_MEDIUM_IC_PX,
26 FONT_MEDIUM_LINE_HEIGHT_PX, FONT_MEDIUM_PX, QueryFontMetricsFlags,
27};
28use app_units::{AU_PER_PX, Au};
29use euclid::default::Size2D as UntypedSize2D;
30use euclid::{Scale, SideOffsets2D, Size2D};
31use malloc_size_of_derive::MallocSizeOf;
32use mime::Mime;
33use parking_lot::RwLock;
34use servo_arc::Arc;
35use std::fmt::Debug;
36use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
37use style_traits::{CSSPixel, DevicePixel};
38
39use crate::device::Device;
40
41pub trait FontMetricsProvider: Debug + Sync {
44 fn query_font_metrics(
46 &self,
47 vertical: bool,
48 font: &Font,
49 base_size: CSSPixelLength,
50 flags: QueryFontMetricsFlags,
51 ) -> FontMetrics;
52 fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length;
54}
55
56#[derive(Debug, MallocSizeOf)]
57pub(super) struct ExtraDeviceData {
58 media_data: MediaData,
60 #[ignore_malloc_size_of = "Owned by embedder"]
62 font_metrics_provider: Box<dyn FontMetricsProvider>,
63}
64
65#[derive(Debug, MallocSizeOf, Clone, PartialEq)]
66pub struct MediaData {
68 pub media_type: MediaType,
70 pub viewport_size: Size2D<f32, CSSPixel>,
72 pub device_size: Size2D<f32, DevicePixel>,
74 pub device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
76 #[ignore_malloc_size_of = "Pure stack type"]
78 pub quirks_mode: QuirksMode,
79 #[ignore_malloc_size_of = "Pure stack type"]
81 pub prefers_color_scheme: PrefersColorScheme,
82 #[ignore_malloc_size_of = "Pure stack type"]
84 pub primary_pointer_capabilities: PointerCapabilities,
85 #[ignore_malloc_size_of = "Pure stack type"]
87 pub all_pointer_capabilities: PointerCapabilities,
88}
89
90impl Device {
91 pub fn new(
93 default_values: Arc<ComputedValues>,
94 font_metrics_provider: Box<dyn FontMetricsProvider>,
95 media_data: MediaData,
96 ) -> Device {
97 let root_style = RwLock::new(Arc::clone(&default_values));
98 Device {
99 root_style,
100 root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()),
101 root_line_height: AtomicU32::new(FONT_MEDIUM_LINE_HEIGHT_PX.to_bits()),
102 root_font_metrics_ex: AtomicU32::new(FONT_MEDIUM_EX_PX.to_bits()),
103 root_font_metrics_cap: AtomicU32::new(FONT_MEDIUM_CAP_PX.to_bits()),
104 root_font_metrics_ch: AtomicU32::new(FONT_MEDIUM_CH_PX.to_bits()),
105 root_font_metrics_ic: AtomicU32::new(FONT_MEDIUM_IC_PX.to_bits()),
106 used_root_font_size: AtomicBool::new(false),
107 used_root_line_height: AtomicBool::new(false),
108 used_root_font_metrics: RwLock::new(false),
109 used_font_metrics: AtomicBool::new(false),
110 used_viewport_size: AtomicBool::new(false),
111 used_dynamic_viewport_size: AtomicBool::new(false),
112 environment: CssEnvironment,
113 default_values,
114 body_text_color: RwLock::new(AbsoluteColor::BLACK),
115 extra: ExtraDeviceData {
116 media_data,
117 font_metrics_provider,
118 },
119 }
120 }
121
122 pub fn calc_line_height(
126 &self,
127 font: &crate::properties::style_structs::Font,
128 _writing_mode: WritingMode,
129 _element: Option<()>,
130 ) -> NonNegativeLength {
131 (match font.line_height {
132 LineHeight::Normal => CSSPixelLength::new(0.),
134 LineHeight::Number(number) => font.font_size.computed_size() * number.0,
135 LineHeight::Length(length) => length.0,
136 })
137 .into()
138 }
139
140 pub fn quirks_mode(&self) -> QuirksMode {
142 self.extra.media_data.quirks_mode
143 }
144
145 #[inline]
148 pub fn document_random_seed(&self) -> u64 {
149 0
151 }
152
153 pub fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length {
155 self.extra
156 .font_metrics_provider
157 .base_size_for_generic(generic)
158 }
159
160 pub fn animation_name_may_be_referenced(&self, _: &KeyframesName) -> bool {
162 true
164 }
165
166 #[inline]
168 pub fn media_data(&self) -> &MediaData {
169 &self.extra.media_data
170 }
171
172 pub fn media_data_mut(&mut self) -> &mut MediaData {
178 &mut self.extra.media_data
179 }
180
181 pub fn set_media_data(&mut self, media_data: MediaData) {
187 self.extra.media_data = media_data;
188 }
189
190 pub fn viewport_size(&self) -> Size2D<f32, CSSPixel> {
192 self.extra.media_data.viewport_size
193 }
194
195 pub fn set_viewport_size(&mut self, viewport_size: Size2D<f32, CSSPixel>) {
201 self.extra.media_data.viewport_size = viewport_size;
202 }
203
204 #[inline]
207 pub fn au_viewport_size(&self) -> UntypedSize2D<Au> {
208 Size2D::new(
209 Au::from_f32_px(self.extra.media_data.viewport_size.width),
210 Au::from_f32_px(self.extra.media_data.viewport_size.height),
211 )
212 }
213
214 pub fn au_viewport_size_for_viewport_unit_resolution(
216 &self,
217 _: ViewportVariant,
218 ) -> UntypedSize2D<Au> {
219 self.used_viewport_size.store(true, Ordering::Relaxed);
220 self.au_viewport_size()
223 }
224
225 pub fn app_units_per_device_pixel(&self) -> i32 {
227 (AU_PER_PX as f32 / self.extra.media_data.device_pixel_ratio.0) as i32
228 }
229
230 pub fn device_pixel_ratio_ignoring_full_zoom(&self) -> Scale<f32, CSSPixel, DevicePixel> {
232 self.extra.media_data.device_pixel_ratio
233 }
234
235 pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
237 self.extra.media_data.device_pixel_ratio
238 }
239
240 pub fn set_device_pixel_ratio(
246 &mut self,
247 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
248 ) {
249 self.extra.media_data.device_pixel_ratio = device_pixel_ratio;
250 }
251
252 pub fn set_device_size(&mut self, device_size: Size2D<f32, DevicePixel>) {
258 self.extra.media_data.device_size = device_size;
259 }
260
261 #[inline]
263 pub fn device_size(&self) -> Size2D<f32, DevicePixel> {
264 self.extra.media_data.device_size
265 }
266
267 pub fn scrollbar_inline_size(&self) -> CSSPixelLength {
269 CSSPixelLength::new(0.0)
271 }
272
273 pub fn query_font_metrics(
275 &self,
276 vertical: bool,
277 font: &Font,
278 base_size: CSSPixelLength,
279 flags: QueryFontMetricsFlags,
280 track_usage: bool,
281 ) -> FontMetrics {
282 if track_usage {
283 self.used_font_metrics.store(true, Ordering::Relaxed);
284 }
285 self.extra
286 .font_metrics_provider
287 .query_font_metrics(vertical, font, base_size, flags)
288 }
289
290 pub fn set_media_type(&mut self, media_type: MediaType) {
296 self.extra.media_data.media_type = media_type;
297 }
298
299 pub fn media_type(&self) -> MediaType {
301 self.extra.media_data.media_type.clone()
302 }
303
304 pub fn forced_colors(&self) -> ForcedColors {
306 ForcedColors::None
307 }
308
309 pub fn default_background_color(&self) -> AbsoluteColor {
311 AbsoluteColor::WHITE
312 }
313
314 pub fn default_color(&self) -> AbsoluteColor {
316 AbsoluteColor::BLACK
317 }
318
319 pub fn set_color_scheme(&mut self, new_color_scheme: PrefersColorScheme) {
325 self.extra.media_data.prefers_color_scheme = new_color_scheme;
326 }
327
328 pub fn color_scheme(&self) -> PrefersColorScheme {
330 self.extra.media_data.prefers_color_scheme
331 }
332
333 pub fn set_primary_pointer_capabilities(&mut self, capabilities: PointerCapabilities) {
339 self.extra.media_data.primary_pointer_capabilities = capabilities;
340 }
341
342 pub fn primary_pointer_capabilities(&self) -> PointerCapabilities {
344 self.extra.media_data.primary_pointer_capabilities
345 }
346
347 pub fn set_all_pointer_capabilities(&mut self, capabilities: PointerCapabilities) {
353 self.extra.media_data.all_pointer_capabilities = capabilities;
354 }
355
356 pub fn all_pointer_capabilities(&self) -> PointerCapabilities {
358 self.extra.media_data.all_pointer_capabilities
359 }
360
361 pub(crate) fn is_dark_color_scheme(&self, color_scheme_flags: ColorSchemeFlags) -> bool {
362 let supports_dark_mode = color_scheme_flags.contains(ColorSchemeFlags::DARK);
365 let supports_light_mode = color_scheme_flags.contains(ColorSchemeFlags::LIGHT);
366
367 if supports_dark_mode != supports_light_mode {
369 return supports_dark_mode;
370 }
371
372 return self.color_scheme() == PrefersColorScheme::Dark;
375 }
376
377 pub(crate) fn system_color(
378 &self,
379 system_color: SystemColor,
380 color_scheme_flags: ColorSchemeFlags,
381 ) -> AbsoluteColor {
382 fn srgb(r: u8, g: u8, b: u8) -> AbsoluteColor {
383 AbsoluteColor::srgb_legacy(r, g, b, 1f32)
384 }
385
386 if self.is_dark_color_scheme(color_scheme_flags) {
389 match system_color {
390 SystemColor::Accentcolor => srgb(10, 132, 255),
391 SystemColor::Accentcolortext => srgb(255, 255, 255),
392 SystemColor::Activetext => srgb(255, 0, 0),
393 SystemColor::Linktext => srgb(158, 158, 255),
394 SystemColor::Visitedtext => srgb(208, 173, 240),
395 SystemColor::Buttonborder
396 | SystemColor::Activeborder
398 | SystemColor::Inactiveborder
399 | SystemColor::Threeddarkshadow
400 | SystemColor::Threedshadow
401 | SystemColor::Windowframe => srgb(255, 255, 255),
402 SystemColor::Buttonface
403 | SystemColor::Buttonhighlight
405 | SystemColor::Buttonshadow
406 | SystemColor::Threedface
407 | SystemColor::Threedhighlight
408 | SystemColor::Threedlightshadow => srgb(107, 107, 107),
409 SystemColor::Buttontext => srgb(245, 245, 245),
410 SystemColor::Canvas
411 | SystemColor::Activecaption
413 | SystemColor::Appworkspace
414 | SystemColor::Background
415 | SystemColor::Inactivecaption
416 | SystemColor::Infobackground
417 | SystemColor::Menu
418 | SystemColor::Scrollbar
419 | SystemColor::Window => srgb(30, 30, 30),
420 SystemColor::Canvastext
421 | SystemColor::Captiontext
423 | SystemColor::Infotext
424 | SystemColor::Menutext
425 | SystemColor::Windowtext => srgb(232, 232, 232),
426 SystemColor::Field => srgb(45, 45, 45),
427 SystemColor::Fieldtext => srgb(240, 240, 240),
428 SystemColor::Graytext
429 | SystemColor::Inactivecaptiontext => srgb(155, 155, 155),
431 SystemColor::Highlight => srgb(38, 79, 120),
432 SystemColor::Highlighttext => srgb(255, 255, 255),
433 SystemColor::Mark => srgb(102, 92, 0),
434 SystemColor::Marktext => srgb(255, 255, 255),
435 SystemColor::Selecteditem => srgb(153, 200, 255),
436 SystemColor::Selecteditemtext => srgb(59, 59, 59),
437 }
438 } else {
439 match system_color {
440 SystemColor::Accentcolor => srgb(0, 102, 204),
441 SystemColor::Accentcolortext => srgb(255, 255, 255),
442 SystemColor::Activetext => srgb(238, 0, 0),
443 SystemColor::Linktext => srgb(0, 0, 238),
444 SystemColor::Visitedtext => srgb(85, 26, 139),
445 SystemColor::Buttonborder
446 | SystemColor::Activeborder
448 | SystemColor::Inactiveborder
449 | SystemColor::Threeddarkshadow
450 | SystemColor::Threedshadow
451 | SystemColor::Windowframe => srgb(169, 169, 169),
452 SystemColor::Buttonface
453 | SystemColor::Buttonhighlight
455 | SystemColor::Buttonshadow
456 | SystemColor::Threedface
457 | SystemColor::Threedhighlight
458 | SystemColor::Threedlightshadow => srgb(220, 220, 220),
459 SystemColor::Buttontext => srgb(0, 0, 0),
460 SystemColor::Canvas
461 | SystemColor::Activecaption
463 | SystemColor::Appworkspace
464 | SystemColor::Background
465 | SystemColor::Inactivecaption
466 | SystemColor::Infobackground
467 | SystemColor::Menu
468 | SystemColor::Scrollbar
469 | SystemColor::Window => srgb(255, 255, 255),
470 SystemColor::Canvastext
471 | SystemColor::Captiontext
473 | SystemColor::Infotext
474 | SystemColor::Menutext
475 | SystemColor::Windowtext => srgb(0, 0, 0),
476 SystemColor::Field => srgb(255, 255, 255),
477 SystemColor::Fieldtext => srgb(0, 0, 0),
478 SystemColor::Graytext
479 | SystemColor::Inactivecaptiontext => srgb(109, 109, 109),
481 SystemColor::Highlight => srgb(0, 65, 198),
482 SystemColor::Highlighttext => srgb(0, 0, 0),
483 SystemColor::Mark => srgb(255, 235, 59),
484 SystemColor::Marktext => srgb(0, 0, 0),
485 SystemColor::Selecteditem => srgb(0, 102, 204),
486 SystemColor::Selecteditemtext => srgb(255, 255, 255),
487 }
488 }
489 }
490
491 #[inline]
493 pub(super) fn text_zoom(&self) -> f32 {
494 1.
496 }
497
498 pub fn safe_area_insets(&self) -> SideOffsets2D<f32, CSSPixel> {
500 SideOffsets2D::zero()
501 }
502
503 pub fn is_supported_mime_type(&self, mime_type: &str) -> bool {
505 match mime_type.parse::<Mime>() {
506 Ok(m) => {
507 m == mime::IMAGE_BMP
510 || m == mime::IMAGE_GIF
511 || m == mime::IMAGE_PNG
512 || m == mime::IMAGE_JPEG
513 || m == "image/x-icon"
514 || m == "image/webp"
515 },
516 _ => false,
517 }
518 }
519
520 #[inline]
522 pub fn chrome_rules_enabled_for_document(&self) -> bool {
523 false
524 }
525
526 #[inline]
529 pub fn link_parameters(&self) -> Option<&LinkParameters> {
530 None
531 }
532}