1use crate::custom_properties::CssEnvironment;
8#[cfg(feature = "servo")]
9use crate::derives::*;
10use crate::properties::ComputedValues;
11use crate::values::computed::font::QueryFontMetricsFlags;
12use crate::values::computed::Length;
13use parking_lot::RwLock;
14use servo_arc::Arc;
15use std::mem;
16use std::sync::atomic::{AtomicBool, AtomicU32, Ordering};
17
18#[cfg(feature = "gecko")]
19use crate::device::gecko::ExtraDeviceData;
20#[cfg(feature = "servo")]
21use crate::device::servo::ExtraDeviceData;
22
23#[cfg(feature = "gecko")]
24pub mod gecko;
25#[cfg(feature = "servo")]
26pub mod servo;
27
28#[cfg_attr(feature = "servo", derive(Debug, MallocSizeOf))]
41pub struct Device {
42 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc is shared")]
44 default_values: Arc<ComputedValues>,
45 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Arc")]
48 root_style: RwLock<Arc<ComputedValues>>,
49 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
51 root_font_size: AtomicU32,
52 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
54 root_line_height: AtomicU32,
55 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
57 root_font_metrics_ex: AtomicU32,
58 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
60 root_font_metrics_cap: AtomicU32,
61 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
63 root_font_metrics_ch: AtomicU32,
64 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
66 root_font_metrics_ic: AtomicU32,
67 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
70 used_root_font_size: AtomicBool,
71 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
74 used_root_line_height: AtomicBool,
75 #[cfg_attr(feature = "servo", ignore_malloc_size_of = "Pure stack type")]
79 used_root_font_metrics: RwLock<bool>,
80 used_font_metrics: AtomicBool,
82 used_viewport_size: AtomicBool,
85 used_dynamic_viewport_size: AtomicBool,
88 environment: CssEnvironment,
91
92 extra: ExtraDeviceData,
94}
95
96impl Device {
97 #[inline]
99 pub fn environment(&self) -> &CssEnvironment {
100 &self.environment
101 }
102
103 pub fn default_computed_values(&self) -> &ComputedValues {
106 &self.default_values
107 }
108
109 pub fn default_computed_values_arc(&self) -> &Arc<ComputedValues> {
111 &self.default_values
112 }
113
114 pub fn set_root_style(&self, style: &Arc<ComputedValues>) {
117 *self.root_style.write() = style.clone();
118 }
119
120 pub fn root_font_size(&self) -> Length {
122 self.used_root_font_size.store(true, Ordering::Relaxed);
123 Length::new(f32::from_bits(self.root_font_size.load(Ordering::Relaxed)))
124 }
125
126 pub fn set_root_font_size(&self, size: f32) {
128 self.root_font_size.store(size.to_bits(), Ordering::Relaxed)
129 }
130
131 pub fn root_line_height(&self) -> Length {
133 self.used_root_line_height.store(true, Ordering::Relaxed);
134 Length::new(f32::from_bits(
135 self.root_line_height.load(Ordering::Relaxed),
136 ))
137 }
138
139 pub fn set_root_line_height(&self, size: f32) {
141 self.root_line_height
142 .store(size.to_bits(), Ordering::Relaxed);
143 }
144
145 pub fn root_font_metrics_ex(&self) -> Length {
147 self.ensure_root_font_metrics_updated();
148 Length::new(f32::from_bits(
149 self.root_font_metrics_ex.load(Ordering::Relaxed),
150 ))
151 }
152
153 pub fn set_root_font_metrics_ex(&self, size: f32) -> bool {
155 let size = size.to_bits();
156 let previous = self.root_font_metrics_ex.swap(size, Ordering::Relaxed);
157 previous != size
158 }
159
160 pub fn root_font_metrics_cap(&self) -> Length {
162 self.ensure_root_font_metrics_updated();
163 Length::new(f32::from_bits(
164 self.root_font_metrics_cap.load(Ordering::Relaxed),
165 ))
166 }
167
168 pub fn set_root_font_metrics_cap(&self, size: f32) -> bool {
170 let size = size.to_bits();
171 let previous = self.root_font_metrics_cap.swap(size, Ordering::Relaxed);
172 previous != size
173 }
174
175 pub fn root_font_metrics_ch(&self) -> Length {
177 self.ensure_root_font_metrics_updated();
178 Length::new(f32::from_bits(
179 self.root_font_metrics_ch.load(Ordering::Relaxed),
180 ))
181 }
182
183 pub fn set_root_font_metrics_ch(&self, size: f32) -> bool {
185 let size = size.to_bits();
186 let previous = self.root_font_metrics_ch.swap(size, Ordering::Relaxed);
187 previous != size
188 }
189
190 pub fn root_font_metrics_ic(&self) -> Length {
192 self.ensure_root_font_metrics_updated();
193 Length::new(f32::from_bits(
194 self.root_font_metrics_ic.load(Ordering::Relaxed),
195 ))
196 }
197
198 pub fn set_root_font_metrics_ic(&self, size: f32) -> bool {
200 let size = size.to_bits();
201 let previous = self.root_font_metrics_ic.swap(size, Ordering::Relaxed);
202 previous != size
203 }
204
205 fn ensure_root_font_metrics_updated(&self) {
206 let mut guard = self.used_root_font_metrics.write();
207 let previously_computed = mem::replace(&mut *guard, true);
208 if !previously_computed {
209 self.update_root_font_metrics();
210 }
211 }
212
213 pub fn update_root_font_metrics(&self) -> bool {
216 let root_style = self.root_style.read();
217 let root_effective_zoom = (*root_style).effective_zoom;
218 let root_font_size = (*root_style).get_font().clone_font_size().computed_size();
219
220 let root_font_metrics = self.query_font_metrics(
221 (*root_style).writing_mode.is_upright(),
222 &(*root_style).get_font(),
223 root_font_size,
224 QueryFontMetricsFlags::USE_USER_FONT_SET
225 | QueryFontMetricsFlags::NEEDS_CH
226 | QueryFontMetricsFlags::NEEDS_IC,
227 false,
228 );
229
230 let mut root_font_metrics_changed = false;
231 root_font_metrics_changed |= self.set_root_font_metrics_ex(
232 root_effective_zoom.unzoom(root_font_metrics.x_height_or_default(root_font_size).px()),
233 );
234 root_font_metrics_changed |= self.set_root_font_metrics_ch(
235 root_effective_zoom.unzoom(
236 root_font_metrics
237 .zero_advance_measure_or_default(
238 root_font_size,
239 (*root_style).writing_mode.is_upright(),
240 )
241 .px(),
242 ),
243 );
244 root_font_metrics_changed |= self.set_root_font_metrics_cap(
245 root_effective_zoom.unzoom(root_font_metrics.cap_height_or_default().px()),
246 );
247 root_font_metrics_changed |= self.set_root_font_metrics_ic(
248 root_effective_zoom.unzoom(root_font_metrics.ic_width_or_default(root_font_size).px()),
249 );
250
251 root_font_metrics_changed
252 }
253
254 pub fn used_root_font_size(&self) -> bool {
256 self.used_root_font_size.load(Ordering::Relaxed)
257 }
258
259 pub fn used_root_line_height(&self) -> bool {
261 self.used_root_line_height.load(Ordering::Relaxed)
262 }
263
264 pub fn used_root_font_metrics(&self) -> bool {
266 *self.used_root_font_metrics.read()
267 }
268
269 pub fn used_viewport_size(&self) -> bool {
271 self.used_viewport_size.load(Ordering::Relaxed)
272 }
273
274 pub fn used_dynamic_viewport_size(&self) -> bool {
276 self.used_dynamic_viewport_size.load(Ordering::Relaxed)
277 }
278
279 pub fn used_font_metrics(&self) -> bool {
281 self.used_font_metrics.load(Ordering::Relaxed)
282 }
283}