Use bitflags! for RestyleDamage

This commit is contained in:
Brendan Zabarauskas 2014-06-05 15:33:46 -07:00
parent e0fe3e1ac0
commit 7675b0ced0
5 changed files with 28 additions and 148 deletions

View file

@ -68,7 +68,7 @@ impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> {
let default = if self.node_is_element() { let default = if self.node_is_element() {
RestyleDamage::all() RestyleDamage::all()
} else { } else {
RestyleDamage::none() RestyleDamage::empty()
}; };
let layout_data_ref = self.borrow_layout_data(); let layout_data_ref = self.borrow_layout_data();
@ -76,7 +76,6 @@ impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> {
.get_ref() .get_ref()
.data .data
.restyle_damage .restyle_damage
.map(|x| RestyleDamage::from_int(x))
.unwrap_or(default) .unwrap_or(default)
} }
@ -84,7 +83,7 @@ impl<'ln> NodeUtil for ThreadSafeLayoutNode<'ln> {
fn set_restyle_damage(&self, damage: RestyleDamage) { fn set_restyle_damage(&self, damage: RestyleDamage) {
let mut layout_data_ref = self.mutate_layout_data(); let mut layout_data_ref = self.mutate_layout_data();
match &mut *layout_data_ref { match &mut *layout_data_ref {
&Some(ref mut layout_data) => layout_data.data.restyle_damage = Some(damage.to_int()), &Some(ref mut layout_data) => layout_data.data.restyle_damage = Some(damage),
_ => fail!("no layout data for this node"), _ => fail!("no layout data for this node"),
} }
} }

View file

@ -4,100 +4,34 @@
use style::ComputedValues; use style::ComputedValues;
/// Individual layout actions that may be necessary after restyling. bitflags! {
/// #[doc = "Individual layout actions that may be necessary after restyling."]
/// If you add to this enum, also add the value to RestyleDamage::all below. flags RestyleDamage: int {
/// (FIXME: do this automatically) #[doc = "Repaint the node itself."]
pub enum RestyleEffect { #[doc = "Currently unused; need to decide how this propagates."]
/// Repaint the node itself. static Repaint = 0x01,
/// Currently unused; need to decide how this propagates.
Repaint = 0x01,
/// Recompute intrinsic widths (minimum and preferred). #[doc = "Recompute intrinsic widths (minimum and preferred)."]
/// Propagates down the flow tree because the computation is #[doc = "Propagates down the flow tree because the computation is"]
/// bottom-up. #[doc = "bottom-up."]
BubbleWidths = 0x02, static BubbleWidths = 0x02,
/// Recompute actual widths and heights. #[doc = "Recompute actual widths and heights."]
/// Propagates up the flow tree because the computation is #[doc = "Propagates up the flow tree because the computation is"]
/// top-down. #[doc = "top-down."]
Reflow = 0x04, static Reflow = 0x04
}
} }
/// A set of RestyleEffects.
// FIXME: Switch to librustc/util/enum_set.rs if that gets moved into
// libextra (Rust #8054)
pub struct RestyleDamage {
bits: int
}
// Provide literal syntax of the form restyle_damage!(Repaint, Reflow)
macro_rules! restyle_damage(
( $($damage:ident),* ) => (
RestyleDamage::none() $( .add($damage) )*
)
)
impl RestyleDamage { impl RestyleDamage {
pub fn none() -> RestyleDamage {
RestyleDamage { bits: 0 }
}
pub fn all() -> RestyleDamage {
restyle_damage!(Repaint, BubbleWidths, Reflow)
}
/// Create a RestyleDamage from the underlying bit field.
/// We would rather not allow this, but some types in script
/// need to store RestyleDamage without depending on this crate.
pub fn from_int(n: int) -> RestyleDamage {
RestyleDamage { bits: n }
}
pub fn to_int(self) -> int {
self.bits
}
pub fn is_empty(self) -> bool {
self.bits == 0
}
pub fn is_nonempty(self) -> bool {
self.bits != 0
}
pub fn add(self, effect: RestyleEffect) -> RestyleDamage {
RestyleDamage { bits: self.bits | (effect as int) }
}
pub fn has(self, effect: RestyleEffect) -> bool {
(self.bits & (effect as int)) != 0
}
pub fn lacks(self, effect: RestyleEffect) -> bool {
(self.bits & (effect as int)) == 0
}
pub fn union(self, other: RestyleDamage) -> RestyleDamage {
RestyleDamage { bits: self.bits | other.bits }
}
pub fn union_in_place(&mut self, other: RestyleDamage) {
self.bits = self.bits | other.bits;
}
pub fn intersect(self, other: RestyleDamage) -> RestyleDamage {
RestyleDamage { bits: self.bits & other.bits }
}
/// Elements of self which should also get set on any ancestor flow. /// Elements of self which should also get set on any ancestor flow.
pub fn propagate_up(self) -> RestyleDamage { pub fn propagate_up(self) -> RestyleDamage {
self.intersect(restyle_damage!(Reflow)) self & Reflow
} }
/// Elements of self which should also get set on any child flows. /// Elements of self which should also get set on any child flows.
pub fn propagate_down(self) -> RestyleDamage { pub fn propagate_down(self) -> RestyleDamage {
self.intersect(restyle_damage!(BubbleWidths)) self & BubbleWidths
} }
} }
@ -108,13 +42,13 @@ macro_rules! add_if_not_equal(
($old:ident, $new:ident, $damage:ident, ($old:ident, $new:ident, $damage:ident,
[ $($effect:ident),* ], [ $($style_struct_getter:ident.$name:ident),* ]) => ({ [ $($effect:ident),* ], [ $($style_struct_getter:ident.$name:ident),* ]) => ({
if $( ($old.$style_struct_getter().$name != $new.$style_struct_getter().$name) )||* { if $( ($old.$style_struct_getter().$name != $new.$style_struct_getter().$name) )||* {
$damage.union_in_place( restyle_damage!( $($effect),* ) ); $damage.insert($($effect)|*);
} }
}) })
) )
pub fn compute_damage(old: &ComputedValues, new: &ComputedValues) -> RestyleDamage { pub fn compute_damage(old: &ComputedValues, new: &ComputedValues) -> RestyleDamage {
let mut damage = RestyleDamage::none(); let mut damage = RestyleDamage::empty();
// This checks every CSS property, as enumerated in // This checks every CSS property, as enumerated in
// impl<'self> CssComputedStyle<'self> // impl<'self> CssComputedStyle<'self>
@ -142,57 +76,3 @@ pub fn compute_damage(old: &ComputedValues, new: &ComputedValues) -> RestyleDama
damage damage
} }
#[cfg(test)]
mod restyle_damage_tests {
use super::*;
#[test]
fn none_is_empty() {
let d = RestyleDamage::none();
assert!(!d.has(Repaint));
assert!(!d.has(BubbleWidths));
assert!(d.lacks(Repaint));
assert!(d.lacks(BubbleWidths));
}
#[test]
fn all_is_full() {
let d = RestyleDamage::all();
assert!(d.has(Repaint));
assert!(d.has(BubbleWidths));
assert!(!d.lacks(Repaint));
assert!(!d.lacks(BubbleWidths));
}
#[test]
fn can_add() {
assert!(RestyleDamage::none().add(BubbleWidths).has(BubbleWidths));
}
#[test]
fn can_union() {
let d = restyle_damage!(Repaint).union(restyle_damage!(BubbleWidths));
assert!(d.has(Repaint));
assert!(d.has(BubbleWidths));
}
#[test]
fn can_union_in_place() {
let mut d = restyle_damage!(Repaint);
d.union_in_place(restyle_damage!(BubbleWidths));
assert!(d.has(Repaint));
assert!(d.has(BubbleWidths));
}
#[test]
fn can_intersect() {
let x = restyle_damage!(Repaint, BubbleWidths);
let y = restyle_damage!(Repaint, Reflow);
let d = x.intersect(y);
assert!(d.has(Repaint));
assert!(d.lacks(BubbleWidths));
assert!(d.lacks(Reflow));
}
}

