layout: Use the same code path for computing static positions of regular

flows and static positions of hypothetical boxes.

Before this change, Servo used one code path that computed the position
of flows with `position: static` or `position: relative` and another
separate code path that computed the position of flows with `position:
absolute` or `position: fixed`. The latter code attempted to duplicate
the former code to determine the static position of hypothetical boxes,
but this was both fragile and incorrect in the case of hypothetical
boxes nested inside floats. In fact, it's impossible to determine the
static position of an absolute flow relative to its containing block at
inline-size assignment time, because that static position could depend
on a float that cannot be placed until block-size assignment!

This patch changes block layout to use the same code path for static
positioning of regular flows and static positioning of absolute flows
where applicable. This both simplifies the code and improves its
efficiency, since it allows the `hypothetical_position` field and
`static_block_offsets` data structure to be removed. Moreover, it
improves correctness in the above case (which the new reftest checks).
This allows the sidebar in Facebook Timeline to be positioned properly.
This commit is contained in:
Patrick Walton 2015-04-14 12:13:13 -07:00
parent fe81ce942a
commit acd08c67c6
8 changed files with 420 additions and 491 deletions

View file

@ -34,8 +34,8 @@ use floats::{ClearType, FloatKind, Floats, PlacementInfo};
use flow::{self, AbsolutePositionInfo, BaseFlow, ForceNonfloatedFlag, FlowClass, Flow};
use flow::{ImmutableFlowUtils, MutableFlowUtils, PreorderFlowTraversal};
use flow::{PostorderFlowTraversal, mut_base};
use flow::{HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
use flow::{BLOCK_POSITION_IS_STATIC, HAS_LEFT_FLOATED_DESCENDANTS, HAS_RIGHT_FLOATED_DESCENDANTS};
use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS, INLINE_POSITION_IS_STATIC};
use flow::{LAYERS_NEEDED_FOR_DESCENDANTS, NEEDS_LAYER};
use flow::{IS_ABSOLUTELY_POSITIONED};
use flow::{CLEARS_LEFT, CLEARS_RIGHT};
@ -90,7 +90,6 @@ impl FloatedBlockInfo {
#[derive(Copy)]
struct BSizeConstraintSolution {
block_start: Au,
_block_end: Au,
block_size: Au,
margin_block_start: Au,
margin_block_end: Au
@ -98,14 +97,12 @@ struct BSizeConstraintSolution {
impl BSizeConstraintSolution {
fn new(block_start: Au,
block_end: Au,
block_size: Au,
margin_block_start: Au,
margin_block_end: Au)
-> BSizeConstraintSolution {
BSizeConstraintSolution {
block_start: block_start,
_block_end: block_end,
block_size: block_size,
margin_block_start: margin_block_start,
margin_block_end: margin_block_end,
@ -127,30 +124,18 @@ impl BSizeConstraintSolution {
block_start: MaybeAuto,
block_end: MaybeAuto,
content_block_size: Au,
available_block_size: Au,
static_b_offset: Au)
available_block_size: Au)
-> BSizeConstraintSolution {
// Distance from the block-start edge of the Absolute Containing Block to the
// block-start margin edge of a hypothetical box that would have been the
// first box of the element.
let static_position_block_start = static_b_offset;
let (block_start, block_end, block_size, margin_block_start, margin_block_end) =
let (block_start, block_size, margin_block_start, margin_block_end) =
match (block_start, block_end, block_size) {
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let block_start = static_position_block_start;
// Now it is the same situation as block-start Specified and block-end
// and block-size Auto.
let block_size = content_block_size;
let sum = block_start + block_size + margin_block_start + margin_block_end;
(block_start,
available_block_size - sum,
block_size,
margin_block_start,
margin_block_end)
// Use a dummy value for `block_start`, since it has the static position.
(Au(0), block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Specified(block_start),
MaybeAuto::Specified(block_end),
@ -159,36 +144,26 @@ impl BSizeConstraintSolution {
(MaybeAuto::Auto, MaybeAuto::Auto) => {
let total_margin_val =
available_block_size - block_start - block_end - block_size;
(block_start, block_end, block_size,
(block_start,
block_size,
total_margin_val.scale_by(0.5),
total_margin_val.scale_by(0.5))
}
(MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => {
let sum = block_start + block_end + block_size + margin_block_start;
(block_start,
block_end,
block_size,
margin_block_start,
available_block_size - sum)
}
(MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => {
let sum = block_start + block_end + block_size + margin_block_end;
(block_start,
block_end,
block_size,
available_block_size - sum,
margin_block_end)
(block_start, block_size, available_block_size - sum, margin_block_end)
}
(MaybeAuto::Specified(margin_block_start),
MaybeAuto::Specified(margin_block_end)) => {
// Values are over-constrained. Ignore value for 'block-end'.
let sum = block_start + block_size + margin_block_start +
margin_block_end;
(block_start,
available_block_size - sum,
block_size,
margin_block_start,
margin_block_end)
(block_start, block_size, margin_block_start, margin_block_end)
}
}
}
@ -202,23 +177,14 @@ impl BSizeConstraintSolution {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let sum = block_end + block_size + margin_block_start + margin_block_end;
(available_block_size - sum,
block_end,
block_size,
margin_block_start,
margin_block_end)
(available_block_size - sum, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Specified(block_start),
MaybeAuto::Auto,
MaybeAuto::Specified(block_size)) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let sum = block_start + block_size + margin_block_start + margin_block_end;
(block_start,
available_block_size - sum,
block_size,
margin_block_start,
margin_block_end)
(block_start, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Specified(block_start),
MaybeAuto::Specified(block_end),
@ -226,11 +192,7 @@ impl BSizeConstraintSolution {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let sum = block_start + block_end + margin_block_start + margin_block_end;
(block_start,
block_end,
available_block_size - sum,
margin_block_start,
margin_block_end)
(block_start, available_block_size - sum, margin_block_start, margin_block_end)
}
// If block-size is auto, then block-size is content block-size. Solve for the
@ -239,43 +201,25 @@ impl BSizeConstraintSolution {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let block_size = content_block_size;
let sum = block_start + block_size + margin_block_start + margin_block_end;
(block_start,
available_block_size - sum,
block_size,
margin_block_start,
margin_block_end)
(block_start, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Auto, MaybeAuto::Specified(block_end), MaybeAuto::Auto) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let block_size = content_block_size;
let sum = block_end + block_size + margin_block_start + margin_block_end;
(available_block_size - sum,
block_end,
block_size,
margin_block_start,
margin_block_end)
(available_block_size - sum, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(block_size)) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let block_start = static_position_block_start;
let sum = block_start + block_size + margin_block_start + margin_block_end;
(block_start,
available_block_size - sum,
block_size,
margin_block_start,
margin_block_end)
// Use a dummy value for `block_start`, since it has the static position.
(Au(0), block_size, margin_block_start, margin_block_end)
}
};
BSizeConstraintSolution::new(block_start,
block_end,
block_size,
margin_block_start,
margin_block_end)
BSizeConstraintSolution::new(block_start, block_size, margin_block_start, margin_block_end)
}
/// Solve the vertical constraint equation for absolute replaced elements.
@ -295,42 +239,41 @@ impl BSizeConstraintSolution {
block_start: MaybeAuto,
block_end: MaybeAuto,
_: Au,
available_block_size: Au,
static_b_offset: Au)
available_block_size: Au)
-> BSizeConstraintSolution {
// Distance from the block-start edge of the Absolute Containing Block to the
// block-start margin edge of a hypothetical box that would have been the
// first box of the element.
let static_position_block_start = static_b_offset;
let (block_start, block_end, block_size, margin_block_start, margin_block_end) = match (block_start, block_end) {
let (block_start, block_size, margin_block_start, margin_block_end) =
match (block_start, block_end) {
(MaybeAuto::Auto, MaybeAuto::Auto) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let block_start = static_position_block_start;
let sum = block_start + block_size + margin_block_start + margin_block_end;
(block_start, available_block_size - sum, block_size, margin_block_start, margin_block_end)
// Use a dummy value for `block_start`, since it has the static position.
(Au(0), block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Specified(block_start), MaybeAuto::Specified(block_end)) => {
match (block_start_margin, block_end_margin) {
(MaybeAuto::Auto, MaybeAuto::Auto) => {
let total_margin_val = available_block_size - block_start - block_end - block_size;
(block_start, block_end, block_size,
let total_margin_val = available_block_size - block_start - block_end -
block_size;
(block_start,
block_size,
total_margin_val.scale_by(0.5),
total_margin_val.scale_by(0.5))
}
(MaybeAuto::Specified(margin_block_start), MaybeAuto::Auto) => {
let sum = block_start + block_end + block_size + margin_block_start;
(block_start, block_end, block_size, margin_block_start, available_block_size - sum)
(block_start,
block_size,
margin_block_start,
available_block_size - sum)
}
(MaybeAuto::Auto, MaybeAuto::Specified(margin_block_end)) => {
let sum = block_start + block_end + block_size + margin_block_end;
(block_start, block_end, block_size, available_block_size - sum, margin_block_end)
(block_start, block_size, available_block_size - sum, margin_block_end)
}
(MaybeAuto::Specified(margin_block_start), MaybeAuto::Specified(margin_block_end)) => {
(MaybeAuto::Specified(margin_block_start),
MaybeAuto::Specified(margin_block_end)) => {
// Values are over-constrained. Ignore value for 'block-end'.
let sum = block_start + block_size + margin_block_start + margin_block_end;
(block_start, available_block_size - sum, block_size, margin_block_start, margin_block_end)
(block_start, block_size, margin_block_start, margin_block_end)
}
}
}
@ -340,16 +283,15 @@ impl BSizeConstraintSolution {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let sum = block_end + block_size + margin_block_start + margin_block_end;
(available_block_size - sum, block_end, block_size, margin_block_start, margin_block_end)
(available_block_size - sum, block_size, margin_block_start, margin_block_end)
}
(MaybeAuto::Specified(block_start), MaybeAuto::Auto) => {
let margin_block_start = block_start_margin.specified_or_zero();
let margin_block_end = block_end_margin.specified_or_zero();
let sum = block_start + block_size + margin_block_start + margin_block_end;
(block_start, available_block_size - sum, block_size, margin_block_start, margin_block_end)
(block_start, block_size, margin_block_start, margin_block_end)
}
};
BSizeConstraintSolution::new(block_start, block_end, block_size, margin_block_start, margin_block_end)
BSizeConstraintSolution::new(block_start, block_size, margin_block_start, margin_block_end)
}
}
@ -590,9 +532,6 @@ pub struct BlockFlow {
/// The associated fragment.
pub fragment: Fragment,
/// Static y offset of an absolute flow from its CB.
pub static_b_offset: Au,
/// The sum of the inline-sizes of all logically left floats that precede this block. This is
/// used to speculatively lay out block formatting contexts.
inline_size_of_preceding_left_floats: Au,
@ -601,9 +540,6 @@ pub struct BlockFlow {
/// used to speculatively lay out block formatting contexts.
inline_size_of_preceding_right_floats: Au,
/// The hypothetical position, used for absolutely-positioned flows.
hypothetical_position: LogicalPoint<Au>,
/// Additional floating flow members.
pub float: Option<Box<FloatedBlockInfo>>,
@ -630,10 +566,8 @@ impl BlockFlow {
BlockFlow {
base: BaseFlow::new(Some((*node).clone()), writing_mode, ForceNonfloatedFlag::ForceNonfloated),
fragment: fragment,
static_b_offset: Au::new(0),
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
hypothetical_position: LogicalPoint::new(writing_mode, Au(0), Au(0)),
float: None,
flags: BlockFlowFlags::empty(),
}
@ -647,10 +581,8 @@ impl BlockFlow {
BlockFlow {
base: BaseFlow::new(Some((*node).clone()), writing_mode, ForceNonfloatedFlag::FloatIfNecessary),
fragment: fragment,
static_b_offset: Au::new(0),
inline_size_of_preceding_left_floats: Au(0),
inline_size_of_preceding_right_floats: Au(0),
hypothetical_position: LogicalPoint::new(writing_mode, Au(0), Au(0)),
float: Some(box FloatedBlockInfo::new(float_kind)),
flags: BlockFlowFlags::empty(),
}
@ -720,15 +652,6 @@ impl BlockFlow {
&mut self.fragment
}
/// Return the static x offset from the appropriate Containing Block for this flow.
pub fn static_i_offset(&self) -> Au {
if self.is_fixed() {
self.base.fixed_static_i_offset
} else {
self.base.absolute_static_i_offset
}
}
/// Return the size of the Containing Block for this flow.
///
/// Right now, this only gets the Containing Block size for absolutely
@ -750,8 +673,6 @@ impl BlockFlow {
///
/// Traverse all your direct absolute descendants, who will then traverse
/// their direct absolute descendants.
/// Also, set the static y offsets for each descendant (using the value
/// which was bubbled up during normal assign-block-size).
///
/// Return true if the traversal is to continue or false to stop.
fn traverse_preorder_absolute_flows<T:PreorderFlowTraversal>(&mut self,
@ -760,15 +681,9 @@ impl BlockFlow {
traversal.process(flow);
let cb_block_start_edge_offset = flow.generated_containing_block_rect().start.b;
let descendant_offset_iter = mut_base(flow).abs_descendants.iter_with_offset();
// Pass in the respective static y offset for each descendant.
for (ref mut descendant_link, ref y_offset) in descendant_offset_iter {
let block = descendant_link.as_block();
// The stored y_offset is wrt to the flow box.
// Translate it to the CB (which is the padding box).
block.static_b_offset = **y_offset - cb_block_start_edge_offset;
block.traverse_preorder_absolute_flows(traversal);
let descendant_offset_iter = mut_base(flow).abs_descendants.iter();
for ref mut descendant_link in descendant_offset_iter {
descendant_link.as_block().traverse_preorder_absolute_flows(traversal)
}
}
@ -898,7 +813,11 @@ impl BlockFlow {
if flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
// Assume that the *hypothetical box* for an absolute flow starts immediately
// after the block-end border edge of the previous flow.
kid.as_block().hypothetical_position.b = cur_b;
if flow::base(kid).flags.contains(BLOCK_POSITION_IS_STATIC) {
flow::mut_base(kid).position.start.b = cur_b +
flow::base(kid).collapsible_margins
.block_start_margin_for_noncollapsible_context()
}
kid.place_float_if_applicable(layout_context);
if !flow::base(kid).flags.is_float() {
kid.assign_block_size_for_inorder_child_if_necessary(layout_context,
@ -989,9 +908,6 @@ impl BlockFlow {
// order (CSS 2.1, Appendix E).
self.base.flags.set(LAYERS_NEEDED_FOR_DESCENDANTS, layers_needed_for_descendants);
// Collect various offsets needed by absolutely positioned descendants.
(&mut *self as &mut Flow).collect_static_block_offsets_from_children();
// Add in our block-end margin and compute our collapsible margins.
let can_collapse_block_end_margin_with_kids =
margins_may_collapse == MarginsMayCollapseFlag::MarginsMayCollapse &&
@ -1149,16 +1065,14 @@ impl BlockFlow {
Au(0),
self.fragment.margin.block_start);
if !self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
let mut origin = LogicalPoint::new(self.base.writing_mode,
self.hypothetical_position.i,
self.base.position.start.i,
self.base.position.start.b);
origin = origin.add_point(&float_offset).add_point(&margin_offset);
self.base.position = LogicalRect::from_point_size(self.base.writing_mode,
origin,
self.base.position.size);
}
}
/// Calculate and set the block-size, offsets, etc. for absolutely positioned flow.
@ -1170,7 +1084,6 @@ impl BlockFlow {
/// + block-size, vertical margins, and y-coordinate for the flow's box.
fn calculate_absolute_block_size_and_margins(&mut self, ctx: &LayoutContext) {
let containing_block_block_size = self.containing_block_size(ctx.shared.screen_size).block;
let static_b_offset = self.static_b_offset;
// This is the stored content block-size value from assign-block-size
let content_block_size = self.fragment.border_box.size.block;
@ -1216,8 +1129,7 @@ impl BlockFlow {
block_start,
block_end,
content_block_size,
available_block_size,
static_b_offset));
available_block_size))
} else {
let mut candidate_block_size_iterator =
CandidateBSizeIterator::new(&self.fragment, Some(containing_block_block_size));
@ -1235,8 +1147,7 @@ impl BlockFlow {
block_start,
block_end,
content_block_size,
available_block_size,
static_b_offset));
available_block_size));
candidate_block_size_iterator.candidate_value
= solution.unwrap().block_size;
@ -1252,7 +1163,9 @@ impl BlockFlow {
self.fragment.margin.block_end = solution.margin_block_end;
self.fragment.border_box.start.b = Au(0);
self.base.position.start.b = solution.block_start + self.fragment.margin.block_start;
if !self.base.flags.contains(BLOCK_POSITION_IS_STATIC) {
self.base.position.start.b = solution.block_start + self.fragment.margin.block_start
}
let block_size = solution.block_size + self.fragment.border_padding.block_start_end();
self.fragment.border_box.size.block = block_size;
@ -1272,17 +1185,6 @@ impl BlockFlow {
}
}
/// Return the block-start outer edge of the hypothetical box for an absolute flow.
///
/// This is wrt its parent flow box.
///
/// During normal layout assign-block-size, the absolute flow's position is
/// roughly set to its static position (the position it would have had in
/// the normal flow).
pub fn get_hypothetical_block_start_edge(&self) -> Au {
self.hypothetical_position.b
}
/// Assigns the computed inline-start content edge and inline-size to all the children of this
/// block flow. Also computes whether each child will be impacted by floats.
///
@ -1401,8 +1303,7 @@ impl BlockFlow {
let kid_mode = flow::base(kid).writing_mode;
{
let kid_base = flow::mut_base(kid);
if !kid_base.flags.contains(IS_ABSOLUTELY_POSITIONED) &&
!kid_base.flags.is_float() {
if kid_base.flags.contains(INLINE_POSITION_IS_STATIC) {
kid_base.position.start.i =
if kid_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() {
inline_start_content_edge
@ -1414,15 +1315,6 @@ impl BlockFlow {
kid_base.block_container_inline_size = content_inline_size;
kid_base.block_container_writing_mode = containing_block_mode;
}
if kid.is_block_like() {
kid.as_block().hypothetical_position.i =
if kid_mode.is_bidi_ltr() == containing_block_mode.is_bidi_ltr() {
inline_start_content_edge
} else {
// The kid's inline 'start' is at the parent's 'end'
inline_end_content_edge
}
}
{
let kid_base = flow::mut_base(kid);
@ -1521,7 +1413,7 @@ impl BlockFlow {
// Offset our position by whatever displacement is needed to not impact the floats.
let rect = self.base.floats.place_between_floats(&info);
self.base.position.start.i = self.hypothetical_position.i + rect.start.i;
self.base.position.start.i = self.base.position.start.i + rect.start.i;
// TODO(pcwalton): If the inline-size of this flow is different from the size we estimated
// earlier, lay it out again.
@ -1791,7 +1683,7 @@ impl Flow for BlockFlow {
// Compute our position relative to the nearest ancestor stacking context. This will be
// passed down later as part of containing block details for absolute descendants.
self.base.stacking_relative_position = if self.is_fixed() {
let absolute_stacking_relative_position = if self.is_fixed() {
// The viewport is initially at (0, 0).
position_start
} else {
@ -1800,6 +1692,22 @@ impl Flow for BlockFlow {
self.base
.absolute_position_info
.stacking_relative_position_of_absolute_containing_block + position_start
};
if !self.base.writing_mode.is_vertical() {
if !self.base.flags.contains(INLINE_POSITION_IS_STATIC) {
self.base.stacking_relative_position.x = absolute_stacking_relative_position.x
}
if !self.base.flags.contains(BLOCK_POSITION_IS_STATIC) {
self.base.stacking_relative_position.y = absolute_stacking_relative_position.y
}
} else {
if !self.base.flags.contains(INLINE_POSITION_IS_STATIC) {
self.base.stacking_relative_position.y = absolute_stacking_relative_position.y
}
if !self.base.flags.contains(BLOCK_POSITION_IS_STATIC) {
self.base.stacking_relative_position.x = absolute_stacking_relative_position.x
}
}
}
@ -1888,13 +1796,34 @@ impl Flow for BlockFlow {
// Process children.
for kid in self.base.child_iter() {
if !flow::base(kid).flags.contains(IS_ABSOLUTELY_POSITIONED) {
if flow::base(kid).flags.contains(INLINE_POSITION_IS_STATIC) ||
flow::base(kid).flags.contains(BLOCK_POSITION_IS_STATIC) {
let kid_base = flow::mut_base(kid);
// FIXME (mbrubeck): `position.size` is inflated by the inline margin size, making
// this incorrect for RTL blocks (see `set_inline_size_constraint_solutions`).
let physical_position = kid_base.position.to_physical(kid_base.writing_mode,
container_size_for_children);
kid_base.stacking_relative_position = origin_for_children + physical_position.origin;
// Set the inline and block positions as necessary.
if !kid_base.writing_mode.is_vertical() {
if kid_base.flags.contains(INLINE_POSITION_IS_STATIC) {
kid_base.stacking_relative_position.x = origin_for_children.x +
physical_position.origin.x
}
if kid_base.flags.contains(BLOCK_POSITION_IS_STATIC) {
kid_base.stacking_relative_position.y = origin_for_children.y +
physical_position.origin.y
}
} else {
if kid_base.flags.contains(INLINE_POSITION_IS_STATIC) {
kid_base.stacking_relative_position.y = origin_for_children.y +
physical_position.origin.y
}
if kid_base.flags.contains(BLOCK_POSITION_IS_STATIC) {
kid_base.stacking_relative_position.x = origin_for_children.x +
physical_position.origin.x
}
}
}
flow::mut_base(kid).absolute_position_info = absolute_position_info_for_children;
@ -2019,7 +1948,6 @@ pub struct ISizeConstraintInput {
pub inline_start: MaybeAuto,
pub inline_end: MaybeAuto,
pub available_inline_size: Au,
pub static_i_offset: Au,
}
impl ISizeConstraintInput {
@ -2028,8 +1956,7 @@ impl ISizeConstraintInput {
inline_end_margin: MaybeAuto,
inline_start: MaybeAuto,
inline_end: MaybeAuto,
available_inline_size: Au,
static_i_offset: Au)
available_inline_size: Au)
-> ISizeConstraintInput {
ISizeConstraintInput {
computed_inline_size: computed_inline_size,
@ -2038,7 +1965,6 @@ impl ISizeConstraintInput {
inline_start: inline_start,
inline_end: inline_end,
available_inline_size: available_inline_size,
static_i_offset: static_i_offset,
}
}
}
@ -2047,7 +1973,6 @@ impl ISizeConstraintInput {
#[derive(Copy, Debug)]
pub struct ISizeConstraintSolution {
pub inline_start: Au,
pub inline_end: Au,
pub inline_size: Au,
pub margin_inline_start: Au,
pub margin_inline_end: Au
@ -2058,7 +1983,6 @@ impl ISizeConstraintSolution {
-> ISizeConstraintSolution {
ISizeConstraintSolution {
inline_start: Au(0),
inline_end: Au(0),
inline_size: inline_size,
margin_inline_start: margin_inline_start,
margin_inline_end: margin_inline_end,
@ -2066,14 +1990,12 @@ impl ISizeConstraintSolution {
}
fn for_absolute_flow(inline_start: Au,
inline_end: Au,
inline_size: Au,
margin_inline_start: Au,
margin_inline_end: Au)
-> ISizeConstraintSolution {
ISizeConstraintSolution {
inline_start: inline_start,
inline_end: inline_end,
inline_size: inline_size,
margin_inline_start: margin_inline_start,
margin_inline_end: margin_inline_end,
@ -2123,14 +2045,16 @@ pub trait ISizeAndMarginsComputer {
let available_inline_size = containing_block_inline_size -
block.fragment.border_padding.inline_start_end();
return ISizeConstraintInput::new(
computed_inline_size,
MaybeAuto::from_style(margin.inline_start, containing_block_inline_size),
MaybeAuto::from_style(margin.inline_end, containing_block_inline_size),
MaybeAuto::from_style(position.inline_start, containing_block_inline_size),
MaybeAuto::from_style(position.inline_end, containing_block_inline_size),
available_inline_size,
block.static_i_offset());
ISizeConstraintInput::new(computed_inline_size,
MaybeAuto::from_style(margin.inline_start,
containing_block_inline_size),
MaybeAuto::from_style(margin.inline_end,
containing_block_inline_size),
MaybeAuto::from_style(position.inline_start,
containing_block_inline_size),
MaybeAuto::from_style(position.inline_end,
containing_block_inline_size),
available_inline_size)
}
/// Set the used values for inline-size and margins from the relevant constraint equation.
@ -2381,7 +2305,6 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
inline_start,
inline_end,
available_inline_size,
static_i_offset,
..
} = input;
@ -2392,62 +2315,64 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
// FIXME (mbrubeck): Handle vertical writing modes.
let parent_has_same_direction = container_mode.is_bidi_ltr() == block_mode.is_bidi_ltr();
// Distance from the inline-start edge of the Absolute Containing Block to the
// inline-start margin edge of a hypothetical box that would have been the
// first box of the element.
let static_position_inline_start = static_i_offset;
let (inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end) = match (inline_start, inline_end, computed_inline_size) {
let (inline_start, inline_size, margin_inline_start, margin_inline_end) =
match (inline_start, inline_end, computed_inline_size) {
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Auto) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
let inline_start = static_position_inline_start;
// Now it is the same situation as inline-start Specified and inline-end
// and inline-size Auto.
// Set inline-end to zero to calculate inline-size
let inline_size = block.get_shrink_to_fit_inline_size(
available_inline_size - (inline_start + margin_start + margin_end));
let sum = inline_start + inline_size + margin_start + margin_end;
(inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
// Set inline-end to zero to calculate inline-size.
let inline_size =
block.get_shrink_to_fit_inline_size(available_inline_size -
(margin_start + margin_end));
(Au(0), inline_size, margin_start, margin_end)
}
(MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end), MaybeAuto::Specified(inline_size)) => {
(MaybeAuto::Specified(inline_start),
MaybeAuto::Specified(inline_end),
MaybeAuto::Specified(inline_size)) => {
match (inline_start_margin, inline_end_margin) {
(MaybeAuto::Auto, MaybeAuto::Auto) => {
let total_margin_val = available_inline_size - inline_start - inline_end - inline_size;
let total_margin_val =
available_inline_size - inline_start - inline_end - inline_size;
if total_margin_val < Au(0) {
if parent_has_same_direction {
// margin-inline-start becomes 0
(inline_start, inline_end, inline_size, Au(0), total_margin_val)
(inline_start, inline_size, Au(0), total_margin_val)
} else {
// margin-inline-end becomes 0, because it's toward the parent's
// inline-start edge.
(inline_start, inline_end, inline_size, total_margin_val, Au(0))
(inline_start, inline_size, total_margin_val, Au(0))
}
} else {
// Equal margins
(inline_start, inline_end, inline_size,
(inline_start,
inline_size,
total_margin_val.scale_by(0.5),
total_margin_val.scale_by(0.5))
}
}
(MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => {
let sum = inline_start + inline_end + inline_size + margin_start;
(inline_start, inline_end, inline_size, margin_start, available_inline_size - sum)
(inline_start, inline_size, margin_start, available_inline_size - sum)
}
(MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => {
let sum = inline_start + inline_end + inline_size + margin_end;
(inline_start, inline_end, inline_size, available_inline_size - sum, margin_end)
(inline_start, inline_size, available_inline_size - sum, margin_end)
}
(MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => {
// Values are over-constrained.
let sum = inline_start + inline_size + margin_start + margin_end;
if parent_has_same_direction {
// Ignore value for 'inline-end'
(inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
(inline_start, inline_size, margin_start, margin_end)
} else {
// Ignore value for 'inline-start'
(available_inline_size - sum, inline_end, inline_size, margin_start, margin_end)
(available_inline_size - sum,
inline_size,
margin_start,
margin_end)
}
}
}
@ -2455,23 +2380,28 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
// For the rest of the cases, auto values for margin are set to 0
// If only one is Auto, solve for it
(MaybeAuto::Auto, MaybeAuto::Specified(inline_end), MaybeAuto::Specified(inline_size)) => {
(MaybeAuto::Auto,
MaybeAuto::Specified(inline_end),
MaybeAuto::Specified(inline_size)) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
let sum = inline_end + inline_size + margin_start + margin_end;
(available_inline_size - sum, inline_end, inline_size, margin_start, margin_end)
(available_inline_size - sum, inline_size, margin_start, margin_end)
}
(MaybeAuto::Specified(inline_start), MaybeAuto::Auto, MaybeAuto::Specified(inline_size)) => {
(MaybeAuto::Specified(inline_start),
MaybeAuto::Auto,
MaybeAuto::Specified(inline_size)) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
let sum = inline_start + inline_size + margin_start + margin_end;
(inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
(inline_start, inline_size, margin_start, margin_end)
}
(MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end), MaybeAuto::Auto) => {
(MaybeAuto::Specified(inline_start),
MaybeAuto::Specified(inline_end),
MaybeAuto::Auto) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
let sum = inline_start + inline_end + margin_start + margin_end;
(inline_start, inline_end, available_inline_size - sum, margin_start, margin_end)
(inline_start, available_inline_size - sum, margin_start, margin_end)
}
// If inline-size is auto, then inline-size is shrink-to-fit. Solve for the
@ -2480,19 +2410,20 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
// Set inline-end to zero to calculate inline-size
let inline_size = block.get_shrink_to_fit_inline_size(
available_inline_size - (inline_start + margin_start + margin_end));
let sum = inline_start + inline_size + margin_start + margin_end;
(inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
let inline_size =
block.get_shrink_to_fit_inline_size(available_inline_size -
(margin_start + margin_end));
(inline_start, inline_size, margin_start, margin_end)
}
(MaybeAuto::Auto, MaybeAuto::Specified(inline_end), MaybeAuto::Auto) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
// Set inline-start to zero to calculate inline-size
let inline_size = block.get_shrink_to_fit_inline_size(
available_inline_size - (inline_end + margin_start + margin_end));
let inline_size =
block.get_shrink_to_fit_inline_size(available_inline_size -
(margin_start + margin_end));
let sum = inline_end + inline_size + margin_start + margin_end;
(available_inline_size - sum, inline_end, inline_size, margin_start, margin_end)
(available_inline_size - sum, inline_size, margin_start, margin_end)
}
(MaybeAuto::Auto, MaybeAuto::Auto, MaybeAuto::Specified(inline_size)) => {
@ -2500,12 +2431,13 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
let margin_end = inline_end_margin.specified_or_zero();
// Setting 'inline-start' to static position because direction is 'ltr'.
// TODO: Handle 'rtl' when it is implemented.
let inline_start = static_position_inline_start;
let sum = inline_start + inline_size + margin_start + margin_end;
(inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
(Au(0), inline_size, margin_start, margin_end)
}
};
ISizeConstraintSolution::for_absolute_flow(inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end)
ISizeConstraintSolution::for_absolute_flow(inline_start,
inline_size,
margin_inline_start,
margin_inline_end)
}
fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
@ -2515,17 +2447,16 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
fn set_flow_x_coord_if_necessary(&self,
block: &mut BlockFlow,
solution: ISizeConstraintSolution) {
// Set the x-coordinate of the absolute flow wrt to its containing block.
// Set the inline position of the absolute flow wrt to its containing block.
if !block.base.flags.contains(INLINE_POSITION_IS_STATIC) {
block.base.position.start.i = solution.inline_start;
}
}
}
impl ISizeAndMarginsComputer for AbsoluteReplaced {
/// Solve the horizontal constraint equation for absolute replaced elements.
///
/// `static_i_offset`: total offset of current flow's hypothetical
/// position (static position) from its actual Containing Block.
///
/// CSS Section 10.3.8
/// Constraint equation:
/// inline-start + inline-end + inline-size + margin-inline-start + margin-inline-end
@ -2542,7 +2473,6 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
inline_start,
inline_end,
available_inline_size,
static_i_offset,
..
} = input;
// TODO: Check for direction of static-position Containing Block (aka
@ -2558,64 +2488,61 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
"should have already been calculated by now.")
};
// Distance from the inline-start edge of the Absolute Containing Block to the
// inline-start margin edge of a hypothetical box that would have been the
// first box of the element.
let static_position_inline_start = static_i_offset;
let (inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end) = match (inline_start, inline_end) {
let (inline_start, inline_size, margin_inline_start, margin_inline_end) =
match (inline_start, inline_end) {
(MaybeAuto::Auto, MaybeAuto::Auto) => {
let inline_start = static_position_inline_start;
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
let sum = inline_start + inline_size + margin_start + margin_end;
(inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
(Au(0), inline_size, margin_start, margin_end)
}
// If only one is Auto, solve for it
(MaybeAuto::Auto, MaybeAuto::Specified(inline_end)) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
let sum = inline_end + inline_size + margin_start + margin_end;
(available_inline_size - sum, inline_end, inline_size, margin_start, margin_end)
(available_inline_size - sum, inline_size, margin_start, margin_end)
}
(MaybeAuto::Specified(inline_start), MaybeAuto::Auto) => {
let margin_start = inline_start_margin.specified_or_zero();
let margin_end = inline_end_margin.specified_or_zero();
let sum = inline_start + inline_size + margin_start + margin_end;
(inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
(inline_start, inline_size, margin_start, margin_end)
}
(MaybeAuto::Specified(inline_start), MaybeAuto::Specified(inline_end)) => {
match (inline_start_margin, inline_end_margin) {
(MaybeAuto::Auto, MaybeAuto::Auto) => {
let total_margin_val = available_inline_size - inline_start - inline_end - inline_size;
let total_margin_val = available_inline_size - inline_start -
inline_end - inline_size;
if total_margin_val < Au(0) {
// margin-inline-start becomes 0 because direction is 'ltr'.
(inline_start, inline_end, inline_size, Au(0), total_margin_val)
(inline_start, inline_size, Au(0), total_margin_val)
} else {
// Equal margins
(inline_start, inline_end, inline_size,
(inline_start,
inline_size,
total_margin_val.scale_by(0.5),
total_margin_val.scale_by(0.5))
}
}
(MaybeAuto::Specified(margin_start), MaybeAuto::Auto) => {
let sum = inline_start + inline_end + inline_size + margin_start;
(inline_start, inline_end, inline_size, margin_start, available_inline_size - sum)
(inline_start, inline_size, margin_start, available_inline_size - sum)
}
(MaybeAuto::Auto, MaybeAuto::Specified(margin_end)) => {
let sum = inline_start + inline_end + inline_size + margin_end;
(inline_start, inline_end, inline_size, available_inline_size - sum, margin_end)
(inline_start, inline_size, available_inline_size - sum, margin_end)
}
(MaybeAuto::Specified(margin_start), MaybeAuto::Specified(margin_end)) => {
// Values are over-constrained.
// Ignore value for 'inline-end' cos direction is 'ltr'.
let sum = inline_start + inline_size + margin_start + margin_end;
(inline_start, available_inline_size - sum, inline_size, margin_start, margin_end)
(inline_start, inline_size, margin_start, margin_end)
}
}
}
};
ISizeConstraintSolution::for_absolute_flow(inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end)
ISizeConstraintSolution::for_absolute_flow(inline_start,
inline_size,
margin_inline_start,
margin_inline_end)
}
/// Calculate used value of inline-size just like we do for inline replaced elements.

View file

@ -58,11 +58,12 @@ use std::fmt;
use std::iter::Zip;
use std::num::FromPrimitive;
use std::raw;
use std::sync::atomic::{AtomicUsize, Ordering};
use std::slice::IterMut;
use std::sync::Arc;
use std::sync::atomic::{AtomicUsize, Ordering};
use style::computed_values::{clear, empty_cells, float, position, text_align};
use style::properties::ComputedValues;
use std::sync::Arc;
use style::values::computed::LengthOrPercentageOrAuto;
/// Virtual methods that make up a float context.
///
@ -426,16 +427,6 @@ pub trait MutableFlowUtils {
/// Computes the overflow region for this flow.
fn store_overflow(self, _: &LayoutContext);
/// Gathers static block-offsets bubbled up by kids.
///
/// This essentially gives us offsets of all absolutely positioned direct descendants and all
/// fixed descendants, in tree order.
///
/// This is called in a bottom-up traversal (specifically, the assign-block-size traversal).
/// So, kids have their flow origin already set. In the case of absolute flow kids, they have
/// their hypothetical box position already set.
fn collect_static_block_offsets_from_children(self);
/// 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>);
@ -548,7 +539,17 @@ bitflags! {
const AFFECTS_COUNTERS = 0b0000_1000_0000_0000_0000,
#[doc = "Whether this flow's descendants have fragments that affect `counter-reset` or \
`counter-increment` styles."]
const HAS_COUNTER_AFFECTING_CHILDREN = 0b0001_0000_0000_0000_0000
const HAS_COUNTER_AFFECTING_CHILDREN = 0b0001_0000_0000_0000_0000,
#[doc = "Whether this flow behaves as though it had `position: static` for the purposes \
of positioning in the inline direction. This is set for flows with `position: \
static` and `position: relative` as well as absolutely-positioned flows with \
unconstrained positions in the inline direction."]
const INLINE_POSITION_IS_STATIC = 0b0010_0000_0000_0000_0000,
#[doc = "Whether this flow behaves as though it had `position: static` for the purposes \
of positioning in the block direction. This is set for flows with `position: \
static` and `position: relative` as well as absolutely-positioned flows with \
unconstrained positions in the block direction."]
const BLOCK_POSITION_IS_STATIC = 0b0100_0000_0000_0000_0000,
}
}
@ -637,16 +638,12 @@ pub struct Descendants {
/// Links to every descendant. This must be private because it is unsafe to leak `FlowRef`s to
/// layout.
descendant_links: Vec<FlowRef>,
/// Static block-direction offsets of all descendants from the start of this flow box.
pub static_block_offsets: Vec<Au>,
}
impl Descendants {
pub fn new() -> Descendants {
Descendants {
descendant_links: Vec::new(),
static_block_offsets: Vec::new(),
}
}
@ -677,14 +674,6 @@ impl Descendants {
iter: self.descendant_links.iter_mut(),
}
}
/// Return an iterator over (descendant, static y offset).
pub fn iter_with_offset<'a>(&'a mut self) -> DescendantOffsetIter<'a> {
let descendant_iter = DescendantIter {
iter: self.descendant_links.iter_mut(),
};
descendant_iter.zip(self.static_block_offsets.iter_mut())
}
}
pub type AbsDescendants = Descendants;
@ -916,13 +905,24 @@ impl BaseFlow {
force_nonfloated: ForceNonfloatedFlag)
-> BaseFlow {
let mut flags = FlowFlags::empty();
if let Some(node) = node {
match node {
Some(node) => {
let node_style = node.style();
match node_style.get_box().position {
position::T::absolute | position::T::fixed => {
flags.insert(IS_ABSOLUTELY_POSITIONED)
flags.insert(IS_ABSOLUTELY_POSITIONED);
let logical_position = node_style.logical_position();
if logical_position.inline_start == LengthOrPercentageOrAuto::Auto &&
logical_position.inline_end == LengthOrPercentageOrAuto::Auto {
flags.insert(INLINE_POSITION_IS_STATIC);
}
_ => {}
if logical_position.block_start == LengthOrPercentageOrAuto::Auto &&
logical_position.block_end == LengthOrPercentageOrAuto::Auto {
flags.insert(BLOCK_POSITION_IS_STATIC);
}
}
_ => flags.insert(BLOCK_POSITION_IS_STATIC | INLINE_POSITION_IS_STATIC),
}
if force_nonfloated == ForceNonfloatedFlag::FloatIfNecessary {
@ -948,6 +948,8 @@ impl BaseFlow {
flags.insert(AFFECTS_COUNTERS)
}
}
None => flags.insert(BLOCK_POSITION_IS_STATIC | INLINE_POSITION_IS_STATIC),
}
// New flows start out as fully damaged.
let mut damage = incremental::rebuild_and_reflow();
@ -1268,52 +1270,6 @@ impl<'a> MutableFlowUtils for &'a mut (Flow + 'a) {
mut_base(self).overflow = overflow;
}
/// Collect and update static y-offsets bubbled up by kids.
///
/// This would essentially give us offsets of all absolutely positioned
/// direct descendants and all fixed descendants, in tree order.
///
/// Assume that this is called in a bottom-up traversal (specifically, the
/// assign-block-size traversal). So, kids have their flow origin already set.
/// In the case of absolute flow kids, they have their hypothetical box
/// position already set.
fn collect_static_block_offsets_from_children(self) {
let mut absolute_descendant_block_offsets = Vec::new();
for kid in mut_base(self).child_iter() {
let mut gives_absolute_offsets = true;
if kid.is_block_like() {
let kid_block = kid.as_block();
if kid_block.is_fixed() || kid_block.base.flags.contains(IS_ABSOLUTELY_POSITIONED) {
// It won't contribute any offsets for descendants because it would be the
// containing block for them.
gives_absolute_offsets = false;
// Give the offset for the current absolute flow alone.
absolute_descendant_block_offsets.push(
kid_block.get_hypothetical_block_start_edge());
} else if kid_block.is_positioned() {
// It won't contribute any offsets because it would be the containing block
// for the descendants.
gives_absolute_offsets = false;
}
}
if gives_absolute_offsets {
let kid_base = mut_base(kid);
// Avoid copying the offset vector.
let offsets = mem::replace(&mut kid_base.abs_descendants.static_block_offsets,
Vec::new());
// Consume all the static block-offsets bubbled up by kids.
for block_offset in offsets.into_iter() {
// The offsets are with respect to the kid flow's fragment. Translate them to
// that of the current flow.
absolute_descendant_block_offsets.push(
block_offset + kid_base.position.start.b);
}
}
}
mut_base(self).abs_descendants.static_block_offsets = absolute_descendant_block_offsets
}
/// 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>) {

View file

@ -8,8 +8,7 @@ use css::node_style::StyledNode;
use context::LayoutContext;
use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBuilding};
use floats::{FloatKind, Floats, PlacementInfo};
use flow::{self, BaseFlow, FlowClass, Flow, MutableFlowUtils, ForceNonfloatedFlag};
use flow::{IS_ABSOLUTELY_POSITIONED};
use flow::{self, BaseFlow, FlowClass, Flow, ForceNonfloatedFlag, IS_ABSOLUTELY_POSITIONED};
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW, RESOLVE_GENERATED_CONTENT};
use layout_debug;
@ -1184,10 +1183,6 @@ impl Flow for InlineFlow {
fn assign_block_size(&mut self, layout_context: &LayoutContext) {
let _scope = layout_debug_scope!("inline::assign_block_size {:x}", self.base.debug_id());
// Collect various offsets needed by absolutely positioned inline-block or hypothetical
// absolute descendants.
(&mut *self as &mut Flow).collect_static_block_offsets_from_children();
// Divide the fragments into lines.
//
// TODO(pcwalton, #226): Get the CSS `line-height` property from the style of the

View file

@ -80,6 +80,17 @@ impl CollapsibleMargins {
pub fn new() -> CollapsibleMargins {
CollapsibleMargins::None(Au(0), Au(0))
}
/// Returns the amount of margin that should be applied in a noncollapsible context. This is
/// currently used to apply block-start margin for hypothetical boxes, since we do not collapse
/// margins of hypothetical boxes.
pub fn block_start_margin_for_noncollapsible_context(&self) -> Au {
match *self {
CollapsibleMargins::None(block_start, _) => block_start,
CollapsibleMargins::Collapse(ref block_start, _) |
CollapsibleMargins::CollapseThrough(ref block_start) => block_start.collapse(),
}
}
}
enum FinalMarginState {

View file

@ -11,7 +11,7 @@ use block::{ISizeConstraintInput, ISizeConstraintSolution};
use context::LayoutContext;
use floats::FloatKind;
use flow::{self, Flow, FlowClass, IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS};
use flow::{ImmutableFlowUtils, MutableFlowUtils};
use flow::{ImmutableFlowUtils};
use fragment::{Fragment, FragmentBorderBoxIterator};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW};
use layout_debug;
@ -477,9 +477,6 @@ impl TableLikeFlow for BlockFlow {
current_block_offset = current_block_offset + kid_base.position.size.block;
}
// Collect various offsets needed by absolutely positioned descendants.
(&mut *self as &mut Flow).collect_static_block_offsets_from_children();
// Compute any explicitly-specified block size.
// Can't use `for` because we assign to `candidate_block_size_iterator.candidate_value`.
let mut block_size = current_block_offset - block_start_border_padding;

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<style>
#a {
float: right;
width: 250px;
}
#b {
background: blue;
position: absolute;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div id=a><div id=b>asdf</div></div>
</body>
</html>

View file

@ -0,0 +1,21 @@
<!DOCTYPE html>
<html>
<head>
<style>
#a {
float: right;
width: 250px;
}
#b {
background: blue;
width: 100px;
height: 100px;
}
</style>
</head>
<body>
<div id=a><div id=b>asdf</div></div>
</body>
</html>

View file

@ -40,6 +40,7 @@ fragment=top != ../html/acid2.html acid2_ref.html
== abs_float_pref_width_a.html abs_float_pref_width_ref.html
== absolute_content_height_a.html absolute_content_height_ref.html
== absolute_hypothetical_float_a.html absolute_hypothetical_float_ref.html
== acid1_a.html acid1_b.html
== acid2_noscroll.html acid2_ref_broken.html
== after_block_iteration.html after_block_iteration_ref.html