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::{CSSPixelLength, Length, LineHeight, NonNegativeLength};
19use crate::values::specified::color::{ColorSchemeFlags, ForcedColors, SystemColor};
20use crate::values::specified::font::{
21 QueryFontMetricsFlags, FONT_MEDIUM_CAP_PX, FONT_MEDIUM_CH_PX, FONT_MEDIUM_EX_PX,
22 FONT_MEDIUM_IC_PX, FONT_MEDIUM_LINE_HEIGHT_PX, FONT_MEDIUM_PX,
23};
24use crate::values::specified::ViewportVariant;
25use crate::values::KeyframesName;
26use app_units::{Au, AU_PER_PX};
27use euclid::default::Size2D as UntypedSize2D;
28use euclid::{Scale, SideOffsets2D, Size2D};
29use malloc_size_of_derive::MallocSizeOf;
30use mime::Mime;
31use parking_lot::RwLock;
32use servo_arc::Arc;
33use std::fmt::Debug;
34use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
35use style_traits::{CSSPixel, DevicePixel};
36
37use crate::device::Device;
38
39pub trait FontMetricsProvider: Debug + Sync {
42 fn query_font_metrics(
44 &self,
45 vertical: bool,
46 font: &Font,
47 base_size: CSSPixelLength,
48 flags: QueryFontMetricsFlags,
49 ) -> FontMetrics;
50 fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length;
52}
53
54#[derive(Debug, MallocSizeOf)]
55pub(super) struct ExtraDeviceData {
56 media_type: MediaType,
58 viewport_size: Size2D<f32, CSSPixel>,
60 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
62 #[ignore_malloc_size_of = "Pure stack type"]
64 quirks_mode: QuirksMode,
65 #[ignore_malloc_size_of = "Pure stack type"]
67 prefers_color_scheme: PrefersColorScheme,
68 #[ignore_malloc_size_of = "Pure stack type"]
70 primary_pointer_capabilities: PointerCapabilities,
71 #[ignore_malloc_size_of = "Pure stack type"]
73 all_pointer_capabilities: PointerCapabilities,
74 #[ignore_malloc_size_of = "Owned by embedder"]
76 font_metrics_provider: Box<dyn FontMetricsProvider>,
77}
78
79impl Device {
80 pub fn new(
82 media_type: MediaType,
83 quirks_mode: QuirksMode,
84 viewport_size: Size2D<f32, CSSPixel>,
85 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
86 font_metrics_provider: Box<dyn FontMetricsProvider>,
87 default_values: Arc<ComputedValues>,
88 prefers_color_scheme: PrefersColorScheme,
89 primary_pointer_capabilities: PointerCapabilities,
90 all_pointer_capabilities: PointerCapabilities,
91 ) -> Device {
92 let root_style = RwLock::new(Arc::clone(&default_values));
93 Device {
94 root_style,
95 root_font_size: AtomicU32::new(FONT_MEDIUM_PX.to_bits()),
96 root_line_height: AtomicU32::new(FONT_MEDIUM_LINE_HEIGHT_PX.to_bits()),
97 root_font_metrics_ex: AtomicU32::new(FONT_MEDIUM_EX_PX.to_bits()),
98 root_font_metrics_cap: AtomicU32::new(FONT_MEDIUM_CAP_PX.to_bits()),
99 root_font_metrics_ch: AtomicU32::new(FONT_MEDIUM_CH_PX.to_bits()),
100 root_font_metrics_ic: AtomicU32::new(FONT_MEDIUM_IC_PX.to_bits()),
101 used_root_font_size: AtomicBool::new(false),
102 used_root_line_height: AtomicBool::new(false),
103 used_root_font_metrics: RwLock::new(false),
104 used_font_metrics: AtomicBool::new(false),
105 used_viewport_size: AtomicBool::new(false),
106 used_dynamic_viewport_size: AtomicBool::new(false),
107 environment: CssEnvironment,
108 default_values,
109 body_text_color: AtomicU32::new(AbsoluteColor::BLACK.to_nscolor()),
110 extra: ExtraDeviceData {
111 media_type,
112 viewport_size,
113 device_pixel_ratio,
114 quirks_mode,
115 prefers_color_scheme,
116 primary_pointer_capabilities,
117 all_pointer_capabilities,
118 font_metrics_provider,
119 },
120 }
121 }
122
123 pub fn calc_line_height(
127 &self,
128 font: &crate::properties::style_structs::Font,
129 _writing_mode: WritingMode,
130 _element: Option<()>,
131 ) -> NonNegativeLength {
132 (match font.line_height {
133 LineHeight::Normal => CSSPixelLength::new(0.),
135 LineHeight::Number(number) => font.font_size.computed_size() * number.0,
136 LineHeight::Length(length) => length.0,
137 })
138 .into()
139 }
140
141 pub fn quirks_mode(&self) -> QuirksMode {
143 self.extra.quirks_mode
144 }
145
146 pub fn base_size_for_generic(&self, generic: GenericFontFamily) -> Length {
148 self.extra
149 .font_metrics_provider
150 .base_size_for_generic(generic)
151 }
152
153 pub fn animation_name_may_be_referenced(&self, _: &KeyframesName) -> bool {
155 true
157 }
158
159 pub fn viewport_size(&self) -> Size2D<f32, CSSPixel> {
161 self.extra.viewport_size
162 }
163
164 pub fn set_viewport_size(&mut self, viewport_size: Size2D<f32, CSSPixel>) {
170 self.extra.viewport_size = viewport_size;
171 }
172
173 #[inline]
176 pub fn au_viewport_size(&self) -> UntypedSize2D<Au> {
177 Size2D::new(
178 Au::from_f32_px(self.extra.viewport_size.width),
179 Au::from_f32_px(self.extra.viewport_size.height),
180 )
181 }
182
183 pub fn au_viewport_size_for_viewport_unit_resolution(
185 &self,
186 _: ViewportVariant,
187 ) -> UntypedSize2D<Au> {
188 self.used_viewport_size.store(true, Ordering::Relaxed);
189 self.au_viewport_size()
192 }
193
194 pub fn app_units_per_device_pixel(&self) -> i32 {
196 (AU_PER_PX as f32 / self.extra.device_pixel_ratio.0) as i32
197 }
198
199 pub fn device_pixel_ratio_ignoring_full_zoom(&self) -> Scale<f32, CSSPixel, DevicePixel> {
201 self.extra.device_pixel_ratio
202 }
203
204 pub fn device_pixel_ratio(&self) -> Scale<f32, CSSPixel, DevicePixel> {
206 self.extra.device_pixel_ratio
207 }
208
209 pub fn set_device_pixel_ratio(
215 &mut self,
216 device_pixel_ratio: Scale<f32, CSSPixel, DevicePixel>,
217 ) {
218 self.extra.device_pixel_ratio = device_pixel_ratio;
219 }
220
221 pub fn scrollbar_inline_size(&self) -> CSSPixelLength {
223 CSSPixelLength::new(0.0)
225 }
226
227 pub fn query_font_metrics(
229 &self,
230 vertical: bool,
231 font: &Font,
232 base_size: CSSPixelLength,
233 flags: QueryFontMetricsFlags,
234 track_usage: bool,
235 ) -> FontMetrics {
236 if track_usage {
237 self.used_font_metrics.store(true, Ordering::Relaxed);
238 }
239 self.extra
240 .font_metrics_provider
241 .query_font_metrics(vertical, font, base_size, flags)
242 }
243
244 pub fn media_type(&self) -> MediaType {
246 self.extra.media_type.clone()
247 }
248
249 pub fn forced_colors(&self) -> ForcedColors {
251 ForcedColors::None
252 }
253
254 pub fn default_background_color(&self) -> AbsoluteColor {
256 AbsoluteColor::WHITE
257 }
258
259 pub fn default_color(&self) -> AbsoluteColor {
261 AbsoluteColor::BLACK
262 }
263
264 pub fn set_color_scheme(&mut self, new_color_scheme: PrefersColorScheme) {
270 self.extra.prefers_color_scheme = new_color_scheme;
271 }
272
273 pub fn color_scheme(&self) -> PrefersColorScheme {
275 self.extra.prefers_color_scheme
276 }
277
278 pub fn set_primary_pointer_capabilities(&mut self, capabilities: PointerCapabilities) {
284 self.extra.primary_pointer_capabilities = capabilities;
285 }
286
287 pub fn primary_pointer_capabilities(&self) -> PointerCapabilities {
289 self.extra.primary_pointer_capabilities
290 }
291
292 pub fn set_all_pointer_capabilities(&mut self, capabilities: PointerCapabilities) {
298 self.extra.all_pointer_capabilities = capabilities;
299 }
300
301 pub fn all_pointer_capabilities(&self) -> PointerCapabilities {
303 self.extra.all_pointer_capabilities
304 }
305
306 pub(crate) fn is_dark_color_scheme(&self, _: ColorSchemeFlags) -> bool {
307 false
308 }
309
310 pub(crate) fn system_color(
311 &self,
312 system_color: SystemColor,
313 color_scheme_flags: ColorSchemeFlags,
314 ) -> AbsoluteColor {
315 fn srgb(r: u8, g: u8, b: u8) -> AbsoluteColor {
316 AbsoluteColor::srgb_legacy(r, g, b, 1f32)
317 }
318
319 if self.is_dark_color_scheme(color_scheme_flags) {
322 match system_color {
324 SystemColor::Accentcolor => srgb(10, 132, 255),
325 SystemColor::Accentcolortext => srgb(255, 255, 255),
326 SystemColor::Activetext => srgb(255, 0, 0),
327 SystemColor::Linktext => srgb(158, 158, 255),
328 SystemColor::Visitedtext => srgb(208, 173, 240),
329 SystemColor::Buttonborder
330 | SystemColor::Activeborder
332 | SystemColor::Inactiveborder
333 | SystemColor::Threeddarkshadow
334 | SystemColor::Threedshadow
335 | SystemColor::Windowframe => srgb(255, 255, 255),
336 SystemColor::Buttonface
337 | SystemColor::Buttonhighlight
339 | SystemColor::Buttonshadow
340 | SystemColor::Threedface
341 | SystemColor::Threedhighlight
342 | SystemColor::Threedlightshadow => srgb(107, 107, 107),
343 SystemColor::Buttontext => srgb(245, 245, 245),
344 SystemColor::Canvas
345 | SystemColor::Activecaption
347 | SystemColor::Appworkspace
348 | SystemColor::Background
349 | SystemColor::Inactivecaption
350 | SystemColor::Infobackground
351 | SystemColor::Menu
352 | SystemColor::Scrollbar
353 | SystemColor::Window => srgb(30, 30, 30),
354 SystemColor::Canvastext
355 | SystemColor::Captiontext
357 | SystemColor::Infotext
358 | SystemColor::Menutext
359 | SystemColor::Windowtext => srgb(232, 232, 232),
360 SystemColor::Field => srgb(45, 45, 45),
361 SystemColor::Fieldtext => srgb(240, 240, 240),
362 SystemColor::Graytext
363 | SystemColor::Inactivecaptiontext => srgb(155, 155, 155),
365 SystemColor::Highlight => srgb(38, 79, 120),
366 SystemColor::Highlighttext => srgb(255, 255, 255),
367 SystemColor::Mark => srgb(102, 92, 0),
368 SystemColor::Marktext => srgb(255, 255, 255),
369 SystemColor::Selecteditem => srgb(153, 200, 255),
370 SystemColor::Selecteditemtext => srgb(59, 59, 59),
371 }
372 } else {
373 match system_color {
374 SystemColor::Accentcolor => srgb(0, 102, 204),
375 SystemColor::Accentcolortext => srgb(255, 255, 255),
376 SystemColor::Activetext => srgb(238, 0, 0),
377 SystemColor::Linktext => srgb(0, 0, 238),
378 SystemColor::Visitedtext => srgb(85, 26, 139),
379 SystemColor::Buttonborder
380 | SystemColor::Activeborder
382 | SystemColor::Inactiveborder
383 | SystemColor::Threeddarkshadow
384 | SystemColor::Threedshadow
385 | SystemColor::Windowframe => srgb(169, 169, 169),
386 SystemColor::Buttonface
387 | SystemColor::Buttonhighlight
389 | SystemColor::Buttonshadow
390 | SystemColor::Threedface
391 | SystemColor::Threedhighlight
392 | SystemColor::Threedlightshadow => srgb(220, 220, 220),
393 SystemColor::Buttontext => srgb(0, 0, 0),
394 SystemColor::Canvas
395 | SystemColor::Activecaption
397 | SystemColor::Appworkspace
398 | SystemColor::Background
399 | SystemColor::Inactivecaption
400 | SystemColor::Infobackground
401 | SystemColor::Menu
402 | SystemColor::Scrollbar
403 | SystemColor::Window => srgb(255, 255, 255),
404 SystemColor::Canvastext
405 | SystemColor::Captiontext
407 | SystemColor::Infotext
408 | SystemColor::Menutext
409 | SystemColor::Windowtext => srgb(0, 0, 0),
410 SystemColor::Field => srgb(255, 255, 255),
411 SystemColor::Fieldtext => srgb(0, 0, 0),
412 SystemColor::Graytext
413 | SystemColor::Inactivecaptiontext => srgb(109, 109, 109),
415 SystemColor::Highlight => srgb(0, 65, 198),
416 SystemColor::Highlighttext => srgb(0, 0, 0),
417 SystemColor::Mark => srgb(255, 235, 59),
418 SystemColor::Marktext => srgb(0, 0, 0),
419 SystemColor::Selecteditem => srgb(0, 102, 204),
420 SystemColor::Selecteditemtext => srgb(255, 255, 255),
421 }
422 }
423 }
424
425 pub fn safe_area_insets(&self) -> SideOffsets2D<f32, CSSPixel> {
427 SideOffsets2D::zero()
428 }
429
430 pub fn is_supported_mime_type(&self, mime_type: &str) -> bool {
432 match mime_type.parse::<Mime>() {
433 Ok(m) => {
434 m == mime::IMAGE_BMP
437 || m == mime::IMAGE_GIF
438 || m == mime::IMAGE_PNG
439 || m == mime::IMAGE_JPEG
440 || m == "image/x-icon"
441 || m == "image/webp"
442 },
443 _ => false,
444 }
445 }
446
447 #[inline]
449 pub fn chrome_rules_enabled_for_document(&self) -> bool {
450 false
451 }
452}