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 http://mozilla.org/MPL/2.0/. */
4 
5 //! Gecko's restyle damage computation (aka change hints, aka `nsChangeHint`).
6 
7 use gecko_bindings::bindings;
8 use gecko_bindings::structs;
9 use gecko_bindings::structs::nsChangeHint;
10 use matching::{StyleChange, StyleDifference};
11 use properties::ComputedValues;
12 use std::ops::{BitAnd, BitOr, BitOrAssign, Not};
13 
14 /// The representation of Gecko's restyle damage is just a wrapper over
15 /// `nsChangeHint`.
16 #[derive(Clone, Copy, Debug, PartialEq)]
17 pub struct GeckoRestyleDamage(nsChangeHint);
18 
19 impl GeckoRestyleDamage {
20     /// Trivially construct a new `GeckoRestyleDamage`.
21     #[inline]
new(raw: nsChangeHint) -> Self22     pub fn new(raw: nsChangeHint) -> Self {
23         GeckoRestyleDamage(raw)
24     }
25 
26     /// Get the inner change hint for this damage.
27     #[inline]
as_change_hint(&self) -> nsChangeHint28     pub fn as_change_hint(&self) -> nsChangeHint {
29         self.0
30     }
31 
32     /// Get an empty change hint, that is (`nsChangeHint(0)`).
33     #[inline]
empty() -> Self34     pub fn empty() -> Self {
35         GeckoRestyleDamage(nsChangeHint(0))
36     }
37 
38     /// Returns whether this restyle damage represents the empty damage.
39     #[inline]
is_empty(&self) -> bool40     pub fn is_empty(&self) -> bool {
41         self.0 == nsChangeHint(0)
42     }
43 
44     /// Computes the `StyleDifference` (including the appropriate change hint)
45     /// given an old and a new style.
compute_style_difference( old_style: &ComputedValues, new_style: &ComputedValues, ) -> StyleDifference46     pub fn compute_style_difference(
47         old_style: &ComputedValues,
48         new_style: &ComputedValues,
49     ) -> StyleDifference {
50         let mut any_style_changed = false;
51         let mut reset_only = false;
52         let hint = unsafe {
53             bindings::Gecko_CalcStyleDifference(
54                 old_style,
55                 new_style,
56                 &mut any_style_changed,
57                 &mut reset_only,
58             )
59         };
60         if reset_only &&
61            old_style.custom_properties() != new_style.custom_properties() {
62             // The Gecko_CalcStyleDifference call only checks the non-custom
63             // property structs, so we check the custom properties here. Since
64             // they generate no damage themselves, we can skip this check if we
65             // already know we had some inherited (regular) property
66             // differences.
67             any_style_changed = true;
68             reset_only = false;
69         }
70         let change = if any_style_changed {
71             StyleChange::Changed { reset_only }
72         } else {
73             StyleChange::Unchanged
74         };
75         let damage = GeckoRestyleDamage(nsChangeHint(hint));
76         StyleDifference { damage, change }
77     }
78 
79     /// Returns true if this restyle damage contains all the damage of |other|.
contains(self, other: Self) -> bool80     pub fn contains(self, other: Self) -> bool {
81         self & other == other
82     }
83 
84     /// Gets restyle damage to reconstruct the entire frame, subsuming all
85     /// other damage.
reconstruct() -> Self86     pub fn reconstruct() -> Self {
87         GeckoRestyleDamage(structs::nsChangeHint_nsChangeHint_ReconstructFrame)
88     }
89 }
90 
91 impl Default for GeckoRestyleDamage {
default() -> Self92     fn default() -> Self {
93         Self::empty()
94     }
95 }
96 
97 impl BitOr for GeckoRestyleDamage {
98     type Output = Self;
bitor(self, other: Self) -> Self99     fn bitor(self, other: Self) -> Self {
100         GeckoRestyleDamage(self.0 | other.0)
101     }
102 }
103 
104 impl BitOrAssign for GeckoRestyleDamage {
bitor_assign(&mut self, other: Self)105     fn bitor_assign(&mut self, other: Self) {
106         *self = *self | other;
107     }
108 }
109 
110 impl BitAnd for GeckoRestyleDamage {
111     type Output = Self;
bitand(self, other: Self) -> Self112     fn bitand(self, other: Self) -> Self {
113         GeckoRestyleDamage(nsChangeHint((self.0).0 & (other.0).0))
114     }
115 }
116 
117 impl Not for GeckoRestyleDamage {
118     type Output = Self;
not(self) -> Self119     fn not(self) -> Self {
120         GeckoRestyleDamage(nsChangeHint(!(self.0).0))
121     }
122 }
123