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