Auto merge of #7313 - pcwalton:position-relative-percentage-overflow, r=mbrubeck

layout: Make overflow calculation take relative percentages into account.

This necessitated changing overflow to be calculated by the parent flow
if relatively positioned children are present. That is because the
overflow regions cannot be calculated without knowing relative offsets,
which themselves cannot be calculated without knowing the parent size
(because of percentages). To accomplish this without sacrificing
parallelism in the non-relative case, this patch splits overflow into
"early" and "late" computation. Late overflow computation cannot be
parallelized across children, while early overflow computation can.

Makes the "Apple Music" text show up over the full-bleed promotional
background on apple.com.

r? @SimonSapin -- would appreciate a look over the iframe test case that was changed.

<!-- Reviewable:start -->
[<img src="https://reviewable.io/review_button.png" height=40 alt="Review on Reviewable"/>](https://reviewable.io/reviews/servo/servo/7313)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2015-09-01 12:33:07 -06:00
commit dcaf66397a
19 changed files with 223 additions and 108 deletions

View file

@ -36,10 +36,10 @@ use flow::{CLEARS_LEFT, CLEARS_RIGHT};
use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC};
use flow::{IS_ABSOLUTELY_POSITIONED};
use flow::{ImmutableFlowUtils, MutableFlowUtils, OpaqueFlow, PreorderFlowTraversal};
use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow};
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
use flow::{PostorderFlowTraversal, mut_base};
use flow::{self, AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow};
use flow::{PostorderFlowTraversal, PreorderFlowTraversal, mut_base};
use flow::{self, BaseFlow, EarlyAbsolutePositionInfo, ForceNonfloatedFlag, FlowClass, Flow};
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER};
use fragment::{SpecificFragmentInfo};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
@ -485,7 +485,7 @@ impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
}
}
flow.store_overflow(self.layout_context);
flow.early_store_overflow(self.layout_context);
}
}
@ -959,6 +959,19 @@ impl BlockFlow {
//
// FIXME(pcwalton): This looks not idempotent. Is it?
self.fragment.border_box.size.block = block_size;
}
// Write in the size of the relative containing block for children. (This information
// is also needed to handle RTL.)
for kid in self.base.child_iter() {
flow::mut_base(kid).early_absolute_position_info = EarlyAbsolutePositionInfo {
relative_containing_block_size: self.fragment.content_box().size,
relative_containing_block_mode: self.fragment.style().writing_mode,
};
kid.late_store_overflow(layout_context)
}
if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
return
}
@ -1730,7 +1743,7 @@ impl Flow for BlockFlow {
self.base.thread_id = parent_thread_id;
if self.base.restyle_damage.intersects(REFLOW_OUT_OF_FLOW | REFLOW) {
self.assign_block_size(layout_context);
self.store_overflow(layout_context);
(self as &mut Flow).early_store_overflow(layout_context);
// Don't remove the restyle damage; `assign_block_size` decides whether that is
// appropriate (which in the case of e.g. absolutely-positioned flows, it is not).
}
@ -1775,7 +1788,7 @@ impl Flow for BlockFlow {
fn compute_absolute_position(&mut self, layout_context: &LayoutContext) {
if (self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
self.base.absolute_position_info.layers_needed_for_positioned_flows) ||
self.base.late_absolute_position_info.layers_needed_for_positioned_flows) ||
self.base.flags.contains(NEEDS_LAYER) {
self.fragment.flags.insert(HAS_LAYER)
}
@ -1816,7 +1829,7 @@ impl Flow for BlockFlow {
// Absolute position of the containing block + position of absolute
// flow w.r.t. the containing block.
self.base
.absolute_position_info
.late_absolute_position_info
.stacking_relative_position_of_absolute_containing_block + position_start
};
@ -1842,13 +1855,13 @@ impl Flow for BlockFlow {
// other hand, is only established if we are positioned.
let relative_offset =
self.fragment.relative_position(&self.base
.absolute_position_info
.early_absolute_position_info
.relative_containing_block_size);
if self.contains_positioned_fragments() {
let border_box_origin = (self.fragment.border_box -
self.fragment.style.logical_border_width()).start;
self.base
.absolute_position_info
.late_absolute_position_info
.stacking_relative_position_of_absolute_containing_block =
self.base.stacking_relative_position +
(border_box_origin + relative_offset).to_physical(self.base.writing_mode,
@ -1875,14 +1888,12 @@ impl Flow for BlockFlow {
}
} else {
self.base
.absolute_position_info
.late_absolute_position_info
.stacking_relative_position_of_absolute_containing_block
};
let absolute_position_info_for_children = AbsolutePositionInfo {
let late_absolute_position_info_for_children = LateAbsolutePositionInfo {
stacking_relative_position_of_absolute_containing_block:
stacking_relative_position_of_absolute_containing_block_for_children,
relative_containing_block_size: self.fragment.content_box().size,
relative_containing_block_mode: self.base.writing_mode,
layers_needed_for_positioned_flows: self.base
.flags
.contains(LAYERS_NEEDED_FOR_DESCENDANTS),
@ -1934,10 +1945,10 @@ impl Flow for BlockFlow {
self.fragment
.stacking_relative_border_box(&self.base.stacking_relative_position,
&self.base
.absolute_position_info
.early_absolute_position_info
.relative_containing_block_size,
self.base
.absolute_position_info
.early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Own);
let clip = self.fragment.clipping_region_for_children(
@ -1985,7 +1996,8 @@ impl Flow for BlockFlow {
}
}
flow::mut_base(kid).absolute_position_info = absolute_position_info_for_children;
flow::mut_base(kid).late_absolute_position_info =
late_absolute_position_info_for_children;
flow::mut_base(kid).clip = clip.clone();
flow::mut_base(kid).stacking_relative_position_of_display_port =
stacking_relative_position_of_display_port_for_children;
@ -2056,7 +2068,9 @@ impl Flow for BlockFlow {
}
fn compute_overflow(&self) -> Rect<Au> {
self.fragment.compute_overflow()
self.fragment.compute_overflow(&self.base
.early_absolute_position_info
.relative_containing_block_size)
}
fn iterate_through_fragment_border_boxes(&self,
@ -2072,10 +2086,10 @@ impl Flow for BlockFlow {
&self.fragment
.stacking_relative_border_box(&self.base.stacking_relative_position,
&self.base
.absolute_position_info
.early_absolute_position_info
.relative_containing_block_size,
self.base
.absolute_position_info
.early_absolute_position_info
.relative_containing_block_mode,
CoordinateSystem::Own)
.translate(stacking_context_position));