1use crate::color::AbsoluteColor;
8use crate::custom_properties::CssEnvironment;
9#[cfg(feature = "servo")]
10use crate::derives::*;
11use crate::properties::ComputedValues;
12use crate::values::computed::font::QueryFontMetricsFlags;
13use crate::values::computed::Length;
14use parking_lot::RwLock;
15use servo_arc::Arc;
16use std::mem;
17use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
18
19#[cfg(feature = "gecko")]
20use crate::device::gecko::ExtraDeviceData;
21#[cfg(feature = "servo")]
22use crate::device::servo::ExtraDeviceData;
23
24#[cfg(feature = "gecko")]
25pub mod gecko;
26#[cfg(feature = "servo")]
27pub mod servo;
28
29#[cfg_attr(feature = "servo", derive(Debug, MallocSizeOf))]
42pub struct Device {
43 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc is shared")]
45 default_values: Arc<ComputedValues>,
46 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
49 root_style: RwLock<Arc<ComputedValues>>,
50 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
52 root_font_size: AtomicU32,
53 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
55 root_line_height: AtomicU32,
56 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
58 root_font_metrics_ex: AtomicU32,
59 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
61 root_font_metrics_cap: AtomicU32,
62 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
64 root_font_metrics_ch: AtomicU32,
65 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
67 root_font_metrics_ic: AtomicU32,
68 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
71 used_root_font_size: AtomicBool,
72 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
75 used_root_line_height: AtomicBool,
76 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
80 used_root_font_metrics: RwLock<bool>,
81 used_font_metrics: AtomicBool,
83 used_viewport_size: AtomicBool,
86 used_dynamic_viewport_size: AtomicBool,
89 environment: CssEnvironment,
92 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
97 body_text_color: AtomicU32,
98
99 extra: ExtraDeviceData,
101}
102
103impl Device {
104 #[inline]
106 pub fn environment(&self) -> &CssEnvironment {
107 &self.environment
108 }
109
110 pub fn default_computed_values(&self) -> &ComputedValues {
113 &self.default_values
114 }
115
116 pub fn default_computed_values_arc(&self) -> &Arc<ComputedValues> {
118 &self.default_values
119 }
120
121 pub fn set_root_style(&self, style: &Arc<ComputedValues>) {
124 *self.root_style.write() = style.clone();
125 }
126
127 pub fn root_font_size(&self) -> Length {
129 self.used_root_font_size.store(true, Ordering::Relaxed);
130 Length::new(f32::from_bits(self.root_font_size.load(Ordering::Relaxed)))
131 }
132
133 pub fn set_root_font_size(&self, size: f32) {
135 self.root_font_size.store(size.to_bits(), Ordering::Relaxed)
136 }
137
138 pub fn root_line_height(&self) -> Length {
140 self.used_root_line_height.store(true, Ordering::Relaxed);
141 Length::new(f32::from_bits(
142 self.root_line_height.load(Ordering::Relaxed),
143 ))
144 }
145
146 pub fn set_root_line_height(&self, size: f32) {
148 self.root_line_height
149 .store(size.to_bits(), Ordering::Relaxed);
150 }
151
152 pub fn root_font_metrics_ex(&self) -> Length {
154 self.ensure_root_font_metrics_updated();
155 Length::new(f32::from_bits(
156 self.root_font_metrics_ex.load(Ordering::Relaxed),
157 ))
158 }
159
160 pub fn set_root_font_metrics_ex(&self, size: f32) -> bool {
162 let size = size.to_bits();
163 let previous = self.root_font_metrics_ex.swap(size, Ordering::Relaxed);
164 previous != size
165 }
166
167 pub fn root_font_metrics_cap(&self) -> Length {
169 self.ensure_root_font_metrics_updated();
170 Length::new(f32::from_bits(
171 self.root_font_metrics_cap.load(Ordering::Relaxed),
172 ))
173 }
174
175 pub fn set_root_font_metrics_cap(&self, size: f32) -> bool {
177 let size = size.to_bits();
178 let previous = self.root_font_metrics_cap.swap(size, Ordering::Relaxed);
179 previous != size
180 }
181
182 pub fn root_font_metrics_ch(&self) -> Length {
184 self.ensure_root_font_metrics_updated();
185 Length::new(f32::from_bits(
186 self.root_font_metrics_ch.load(Ordering::Relaxed),
187 ))
188 }
189
190 pub fn set_root_font_metrics_ch(&self, size: f32) -> bool {
192 let size = size.to_bits();
193 let previous = self.root_font_metrics_ch.swap(size, Ordering::Relaxed);
194 previous != size
195 }
196
197 pub fn root_font_metrics_ic(&self) -> Length {
199 self.ensure_root_font_metrics_updated();
200 Length::new(f32::from_bits(
201 self.root_font_metrics_ic.load(Ordering::Relaxed),
202 ))
203 }
204
205 pub fn set_root_font_metrics_ic(&self, size: f32) -> bool {
207 let size = size.to_bits();
208 let previous = self.root_font_metrics_ic.swap(size, Ordering::Relaxed);
209 previous != size
210 }
211
212 fn ensure_root_font_metrics_updated(&self) {
213 let mut guard = self.used_root_font_metrics.write();
214 let previously_computed = mem::replace(&mut *guard, true);
215 if !previously_computed {
216 self.update_root_font_metrics();
217 }
218 }
219
220 pub fn update_root_font_metrics(&self) -> bool {
223 let root_style = self.root_style.read();
224 let root_effective_zoom = (*root_style).effective_zoom;
225 let root_font_size = (*root_style).get_font().clone_font_size().computed_size();
226
227 let root_font_metrics = self.query_font_metrics(
228 (*root_style).writing_mode.is_upright(),
229 &(*root_style).get_font(),
230 root_font_size,
231 QueryFontMetricsFlags::USE_USER_FONT_SET
232 | QueryFontMetricsFlags::NEEDS_CH
233 | QueryFontMetricsFlags::NEEDS_IC,
234 false,
235 );
236
237 let mut root_font_metrics_changed = false;
238 root_font_metrics_changed |= self.set_root_font_metrics_ex(
239 root_effective_zoom.unzoom(root_font_metrics.x_height_or_default(root_font_size).px()),
240 );
241 root_font_metrics_changed |= self.set_root_font_metrics_ch(
242 root_effective_zoom.unzoom(
243 root_font_metrics
244 .zero_advance_measure_or_default(
245 root_font_size,
246 (*root_style).writing_mode.is_upright(),
247 )
248 .px(),
249 ),
250 );
251 root_font_metrics_changed |= self.set_root_font_metrics_cap(
252 root_effective_zoom.unzoom(root_font_metrics.cap_height_or_default().px()),
253 );
254 root_font_metrics_changed |= self.set_root_font_metrics_ic(
255 root_effective_zoom.unzoom(root_font_metrics.ic_width_or_default(root_font_size).px()),
256 );
257
258 root_font_metrics_changed
259 }
260
261 pub fn used_root_font_size(&self) -> bool {
263 self.used_root_font_size.load(Ordering::Relaxed)
264 }
265
266 pub fn used_root_line_height(&self) -> bool {
268 self.used_root_line_height.load(Ordering::Relaxed)
269 }
270
271 pub fn used_root_font_metrics(&self) -> bool {
273 *self.used_root_font_metrics.read()
274 }
275
276 pub fn used_viewport_size(&self) -> bool {
278 self.used_viewport_size.load(Ordering::Relaxed)
279 }
280
281 pub fn used_dynamic_viewport_size(&self) -> bool {
283 self.used_dynamic_viewport_size.load(Ordering::Relaxed)
284 }
285
286 pub fn used_font_metrics(&self) -> bool {
288 self.used_font_metrics.load(Ordering::Relaxed)
289 }
290
291 pub fn body_text_color(&self) -> AbsoluteColor {
293 AbsoluteColor::from_nscolor(self.body_text_color.load(Ordering::Relaxed))
294 }
295
296 pub fn set_body_text_color(&self, color: AbsoluteColor) {
300 self.body_text_color
301 .store(color.to_nscolor(), Ordering::Relaxed)
302 }
303}