style/
applicable_declarations.rs1use crate::derives::*;
8use crate::properties::PropertyDeclarationBlock;
9use crate::rule_tree::{CascadeLevel, 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 layer_order: LayerOrder,
44}
45
46const_assert_eq!(
47 std::mem::size_of::<CascadePriority>(),
48 std::mem::size_of::<u32>()
49);
50
51impl PartialOrd for CascadePriority {
52 #[inline]
53 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
54 Some(self.cmp(other))
55 }
56}
57
58impl Ord for CascadePriority {
59 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
60 self.cascade_level.cmp(&other.cascade_level).then_with(|| {
61 let ordering = self.layer_order.cmp(&other.layer_order);
62 if ordering == std::cmp::Ordering::Equal {
63 return ordering;
64 }
65 if self.cascade_level.is_important()
75 && !self.layer_order.is_style_attribute_layer()
76 && !other.layer_order.is_style_attribute_layer()
77 {
78 ordering.reverse()
79 } else {
80 ordering
81 }
82 })
83 }
84}
85
86impl CascadePriority {
87 pub fn new(cascade_level: CascadeLevel, layer_order: LayerOrder) -> Self {
89 Self {
90 cascade_level,
91 layer_order,
92 }
93 }
94
95 #[inline]
97 pub fn layer_order(&self) -> LayerOrder {
98 self.layer_order
99 }
100
101 #[inline]
103 pub fn cascade_level(&self) -> CascadeLevel {
104 self.cascade_level
105 }
106
107 pub fn allows_when_reverted(&self, other: &Self, origin_revert: bool) -> bool {
113 if origin_revert {
114 other.cascade_level.origin() < self.cascade_level.origin()
115 } else {
116 other.unimportant() < self.unimportant()
117 }
118 }
119
120 pub fn unimportant(&self) -> Self {
122 Self::new(self.cascade_level().unimportant(), self.layer_order())
123 }
124
125 pub fn important(&self) -> Self {
127 Self::new(self.cascade_level().important(), self.layer_order())
128 }
129
130 pub fn same_tree_author_normal_at_root_layer() -> Self {
132 Self::new(CascadeLevel::same_tree_author_normal(), LayerOrder::root())
133 }
134}
135
136#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
140pub struct ScopeProximity(u16);
141
142impl PartialOrd for ScopeProximity {
143 #[inline]
144 fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
145 Some(self.cmp(other))
146 }
147}
148
149impl Ord for ScopeProximity {
150 fn cmp(&self, other: &Self) -> std::cmp::Ordering {
151 other.0.cmp(&self.0)
153 }
154}
155
156const PROXIMITY_INFINITY: u16 = u16::MAX;
159
160impl ScopeProximity {
161 pub fn new(proximity: usize) -> Self {
163 if cfg!(debug_assertions) && proximity >= PROXIMITY_INFINITY as usize {
164 warn!("Proximity out of bounds");
165 }
166 Self(proximity.clamp(0, (PROXIMITY_INFINITY - 1) as usize) as u16)
167 }
168
169 pub fn infinity() -> Self {
171 Self(PROXIMITY_INFINITY)
172 }
173
174 pub fn get(&self) -> Option<u16> {
176 (self.0 != PROXIMITY_INFINITY).then(|| self.0)
177 }
178}
179
180#[derive(Clone, Debug, MallocSizeOf, PartialEq)]
186pub struct ApplicableDeclarationBlock {
187 #[ignore_malloc_size_of = "Arc"]
189 pub source: StyleSource,
190 source_order: u32,
194 pub specificity: u32,
196 pub scope_proximity: ScopeProximity,
198 pub cascade_priority: CascadePriority,
200}
201
202impl ApplicableDeclarationBlock {
203 #[inline]
206 pub fn from_declarations(
207 declarations: Arc<Locked<PropertyDeclarationBlock>>,
208 level: CascadeLevel,
209 layer_order: LayerOrder,
210 ) -> Self {
211 ApplicableDeclarationBlock {
212 source: StyleSource::from_declarations(declarations),
213 source_order: 0,
214 specificity: 0,
215 scope_proximity: ScopeProximity::infinity(),
216 cascade_priority: CascadePriority::new(level, layer_order),
217 }
218 }
219
220 #[inline]
222 pub fn new(
223 source: StyleSource,
224 source_order: u32,
225 level: CascadeLevel,
226 specificity: u32,
227 layer_order: LayerOrder,
228 scope_proximity: ScopeProximity,
229 ) -> Self {
230 ApplicableDeclarationBlock {
231 source,
232 source_order: source_order & SOURCE_ORDER_MASK,
233 specificity,
234 scope_proximity,
235 cascade_priority: CascadePriority::new(level, layer_order),
236 }
237 }
238
239 #[inline]
241 pub fn source_order(&self) -> u32 {
242 self.source_order
243 }
244
245 #[inline]
247 pub fn level(&self) -> CascadeLevel {
248 self.cascade_priority.cascade_level()
249 }
250
251 #[inline]
253 pub fn layer_order(&self) -> LayerOrder {
254 self.cascade_priority.layer_order()
255 }
256
257 #[inline]
259 pub fn scope_proximity(&self) -> ScopeProximity {
260 self.scope_proximity
261 }
262
263 #[inline]
266 pub fn for_rule_tree(self) -> (StyleSource, CascadePriority) {
267 (self.source, self.cascade_priority)
268 }
269
270 #[inline]
272 pub fn sort_key(&self) -> (LayerOrder, u32, ScopeProximity, u32) {
273 (
274 self.layer_order(),
275 self.specificity,
276 self.scope_proximity(),
277 self.source_order(),
278 )
279 }
280}
281
282size_of_test!(ApplicableDeclarationBlock, 24);