restyle_damage.rs (3830B)
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 //! Gecko's restyle damage computation (aka change hints, aka `nsChangeHint`). 6 7 use crate::gecko_bindings::bindings; 8 use crate::gecko_bindings::structs; 9 use crate::gecko_bindings::structs::nsChangeHint; 10 use crate::matching::{StyleChange, StyleDifference}; 11 use crate::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] 22 pub fn new(raw: nsChangeHint) -> Self { 23 GeckoRestyleDamage(raw) 24 } 25 26 /// Get the inner change hint for this damage. 27 #[inline] 28 pub fn as_change_hint(&self) -> nsChangeHint { 29 self.0 30 } 31 32 /// Get an empty change hint, that is (`nsChangeHint(0)`). 33 #[inline] 34 pub fn empty() -> Self { 35 GeckoRestyleDamage(nsChangeHint(0)) 36 } 37 38 /// Returns whether this restyle damage represents the empty damage. 39 #[inline] 40 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. 46 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.as_gecko_computed_style(), 55 new_style.as_gecko_computed_style(), 56 &mut any_style_changed, 57 &mut reset_only, 58 ) 59 }; 60 if reset_only && !old_style.custom_properties_equal(new_style) { 61 // The Gecko_CalcStyleDifference call only checks the non-custom 62 // property structs, so we check the custom properties here. Since 63 // they generate no damage themselves, we can skip this check if we 64 // already know we had some inherited (regular) property 65 // differences. 66 any_style_changed = true; 67 reset_only = false; 68 } 69 let change = if any_style_changed { 70 StyleChange::Changed { reset_only } 71 } else { 72 StyleChange::Unchanged 73 }; 74 let damage = GeckoRestyleDamage(nsChangeHint(hint)); 75 StyleDifference { damage, change } 76 } 77 78 /// Returns true if this restyle damage contains all the damage of |other|. 79 pub fn contains(self, other: Self) -> bool { 80 self & other == other 81 } 82 83 /// Gets restyle damage to reconstruct the entire frame, subsuming all 84 /// other damage. 85 pub fn reconstruct() -> Self { 86 GeckoRestyleDamage(structs::nsChangeHint::nsChangeHint_ReconstructFrame) 87 } 88 } 89 90 impl Default for GeckoRestyleDamage { 91 fn default() -> Self { 92 Self::empty() 93 } 94 } 95 96 impl BitOr for GeckoRestyleDamage { 97 type Output = Self; 98 fn bitor(self, other: Self) -> Self { 99 GeckoRestyleDamage(self.0 | other.0) 100 } 101 } 102 103 impl BitOrAssign for GeckoRestyleDamage { 104 fn bitor_assign(&mut self, other: Self) { 105 *self = *self | other; 106 } 107 } 108 109 impl BitAnd for GeckoRestyleDamage { 110 type Output = Self; 111 fn bitand(self, other: Self) -> Self { 112 GeckoRestyleDamage(nsChangeHint((self.0).0 & (other.0).0)) 113 } 114 } 115 116 impl Not for GeckoRestyleDamage { 117 type Output = Self; 118 fn not(self) -> Self { 119 GeckoRestyleDamage(nsChangeHint(!(self.0).0)) 120 } 121 }