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::servo::media_features::PointerCapabilities;
17use crate::values::computed::font::GenericFontFamily;
18use crate::values::computed::{
19 CSSPixelLength, Length, LineHeight, LinkParameters, NonNegativeLength,
20};
21use crate::values::specified::color::{ColorSchemeFlags, ForcedColors, SystemColor};
22use crate::values::specified::font::{
23 QueryFontMetricsFlags, FONT_MEDIUM_CAP_PX, FONT_MEDIUM_CH_PX, FONT_MEDIUM_EX_PX,
24 FONT_MEDIUM_IC_PX, FONT_MEDIUM_LINE_HEIGHT_PX, FONT_MEDIUM_PX,
25};
26use crate::values::specified::ViewportVariant;
27use crate::values::KeyframesName;
28use app_units::{Au, AU_PER_PX};
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_type: MediaType,
60 viewport_size: Size2D<f32, CSSPixel>,
62 device_size: Size2D<f32, DevicePixel>,
64 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
66 #[ignore_malloc_size_of = "Pure stack type"]
68 quirks_mode: QuirksMode,
69 #[ignore_malloc_size_of = "Pure stack type"]
71 prefers_color_scheme: PrefersColorScheme,
72 #[ignore_malloc_size_of = "Pure stack type"]
74 primary_pointer_capabilities: PointerCapabilities,
75 #[ignore_malloc_size_of = "Pure stack type"]
77 all_pointer_capabilities: PointerCapabilities,
78 #[ignore_malloc_size_of = "Owned by embedder"]
80 font_metrics_provider: Box<dyn FontMetricsProvider>,
81}
82
83impl Device {
84 pub fn new(
86 media_type: MediaType,
87 quirks_mode: QuirksMode,
88 viewport_size: Size2D<f32, CSSPixel>,
89 device_size: Size2D<f32, DevicePixel>,
90 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
91 font_metrics_provider: Box<dyn FontMetricsProvider>,
92 default_values: Arc<ComputedValues>,
93 prefers_color_scheme: PrefersColorScheme,
94 primary_pointer_capabilities: PointerCapabilities,
95 all_pointer_capabilities: PointerCapabilities,
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: AtomicU32::new(AbsoluteColor::BLACK.to_nscolor()),
115 extra: ExtraDeviceData {
116 media_type,
117 viewport_size,
118 device_size,
119 device_pixel_ratio,
120 quirks_mode,
121 prefers_color_scheme,
122 primary_pointer_capabilities,
123 all_pointer_capabilities,
124 font_metrics_provider,
125 },
126 }
127 }
128
129 pub fn calc_line_height(
133 &self,
134 font: &crate::properties::style_structs::Font,
135 _writing_mode: WritingMode,
136 _element: Option<()>,
137 ) -> NonNegativeLength {
138 (match font.line_height {
139 LineHeight::Normal => CSSPixelLength::new(0.),
141 LineHeight::Number(number) => font.font_size.computed_size() * number.0,
142 LineHeight::Length(length) => length.0,
143 })
144 .into()
145 }
146
147 pub fn quirks_mode(&self) -> QuirksMode {
149 self.extra.quirks_mode
150 }
151
152 pub fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length {
154 self.extra
155 .font_metrics_provider
156 .base_size_for_generic(generic)
157 }
158
159 pub fn animation_name_may_be_referenced(&self, _: &KeyframesName) -> bool {
161 true
163 }
164
165 pub fn viewport_size(&self) -> Size2D<f32, CSSPixel> {
167 self.extra.viewport_size
168 }
169
170 pub fn set_viewport_size(&mut self, viewport_size: Size2D<f32, CSSPixel>) {
176 self.extra.viewport_size = viewport_size;
177 }
178
179 #[inline]
182 pub fn au_viewport_size(&self) -> UntypedSize2D<Au> {
183 Size2D::new(
184 Au::from_f32_px(self.extra.viewport_size.width),
185 Au::from_f32_px(self.extra.viewport_size.height),
186 )
187 }
188
189 pub fn au_viewport_size_for_viewport_unit_resolution(
191 &self,
192 _: ViewportVariant,
193 ) -> UntypedSize2D<Au> {
194 self.used_viewport_size.store(true, Ordering::Relaxed);
195 self.au_viewport_size()
198 }
199
200 pub fn app_units_per_device_pixel(&self) -> i32 {
202 (AU_PER_PX as f32 / self.extra.device_pixel_ratio.0) as i32
203 }
204
205 pub fn device_pixel_ratio_ignoring_full_zoom(&self) -> Scale<f32, CSSPixel, DevicePixel> {
207 self.extra.device_pixel_ratio
208 }
209
210 pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
212 self.extra.device_pixel_ratio
213 }
214
215 pub fn set_device_pixel_ratio(
221 &mut self,
222 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
223 ) {
224 self.extra.device_pixel_ratio = device_pixel_ratio;
225 }
226
227 pub fn set_device_size(&mut self, device_size: Size2D<f32, DevicePixel>) {
233 self.extra.device_size = device_size;
234 }
235
236 #[inline]
238 pub fn device_size(&self) -> Size2D<f32, DevicePixel> {
239 self.extra.device_size
240 }
241
242 pub fn scrollbar_inline_size(&self) -> CSSPixelLength {
244 CSSPixelLength::new(0.0)
246 }
247
248 pub fn query_font_metrics(
250 &self,
251 vertical: bool,
252 font: &Font,
253 base_size: CSSPixelLength,
254 flags: QueryFontMetricsFlags,
255 track_usage: bool,
256 ) -> FontMetrics {
257 if track_usage {
258 self.used_font_metrics.store(true, Ordering::Relaxed);
259 }
260 self.extra
261 .font_metrics_provider
262 .query_font_metrics(vertical, font, base_size, flags)
263 }
264
265 pub fn set_media_type(&mut self, media_type: MediaType) {
271 self.extra.media_type = media_type;
272 }
273
274 pub fn media_type(&self) -> MediaType {
276 self.extra.media_type.clone()
277 }
278
279 pub fn forced_colors(&self) -> ForcedColors {
281 ForcedColors::None
282 }
283
284 pub fn default_background_color(&self) -> AbsoluteColor {
286 AbsoluteColor::WHITE
287 }
288
289 pub fn default_color(&self) -> AbsoluteColor {
291 AbsoluteColor::BLACK
292 }
293
294 pub fn set_color_scheme(&mut self, new_color_scheme: PrefersColorScheme) {
300 self.extra.prefers_color_scheme = new_color_scheme;
301 }
302
303 pub fn color_scheme(&self) -> PrefersColorScheme {
305 self.extra.prefers_color_scheme
306 }
307
308 pub fn set_primary_pointer_capabilities(&mut self, capabilities: PointerCapabilities) {
314 self.extra.primary_pointer_capabilities = capabilities;
315 }
316
317 pub fn primary_pointer_capabilities(&self) -> PointerCapabilities {
319 self.extra.primary_pointer_capabilities
320 }
321
322 pub fn set_all_pointer_capabilities(&mut self, capabilities: PointerCapabilities) {
328 self.extra.all_pointer_capabilities = capabilities;
329 }
330
331 pub fn all_pointer_capabilities(&self) -> PointerCapabilities {
333 self.extra.all_pointer_capabilities
334 }
335
336 pub(crate) fn is_dark_color_scheme(&self, _: ColorSchemeFlags) -> bool {
337 false
338 }
339
340 pub(crate) fn system_color(
341 &self,
342 system_color: SystemColor,
343 color_scheme_flags: ColorSchemeFlags,
344 ) -> AbsoluteColor {
345 fn srgb(r: u8, g: u8, b: u8) -> AbsoluteColor {
346 AbsoluteColor::srgb_legacy(r, g, b, 1f32)
347 }
348
349 if self.is_dark_color_scheme(color_scheme_flags) {
352 match system_color {
354 SystemColor::Accentcolor => srgb(10, 132, 255),
355 SystemColor::Accentcolortext => srgb(255, 255, 255),
356 SystemColor::Activetext => srgb(255, 0, 0),
357 SystemColor::Linktext => srgb(158, 158, 255),
358 SystemColor::Visitedtext => srgb(208, 173, 240),
359 SystemColor::Buttonborder
360 | SystemColor::Activeborder
362 | SystemColor::Inactiveborder
363 | SystemColor::Threeddarkshadow
364 | SystemColor::Threedshadow
365 | SystemColor::Windowframe => srgb(255, 255, 255),
366 SystemColor::Buttonface
367 | SystemColor::Buttonhighlight
369 | SystemColor::Buttonshadow
370 | SystemColor::Threedface
371 | SystemColor::Threedhighlight
372 | SystemColor::Threedlightshadow => srgb(107, 107, 107),
373 SystemColor::Buttontext => srgb(245, 245, 245),
374 SystemColor::Canvas
375 | SystemColor::Activecaption
377 | SystemColor::Appworkspace
378 | SystemColor::Background
379 | SystemColor::Inactivecaption
380 | SystemColor::Infobackground
381 | SystemColor::Menu
382 | SystemColor::Scrollbar
383 | SystemColor::Window => srgb(30, 30, 30),
384 SystemColor::Canvastext
385 | SystemColor::Captiontext
387 | SystemColor::Infotext
388 | SystemColor::Menutext
389 | SystemColor::Windowtext => srgb(232, 232, 232),
390 SystemColor::Field => srgb(45, 45, 45),
391 SystemColor::Fieldtext => srgb(240, 240, 240),
392 SystemColor::Graytext
393 | SystemColor::Inactivecaptiontext => srgb(155, 155, 155),
395 SystemColor::Highlight => srgb(38, 79, 120),
396 SystemColor::Highlighttext => srgb(255, 255, 255),
397 SystemColor::Mark => srgb(102, 92, 0),
398 SystemColor::Marktext => srgb(255, 255, 255),
399 SystemColor::Selecteditem => srgb(153, 200, 255),
400 SystemColor::Selecteditemtext => srgb(59, 59, 59),
401 }
402 } else {
403 match system_color {
404 SystemColor::Accentcolor => srgb(0, 102, 204),
405 SystemColor::Accentcolortext => srgb(255, 255, 255),
406 SystemColor::Activetext => srgb(238, 0, 0),
407 SystemColor::Linktext => srgb(0, 0, 238),
408 SystemColor::Visitedtext => srgb(85, 26, 139),
409 SystemColor::Buttonborder
410 | SystemColor::Activeborder
412 | SystemColor::Inactiveborder
413 | SystemColor::Threeddarkshadow
414 | SystemColor::Threedshadow
415 | SystemColor::Windowframe => srgb(169, 169, 169),
416 SystemColor::Buttonface
417 | SystemColor::Buttonhighlight
419 | SystemColor::Buttonshadow
420 | SystemColor::Threedface
421 | SystemColor::Threedhighlight
422 | SystemColor::Threedlightshadow => srgb(220, 220, 220),
423 SystemColor::Buttontext => srgb(0, 0, 0),
424 SystemColor::Canvas
425 | SystemColor::Activecaption
427 | SystemColor::Appworkspace
428 | SystemColor::Background
429 | SystemColor::Inactivecaption
430 | SystemColor::Infobackground
431 | SystemColor::Menu
432 | SystemColor::Scrollbar
433 | SystemColor::Window => srgb(255, 255, 255),
434 SystemColor::Canvastext
435 | SystemColor::Captiontext
437 | SystemColor::Infotext
438 | SystemColor::Menutext
439 | SystemColor::Windowtext => srgb(0, 0, 0),
440 SystemColor::Field => srgb(255, 255, 255),
441 SystemColor::Fieldtext => srgb(0, 0, 0),
442 SystemColor::Graytext
443 | SystemColor::Inactivecaptiontext => srgb(109, 109, 109),
445 SystemColor::Highlight => srgb(0, 65, 198),
446 SystemColor::Highlighttext => srgb(0, 0, 0),
447 SystemColor::Mark => srgb(255, 235, 59),
448 SystemColor::Marktext => srgb(0, 0, 0),
449 SystemColor::Selecteditem => srgb(0, 102, 204),
450 SystemColor::Selecteditemtext => srgb(255, 255, 255),
451 }
452 }
453 }
454
455 #[inline]
457 pub(super) fn text_zoom(&self) -> f32 {
458 1.
460 }
461
462 pub fn safe_area_insets(&self) -> SideOffsets2D<f32, CSSPixel> {
464 SideOffsets2D::zero()
465 }
466
467 pub fn is_supported_mime_type(&self, mime_type: &str) -> bool {
469 match mime_type.parse::<Mime>() {
470 Ok(m) => {
471 m == mime::IMAGE_BMP
474 || m == mime::IMAGE_GIF
475 || m == mime::IMAGE_PNG
476 || m == mime::IMAGE_JPEG
477 || m == "image/x-icon"
478 || m == "image/webp"
479 },
480 _ => false,
481 }
482 }
483
484 #[inline]
486 pub fn chrome_rules_enabled_for_document(&self) -> bool {
487 false
488 }
489
490 #[inline]
493 pub fn link_parameters(&self) -> Option<&LinkParameters> {
494 None
495 }
496}