aboutsummaryrefslogtreecommitdiffstats
path: root/components/layout/flow.rs
diff options
context:
space:
mode:
Diffstat (limited to 'components/layout/flow.rs')
-rw-r--r--components/layout/flow.rs85
1 files changed, 68 insertions, 17 deletions
diff --git a/components/layout/flow.rs b/components/layout/flow.rs
index 6d319bdd991..f606a8355f9 100644
--- a/components/layout/flow.rs
+++ b/components/layout/flow.rs
@@ -502,6 +502,17 @@ pub trait MutableOwnedFlowUtils {
///
/// Set this flow as the Containing Block for all the absolute descendants.
fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants);
+
+ /// Sets the flow as the containing block for all absolute descendants that have been marked
+ /// as having reached their containing block. This is needed in order to handle cases like:
+ ///
+ /// <div>
+ /// <span style="position: relative">
+ /// <span style="position: absolute; ..."></span>
+ /// </span>
+ /// </div>
+ fn take_applicable_absolute_descendants(&mut self,
+ absolute_descendants: &mut AbsoluteDescendants);
}
#[derive(RustcEncodable, PartialEq, Debug)]
@@ -723,6 +734,7 @@ impl AbsoluteDescendants {
pub fn push(&mut self, given_descendant: FlowRef) {
self.descendant_links.push(AbsoluteDescendantInfo {
flow: given_descendant,
+ has_reached_containing_block: false,
});
}
@@ -741,29 +753,38 @@ impl AbsoluteDescendants {
iter: self.descendant_links.iter_mut(),
}
}
+
+ /// Mark these descendants as having reached their containing block.
+ pub fn mark_as_having_reached_containing_block(&mut self) {
+ for descendant_info in self.descendant_links.iter_mut() {
+ descendant_info.has_reached_containing_block = true
+ }
+ }
}
-/// TODO(pcwalton): This structure is going to need a flag to record whether the absolute
-/// descendants have reached their containing block yet. The reason is so that we can handle cases
-/// like the following:
-///
-/// <div>
-/// <span id=a style="position: absolute; ...">foo</span>
-/// <span style="position: relative">
-/// <span id=b style="position: absolute; ...">bar</span>
-/// </span>
-/// </div>
-///
-/// When we go to create the `InlineFlow` for the outer `div`, our absolute descendants will
-/// be `a` and `b`. At this point, we need a way to distinguish between the two, because the
-/// containing block for `a` will be different from the containing block for `b`. Specifically,
-/// the latter's containing block is the inline flow itself, while the former's containing
-/// block is going to be some parent of the outer `div`. Hence we need this flag as a way to
-/// distinguish the two; it will be false for `a` and true for `b`.
+/// Information about each absolutely-positioned descendant of the given flow.
#[derive(Clone)]
pub struct AbsoluteDescendantInfo {
/// The absolute descendant flow in question.
flow: FlowRef,
+
+ /// Whether the absolute descendant has reached its containing block. This exists so that we
+ /// can handle cases like the following:
+ ///
+ /// <div>
+ /// <span id=a style="position: absolute; ...">foo</span>
+ /// <span style="position: relative">
+ /// <span id=b style="position: absolute; ...">bar</span>
+ /// </span>
+ /// </div>
+ ///
+ /// When we go to create the `InlineFlow` for the outer `div`, our absolute descendants will
+ /// be `a` and `b`. At this point, we need a way to distinguish between the two, because the
+ /// containing block for `a` will be different from the containing block for `b`. Specifically,
+ /// the latter's containing block is the inline flow itself, while the former's containing
+ /// block is going to be some parent of the outer `div`. Hence we need this flag as a way to
+ /// distinguish the two; it will be false for `a` and true for `b`.
+ has_reached_containing_block: bool,
}
pub struct AbsoluteDescendantIter<'a> {
@@ -1368,6 +1389,36 @@ impl MutableOwnedFlowUtils for FlowRef {
let this = self.clone();
let base = mut_base(flow_ref::deref_mut(self));
base.abs_descendants = abs_descendants;
+ for descendant_link in base.abs_descendants.descendant_links.iter_mut() {
+ debug_assert!(!descendant_link.has_reached_containing_block);
+ let descendant_base = mut_base(flow_ref::deref_mut(&mut descendant_link.flow));
+ descendant_base.absolute_cb.set(this.clone());
+ }
+ }
+
+ /// Sets the flow as the containing block for all absolute descendants that have been marked
+ /// as having reached their containing block. This is needed in order to handle cases like:
+ ///
+ /// <div>
+ /// <span style="position: relative">
+ /// <span style="position: absolute; ..."></span>
+ /// </span>
+ /// </div>
+ fn take_applicable_absolute_descendants(&mut self,
+ absolute_descendants: &mut AbsoluteDescendants) {
+ let mut applicable_absolute_descendants = AbsoluteDescendants::new();
+ for absolute_descendant in absolute_descendants.descendant_links.iter() {
+ if absolute_descendant.has_reached_containing_block {
+ applicable_absolute_descendants.push(absolute_descendant.flow.clone());
+ }
+ }
+ absolute_descendants.descendant_links.retain(|descendant| {
+ !descendant.has_reached_containing_block
+ });
+
+ let this = self.clone();
+ let base = mut_base(flow_ref::deref_mut(self));
+ base.abs_descendants = applicable_absolute_descendants;
for descendant_link in base.abs_descendants.iter() {
let descendant_base = mut_base(descendant_link);
descendant_base.absolute_cb.set(this.clone());