diff options
Diffstat (limited to 'components/layout/flow.rs')
-rw-r--r-- | components/layout/flow.rs | 85 |
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()); |