mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Auto merge of #7177 - pcwalton:intervening-inline-block, r=mbrubeck
layout: Improve our handling of inline absolute containing blocks. Several issues are addressed in this commit: * Inline flows now bubble up their absolute descendants instead of making the inline flow the containing block for them. (In the future, we will need to make the inline flow *sometimes* be the containing block for them, but for now it improves sites to unconditionally bubble up.) * Fragments now look at their inline fragment context to determine whether they are positioned. * Inline flows now push the stacking-relative position of the absolute containing block down to their inline-block fragments. * Inline absolute hypothetical fragments can be containing blocks. * Fixes the logic in `containing_block_range_for_flow_surrounding_fragment_at_index`. The condition to determine whether fragments are positioned was inverted! * `Descendants`/`AbsDescendants` has been refactored in order to become more friendly to inline absolute containing blocks in the future. Improves the inline position of the green drop-down arrow in the Google SERPs. (The block position is still wrong.) r? @mbrubeck <!-- Reviewable:start --> [<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7177) <!-- Reviewable:end -->
This commit is contained in:
commit
d654841288
10 changed files with 236 additions and 93 deletions
|
@ -499,7 +499,7 @@ pub trait MutableOwnedFlowUtils {
|
|||
/// Set absolute descendants for this flow.
|
||||
///
|
||||
/// Set this flow as the Containing Block for all the absolute descendants.
|
||||
fn set_absolute_descendants(&mut self, abs_descendants: AbsDescendants);
|
||||
fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants);
|
||||
}
|
||||
|
||||
#[derive(RustcEncodable, PartialEq, Debug)]
|
||||
|
@ -694,19 +694,17 @@ impl FlowFlags {
|
|||
}
|
||||
}
|
||||
|
||||
/// The Descendants of a flow.
|
||||
///
|
||||
/// Also, details about their position wrt this flow.
|
||||
/// Absolutely-positioned descendants of this flow.
|
||||
#[derive(Clone)]
|
||||
pub struct Descendants {
|
||||
pub struct AbsoluteDescendants {
|
||||
/// Links to every descendant. This must be private because it is unsafe to leak `FlowRef`s to
|
||||
/// layout.
|
||||
descendant_links: Vec<FlowRef>,
|
||||
descendant_links: Vec<AbsoluteDescendantInfo>,
|
||||
}
|
||||
|
||||
impl Descendants {
|
||||
pub fn new() -> Descendants {
|
||||
Descendants {
|
||||
impl AbsoluteDescendants {
|
||||
pub fn new() -> AbsoluteDescendants {
|
||||
AbsoluteDescendants {
|
||||
descendant_links: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
@ -720,40 +718,63 @@ impl Descendants {
|
|||
}
|
||||
|
||||
pub fn push(&mut self, given_descendant: FlowRef) {
|
||||
self.descendant_links.push(given_descendant);
|
||||
self.descendant_links.push(AbsoluteDescendantInfo {
|
||||
flow: given_descendant,
|
||||
});
|
||||
}
|
||||
|
||||
/// Push the given descendants on to the existing descendants.
|
||||
///
|
||||
/// Ignore any static y offsets, because they are None before layout.
|
||||
pub fn push_descendants(&mut self, given_descendants: Descendants) {
|
||||
pub fn push_descendants(&mut self, given_descendants: AbsoluteDescendants) {
|
||||
for elem in given_descendants.descendant_links.into_iter() {
|
||||
self.descendant_links.push(elem);
|
||||
}
|
||||
}
|
||||
|
||||
/// Return an iterator over the descendant flows.
|
||||
pub fn iter<'a>(&'a mut self) -> DescendantIter<'a> {
|
||||
DescendantIter {
|
||||
pub fn iter<'a>(&'a mut self) -> AbsoluteDescendantIter<'a> {
|
||||
AbsoluteDescendantIter {
|
||||
iter: self.descendant_links.iter_mut(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub type AbsDescendants = Descendants;
|
||||
|
||||
pub struct DescendantIter<'a> {
|
||||
iter: IterMut<'a, FlowRef>,
|
||||
/// 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`.
|
||||
#[derive(Clone)]
|
||||
pub struct AbsoluteDescendantInfo {
|
||||
/// The absolute descendant flow in question.
|
||||
flow: FlowRef,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for DescendantIter<'a> {
|
||||
pub struct AbsoluteDescendantIter<'a> {
|
||||
iter: IterMut<'a, AbsoluteDescendantInfo>,
|
||||
}
|
||||
|
||||
impl<'a> Iterator for AbsoluteDescendantIter<'a> {
|
||||
type Item = &'a mut (Flow + 'a);
|
||||
fn next(&mut self) -> Option<&'a mut (Flow + 'a)> {
|
||||
self.iter.next().map(|flow| &mut **flow)
|
||||
self.iter.next().map(|info| &mut *info.flow)
|
||||
}
|
||||
}
|
||||
|
||||
pub type DescendantOffsetIter<'a> = Zip<DescendantIter<'a>, IterMut<'a, Au>>;
|
||||
pub type AbsoluteDescendantOffsetIter<'a> = Zip<AbsoluteDescendantIter<'a>, IterMut<'a, Au>>;
|
||||
|
||||
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
|
||||
/// confused with absolutely-positioned flows).
|
||||
|
@ -837,7 +858,7 @@ pub struct BaseFlow {
|
|||
|
||||
/// Details about descendants with position 'absolute' or 'fixed' for which we are the
|
||||
/// containing block. This is in tree order. This includes any direct children.
|
||||
pub abs_descendants: AbsDescendants,
|
||||
pub abs_descendants: AbsoluteDescendants,
|
||||
|
||||
/// The inline-size of the block container of this flow. Used for computing percentage and
|
||||
/// automatic values for `width`.
|
||||
|
@ -1034,7 +1055,7 @@ impl BaseFlow {
|
|||
floats: Floats::new(writing_mode),
|
||||
collapsible_margins: CollapsibleMargins::new(),
|
||||
stacking_relative_position: Point2D::zero(),
|
||||
abs_descendants: Descendants::new(),
|
||||
abs_descendants: AbsoluteDescendants::new(),
|
||||
block_container_inline_size: Au(0),
|
||||
block_container_writing_mode: writing_mode,
|
||||
block_container_explicit_block_size: None,
|
||||
|
@ -1367,7 +1388,7 @@ impl MutableOwnedFlowUtils for FlowRef {
|
|||
/// This is called during flow construction, so nothing else can be accessing the descendant
|
||||
/// flows. This is enforced by the fact that we have a mutable `FlowRef`, which only flow
|
||||
/// construction is allowed to possess.
|
||||
fn set_absolute_descendants(&mut self, abs_descendants: AbsDescendants) {
|
||||
fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants) {
|
||||
let this = self.clone();
|
||||
let base = mut_base(&mut **self);
|
||||
base.abs_descendants = abs_descendants;
|
||||
|
@ -1414,7 +1435,10 @@ impl ContainingBlockLink {
|
|||
panic!("Link to containing block not established; perhaps you forgot to call \
|
||||
`set_absolute_descendants`?")
|
||||
}
|
||||
Some(ref link) => link.upgrade().unwrap().generated_containing_block_size(for_flow),
|
||||
Some(ref link) => {
|
||||
let flow = link.upgrade().unwrap();
|
||||
flow.generated_containing_block_size(for_flow)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1429,6 +1453,8 @@ impl ContainingBlockLink {
|
|||
let flow = link.upgrade().unwrap();
|
||||
if flow.is_block_like() {
|
||||
flow.as_immutable_block().explicit_block_containing_size(layout_context)
|
||||
} else if flow.is_inline_flow() {
|
||||
Some(flow.as_immutable_inline().minimum_block_size_above_baseline)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue