mirror of
https://github.com/servo/servo.git
synced 2025-08-06 14:10:11 +01:00
Refactor assign_height and assign_width for block flow.
This commit is contained in:
parent
3401a568f2
commit
8dbec50178
1 changed files with 274 additions and 180 deletions
|
@ -625,47 +625,38 @@ impl BlockFlow {
|
||||||
self.base.fixed_descendants.static_y_offsets = fixed_descendant_y_offsets;
|
self.base.fixed_descendants.static_y_offsets = fixed_descendant_y_offsets;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign height for current flow.
|
/// Calculate clearance, top_offset, bottom_offset, and left_offset for the box.
|
||||||
///
|
/// If `ignore_clear` is true, clearance does not need to be calculated.
|
||||||
/// + Collapse margins for flow's children and set in-flow child flows'
|
pub fn initialize_offsets(&mut self, ignore_clear: bool) -> (Au, Au, Au, Au) {
|
||||||
/// y-coordinates now that we know their heights.
|
match self.box_ {
|
||||||
/// + Calculate and set the height of the current flow.
|
None => (Au(0), Au(0), Au(0), Au(0)),
|
||||||
/// + Calculate height, vertical margins, and y-coordinate for the flow's
|
Some(ref box_) => {
|
||||||
/// box. Ideally, this should be calculated using CSS Section 10.6.7
|
let clearance = match box_.clear() {
|
||||||
///
|
Some(clear) if !ignore_clear => self.base.floats.clearance(clear),
|
||||||
/// For absolute flows, store the calculated content height for the flow.
|
_ => Au::new(0)
|
||||||
/// Defer the calculation of the other values till a later traversal.
|
|
||||||
///
|
|
||||||
/// inline(always) because this is only ever called by in-order or non-in-order top-level
|
|
||||||
/// methods
|
|
||||||
#[inline(always)]
|
|
||||||
fn assign_height_block_base(&mut self, ctx: &mut LayoutContext, inorder: bool) {
|
|
||||||
let mut cur_y = Au::new(0);
|
|
||||||
let mut clearance = Au::new(0);
|
|
||||||
// Offset to content edge of box_
|
|
||||||
let mut top_offset = Au::new(0);
|
|
||||||
let mut bottom_offset = Au::new(0);
|
|
||||||
let mut left_offset = Au::new(0);
|
|
||||||
|
|
||||||
for box_ in self.box_.iter() {
|
|
||||||
// Note: Ignoring clearance for absolute flows as of now.
|
|
||||||
if !self.is_absolutely_positioned() {
|
|
||||||
clearance = match box_.clear() {
|
|
||||||
None => Au::new(0),
|
|
||||||
Some(clear) => {
|
|
||||||
self.base.floats.clearance(clear)
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// Offset to content edge of box_
|
||||||
|
let top_offset = clearance + box_.margin.get().top + box_.border.get().top +
|
||||||
|
box_.padding.get().top;
|
||||||
|
let bottom_offset = box_.margin.get().bottom + box_.border.get().bottom +
|
||||||
|
box_.padding.get().bottom;
|
||||||
|
let left_offset = box_.offset();
|
||||||
|
|
||||||
|
(clearance, top_offset, bottom_offset, left_offset)
|
||||||
}
|
}
|
||||||
|
|
||||||
top_offset = clearance + box_.margin.get().top + box_.border.get().top +
|
|
||||||
box_.padding.get().top;
|
|
||||||
cur_y = cur_y + top_offset;
|
|
||||||
bottom_offset = box_.margin.get().bottom + box_.border.get().bottom +
|
|
||||||
box_.padding.get().bottom;
|
|
||||||
left_offset = box_.offset();
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// In case of inorder assign_height traversal and not absolute flow,
|
||||||
|
/// 'assign_height's of all children are visited
|
||||||
|
/// and Float info is shared between adjacent children.
|
||||||
|
/// Float info of the last child is saved in parent flow.
|
||||||
|
pub fn handle_children_floats_if_necessary(&mut self,
|
||||||
|
ctx: &mut LayoutContext,
|
||||||
|
inorder: bool,
|
||||||
|
left_offset: Au,
|
||||||
|
top_offset: Au) {
|
||||||
// Note: Ignoring floats for absolute flow as of now.
|
// Note: Ignoring floats for absolute flow as of now.
|
||||||
if inorder && !self.is_absolutely_positioned() {
|
if inorder && !self.is_absolutely_positioned() {
|
||||||
// Floats for blocks work like this:
|
// Floats for blocks work like this:
|
||||||
|
@ -684,9 +675,41 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
self.base.floats = floats;
|
self.base.floats = floats;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// The amount of margin that we can potentially collapse with
|
/// Compute margin_top and margin_bottom. Also, it is decided whether top margin and
|
||||||
let mut collapsible = Au::new(0);
|
/// bottom margin are collapsible according to CSS 2.1 § 8.3.1.
|
||||||
|
pub fn precompute_margin(&mut self) -> (Au, Au, bool, bool) {
|
||||||
|
match self.box_ {
|
||||||
|
// Margins for an absolutely positioned element do not collapse with
|
||||||
|
// its children.
|
||||||
|
Some(ref box_) if !self.is_absolutely_positioned() => {
|
||||||
|
let top_margin_collapsible = !self.is_root &&
|
||||||
|
box_.border.get().top == Au(0) &&
|
||||||
|
box_.padding.get().top == Au(0);
|
||||||
|
|
||||||
|
let bottom_margin_collapsible = !self.is_root &&
|
||||||
|
box_.border.get().bottom == Au(0) &&
|
||||||
|
box_.padding.get().bottom == Au(0);
|
||||||
|
|
||||||
|
let margin_top = box_.margin.get().top;
|
||||||
|
let margin_bottom = box_.margin.get().bottom;
|
||||||
|
|
||||||
|
(margin_top, margin_bottom, top_margin_collapsible, bottom_margin_collapsible)
|
||||||
|
},
|
||||||
|
_ => (Au(0), Au(0), false, false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute collapsed margins between adjacent children or between the first/last child and parent
|
||||||
|
/// according to CSS 2.1 § 8.3.1. Current y position(cur_y) is continually updated for collapsing result.
|
||||||
|
pub fn compute_margin_collapse(&mut self,
|
||||||
|
cur_y: &mut Au,
|
||||||
|
top_offset: &mut Au,
|
||||||
|
margin_top: &mut Au,
|
||||||
|
margin_bottom: &mut Au,
|
||||||
|
top_margin_collapsible: bool,
|
||||||
|
bottom_margin_collapsible: bool) -> Au {
|
||||||
// How much to move up by to get to the beginning of
|
// How much to move up by to get to the beginning of
|
||||||
// current kid flow.
|
// current kid flow.
|
||||||
// Example: if previous sibling's margin-bottom is 20px and your
|
// Example: if previous sibling's margin-bottom is 20px and your
|
||||||
|
@ -694,55 +717,38 @@ impl BlockFlow {
|
||||||
// will be at the bottom margin edge of the previous sibling, we have
|
// will be at the bottom margin edge of the previous sibling, we have
|
||||||
// to move up by 12px to get to our top margin edge. So, `collapsing`
|
// to move up by 12px to get to our top margin edge. So, `collapsing`
|
||||||
// will be set to 12px
|
// will be set to 12px
|
||||||
let mut collapsing = Au::new(0);
|
|
||||||
let mut margin_top = Au::new(0);
|
|
||||||
let mut margin_bottom = Au::new(0);
|
|
||||||
let mut top_margin_collapsible = false;
|
|
||||||
let mut bottom_margin_collapsible = false;
|
|
||||||
let mut first_in_flow = true;
|
let mut first_in_flow = true;
|
||||||
// Margins for an absolutely positioned element do not collapse with
|
let mut collapsing = Au::new(0);
|
||||||
// its children.
|
// The amount of margin that we can potentially collapse with
|
||||||
if !self.is_absolutely_positioned() {
|
let mut collapsible = if top_margin_collapsible {
|
||||||
for box_ in self.box_.iter() {
|
*margin_top
|
||||||
if !self.is_root() && box_.border.get().top == Au(0)
|
} else {
|
||||||
&& box_.padding.get().top == Au(0) {
|
Au(0)
|
||||||
|
};
|
||||||
collapsible = box_.margin.get().top;
|
|
||||||
top_margin_collapsible = true;
|
|
||||||
}
|
|
||||||
if !self.is_root() && box_.border.get().bottom == Au(0) &&
|
|
||||||
box_.padding.get().bottom == Au(0) {
|
|
||||||
bottom_margin_collapsible = true;
|
|
||||||
}
|
|
||||||
margin_top = box_.margin.get().top;
|
|
||||||
margin_bottom = box_.margin.get().bottom;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// At this point, cur_y is at the content edge of the flow's box_
|
// At this point, cur_y is at the content edge of the flow's box_
|
||||||
for kid in self.base.child_iter() {
|
for kid in self.base.child_iter() {
|
||||||
// At this point, cur_y is at bottom margin edge of previous kid
|
// At this point, cur_y is at bottom margin edge of previous kid
|
||||||
|
|
||||||
if kid.is_absolutely_positioned() {
|
if kid.is_absolutely_positioned() {
|
||||||
// Assume that the `hypothetical box` for an absolute flow
|
// Assume that the `hypothetical box` for an absolute flow
|
||||||
// starts immediately after the bottom margin edge of the
|
// starts immediately after the bottom margin edge of the
|
||||||
// previous flow.
|
// previous flow.
|
||||||
kid.as_block().base.position.origin.y = cur_y;
|
kid.as_block().base.position.origin.y = *cur_y;
|
||||||
// Skip the collapsing for absolute flow kids and continue
|
// Skip the collapsing for absolute flow kids and continue
|
||||||
// with the next flow.
|
// with the next flow.
|
||||||
} else {
|
} else {
|
||||||
kid.collapse_margins(top_margin_collapsible,
|
kid.collapse_margins(top_margin_collapsible,
|
||||||
&mut first_in_flow,
|
&mut first_in_flow,
|
||||||
&mut margin_top,
|
margin_top,
|
||||||
&mut top_offset,
|
top_offset,
|
||||||
&mut collapsing,
|
&mut collapsing,
|
||||||
&mut collapsible);
|
&mut collapsible);
|
||||||
let child_node = flow::mut_base(kid);
|
let child_node = flow::mut_base(kid);
|
||||||
cur_y = cur_y - collapsing;
|
*cur_y = *cur_y - collapsing;
|
||||||
// At this point, after moving up by `collapsing`, cur_y is at the
|
// At this point, after moving up by `collapsing`, cur_y is at the
|
||||||
// top margin edge of kid
|
// top margin edge of kid
|
||||||
child_node.position.origin.y = cur_y;
|
child_node.position.origin.y = *cur_y;
|
||||||
cur_y = cur_y + child_node.position.size.height;
|
*cur_y = *cur_y + child_node.position.size.height;
|
||||||
// At this point, cur_y is at the bottom margin edge of kid
|
// At this point, cur_y is at the bottom margin edge of kid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -754,14 +760,128 @@ impl BlockFlow {
|
||||||
// The bottom margin for an absolutely positioned element does not
|
// The bottom margin for an absolutely positioned element does not
|
||||||
// collapse even with its children.
|
// collapse even with its children.
|
||||||
collapsing = if bottom_margin_collapsible && !self.is_absolutely_positioned() {
|
collapsing = if bottom_margin_collapsible && !self.is_absolutely_positioned() {
|
||||||
if margin_bottom < collapsible {
|
if *margin_bottom < collapsible {
|
||||||
margin_bottom = collapsible;
|
*margin_bottom = collapsible;
|
||||||
}
|
}
|
||||||
collapsible
|
collapsible
|
||||||
} else {
|
} else {
|
||||||
Au::new(0)
|
Au::new(0)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
collapsing
|
||||||
|
}
|
||||||
|
|
||||||
|
/// For an absolutely positioned element, store the content height for use in calculating
|
||||||
|
/// the absolute flow's dimensions later.
|
||||||
|
pub fn store_content_height_if_absolutely_positioned(&mut self,
|
||||||
|
height: Au) -> bool {
|
||||||
|
if self.is_absolutely_positioned() {
|
||||||
|
for box_ in self.box_.iter() {
|
||||||
|
let mut temp_position = box_.border_box.get();
|
||||||
|
temp_position.size.height = height;
|
||||||
|
box_.border_box.set(temp_position);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute the box height and set border_box and margin of the box.
|
||||||
|
pub fn compute_height_position(&mut self,
|
||||||
|
height: &mut Au,
|
||||||
|
border_and_padding: Au,
|
||||||
|
margin_top: Au,
|
||||||
|
margin_bottom: Au,
|
||||||
|
clearance: Au) {
|
||||||
|
// Here, height is content height of box_
|
||||||
|
let mut noncontent_height = border_and_padding;
|
||||||
|
for box_ in self.box_.iter() {
|
||||||
|
let mut position = box_.border_box.get();
|
||||||
|
let mut margin = box_.margin.get();
|
||||||
|
|
||||||
|
// The associated box is the border box of this flow.
|
||||||
|
// Margin after collapse
|
||||||
|
margin.top = margin_top;
|
||||||
|
margin.bottom = margin_bottom;
|
||||||
|
|
||||||
|
position.origin.y = clearance + margin.top;
|
||||||
|
// Border box height
|
||||||
|
position.size.height = *height + noncontent_height;
|
||||||
|
|
||||||
|
noncontent_height = noncontent_height + clearance + margin.top + margin.bottom;
|
||||||
|
|
||||||
|
box_.border_box.set(position);
|
||||||
|
box_.margin.set(margin);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Height of margin box + clearance
|
||||||
|
self.base.position.size.height = *height + noncontent_height;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Set floats_out at the last step of the assign height calculation.
|
||||||
|
pub fn set_floats_out_if_inorder(&mut self,
|
||||||
|
inorder: bool,
|
||||||
|
height: Au,
|
||||||
|
cur_y: Au,
|
||||||
|
top_offset: Au,
|
||||||
|
bottom_offset: Au,
|
||||||
|
left_offset: Au) {
|
||||||
|
if inorder {
|
||||||
|
let extra_height = height - (cur_y - top_offset) + bottom_offset;
|
||||||
|
self.base.floats.translate(Point2D(left_offset, -extra_height));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign heights for all flows in absolute flow tree and store overflow for all
|
||||||
|
/// absolute descendants.
|
||||||
|
pub fn assign_height_absolute_flows(&mut self, ctx: &mut LayoutContext) {
|
||||||
|
if self.is_root_of_absolute_flow_tree() {
|
||||||
|
// Assign heights for all flows in this Absolute flow tree.
|
||||||
|
// This is preorder because the height of an absolute flow may depend on
|
||||||
|
// the height of its CB, which may also be an absolute flow.
|
||||||
|
self.traverse_preorder_absolute_flows(&mut AbsoluteAssignHeightsTraversal(ctx));
|
||||||
|
// Store overflow for all absolute descendants.
|
||||||
|
self.traverse_postorder_absolute_flows(&mut AbsoluteStoreOverflowTraversal {
|
||||||
|
layout_context: ctx,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign height for current flow.
|
||||||
|
///
|
||||||
|
/// + Collapse margins for flow's children and set in-flow child flows'
|
||||||
|
/// y-coordinates now that we know their heights.
|
||||||
|
/// + Calculate and set the height of the current flow.
|
||||||
|
/// + Calculate height, vertical margins, and y-coordinate for the flow's
|
||||||
|
/// box. Ideally, this should be calculated using CSS Section 10.6.7
|
||||||
|
///
|
||||||
|
/// For absolute flows, store the calculated content height for the flow.
|
||||||
|
/// Defer the calculation of the other values till a later traversal.
|
||||||
|
///
|
||||||
|
/// inline(always) because this is only ever called by in-order or non-in-order top-level
|
||||||
|
/// methods
|
||||||
|
#[inline(always)]
|
||||||
|
fn assign_height_block_base(&mut self, ctx: &mut LayoutContext, inorder: bool) {
|
||||||
|
|
||||||
|
// Note: Ignoring clearance for absolute flows as of now.
|
||||||
|
let ignore_clear = self.is_absolutely_positioned();
|
||||||
|
let (clearance, mut top_offset, bottom_offset, left_offset) =
|
||||||
|
self.initialize_offsets(ignore_clear);
|
||||||
|
|
||||||
|
self.handle_children_floats_if_necessary(ctx, inorder,
|
||||||
|
left_offset, top_offset);
|
||||||
|
|
||||||
|
let (mut margin_top, mut margin_bottom,
|
||||||
|
top_margin_collapsible, bottom_margin_collapsible) = self.precompute_margin();
|
||||||
|
|
||||||
|
let mut cur_y = top_offset;
|
||||||
|
let collapsing = self.compute_margin_collapse(&mut cur_y,
|
||||||
|
&mut top_offset,
|
||||||
|
&mut margin_top,
|
||||||
|
&mut margin_bottom,
|
||||||
|
top_margin_collapsible,
|
||||||
|
bottom_margin_collapsible);
|
||||||
|
|
||||||
// TODO: A box's own margins collapse if the 'min-height' property is zero, and it has neither
|
// TODO: A box's own margins collapse if the 'min-height' property is zero, and it has neither
|
||||||
// top or bottom borders nor top or bottom padding, and it has a 'height' of either 0 or 'auto',
|
// top or bottom borders nor top or bottom padding, and it has a 'height' of either 0 or 'auto',
|
||||||
// and it does not contain a line box, and all of its in-flow children's margins (if any) collapse.
|
// and it does not contain a line box, and all of its in-flow children's margins (if any) collapse.
|
||||||
|
@ -782,17 +902,12 @@ impl BlockFlow {
|
||||||
cur_y - top_offset - collapsing
|
cur_y - top_offset - collapsing
|
||||||
};
|
};
|
||||||
|
|
||||||
if self.is_absolutely_positioned() {
|
// For an absolutely positioned element, store the content height and stop the function.
|
||||||
// Store the content height for use in calculating the absolute
|
if self.store_content_height_if_absolutely_positioned(height) {
|
||||||
// flow's dimensions later.
|
|
||||||
for box_ in self.box_.iter() {
|
|
||||||
let mut temp_position = box_.border_box.get();
|
|
||||||
temp_position.size.height = height;
|
|
||||||
box_.border_box.set(temp_position);
|
|
||||||
}
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut border_and_padding = Au::new(0);
|
||||||
for box_ in self.box_.iter() {
|
for box_ in self.box_.iter() {
|
||||||
let style = box_.style();
|
let style = box_.style();
|
||||||
|
|
||||||
|
@ -803,51 +918,19 @@ impl BlockFlow {
|
||||||
Auto => height,
|
Auto => height,
|
||||||
Specified(value) => value
|
Specified(value) => value
|
||||||
};
|
};
|
||||||
|
|
||||||
|
border_and_padding = box_.padding.get().top + box_.padding.get().bottom +
|
||||||
|
box_.border.get().top + box_.border.get().bottom;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Here, height is content height of box_
|
self.compute_height_position(&mut height,
|
||||||
|
border_and_padding,
|
||||||
|
margin_top,
|
||||||
|
margin_bottom,
|
||||||
|
clearance);
|
||||||
|
|
||||||
let mut noncontent_height = Au::new(0);
|
self.set_floats_out_if_inorder(inorder, height, cur_y, top_offset, bottom_offset, left_offset);
|
||||||
for box_ in self.box_.iter() {
|
self.assign_height_absolute_flows(ctx);
|
||||||
let mut position = box_.border_box.get();
|
|
||||||
let mut margin = box_.margin.get();
|
|
||||||
|
|
||||||
// The associated box is the border box of this flow.
|
|
||||||
// Margin after collapse
|
|
||||||
margin.top = margin_top;
|
|
||||||
margin.bottom = margin_bottom;
|
|
||||||
|
|
||||||
noncontent_height = box_.padding.get().top + box_.padding.get().bottom +
|
|
||||||
box_.border.get().top + box_.border.get().bottom;
|
|
||||||
|
|
||||||
position.origin.y = clearance + margin.top;
|
|
||||||
// Border box height
|
|
||||||
position.size.height = height + noncontent_height;
|
|
||||||
|
|
||||||
noncontent_height = noncontent_height + clearance + margin.top + margin.bottom;
|
|
||||||
|
|
||||||
box_.border_box.set(position);
|
|
||||||
box_.margin.set(margin);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Height of margin box + clearance
|
|
||||||
self.base.position.size.height = height + noncontent_height;
|
|
||||||
|
|
||||||
if inorder {
|
|
||||||
let extra_height = height - (cur_y - top_offset) + bottom_offset;
|
|
||||||
self.base.floats.translate(Point2D(left_offset, -extra_height));
|
|
||||||
}
|
|
||||||
|
|
||||||
if self.is_root_of_absolute_flow_tree() {
|
|
||||||
// Assign heights for all flows in this Absolute flow tree.
|
|
||||||
// This is preorder because the height of an absolute flow may depend on
|
|
||||||
// the height of its CB, which may also be an absolute flow.
|
|
||||||
self.traverse_preorder_absolute_flows(&mut AbsoluteAssignHeightsTraversal(ctx));
|
|
||||||
// Store overflow for all absolute descendants.
|
|
||||||
self.traverse_postorder_absolute_flows(&mut AbsoluteStoreOverflowTraversal {
|
|
||||||
layout_context: ctx,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
if self.is_root() {
|
if self.is_root() {
|
||||||
self.assign_height_store_overflow_fixed_flows(ctx);
|
self.assign_height_store_overflow_fixed_flows(ctx);
|
||||||
}
|
}
|
||||||
|
@ -990,6 +1073,74 @@ impl BlockFlow {
|
||||||
box_.border_box.set(position);
|
box_.border_box.set(position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// In case of float, initialize containing_width at the beginning step of assign_width.
|
||||||
|
pub fn set_containing_width_if_float(&mut self, containing_block_width: Au) {
|
||||||
|
if self.is_float() {
|
||||||
|
self.float.get_mut_ref().containing_width = containing_block_width;
|
||||||
|
|
||||||
|
// Parent usually sets this, but floats are never inorder
|
||||||
|
self.base.flags_info.flags.set_inorder(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Assign the computed left_content_edge and content_width to children.
|
||||||
|
pub fn propagate_assigned_width_to_children(&mut self, left_content_edge: Au,
|
||||||
|
content_width: Au) {
|
||||||
|
let has_inorder_children = if self.is_float() {
|
||||||
|
self.base.num_floats > 0
|
||||||
|
} else {
|
||||||
|
self.base.flags_info.flags.inorder() || self.base.num_floats > 0
|
||||||
|
};
|
||||||
|
|
||||||
|
let kid_abs_cb_x_offset;
|
||||||
|
if self.is_positioned() {
|
||||||
|
match self.box_ {
|
||||||
|
Some(ref box_) => {
|
||||||
|
// Pass yourself as a new Containing Block
|
||||||
|
// The static x offset for any immediate kid flows will be the
|
||||||
|
// left padding
|
||||||
|
kid_abs_cb_x_offset = box_.padding.get().left;
|
||||||
|
}
|
||||||
|
None => fail!("BlockFlow: no principal box found"),
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// For kids, the left margin edge will be at our left content edge.
|
||||||
|
// The current static offset is at our left margin
|
||||||
|
// edge. So move in to the left content edge.
|
||||||
|
kid_abs_cb_x_offset = self.base.absolute_static_x_offset + left_content_edge;
|
||||||
|
}
|
||||||
|
let kid_fixed_cb_x_offset = self.base.fixed_static_x_offset + left_content_edge;
|
||||||
|
|
||||||
|
// FIXME(ksh8281): avoid copy
|
||||||
|
let flags_info = self.base.flags_info.clone();
|
||||||
|
for kid in self.base.child_iter() {
|
||||||
|
assert!(kid.is_block_flow() || kid.is_inline_flow());
|
||||||
|
|
||||||
|
if kid.is_block_flow() {
|
||||||
|
let kid_block = kid.as_block();
|
||||||
|
kid_block.base.absolute_static_x_offset = kid_abs_cb_x_offset;
|
||||||
|
kid_block.base.fixed_static_x_offset = kid_fixed_cb_x_offset;
|
||||||
|
}
|
||||||
|
let child_base = flow::mut_base(kid);
|
||||||
|
// Left margin edge of kid flow is at our left content edge
|
||||||
|
child_base.position.origin.x = left_content_edge;
|
||||||
|
// Width of kid flow is our content width
|
||||||
|
child_base.position.size.width = content_width;
|
||||||
|
child_base.flags_info.flags.set_inorder(has_inorder_children);
|
||||||
|
|
||||||
|
if !child_base.flags_info.flags.inorder() {
|
||||||
|
child_base.floats = Floats::new();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Per CSS 2.1 § 16.3.1, text decoration propagates to all children in flow.
|
||||||
|
//
|
||||||
|
// TODO(pcwalton): When we have out-of-flow children, don't unconditionally propagate.
|
||||||
|
|
||||||
|
child_base.flags_info.propagate_text_decoration_from_parent(&flags_info);
|
||||||
|
child_base.flags_info.propagate_text_alignment_from_parent(&flags_info)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Add display items for current block.
|
/// Add display items for current block.
|
||||||
///
|
///
|
||||||
/// Set the absolute position for children after doing any offsetting for
|
/// Set the absolute position for children after doing any offsetting for
|
||||||
|
@ -1323,12 +1474,7 @@ impl Flow for BlockFlow {
|
||||||
let mut left_content_edge = Au::new(0);
|
let mut left_content_edge = Au::new(0);
|
||||||
let mut content_width = containing_block_width;
|
let mut content_width = containing_block_width;
|
||||||
|
|
||||||
if self.is_float() {
|
self.set_containing_width_if_float(containing_block_width);
|
||||||
self.float.get_mut_ref().containing_width = containing_block_width;
|
|
||||||
|
|
||||||
// Parent usually sets this, but floats are never inorder
|
|
||||||
self.base.flags_info.flags.set_inorder(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
self.compute_used_width(ctx, containing_block_width);
|
self.compute_used_width(ctx, containing_block_width);
|
||||||
|
|
||||||
|
@ -1345,59 +1491,7 @@ impl Flow for BlockFlow {
|
||||||
self.base.position.size.width = content_width;
|
self.base.position.size.width = content_width;
|
||||||
}
|
}
|
||||||
|
|
||||||
let has_inorder_children = if self.is_float() {
|
self.propagate_assigned_width_to_children(left_content_edge, content_width);
|
||||||
self.base.num_floats > 0
|
|
||||||
} else {
|
|
||||||
self.base.flags_info.flags.inorder() || self.base.num_floats > 0
|
|
||||||
};
|
|
||||||
|
|
||||||
let kid_abs_cb_x_offset;
|
|
||||||
if self.is_positioned() {
|
|
||||||
match self.box_ {
|
|
||||||
Some(ref box_) => {
|
|
||||||
// Pass yourself as a new Containing Block
|
|
||||||
// The static x offset for any immediate kid flows will be the
|
|
||||||
// left padding
|
|
||||||
kid_abs_cb_x_offset = box_.padding.get().left;
|
|
||||||
}
|
|
||||||
None => fail!("BlockFlow: no principal box found"),
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
// For kids, the left margin edge will be at our left content edge.
|
|
||||||
// The current static offset is at our left margin
|
|
||||||
// edge. So move in to the left content edge.
|
|
||||||
kid_abs_cb_x_offset = self.base.absolute_static_x_offset + left_content_edge;
|
|
||||||
}
|
|
||||||
let kid_fixed_cb_x_offset = self.base.fixed_static_x_offset + left_content_edge;
|
|
||||||
|
|
||||||
// FIXME(ksh8281): avoid copy
|
|
||||||
let flags_info = self.base.flags_info.clone();
|
|
||||||
for kid in self.base.child_iter() {
|
|
||||||
assert!(kid.is_block_flow() || kid.is_inline_flow());
|
|
||||||
|
|
||||||
if kid.is_block_flow() {
|
|
||||||
let kid_block = kid.as_block();
|
|
||||||
kid_block.base.absolute_static_x_offset = kid_abs_cb_x_offset;
|
|
||||||
kid_block.base.fixed_static_x_offset = kid_fixed_cb_x_offset;
|
|
||||||
}
|
|
||||||
let child_base = flow::mut_base(kid);
|
|
||||||
// Left margin edge of kid flow is at our left content edge
|
|
||||||
child_base.position.origin.x = left_content_edge;
|
|
||||||
// Width of kid flow is our content width
|
|
||||||
child_base.position.size.width = content_width;
|
|
||||||
child_base.flags_info.flags.set_inorder(has_inorder_children);
|
|
||||||
|
|
||||||
if !child_base.flags_info.flags.inorder() {
|
|
||||||
child_base.floats = Floats::new();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Per CSS 2.1 § 16.3.1, text decoration propagates to all children in flow.
|
|
||||||
//
|
|
||||||
// TODO(pcwalton): When we have out-of-flow children, don't unconditionally propagate.
|
|
||||||
|
|
||||||
child_base.flags_info.propagate_text_decoration_from_parent(&flags_info);
|
|
||||||
child_base.flags_info.propagate_text_alignment_from_parent(&flags_info)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// This is called on kid flows by a parent.
|
/// This is called on kid flows by a parent.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue