1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
|
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
use bitflags::bitflags;
use style::computed_values::float::T as Float;
use style::selector_parser::RestyleDamage;
use style::servo::restyle_damage::ServoRestyleDamage;
use crate::flow::{Flow, FlowFlags, GetBaseFlow};
/// Used in a flow traversal to indicate whether this re-layout should be incremental or not.
#[derive(Clone, Copy, PartialEq)]
pub enum RelayoutMode {
Incremental,
Force,
}
bitflags! {
pub struct SpecialRestyleDamage: u8 {
/// If this flag is set, we need to reflow the entire document. This is more or less a
/// temporary hack to deal with cases that we don't handle incrementally yet.
const REFLOW_ENTIRE_DOCUMENT = 0x01;
}
}
impl dyn Flow {
pub fn compute_layout_damage(&mut self) -> SpecialRestyleDamage {
let mut special_damage = SpecialRestyleDamage::empty();
let is_absolutely_positioned = self
.base()
.flags
.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
// In addition to damage, we use this phase to compute whether nodes affect CSS counters.
let mut has_counter_affecting_children = false;
{
let self_base = self.mut_base();
// Take a snapshot of the parent damage before updating it with damage from children.
let parent_damage = self_base.restyle_damage;
for kid in self_base.children.iter_mut() {
let child_is_absolutely_positioned = kid
.base()
.flags
.contains(FlowFlags::IS_ABSOLUTELY_POSITIONED);
kid.mut_base().restyle_damage.insert(
parent_damage
.damage_for_child(is_absolutely_positioned, child_is_absolutely_positioned),
);
{
let kid: &mut dyn Flow = kid;
special_damage.insert(kid.compute_layout_damage());
}
self_base.restyle_damage.insert(
kid.base()
.restyle_damage
.damage_for_parent(child_is_absolutely_positioned),
);
has_counter_affecting_children = has_counter_affecting_children ||
kid.base().flags.intersects(
FlowFlags::AFFECTS_COUNTERS | FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN,
);
}
}
let self_base = self.mut_base();
if self_base.flags.float_kind() != Float::None &&
self_base
.restyle_damage
.intersects(ServoRestyleDamage::REFLOW)
{
special_damage.insert(SpecialRestyleDamage::REFLOW_ENTIRE_DOCUMENT);
}
if has_counter_affecting_children {
self_base
.flags
.insert(FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN)
} else {
self_base
.flags
.remove(FlowFlags::HAS_COUNTER_AFFECTING_CHILDREN)
}
special_damage
}
pub fn reflow_entire_document(&mut self) {
let self_base = self.mut_base();
self_base
.restyle_damage
.insert(RestyleDamage::rebuild_and_reflow());
self_base
.restyle_damage
.remove(ServoRestyleDamage::RECONSTRUCT_FLOW);
for kid in self_base.children.iter_mut() {
kid.reflow_entire_document();
}
}
}
|