mirror of
https://github.com/servo/servo.git
synced 2025-06-06 16:45:39 +00:00
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.
This commit is contained in:
parent
108251bece
commit
b66f17a445
12 changed files with 203 additions and 75 deletions
|
@ -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));
|
||||
|
|
|
@ -1152,9 +1152,9 @@ impl FragmentDisplayListBuilding for Fragment {
|
|||
StackingContextCreationMode::Normal |
|
||||
StackingContextCreationMode::OuterScrollWrapper => {
|
||||
self.stacking_relative_border_box(&base_flow.stacking_relative_position,
|
||||
&base_flow.absolute_position_info
|
||||
&base_flow.early_absolute_position_info
|
||||
.relative_containing_block_size,
|
||||
base_flow.absolute_position_info
|
||||
base_flow.early_absolute_position_info
|
||||
.relative_containing_block_mode,
|
||||
CoordinateSystem::Parent)
|
||||
}
|
||||
|
@ -1533,8 +1533,12 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
.build_display_list(display_list,
|
||||
layout_context,
|
||||
&self.base.stacking_relative_position,
|
||||
&self.base.absolute_position_info.relative_containing_block_size,
|
||||
self.base.absolute_position_info.relative_containing_block_mode,
|
||||
&self.base
|
||||
.early_absolute_position_info
|
||||
.relative_containing_block_size,
|
||||
self.base
|
||||
.early_absolute_position_info
|
||||
.relative_containing_block_mode,
|
||||
border_painting_mode,
|
||||
background_border_level,
|
||||
&clip,
|
||||
|
@ -1616,8 +1620,8 @@ impl BlockFlowDisplayListBuilding for BlockFlow {
|
|||
&mut outer_display_list_for_overflow_scroll,
|
||||
layout_context,
|
||||
&self.base.stacking_relative_position,
|
||||
&self.base.absolute_position_info.relative_containing_block_size,
|
||||
self.base.absolute_position_info.relative_containing_block_mode,
|
||||
&self.base.early_absolute_position_info.relative_containing_block_size,
|
||||
self.base.early_absolute_position_info.relative_containing_block_mode,
|
||||
border_painting_mode,
|
||||
BackgroundAndBorderLevel::RootOfStackingContext,
|
||||
&clip,
|
||||
|
@ -1775,10 +1779,10 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
|
|||
layout_context,
|
||||
&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,
|
||||
BorderPaintingMode::Separate,
|
||||
BackgroundAndBorderLevel::Content,
|
||||
|
@ -1857,11 +1861,11 @@ impl ListItemFlowDisplayListBuilding for ListItemFlow {
|
|||
&self.block_flow.base.stacking_relative_position,
|
||||
&self.block_flow
|
||||
.base
|
||||
.absolute_position_info
|
||||
.early_absolute_position_info
|
||||
.relative_containing_block_size,
|
||||
self.block_flow
|
||||
.base
|
||||
.absolute_position_info
|
||||
.early_absolute_position_info
|
||||
.relative_containing_block_mode,
|
||||
BorderPaintingMode::Separate,
|
||||
BackgroundAndBorderLevel::Content,
|
||||
|
|
|
@ -222,7 +222,11 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
|
|||
if impacted {
|
||||
mut_base(self).thread_id = parent_thread_id;
|
||||
self.assign_block_size(layout_context);
|
||||
self.store_overflow(layout_context);
|
||||
// FIXME(pcwalton): Should use `early_store_overflow()` here but that fails due to a
|
||||
// compiler bug (`Self` does not have a constant size).
|
||||
if !self.contains_relatively_positioned_fragments() {
|
||||
self.store_overflow(layout_context)
|
||||
}
|
||||
mut_base(self).restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
|
||||
}
|
||||
impacted
|
||||
|
@ -246,7 +250,7 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
|
|||
match self.class() {
|
||||
FlowClass::Block |
|
||||
FlowClass::TableCaption |
|
||||
FlowClass::TableCell if !base(self).children.is_empty() => {
|
||||
FlowClass::TableCell => {
|
||||
// FIXME(#2795): Get the real container size.
|
||||
let container_size = Size2D::zero();
|
||||
for kid in mut_base(self).children.iter_mut() {
|
||||
|
@ -310,13 +314,6 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
|
|||
// different behaviour for different types of Flow, so they can't go into
|
||||
// the Immutable / Mutable Flow Utils traits without additional casts.
|
||||
|
||||
/// Return true if store overflow is delayed for this flow.
|
||||
///
|
||||
/// Currently happens only for absolutely positioned flows.
|
||||
fn is_store_overflow_delayed(&mut self) -> bool {
|
||||
false
|
||||
}
|
||||
|
||||
fn is_root(&self) -> bool {
|
||||
false
|
||||
}
|
||||
|
@ -459,6 +456,11 @@ pub trait ImmutableFlowUtils {
|
|||
/// Returns true if this flow is an inline flow.
|
||||
fn is_inline_flow(self) -> bool;
|
||||
|
||||
/// Returns true if this flow can have its overflow area calculated early (during its
|
||||
/// block-size assignment) or false if it must have its overflow area calculated late (during
|
||||
/// its parent's block-size assignment).
|
||||
fn can_calculate_overflow_area_early(self) -> bool;
|
||||
|
||||
/// Dumps the flow tree for debugging.
|
||||
fn dump(self);
|
||||
|
||||
|
@ -495,6 +497,12 @@ pub trait MutableFlowUtils {
|
|||
/// Calls `repair_style` and `bubble_inline_sizes`. You should use this method instead of
|
||||
/// calling them individually, since there is no reason not to perform both operations.
|
||||
fn repair_style_and_bubble_inline_sizes(self, style: &Arc<ComputedValues>);
|
||||
|
||||
/// Calls `store_overflow()` if the overflow can be calculated early.
|
||||
fn early_store_overflow(self, layout_context: &LayoutContext);
|
||||
|
||||
/// Calls `store_overflow()` if the overflow cannot be calculated early.
|
||||
fn late_store_overflow(self, layout_context: &LayoutContext);
|
||||
}
|
||||
|
||||
pub trait MutableOwnedFlowUtils {
|
||||
|
@ -780,15 +788,30 @@ impl<'a> Iterator for AbsoluteDescendantIter<'a> {
|
|||
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).
|
||||
#[derive(RustcEncodable, Copy, Clone)]
|
||||
pub struct AbsolutePositionInfo {
|
||||
/// confused with absolutely-positioned flows) that is computed during block-size assignment.
|
||||
pub struct EarlyAbsolutePositionInfo {
|
||||
/// The size of the containing block for relatively-positioned descendants.
|
||||
pub relative_containing_block_size: LogicalSize<Au>,
|
||||
|
||||
/// The writing mode for `relative_containing_block_size`.
|
||||
pub relative_containing_block_mode: WritingMode,
|
||||
}
|
||||
|
||||
impl EarlyAbsolutePositionInfo {
|
||||
pub fn new(writing_mode: WritingMode) -> EarlyAbsolutePositionInfo {
|
||||
// FIXME(pcwalton): The initial relative containing block-size should be equal to the size
|
||||
// of the root layer.
|
||||
EarlyAbsolutePositionInfo {
|
||||
relative_containing_block_size: LogicalSize::zero(writing_mode),
|
||||
relative_containing_block_mode: writing_mode,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
|
||||
/// confused with absolutely-positioned flows) that is computed during final position assignment.
|
||||
#[derive(RustcEncodable, Copy, Clone)]
|
||||
pub struct LateAbsolutePositionInfo {
|
||||
/// The position of the absolute containing block relative to the nearest ancestor stacking
|
||||
/// context. If the absolute containing block establishes the stacking context for this flow,
|
||||
/// and this flow is not itself absolutely-positioned, then this is (0, 0).
|
||||
|
@ -800,13 +823,9 @@ pub struct AbsolutePositionInfo {
|
|||
pub layers_needed_for_positioned_flows: bool,
|
||||
}
|
||||
|
||||
impl AbsolutePositionInfo {
|
||||
pub fn new(writing_mode: WritingMode) -> AbsolutePositionInfo {
|
||||
// FIXME(pcwalton): The initial relative containing block-size should be equal to the size
|
||||
// of the root layer.
|
||||
AbsolutePositionInfo {
|
||||
relative_containing_block_size: LogicalSize::zero(writing_mode),
|
||||
relative_containing_block_mode: writing_mode,
|
||||
impl LateAbsolutePositionInfo {
|
||||
pub fn new() -> LateAbsolutePositionInfo {
|
||||
LateAbsolutePositionInfo {
|
||||
stacking_relative_position_of_absolute_containing_block: Point2D::zero(),
|
||||
layers_needed_for_positioned_flows: false,
|
||||
}
|
||||
|
@ -875,8 +894,13 @@ pub struct BaseFlow {
|
|||
pub absolute_cb: ContainingBlockLink,
|
||||
|
||||
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
|
||||
/// confused with absolutely-positioned flows).
|
||||
pub absolute_position_info: AbsolutePositionInfo,
|
||||
/// confused with absolutely-positioned flows) that is computed during block-size assignment.
|
||||
pub early_absolute_position_info: EarlyAbsolutePositionInfo,
|
||||
|
||||
/// Information needed to compute absolute (i.e. viewport-relative) flow positions (not to be
|
||||
/// confused with absolutely-positioned flows) that is computed during final position
|
||||
/// assignment.
|
||||
pub late_absolute_position_info: LateAbsolutePositionInfo,
|
||||
|
||||
/// The clipping region for this flow and its descendants, in layer coordinates.
|
||||
pub clip: ClippingRegion,
|
||||
|
@ -1038,7 +1062,8 @@ impl BaseFlow {
|
|||
block_container_explicit_block_size: None,
|
||||
absolute_cb: ContainingBlockLink::new(),
|
||||
display_list_building_result: DisplayListBuildingResult::None,
|
||||
absolute_position_info: AbsolutePositionInfo::new(writing_mode),
|
||||
early_absolute_position_info: EarlyAbsolutePositionInfo::new(writing_mode),
|
||||
late_absolute_position_info: LateAbsolutePositionInfo::new(),
|
||||
clip: ClippingRegion::max(),
|
||||
stacking_relative_position_of_display_port: Rect::zero(),
|
||||
flags: flags,
|
||||
|
@ -1276,6 +1301,13 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
|
|||
}
|
||||
}
|
||||
|
||||
/// Returns true if this flow can have its overflow area calculated early (during its
|
||||
/// block-size assignment) or false if it must have its overflow area calculated late (during
|
||||
/// its parent's block-size assignment).
|
||||
fn can_calculate_overflow_area_early(self) -> bool {
|
||||
!self.contains_relatively_positioned_fragments()
|
||||
}
|
||||
|
||||
/// Dumps the flow tree for debugging.
|
||||
fn dump(self) {
|
||||
self.dump_with_level(0)
|
||||
|
@ -1354,6 +1386,20 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
|||
|
||||
traversal.process(*self)
|
||||
}
|
||||
|
||||
/// Calls `store_overflow()` if the overflow can be calculated early.
|
||||
fn early_store_overflow(self, layout_context: &LayoutContext) {
|
||||
if self.can_calculate_overflow_area_early() {
|
||||
self.store_overflow(layout_context)
|
||||
}
|
||||
}
|
||||
|
||||
/// Calls `store_overflow()` if the overflow cannot be calculated early.
|
||||
fn late_store_overflow(self, layout_context: &LayoutContext) {
|
||||
if !self.can_calculate_overflow_area_early() {
|
||||
self.store_overflow(layout_context)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl MutableOwnedFlowUtils for FlowRef {
|
||||
|
|
|
@ -2049,7 +2049,7 @@ impl Fragment {
|
|||
}
|
||||
|
||||
/// Computes the overflow rect of this fragment relative to the start of the flow.
|
||||
pub fn compute_overflow(&self) -> Rect<Au> {
|
||||
pub fn compute_overflow(&self, relative_containing_block_size: &LogicalSize<Au>) -> Rect<Au> {
|
||||
// FIXME(pcwalton, #2795): Get the real container size.
|
||||
let container_size = Size2D::zero();
|
||||
let mut border_box = self.border_box.to_physical(self.style.writing_mode, container_size);
|
||||
|
@ -2058,10 +2058,9 @@ impl Fragment {
|
|||
//
|
||||
// FIXME(pcwalton): I'm not a fan of the way this makes us crawl though so many styles all
|
||||
// the time. Can't we handle relative positioning by just adjusting `border_box`?
|
||||
let relative_position =
|
||||
self.relative_position(&LogicalSize::zero(self.style.writing_mode));
|
||||
border_box = border_box.translate_by_size(&relative_position.to_physical(
|
||||
self.style.writing_mode));
|
||||
let relative_position = self.relative_position(relative_containing_block_size);
|
||||
border_box =
|
||||
border_box.translate_by_size(&relative_position.to_physical(self.style.writing_mode));
|
||||
let mut overflow = border_box;
|
||||
|
||||
// Box shadows cause us to draw outside our border box.
|
||||
|
|
|
@ -1645,10 +1645,10 @@ impl Flow for InlineFlow {
|
|||
let stacking_relative_border_box =
|
||||
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::Parent);
|
||||
let clip = fragment.clipping_region_for_children(&self.base.clip,
|
||||
|
@ -1661,13 +1661,14 @@ impl Flow for InlineFlow {
|
|||
flow::mut_base(flow).clip = clip;
|
||||
|
||||
let block_flow = flow.as_mut_block();
|
||||
block_flow.base.absolute_position_info = self.base.absolute_position_info;
|
||||
block_flow.base.late_absolute_position_info =
|
||||
self.base.late_absolute_position_info;
|
||||
|
||||
let stacking_relative_position = self.base.stacking_relative_position;
|
||||
if is_positioned {
|
||||
let padding_box_origin = containing_block_positions.next().unwrap();
|
||||
block_flow.base
|
||||
.absolute_position_info
|
||||
.late_absolute_position_info
|
||||
.stacking_relative_position_of_absolute_containing_block =
|
||||
stacking_relative_position + *padding_box_origin;
|
||||
}
|
||||
|
@ -1681,7 +1682,8 @@ impl Flow for InlineFlow {
|
|||
let flow = flow_ref::deref_mut(&mut info.flow_ref);
|
||||
flow::mut_base(flow).clip = clip;
|
||||
let block_flow = flow.as_mut_block();
|
||||
block_flow.base.absolute_position_info = self.base.absolute_position_info;
|
||||
block_flow.base.late_absolute_position_info =
|
||||
self.base.late_absolute_position_info;
|
||||
|
||||
block_flow.base.stacking_relative_position =
|
||||
stacking_relative_border_box.origin;
|
||||
|
@ -1693,12 +1695,13 @@ impl Flow for InlineFlow {
|
|||
flow::mut_base(flow).clip = clip;
|
||||
|
||||
let block_flow = flow.as_mut_block();
|
||||
block_flow.base.absolute_position_info = self.base.absolute_position_info;
|
||||
block_flow.base.late_absolute_position_info =
|
||||
self.base.late_absolute_position_info;
|
||||
|
||||
let stacking_relative_position = self.base.stacking_relative_position;
|
||||
let padding_box_origin = containing_block_positions.next().unwrap();
|
||||
block_flow.base
|
||||
.absolute_position_info
|
||||
.late_absolute_position_info
|
||||
.stacking_relative_position_of_absolute_containing_block =
|
||||
stacking_relative_position + *padding_box_origin;
|
||||
|
||||
|
@ -1725,7 +1728,8 @@ impl Flow for InlineFlow {
|
|||
fn compute_overflow(&self) -> Rect<Au> {
|
||||
let mut overflow = ZERO_RECT;
|
||||
for fragment in &self.fragments.fragments {
|
||||
overflow = overflow.union(&fragment.compute_overflow())
|
||||
overflow = overflow.union(&fragment.compute_overflow(
|
||||
&self.base.early_absolute_position_info.relative_containing_block_size))
|
||||
}
|
||||
overflow
|
||||
}
|
||||
|
@ -1742,9 +1746,9 @@ impl Flow for InlineFlow {
|
|||
|
||||
let stacking_relative_position = &self.base.stacking_relative_position;
|
||||
let relative_containing_block_size =
|
||||
&self.base.absolute_position_info.relative_containing_block_size;
|
||||
&self.base.early_absolute_position_info.relative_containing_block_size;
|
||||
let relative_containing_block_mode =
|
||||
self.base.absolute_position_info.relative_containing_block_mode;
|
||||
self.base.early_absolute_position_info.relative_containing_block_mode;
|
||||
iterator.process(fragment,
|
||||
level,
|
||||
&fragment.stacking_relative_border_box(stacking_relative_position,
|
||||
|
|
|
@ -184,11 +184,11 @@ impl Flow for ListItemFlow {
|
|||
.stacking_relative_position,
|
||||
&self.block_flow
|
||||
.base
|
||||
.absolute_position_info
|
||||
.early_absolute_position_info
|
||||
.relative_containing_block_size,
|
||||
self.block_flow
|
||||
.base
|
||||
.absolute_position_info
|
||||
.early_absolute_position_info
|
||||
.relative_containing_block_mode,
|
||||
CoordinateSystem::Own)
|
||||
.translate(stacking_context_position));
|
||||
|
|
|
@ -10,8 +10,8 @@ use block::{ISizeConstraintInput, ISizeConstraintSolution};
|
|||
use block::{self, BlockFlow, CandidateBSizeIterator, ISizeAndMarginsComputer};
|
||||
use context::LayoutContext;
|
||||
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
|
||||
use flow::{ImmutableFlowUtils, OpaqueFlow};
|
||||
use flow::{self, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
|
||||
use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS};
|
||||
use flow::{IMPACTED_BY_RIGHT_FLOATS, ImmutableFlowUtils, MutableFlowUtils, OpaqueFlow};
|
||||
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
|
||||
use layout_debug;
|
||||
|
@ -761,7 +761,7 @@ pub trait TableLikeFlow {
|
|||
|
||||
impl TableLikeFlow for BlockFlow {
|
||||
fn assign_block_size_for_table_like_flow<'a>(&mut self,
|
||||
_: &'a LayoutContext<'a>,
|
||||
layout_context: &'a LayoutContext<'a>,
|
||||
block_direction_spacing: Au) {
|
||||
debug_assert!(self.fragment.style.get_inheritedtable().border_collapse ==
|
||||
border_collapse::T::separate || block_direction_spacing == Au(0));
|
||||
|
@ -838,6 +838,16 @@ impl TableLikeFlow for BlockFlow {
|
|||
self.fragment.border_box.size.block = current_block_offset;
|
||||
self.fragment.border_box.start.b = Au(0);
|
||||
self.base.position.size.block = current_block_offset;
|
||||
|
||||
// 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)
|
||||
}
|
||||
}
|
||||
|
||||
self.base.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
use block::{BlockFlow, ISizeAndMarginsComputer};
|
||||
use context::LayoutContext;
|
||||
use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode};
|
||||
use flow::{self, FlowClass, Flow, ImmutableFlowUtils, OpaqueFlow};
|
||||
use flow::{self, EarlyAbsolutePositionInfo, FlowClass, Flow, ImmutableFlowUtils, OpaqueFlow};
|
||||
use flow_list::MutFlowListIterator;
|
||||
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||
use layout_debug;
|
||||
|
@ -162,7 +162,15 @@ impl TableRowFlow {
|
|||
}
|
||||
|
||||
// Assign the child's block size.
|
||||
child_table_cell.block_flow.base.position.size.block = block_size
|
||||
child_table_cell.block_flow.base.position.size.block = block_size;
|
||||
|
||||
// Write in the size of the relative containing block for children. (This information
|
||||
// is also needed to handle RTL.)
|
||||
child_table_cell.block_flow.base.early_absolute_position_info =
|
||||
EarlyAbsolutePositionInfo {
|
||||
relative_containing_block_size: self.block_flow.fragment.content_box().size,
|
||||
relative_containing_block_mode: self.block_flow.fragment.style().writing_mode,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -7,8 +7,8 @@
|
|||
use construct::FlowConstructor;
|
||||
use context::LayoutContext;
|
||||
use css::matching::{ApplicableDeclarations, MatchMethods, StyleSharingResult};
|
||||
use flow::{PreorderFlowTraversal, PostorderFlowTraversal};
|
||||
use flow::{self, Flow};
|
||||
use flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
|
||||
use incremental::{self, BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
|
||||
use script::layout_interface::ReflowGoal;
|
||||
use wrapper::{ThreadSafeLayoutNode, UnsafeLayoutNode};
|
||||
|
@ -368,7 +368,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflow<'a> {
|
|||
}
|
||||
|
||||
flow.assign_block_size(self.layout_context);
|
||||
flow.store_overflow(self.layout_context);
|
||||
flow.early_store_overflow(self.layout_context);
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
|
|
@ -294,6 +294,7 @@ flaky_cpu == linebreak_simple_a.html linebreak_simple_b.html
|
|||
== position_relative_painting_order_a.html position_relative_painting_order_ref.html
|
||||
== position_relative_stacking_context_a.html position_relative_stacking_context_ref.html
|
||||
== position_relative_top_percentage_a.html position_relative_top_percentage_b.html
|
||||
== position_relative_vertical_percentage_overflow_a.html position_relative_vertical_percentage_overflow_ref.html
|
||||
== pre_ignorable_whitespace_a.html pre_ignorable_whitespace_ref.html
|
||||
== pre_with_tab.html pre_with_tab_ref.html
|
||||
== pseudo_element_a.html pseudo_element_b.html
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
}
|
||||
#a {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 100px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
transform: translateX(0px); /* force creation of stacking context */
|
||||
}
|
||||
#b {
|
||||
display: block;
|
||||
position: relative;
|
||||
top: -50%;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: purple;
|
||||
}
|
||||
</style>
|
||||
<div id=a><div id=b>
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
<!DOCTYPE html>
|
||||
<style>
|
||||
body, html {
|
||||
margin: 0;
|
||||
}
|
||||
#a {
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 50px;
|
||||
left: 100px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
background: purple;
|
||||
}
|
||||
</style>
|
||||
<div id=a>
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue