layout: Make the compositor rather than layout determine the position of

each iframe.

The old code that attempted to do this during layout wasn't able to work
for multiple reasons: it couldn't know where the iframe was going to be
on the page (because of nested iframes), and at the time it was building
the display list for a fragment it couldn't know where that fragment was
going to be in page coordinates.

This patch rewrites that code so that both the sizes and positions of
iframes are determined by the compositor. Layout layerizes all iframes
and marks the iframe layers with the appropriate pipeline and subpage
IDs so that the compositor can place them correctly. This approach is
similar in spirit to Gecko's `RefLayer` infrastructure. The logic that
determines when it is time to take the screenshot for reftests has been
significantly revamped to deal with this change in delegation of
responsibility.

Additionally, this code removes the infrastructure that sends layout
data back to the layout task to be destroyed, since it is now all
thread-safe and can be destroyed on the script task.

The failing tests now fail because of a pre-existing bug related to
intrinsic heights and borders on inline replaced elements. They happened
to pass before because we never rendered the iframes at all, which meant
they never had a chance to draw the red border the tests expect to not
render!

Closes #7377.
This commit is contained in:
Patrick Walton 2015-08-27 16:29:57 -07:00
parent ed0d70e234
commit c72d0c2ed0
20 changed files with 602 additions and 389 deletions

View file

@ -9,7 +9,7 @@ use context::LayoutContext;
use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding};
use euclid::{Point2D, Rect, Size2D};
use floats::{FloatKind, Floats, PlacementInfo};
use flow::{EarlyAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow};
use flow::{EarlyAbsolutePositionInfo, LAYERS_NEEDED_FOR_DESCENDANTS, MutableFlowUtils, OpaqueFlow};
use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, IS_ABSOLUTELY_POSITIONED};
use flow_ref;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
@ -1465,6 +1465,7 @@ impl Flow for InlineFlow {
// Now, go through each line and lay out the fragments inside.
let mut line_distance_from_flow_block_start = Au(0);
let mut layers_needed_for_descendants = false;
let line_count = self.lines.len();
for line_index in 0..line_count {
let line = &mut self.lines[line_index];
@ -1493,6 +1494,10 @@ impl Flow for InlineFlow {
for fragment_index in line.range.each_index() {
let fragment = &mut self.fragments.fragments[fragment_index.to_usize()];
if fragment.needs_layer() && !fragment.is_positioned() {
layers_needed_for_descendants = true
}
let InlineMetrics {
mut block_size_above_baseline,
mut depth_below_baseline,
@ -1589,6 +1594,10 @@ impl Flow for InlineFlow {
kid.assign_block_size_for_inorder_child_if_necessary(layout_context, thread_id);
}
// Mark ourselves for layerization if that will be necessary to paint in the proper
// order (CSS 2.1, Appendix E).
self.base.flags.set(LAYERS_NEEDED_FOR_DESCENDANTS, layers_needed_for_descendants);
if self.contains_positioned_fragments() {
// Assign block-sizes for all flows in this absolute flow tree.
// This is preorder because the block-size of an absolute flow may depend on
@ -1773,10 +1782,12 @@ impl Flow for InlineFlow {
fn compute_overflow(&self) -> Rect<Au> {
let mut overflow = ZERO_RECT;
let flow_size = self.base.position.size.to_physical(self.base.writing_mode);
let relative_containing_block_size =
&self.base.early_absolute_position_info.relative_containing_block_size;
for fragment in &self.fragments.fragments {
overflow = overflow.union(&fragment.compute_overflow(
&self.base.early_absolute_position_info.relative_containing_block_size,
self.base.early_absolute_position_info.relative_containing_block_mode));
overflow = overflow.union(&fragment.compute_overflow(&flow_size,
&relative_containing_block_size))
}
overflow
}