View file

@ -750,7 +750,7 @@ impl InlineFragments {
style: other_style, style: other_style,
range: mut other_range range: mut other_range
} = other_range; } = other_range;
other_range.shift_by(adjustment); other_range.shift_by(adjustment);
self.push_range(other_style, other_range) self.push_range(other_style, other_range)
} }

View file

@ -118,7 +118,7 @@ impl PostorderFlowTraversal for ComputeDamageTraversal {
fn process(&mut self, flow: &mut Flow) -> bool { fn process(&mut self, flow: &mut Flow) -> bool {
let mut damage = flow::base(flow).restyle_damage; let mut damage = flow::base(flow).restyle_damage;
for child in flow::child_iter(flow) { for child in flow::child_iter(flow) {
damage.union_in_place(flow::base(child).restyle_damage.propagate_up()) damage.insert(flow::base(child).restyle_damage.propagate_up())
} }
flow::mut_base(flow).restyle_damage = damage; flow::mut_base(flow).restyle_damage = damage;
true true
@ -136,14 +136,14 @@ impl PreorderFlowTraversal for PropagateDamageTraversal {
#[inline] #[inline]
fn process(&mut self, flow: &mut Flow) -> bool { fn process(&mut self, flow: &mut Flow) -> bool {
if self.all_style_damage { if self.all_style_damage {
flow::mut_base(flow).restyle_damage.union_in_place(RestyleDamage::all()) flow::mut_base(flow).restyle_damage.insert(RestyleDamage::all())
} }
debug!("restyle damage = {:?}", flow::base(flow).restyle_damage); debug!("restyle damage = {:?}", flow::base(flow).restyle_damage);
let prop = flow::base(flow).restyle_damage.propagate_down(); let prop = flow::base(flow).restyle_damage.propagate_down();
if prop.is_nonempty() { if !prop.is_empty() {
for kid_ctx in flow::child_iter(flow) { for kid_ctx in flow::child_iter(flow) {
flow::mut_base(kid_ctx).restyle_damage.union_in_place(prop) flow::mut_base(kid_ctx).restyle_damage.insert(prop)
} }
} }
true true

View file

@ -3,6 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use layout::construct::{ConstructionResult, NoConstructionResult}; use layout::construct::{ConstructionResult, NoConstructionResult};
use layout::incremental::RestyleDamage;
use layout::parallel::DomParallelInfo; use layout::parallel::DomParallelInfo;
use layout::wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode}; use layout::wrapper::{LayoutNode, TLayoutNode, ThreadSafeLayoutNode};
@ -28,7 +29,7 @@ pub struct PrivateLayoutData {
pub after_style: Option<Arc<ComputedValues>>, pub after_style: Option<Arc<ComputedValues>>,
/// Description of how to account for recent style changes. /// Description of how to account for recent style changes.
pub restyle_damage: Option<int>, pub restyle_damage: Option<RestyleDamage>,
/// The current results of flow construction for this node. This is either a flow or a /// The current results of flow construction for this node. This is either a flow or a
/// `ConstructionItem`. See comments in `construct.rs` for more details. /// `ConstructionItem`. See comments in `construct.rs` for more details.