1use crate::color::AbsoluteColor;
8use crate::context::QuirksMode;
9use crate::substitution::env::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::hash::{DefaultHasher, Hasher};
37use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
38use style_traits::{CSSPixel, DevicePixel};
39
40use crate::device::Device;
41
42pub trait FontMetricsProvider: Debug + Sync {
45 fn query_font_metrics(
47 &self,
48 vertical: bool,
49 font: &Font,
50 base_size: CSSPixelLength,
51 flags: QueryFontMetricsFlags,
52 ) -> FontMetrics;
53 fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length;
55}
56
57#[derive(Debug, MallocSizeOf)]
58pub(super) struct ExtraDeviceData {
59 media_data: MediaData,
61 #[ignore_malloc_size_of = "Owned by embedder"]
63 font_metrics_provider: Box<dyn FontMetricsProvider>,
64}
65
66#[derive(Debug, MallocSizeOf, Clone, PartialEq)]
67pub struct MediaData {
69 pub media_type: MediaType,
71 pub viewport_size: Size2D<f32, CSSPixel>,
73 pub device_size: Size2D<f32, DevicePixel>,
75 pub device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
77 #[ignore_malloc_size_of = "Pure stack type"]
79 pub quirks_mode: QuirksMode,
80 #[ignore_malloc_size_of = "Pure stack type"]
82 pub prefers_color_scheme: PrefersColorScheme,
83 #[ignore_malloc_size_of = "Pure stack type"]
85 pub primary_pointer_capabilities: PointerCapabilities,
86 #[ignore_malloc_size_of = "Pure stack type"]
88 pub all_pointer_capabilities: PointerCapabilities,
89}
90
91impl Device {
92 pub fn new(
94 default_values: Arc<ComputedValues>,
95 font_metrics_provider: Box<dyn FontMetricsProvider>,
96 submit_string: Box<str>,
97 media_data: MediaData,
98 ) -> Device {
99 let root_style = RwLock::new(Arc::clone(&default_values));
100 Device {
101 root_style,
102 root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()),
103 root_line_height: AtomicU32::new(FONT_MEDIUM_LINE_HEIGHT_PX.to_bits()),
104 root_font_metrics_ex: AtomicU32::new(FONT_MEDIUM_EX_PX.to_bits()),
105 root_font_metrics_cap: AtomicU32::new(FONT_MEDIUM_CAP_PX.to_bits()),
106 root_font_metrics_ch: AtomicU32::new(FONT_MEDIUM_CH_PX.to_bits()),
107 root_font_metrics_ic: AtomicU32::new(FONT_MEDIUM_IC_PX.to_bits()),
108 used_root_font_size: AtomicBool::new(false),
109 used_root_line_height: AtomicBool::new(false),
110 used_root_font_metrics: RwLock::new(false),
111 used_font_metrics: AtomicBool::new(false),
112 used_viewport_size: AtomicBool::new(false),
113 used_dynamic_viewport_size: AtomicBool::new(false),
114 environment: CssEnvironment,
115 default_values,
116 body_text_color: RwLock::new(AbsoluteColor::BLACK),
117 submit_string,
118 extra: ExtraDeviceData {
119 media_data,
120 font_metrics_provider,
121 },
122 }
123 }
124
125 pub fn calc_line_height(
129 &self,
130 font: &crate::properties::style_structs::Font,
131 _writing_mode: WritingMode,
132 _element: Option<()>,
133 ) -> NonNegativeLength {
134 (match font.line_height {
135 LineHeight::Normal => CSSPixelLength::new(0.),
137 LineHeight::Number(number) => font.font_size.computed_size() * number.0,
138 LineHeight::Length(length) => length.0,
139 })
140 .into()
141 }
142
143 pub fn quirks_mode(&self) -> QuirksMode {
145 self.extra.media_data.quirks_mode
146 }
147
148 #[inline]
151 pub fn document_random_hasher(&self) -> impl Hasher {
152 DefaultHasher::new()
154 }
155
156 pub fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length {
158 self.extra
159 .font_metrics_provider
160 .base_size_for_generic(generic)
161 }
162
163 pub fn animation_name_may_be_referenced(&self, _: &KeyframesName) -> bool {
165 true
167 }
168
169 #[inline]
171 pub fn media_data(&self) -> &MediaData {
172 &self.extra.media_data
173 }
174
175 pub fn media_data_mut(&mut self) -> &mut MediaData {
181 &mut self.extra.media_data
182 }
183
184 pub fn set_media_data(&mut self, media_data: MediaData) {
190 self.extra.media_data = media_data;
191 }
192
193 pub fn viewport_size(&self) -> Size2D<f32, CSSPixel> {
195 self.extra.media_data.viewport_size
196 }
197
198 pub fn set_viewport_size(&mut self, viewport_size: Size2D<f32, CSSPixel>) {
204 self.extra.media_data.viewport_size = viewport_size;
205 }
206
207 #[inline]
210 pub fn au_viewport_size(&self) -> UntypedSize2D<Au> {
211 Size2D::new(
212 Au::from_f32_px(self.extra.media_data.viewport_size.width),
213 Au::from_f32_px(self.extra.media_data.viewport_size.height),
214 )
215 }
216
217 pub fn au_viewport_size_for_viewport_unit_resolution(
219 &self,
220 _: ViewportVariant,
221 ) -> UntypedSize2D<Au> {
222 self.used_viewport_size.store(true, Ordering::Relaxed);
223 self.au_viewport_size()
226 }
227
228 pub fn app_units_per_device_pixel(&self) -> i32 {
230 (AU_PER_PX as f32 / self.extra.media_data.device_pixel_ratio.0) as i32
231 }
232
233 pub fn device_pixel_ratio_ignoring_full_zoom(&self) -> Scale<f32, CSSPixel, DevicePixel> {
235 self.extra.media_data.device_pixel_ratio
236 }
237
238 pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
240 self.extra.media_data.device_pixel_ratio
241 }
242
243 pub fn set_device_pixel_ratio(
249 &mut self,
250 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
251 ) {
252 self.extra.media_data.device_pixel_ratio = device_pixel_ratio;
253 }
254
255 pub fn set_device_size(&mut self, device_size: Size2D<f32, DevicePixel>) {
261 self.extra.media_data.device_size = device_size;
262 }
263
264 #[inline]
266 pub fn device_size(&self) -> Size2D<f32, DevicePixel> {
267 self.extra.media_data.device_size
268 }
269
270 pub fn scrollbar_inline_size(&self) -> CSSPixelLength {
272 CSSPixelLength::new(0.0)
274 }
275
276 pub fn query_font_metrics(
278 &self,
279 vertical: bool,
280 font: &Font,
281 base_size: CSSPixelLength,
282 flags: QueryFontMetricsFlags,
283 track_usage: bool,
284 ) -> FontMetrics {
285 if track_usage {
286 self.used_font_metrics.store(true, Ordering::Relaxed);
287 }
288 self.extra
289 .font_metrics_provider
290 .query_font_metrics(vertical, font, base_size, flags)
291 }
292
293 pub fn set_media_type(&mut self, media_type: MediaType) {
299 self.extra.media_data.media_type = media_type;
300 }
301
302 pub fn media_type(&self) -> MediaType {
304 self.extra.media_data.media_type.clone()
305 }
306
307 pub fn forced_colors(&self) -> ForcedColors {
309 ForcedColors::None
310 }
311
312 pub fn default_background_color(&self) -> AbsoluteColor {
314 AbsoluteColor::WHITE
315 }
316
317 pub fn default_color(&self) -> AbsoluteColor {
319 AbsoluteColor::BLACK
320 }
321
322 pub fn set_color_scheme(&mut self, new_color_scheme: PrefersColorScheme) {
328 self.extra.media_data.prefers_color_scheme = new_color_scheme;
329 }
330
331 pub fn color_scheme(&self) -> PrefersColorScheme {
333 self.extra.media_data.prefers_color_scheme
334 }
335
336 pub fn set_primary_pointer_capabilities(&mut self, capabilities: PointerCapabilities) {
342 self.extra.media_data.primary_pointer_capabilities = capabilities;
343 }
344
345 pub fn primary_pointer_capabilities(&self) -> PointerCapabilities {
347 self.extra.media_data.primary_pointer_capabilities
348 }
349
350 pub fn set_all_pointer_capabilities(&mut self, capabilities: PointerCapabilities) {
356 self.extra.media_data.all_pointer_capabilities = capabilities;
357 }
358
359 pub fn all_pointer_capabilities(&self) -> PointerCapabilities {
361 self.extra.media_data.all_pointer_capabilities
362 }
363
364 pub(crate) fn is_dark_color_scheme(&self, color_scheme_flags: ColorSchemeFlags) -> bool {
365 let supports_dark_mode = color_scheme_flags.contains(ColorSchemeFlags::DARK);
368 let supports_light_mode = color_scheme_flags.contains(ColorSchemeFlags::LIGHT);
369
370 if supports_dark_mode != supports_light_mode {
372 return supports_dark_mode;
373 }
374
375 return self.color_scheme() == PrefersColorScheme::Dark;
378 }
379
380 pub(crate) fn system_color(
381 &self,
382 system_color: SystemColor,
383 color_scheme_flags: ColorSchemeFlags,
384 ) -> AbsoluteColor {
385 fn srgb(r: u8, g: u8, b: u8) -> AbsoluteColor {
386 AbsoluteColor::srgb_legacy(r, g, b, 1f32)
387 }
388
389 if self.is_dark_color_scheme(color_scheme_flags) {
392 match system_color {
393 SystemColor::Accentcolor => srgb(10, 132, 255),
394 SystemColor::Accentcolortext => srgb(255, 255, 255),
395 SystemColor::Activetext => srgb(255, 0, 0),
396 SystemColor::Linktext => srgb(158, 158, 255),
397 SystemColor::Visitedtext => srgb(208, 173, 240),
398 SystemColor::Buttonborder
399 | SystemColor::Activeborder
401 | SystemColor::Inactiveborder
402 | SystemColor::Threeddarkshadow
403 | SystemColor::Threedshadow
404 | SystemColor::Windowframe => srgb(255, 255, 255),
405 SystemColor::Buttonface
406 | SystemColor::Buttonhighlight
408 | SystemColor::Buttonshadow
409 | SystemColor::Threedface
410 | SystemColor::Threedhighlight
411 | SystemColor::Threedlightshadow => srgb(107, 107, 107),
412 SystemColor::Buttontext => srgb(245, 245, 245),
413 SystemColor::Canvas
414 | SystemColor::Activecaption
416 | SystemColor::Appworkspace
417 | SystemColor::Background
418 | SystemColor::Inactivecaption
419 | SystemColor::Infobackground
420 | SystemColor::Menu
421 | SystemColor::Scrollbar
422 | SystemColor::Window => srgb(30, 30, 30),
423 SystemColor::Canvastext
424 | SystemColor::Captiontext
426 | SystemColor::Infotext
427 | SystemColor::Menutext
428 | SystemColor::Windowtext => srgb(232, 232, 232),
429 SystemColor::Field => srgb(45, 45, 45),
430 SystemColor::Fieldtext => srgb(240, 240, 240),
431 SystemColor::Graytext
432 | SystemColor::Inactivecaptiontext => srgb(155, 155, 155),
434 SystemColor::Highlight => srgb(38, 79, 120),
435 SystemColor::Highlighttext => srgb(255, 255, 255),
436 SystemColor::Mark => srgb(102, 92, 0),
437 SystemColor::Marktext => srgb(255, 255, 255),
438 SystemColor::Selecteditem => srgb(153, 200, 255),
439 SystemColor::Selecteditemtext => srgb(59, 59, 59),
440 }
441 } else {
442 match system_color {
443 SystemColor::Accentcolor => srgb(0, 102, 204),
444 SystemColor::Accentcolortext => srgb(255, 255, 255),
445 SystemColor::Activetext => srgb(238, 0, 0),
446 SystemColor::Linktext => srgb(0, 0, 238),
447 SystemColor::Visitedtext => srgb(85, 26, 139),
448 SystemColor::Buttonborder
449 | SystemColor::Activeborder
451 | SystemColor::Inactiveborder
452 | SystemColor::Threeddarkshadow
453 | SystemColor::Threedshadow
454 | SystemColor::Windowframe => srgb(169, 169, 169),
455 SystemColor::Buttonface
456 | SystemColor::Buttonhighlight
458 | SystemColor::Buttonshadow
459 | SystemColor::Threedface
460 | SystemColor::Threedhighlight
461 | SystemColor::Threedlightshadow => srgb(220, 220, 220),
462 SystemColor::Buttontext => srgb(0, 0, 0),
463 SystemColor::Canvas
464 | SystemColor::Activecaption
466 | SystemColor::Appworkspace
467 | SystemColor::Background
468 | SystemColor::Inactivecaption
469 | SystemColor::Infobackground
470 | SystemColor::Menu
471 | SystemColor::Scrollbar
472 | SystemColor::Window => srgb(255, 255, 255),
473 SystemColor::Canvastext
474 | SystemColor::Captiontext
476 | SystemColor::Infotext
477 | SystemColor::Menutext
478 | SystemColor::Windowtext => srgb(0, 0, 0),
479 SystemColor::Field => srgb(255, 255, 255),
480 SystemColor::Fieldtext => srgb(0, 0, 0),
481 SystemColor::Graytext
482 | SystemColor::Inactivecaptiontext => srgb(109, 109, 109),
484 SystemColor::Highlight => srgb(0, 65, 198),
485 SystemColor::Highlighttext => srgb(0, 0, 0),
486 SystemColor::Mark => srgb(255, 235, 59),
487 SystemColor::Marktext => srgb(0, 0, 0),
488 SystemColor::Selecteditem => srgb(0, 102, 204),
489 SystemColor::Selecteditemtext => srgb(255, 255, 255),
490 }
491 }
492 }
493
494 #[inline]
496 pub(super) fn text_zoom(&self) -> f32 {
497 1.
499 }
500
501 pub fn safe_area_insets(&self) -> SideOffsets2D<f32, CSSPixel> {
503 SideOffsets2D::zero()
504 }
505
506 pub fn is_supported_mime_type(&self, mime_type: &str) -> bool {
508 match mime_type.parse::<Mime>() {
509 Ok(m) => {
510 m == mime::IMAGE_BMP
513 || m == mime::IMAGE_GIF
514 || m == mime::IMAGE_PNG
515 || m == mime::IMAGE_JPEG
516 || m == "image/x-icon"
517 || m == "image/webp"
518 },
519 _ => false,
520 }
521 }
522
523 #[inline]
525 pub fn chrome_rules_enabled_for_document(&self) -> bool {
526 false
527 }
528
529 #[inline]
532 pub fn link_parameters(&self) -> Option<&LinkParameters> {
533 None
534 }
535}