1use crate::derives::*;
8use crate::properties::PropertyDeclarationBlock;
9use crate::rule_tree::{CascadeLevel, RuleCascadeFlags, StyleSource};
10use crate::shared_lock::Locked;
11use crate::stylesheets::layer_rule::LayerOrder;
12use servo_arc::Arc;
13use smallvec::SmallVec;
14
15pub type ApplicableDeclarationList = SmallVec<[ApplicableDeclarationBlock; 16]>;
23
24const SOURCE_ORDER_BITS: usize = 24;
36const SOURCE_ORDER_MAX: u32 = (1 << SOURCE_ORDER_BITS) - 1;
37const SOURCE_ORDER_MASK: u32 = SOURCE_ORDER_MAX;
38
39#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
41pub struct CascadePriority {
42 cascade_level: CascadeLevel,
43 flags: RuleCascadeFlags,
44 layer_order: LayerOrder,
45}
46
47const_assert_eq!(
48 std::mem::size_of::<CascadePriority>(),
49 std::mem::size_of::<u32>()
50);
51
52impl PartialOrd for CascadePriority {
53 #[inline]
54 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
55 Some(self.cmp(other))
56 }
57}
58
59impl Ord for CascadePriority {
60 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
61 self.cascade_level.cmp(&other.cascade_level).then_with(|| {
62 let ordering = self.layer_order.cmp(&other.layer_order);
63 if ordering == std::cmp::Ordering::Equal {
64 return ordering;
65 }
66 if self.cascade_level.is_important()
76 && !self.layer_order.is_style_attribute_layer()
77 && !other.layer_order.is_style_attribute_layer()
78 {
79 ordering.reverse()
80 } else {
81 ordering
82 }
83 })
84 }
85}
86
87#[derive(Clone, Copy, Debug, Eq, PartialEq)]
89pub enum RevertKind {
90 Origin,
92 Layer,
94 Rule,
96}
97
98impl CascadePriority {
99 pub fn new(
101 cascade_level: CascadeLevel,
102 layer_order: LayerOrder,
103 flags: RuleCascadeFlags,
104 ) -> Self {
105 Self {
106 cascade_level,
107 flags,
108 layer_order,
109 }
110 }
111
112 #[inline]
114 pub fn flags(&self) -> RuleCascadeFlags {
115 self.flags
116 }
117
118 #[inline]
120 pub fn set_flags(&mut self, flags: RuleCascadeFlags) {
121 self.flags.insert(flags);
122 }
123
124 #[inline]
126 pub fn layer_order(&self) -> LayerOrder {
127 self.layer_order
128 }
129
130 #[inline]
132 pub fn cascade_level(&self) -> CascadeLevel {
133 self.cascade_level
134 }
135
136 pub fn allows_when_reverted(&self, other: &Self, kind: RevertKind) -> bool {
141 match kind {
142 RevertKind::Origin => {
143 other.cascade_level.origin().origin() < self.cascade_level.origin().origin()
144 },
145 RevertKind::Layer => other.unimportant() < self.unimportant(),
146 RevertKind::Rule => true,
149 }
150 }
151
152 pub fn unimportant(&self) -> Self {
154 Self {
155 cascade_level: self.cascade_level.unimportant(),
156 flags: self.flags,
157 layer_order: self.layer_order,
158 }
159 }
160
161 pub fn important(&self) -> Self {
163 Self {
164 cascade_level: self.cascade_level.important(),
165 flags: self.flags,
166 layer_order: self.layer_order,
167 }
168 }
169
170 pub fn same_tree_author_normal_at_root_layer() -> Self {
172 Self::new(
173 CascadeLevel::same_tree_author_normal(),
174 LayerOrder::root(),
175 RuleCascadeFlags::empty(),
176 )
177 }
178}
179
180#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
184pub struct ScopeProximity(u16);
185
186impl PartialOrd for ScopeProximity {
187 #[inline]
188 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
189 Some(self.cmp(other))
190 }
191}
192
193impl Ord for ScopeProximity {
194 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
195 other.0.cmp(&self.0)
197 }
198}
199
200const PROXIMITY_INFINITY: u16 = u16::MAX;
203
204impl ScopeProximity {
205 pub fn new(proximity: usize) -> Self {
207 if cfg!(debug_assertions) && proximity >= PROXIMITY_INFINITY as usize {
208 warn!("Proximity out of bounds");
209 }
210 Self(proximity.clamp(0, (PROXIMITY_INFINITY - 1) as usize) as u16)
211 }
212
213 pub fn infinity() -> Self {
215 Self(PROXIMITY_INFINITY)
216 }
217
218 pub fn get(&self) -> Option<u16> {
220 (self.0 != PROXIMITY_INFINITY).then(|| self.0)
221 }
222}
223
224#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
230pub struct ApplicableDeclarationBlock {
231 #[ignore_malloc_size_of = "Arc"]
233 pub source: StyleSource,
234 source_order: u32,
238 pub specificity: u32,
240 pub scope_proximity: ScopeProximity,
242 pub cascade_priority: CascadePriority,
244}
245
246impl ApplicableDeclarationBlock {
247 #[inline]
250 pub fn from_declarations(
251 declarations: Arc<Locked<PropertyDeclarationBlock>>,
252 level: CascadeLevel,
253 layer_order: LayerOrder,
254 ) -> Self {
255 ApplicableDeclarationBlock {
256 source: StyleSource::from_declarations(declarations),
257 source_order: 0,
258 specificity: 0,
259 scope_proximity: ScopeProximity::infinity(),
260 cascade_priority: CascadePriority::new(level, layer_order, RuleCascadeFlags::empty()),
261 }
262 }
263
264 #[inline]
266 pub fn new(
267 source: StyleSource,
268 source_order: u32,
269 level: CascadeLevel,
270 specificity: u32,
271 layer_order: LayerOrder,
272 scope_proximity: ScopeProximity,
273 flags: RuleCascadeFlags,
274 ) -> Self {
275 ApplicableDeclarationBlock {
276 source,
277 source_order: source_order & SOURCE_ORDER_MASK,
278 specificity,
279 scope_proximity,
280 cascade_priority: CascadePriority::new(level, layer_order, flags),
281 }
282 }
283
284 #[inline]
286 pub fn source_order(&self) -> u32 {
287 self.source_order
288 }
289
290 #[inline]
292 pub fn level(&self) -> CascadeLevel {
293 self.cascade_priority.cascade_level()
294 }
295
296 #[inline]
298 pub fn layer_order(&self) -> LayerOrder {
299 self.cascade_priority.layer_order()
300 }
301
302 #[inline]
304 pub fn scope_proximity(&self) -> ScopeProximity {
305 self.scope_proximity
306 }
307
308 #[inline]
311 pub fn for_rule_tree(self) -> (StyleSource, CascadePriority) {
312 (self.source, self.cascade_priority)
313 }
314
315 #[inline]
317 pub fn sort_key(&self) -> (LayerOrder, u32, ScopeProximity, u32) {
318 (
319 self.layer_order(),
320 self.specificity,
321 self.scope_proximity(),
322 self.source_order(),
323 )
324 }
325}
326
327size_of_test!(ApplicableDeclarationBlock, 24);