1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
4 
5 //! A style rule.
6 
7 use crate::properties::PropertyDeclarationBlock;
8 use crate::selector_parser::SelectorImpl;
9 use crate::shared_lock::{DeepCloneParams, DeepCloneWithLock, Locked};
10 use crate::shared_lock::{SharedRwLock, SharedRwLockReadGuard, ToCssWithGuard};
11 use crate::str::CssStringWriter;
12 use cssparser::SourceLocation;
13 #[cfg(feature = "gecko")]
14 use malloc_size_of::MallocUnconditionalShallowSizeOf;
15 #[cfg(feature = "gecko")]
16 use malloc_size_of::{MallocSizeOf, MallocSizeOfOps};
17 use selectors::SelectorList;
18 use servo_arc::Arc;
19 use std::fmt::{self, Write};
20 
21 /// A style rule, with selectors and declarations.
22 #[derive(Debug, ToShmem)]
23 pub struct StyleRule {
24     /// The list of selectors in this rule.
25     pub selectors: SelectorList<SelectorImpl>,
26     /// The declaration block with the properties it contains.
27     pub block: Arc<Locked<PropertyDeclarationBlock>>,
28     /// The location in the sheet where it was found.
29     pub source_location: SourceLocation,
30 }
31 
32 impl DeepCloneWithLock for StyleRule {
33     /// Deep clones this StyleRule.
deep_clone_with_lock( &self, lock: &SharedRwLock, guard: &SharedRwLockReadGuard, _params: &DeepCloneParams, ) -> StyleRule34     fn deep_clone_with_lock(
35         &self,
36         lock: &SharedRwLock,
37         guard: &SharedRwLockReadGuard,
38         _params: &DeepCloneParams,
39     ) -> StyleRule {
40         StyleRule {
41             selectors: self.selectors.clone(),
42             block: Arc::new(lock.wrap(self.block.read_with(guard).clone())),
43             source_location: self.source_location.clone(),
44         }
45     }
46 }
47 
48 impl StyleRule {
49     /// Measure heap usage.
50     #[cfg(feature = "gecko")]
size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize51     pub fn size_of(&self, guard: &SharedRwLockReadGuard, ops: &mut MallocSizeOfOps) -> usize {
52         let mut n = 0;
53         n += self.selectors.0.size_of(ops);
54         n += self.block.unconditional_shallow_size_of(ops) +
55             self.block.read_with(guard).size_of(ops);
56         n
57     }
58 }
59 
60 impl ToCssWithGuard for StyleRule {
61     /// https://drafts.csswg.org/cssom/#serialize-a-css-rule CSSStyleRule
to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result62     fn to_css(&self, guard: &SharedRwLockReadGuard, dest: &mut CssStringWriter) -> fmt::Result {
63         use cssparser::ToCss;
64 
65         // Step 1
66         self.selectors.to_css(dest)?;
67         // Step 2
68         dest.write_str(" { ")?;
69         // Step 3
70         let declaration_block = self.block.read_with(guard);
71         declaration_block.to_css(dest)?;
72         // Step 4
73         if !declaration_block.declarations().is_empty() {
74             dest.write_str(" ")?;
75         }
76         // Step 5
77         dest.write_str("}")
78     }
79 }
80