auto merge of #2020 : lpy/servo/issue2012, r=larsbergstrom

see #2012
This commit is contained in:
bors-servo 2014-04-10 11:16:35 -04:00
commit 4cac445754
7 changed files with 268 additions and 384 deletions

View file

@ -484,7 +484,7 @@ pub struct BlockFlow {
base: BaseFlow, base: BaseFlow,
/// The associated box. /// The associated box.
box_: Option<Box>, box_: Box,
/// TODO: is_root should be a bit field to conserve memory. /// TODO: is_root should be a bit field to conserve memory.
/// Whether this block flow is the root flow. /// Whether this block flow is the root flow.
@ -501,7 +501,7 @@ impl BlockFlow {
pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> BlockFlow { pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> BlockFlow {
BlockFlow { BlockFlow {
base: BaseFlow::new((*node).clone()), base: BaseFlow::new((*node).clone()),
box_: Some(Box::new(constructor, node)), box_: Box::new(constructor, node),
is_root: false, is_root: false,
static_y_offset: Au::new(0), static_y_offset: Au::new(0),
float: None float: None
@ -511,7 +511,7 @@ impl BlockFlow {
pub fn from_node_and_box(node: &ThreadSafeLayoutNode, box_: Box) -> BlockFlow { pub fn from_node_and_box(node: &ThreadSafeLayoutNode, box_: Box) -> BlockFlow {
BlockFlow { BlockFlow {
base: BaseFlow::new((*node).clone()), base: BaseFlow::new((*node).clone()),
box_: Some(box_), box_: box_,
is_root: false, is_root: false,
static_y_offset: Au::new(0), static_y_offset: Au::new(0),
float: None float: None
@ -524,7 +524,7 @@ impl BlockFlow {
-> BlockFlow { -> BlockFlow {
BlockFlow { BlockFlow {
base: BaseFlow::new((*node).clone()), base: BaseFlow::new((*node).clone()),
box_: Some(Box::new(constructor, node)), box_: Box::new(constructor, node),
is_root: false, is_root: false,
static_y_offset: Au::new(0), static_y_offset: Au::new(0),
float: Some(~FloatedBlockInfo::new(float_kind)) float: Some(~FloatedBlockInfo::new(float_kind))
@ -590,10 +590,7 @@ impl BlockFlow {
/// Return this flow's box. /// Return this flow's box.
pub fn box_<'a>(&'a mut self) -> &'a mut Box { pub fn box_<'a>(&'a mut self) -> &'a mut Box {
match self.box_ { &mut self.box_
Some(ref mut box_) => box_,
None => fail!("BlockFlow: no principal box found")
}
} }
/// Return the static x offset from the appropriate Containing Block for this flow. /// Return the static x offset from the appropriate Containing Block for this flow.
@ -694,22 +691,14 @@ impl BlockFlow {
/// The only two types of replaced boxes currently are text boxes and /// The only two types of replaced boxes currently are text boxes and
/// image boxes. /// image boxes.
fn is_replaced_content(&self) -> bool { fn is_replaced_content(&self) -> bool {
match self.box_ { match self.box_.specific {
Some(ref box_) => { ScannedTextBox(_) | ImageBox(_) => true,
match box_.specific { _ => false,
ScannedTextBox(_) | ImageBox(_) => true,
_ => false,
}
}
None => false,
} }
} }
pub fn teardown(&mut self) { pub fn teardown(&mut self) {
for box_ in self.box_.iter() { self.box_.teardown();
box_.teardown();
}
self.box_ = None;
self.float = None; self.float = None;
} }
@ -791,11 +780,9 @@ impl BlockFlow {
self.base.position.size.height = self.base.position.size.height + top_margin_value + self.base.position.size.height = self.base.position.size.height + top_margin_value +
bottom_margin_value; bottom_margin_value;
for fragment in self.box_.iter() { let mut position = self.box_.border_box.get();
let mut position = fragment.border_box.get(); position.size.height = position.size.height + top_margin_value + bottom_margin_value;
position.size.height = position.size.height + top_margin_value + bottom_margin_value; self.box_.border_box.set(position);
fragment.border_box.set(position);
}
} }
/// Assign height for current flow. /// Assign height for current flow.
@ -819,9 +806,6 @@ impl BlockFlow {
// Our current border-box position. // Our current border-box position.
let mut cur_y = Au(0); let mut cur_y = Au(0);
// The sum of our top border and top padding.
let mut top_offset = Au(0);
// Absolute positioning establishes a block formatting context. Don't propagate floats // Absolute positioning establishes a block formatting context. Don't propagate floats
// in or out. (But do propagate them between kids.) // in or out. (But do propagate them between kids.)
if inorder && self.is_absolutely_positioned() { if inorder && self.is_absolutely_positioned() {
@ -832,20 +816,19 @@ impl BlockFlow {
} }
let mut margin_collapse_info = MarginCollapseInfo::new(); let mut margin_collapse_info = MarginCollapseInfo::new();
for fragment in self.box_.iter() { self.base.floats.translate(Point2D(-self.box_.left_offset(), Au(0)));
self.base.floats.translate(Point2D(-fragment.left_offset(), Au(0)));
top_offset = fragment.border.get().top + fragment.padding.get().top; // The sum of our top border and top padding.
translate_including_floats(&mut cur_y, top_offset, inorder, &mut self.base.floats); let top_offset = self.box_.border.get().top + self.box_.padding.get().top;
translate_including_floats(&mut cur_y, top_offset, inorder, &mut self.base.floats);
let can_collapse_top_margin_with_kids = let can_collapse_top_margin_with_kids =
margins_may_collapse == MarginsMayCollapse && margins_may_collapse == MarginsMayCollapse &&
!self.is_absolutely_positioned() && !self.is_absolutely_positioned() &&
fragment.border.get().top == Au(0) && self.box_.border.get().top == Au(0) &&
fragment.padding.get().top == Au(0); self.box_.padding.get().top == Au(0);
margin_collapse_info.initialize_top_margin(fragment, margin_collapse_info.initialize_top_margin(&self.box_,
can_collapse_top_margin_with_kids); can_collapse_top_margin_with_kids);
}
// 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.
let mut floats = self.base.floats.clone(); let mut floats = self.base.floats.clone();
@ -954,19 +937,17 @@ impl BlockFlow {
self.collect_static_y_offsets_from_kids(); self.collect_static_y_offsets_from_kids();
// Add in our bottom margin and compute our collapsible margins. // Add in our bottom margin and compute our collapsible margins.
for fragment in self.box_.iter() { let can_collapse_bottom_margin_with_kids =
let can_collapse_bottom_margin_with_kids = margins_may_collapse == MarginsMayCollapse &&
margins_may_collapse == MarginsMayCollapse && !self.is_absolutely_positioned() &&
!self.is_absolutely_positioned() && self.box_.border.get().bottom == Au(0) &&
fragment.border.get().bottom == Au(0) && self.box_.padding.get().bottom == Au(0);
fragment.padding.get().bottom == Au(0); let (collapsible_margins, delta) =
let (collapsible_margins, delta) = margin_collapse_info.finish_and_compute_collapsible_margins(
margin_collapse_info.finish_and_compute_collapsible_margins( &self.box_,
fragment, can_collapse_bottom_margin_with_kids);
can_collapse_bottom_margin_with_kids); self.base.collapsible_margins = collapsible_margins;
self.base.collapsible_margins = collapsible_margins; translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
}
// FIXME(#2003, pcwalton): The max is taken here so that you can scroll the page, but this // FIXME(#2003, pcwalton): The max is taken here so that you can scroll the page, but this
// is not correct behavior according to CSS 2.1 § 10.5. Instead I think we should treat the // is not correct behavior according to CSS 2.1 § 10.5. Instead I think we should treat the
@ -989,42 +970,38 @@ impl BlockFlow {
// Store the content height for use in calculating the absolute flow's dimensions // Store the content height for use in calculating the absolute flow's dimensions
// later. // later.
for box_ in self.box_.iter() { let mut temp_position = self.box_.border_box.get();
let mut temp_position = box_.border_box.get(); temp_position.size.height = height;
temp_position.size.height = height; self.box_.border_box.set(temp_position);
box_.border_box.set(temp_position);
}
return return
} }
for fragment in self.box_.iter() { let mut candidate_height_iterator = CandidateHeightIterator::new(self.box_.style(),
let mut candidate_height_iterator = CandidateHeightIterator::new(fragment.style(), None);
None); for (candidate_height, new_candidate_height) in candidate_height_iterator {
for (candidate_height, new_candidate_height) in candidate_height_iterator { *new_candidate_height = match candidate_height {
*new_candidate_height = match candidate_height { Auto => height,
Auto => height, Specified(value) => value
Specified(value) => value
}
} }
// Adjust `cur_y` as necessary to account for the explicitly-specified height.
height = candidate_height_iterator.candidate_value;
let delta = height - (cur_y - top_offset);
translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
// Compute content height and noncontent height.
let bottom_offset = fragment.border.get().bottom + fragment.padding.get().bottom;
translate_including_floats(&mut cur_y, bottom_offset, inorder, &mut floats);
// Now that `cur_y` is at the bottom of the border box, compute the final border box
// position.
let mut border_box = fragment.border_box.get();
border_box.size.height = cur_y;
border_box.origin.y = Au(0);
fragment.border_box.set(border_box);
self.base.position.size.height = cur_y;
} }
// Adjust `cur_y` as necessary to account for the explicitly-specified height.
height = candidate_height_iterator.candidate_value;
let delta = height - (cur_y - top_offset);
translate_including_floats(&mut cur_y, delta, inorder, &mut floats);
// Compute content height and noncontent height.
let bottom_offset = self.box_.border.get().bottom + self.box_.padding.get().bottom;
translate_including_floats(&mut cur_y, bottom_offset, inorder, &mut floats);
// Now that `cur_y` is at the bottom of the border box, compute the final border box
// position.
let mut border_box = self.box_.border_box.get();
border_box.size.height = cur_y;
border_box.origin.y = Au(0);
self.box_.border_box.set(border_box);
self.base.position.size.height = cur_y;
self.base.floats = floats.clone(); self.base.floats = floats.clone();
self.adjust_boxes_for_collapsed_margins_if_root(); self.adjust_boxes_for_collapsed_margins_if_root();
@ -1054,25 +1031,18 @@ impl BlockFlow {
/// Therefore, assign_height_float was already called on this kid flow by /// Therefore, assign_height_float was already called on this kid flow by
/// the traversal function. So, the values used are well-defined. /// the traversal function. So, the values used are well-defined.
pub fn assign_height_float_inorder(&mut self) { pub fn assign_height_float_inorder(&mut self) {
let mut height = Au(0); let height = self.box_.border_box.get().size.height;
let mut clearance = Au(0); let clearance = match self.box_.clear() {
let mut full_noncontent_width = Au(0); None => Au(0),
let mut margin_height = Au(0); Some(clear) => self.base.floats.clearance(clear),
};
for box_ in self.box_.iter() { let noncontent_width = self.box_.padding.get().left + self.box_.padding.get().right +
height = box_.border_box.get().size.height; self.box_.border.get().left + self.box_.border.get().right;
clearance = match box_.clear() {
None => Au(0),
Some(clear) => self.base.floats.clearance(clear),
};
let noncontent_width = box_.padding.get().left + box_.padding.get().right + let full_noncontent_width = noncontent_width + self.box_.margin.get().left +
box_.border.get().left + box_.border.get().right; self.box_.margin.get().right;
let margin_height = self.box_.margin.get().top + self.box_.margin.get().bottom;
full_noncontent_width = noncontent_width + box_.margin.get().left +
box_.margin.get().right;
margin_height = box_.margin.get().top + box_.margin.get().bottom;
}
let info = PlacementInfo { let info = PlacementInfo {
size: Size2D(self.base.position.size.width + full_noncontent_width, size: Size2D(self.base.position.size.width + full_noncontent_width,
@ -1112,12 +1082,9 @@ impl BlockFlow {
drop(floats); drop(floats);
} }
let mut cur_y = Au(0); let mut cur_y = Au(0);
let mut top_offset = Au(0);
for box_ in self.box_.iter() { let top_offset = self.box_.margin.get().top + self.box_.border.get().top + self.box_.padding.get().top;
top_offset = box_.margin.get().top + box_.border.get().top + box_.padding.get().top; cur_y = cur_y + top_offset;
cur_y = cur_y + top_offset;
}
// cur_y is now at the top content edge // cur_y is now at the top content edge
@ -1131,18 +1098,17 @@ impl BlockFlow {
let content_height = cur_y - top_offset; let content_height = cur_y - top_offset;
let mut noncontent_height; let mut noncontent_height;
let box_ = self.box_.as_ref().unwrap(); let mut position = self.box_.border_box.get();
let mut position = box_.border_box.get();
// The associated box is the border box of this flow. // The associated box is the border box of this flow.
position.origin.y = box_.margin.get().top; position.origin.y = self.box_.margin.get().top;
noncontent_height = box_.padding.get().top + box_.padding.get().bottom + noncontent_height = self.box_.padding.get().top + self.box_.padding.get().bottom +
box_.border.get().top + box_.border.get().bottom; self.box_.border.get().top + self.box_.border.get().bottom;
// Calculate content height, taking `min-height` and `max-height` into account. // Calculate content height, taking `min-height` and `max-height` into account.
let mut candidate_height_iterator = CandidateHeightIterator::new(box_.style(), None); let mut candidate_height_iterator = CandidateHeightIterator::new(self.box_.style(), None);
for (candidate_height, new_candidate_height) in candidate_height_iterator { for (candidate_height, new_candidate_height) in candidate_height_iterator {
*new_candidate_height = match candidate_height { *new_candidate_height = match candidate_height {
Auto => content_height, Auto => content_height,
@ -1155,7 +1121,7 @@ impl BlockFlow {
debug!("assign_height_float -- height: {}", content_height + noncontent_height); debug!("assign_height_float -- height: {}", content_height + noncontent_height);
position.size.height = content_height + noncontent_height; position.size.height = content_height + noncontent_height;
box_.border_box.set(position); self.box_.border_box.set(position);
} }
fn build_display_list_block_common(&mut self, fn build_display_list_block_common(&mut self,
@ -1165,28 +1131,25 @@ impl BlockFlow {
offset: Point2D<Au>, offset: Point2D<Au>,
background_border_level: BackgroundAndBorderLevel) { background_border_level: BackgroundAndBorderLevel) {
let mut info = *info; let mut info = *info;
let mut rel_offset = Point2D(Au(0), Au(0)); let rel_offset = self.box_.relative_position(&info.relative_containing_block_size);
for fragment in self.box_.iter() {
rel_offset = fragment.relative_position(&info.relative_containing_block_size);
// Add the box that starts the block context. // Add the box that starts the block context.
fragment.build_display_list(stacking_context, self.box_.build_display_list(stacking_context,
builder, builder,
&info, &info,
self.base.abs_position + rel_offset + offset, self.base.abs_position + rel_offset + offset,
(&*self) as &Flow, (&*self) as &Flow,
background_border_level); background_border_level);
// For relatively-positioned descendants, the containing block formed by a block is // For relatively-positioned descendants, the containing block formed by a block is
// just the content box. The containing block for absolutely-positioned descendants, // just the content box. The containing block for absolutely-positioned descendants,
// on the other hand, only established if we are positioned. // on the other hand, only established if we are positioned.
info.relative_containing_block_size = fragment.content_box_size(); info.relative_containing_block_size = self.box_.content_box_size();
if self.is_positioned() { if self.is_positioned() {
info.absolute_containing_block_position = info.absolute_containing_block_position =
self.base.abs_position + self.base.abs_position +
self.generated_cb_position() + self.generated_cb_position() +
fragment.relative_position(&info.relative_containing_block_size) self.box_.relative_position(&info.relative_containing_block_size)
}
} }
let this_position = self.base.abs_position; let this_position = self.base.abs_position;
@ -1268,40 +1231,54 @@ impl BlockFlow {
let containing_block_height = self.containing_block_size(ctx.screen_size).height; let containing_block_height = self.containing_block_size(ctx.screen_size).height;
let static_y_offset = self.static_y_offset; let static_y_offset = self.static_y_offset;
for box_ in self.box_.iter() { // This is the stored content height value from assign-height
// This is the stored content height value from assign-height let content_height = self.box_.border_box.get().size.height - self.box_.noncontent_height();
let content_height = box_.border_box.get().size.height - box_.noncontent_height();
let style = box_.style(); let style = self.box_.style();
// Non-auto margin-top and margin-bottom values have already been // Non-auto margin-top and margin-bottom values have already been
// calculated during assign-width. // calculated during assign-width.
let margin = box_.margin.get(); let margin = self.box_.margin.get();
let margin_top = match MaybeAuto::from_style(style.Margin.get().margin_top, Au(0)) { let margin_top = match MaybeAuto::from_style(style.Margin.get().margin_top, Au(0)) {
Auto => Auto, Auto => Auto,
_ => Specified(margin.top) _ => Specified(margin.top)
}; };
let margin_bottom = match MaybeAuto::from_style(style.Margin.get().margin_bottom, Au(0)) { let margin_bottom = match MaybeAuto::from_style(style.Margin.get().margin_bottom, Au(0)) {
Auto => Auto, Auto => Auto,
_ => Specified(margin.bottom) _ => Specified(margin.bottom)
}; };
let (top, bottom) = let (top, bottom) =
(MaybeAuto::from_style(style.PositionOffsets.get().top, containing_block_height), (MaybeAuto::from_style(style.PositionOffsets.get().top, containing_block_height),
MaybeAuto::from_style(style.PositionOffsets.get().bottom, containing_block_height)); MaybeAuto::from_style(style.PositionOffsets.get().bottom, containing_block_height));
let available_height = containing_block_height - box_.noncontent_height(); let available_height = containing_block_height - self.box_.noncontent_height();
let mut solution = None; let mut solution = None;
if self.is_replaced_content() { if self.is_replaced_content() {
// Calculate used value of height just like we do for inline replaced elements. // Calculate used value of height just like we do for inline replaced elements.
// TODO: Pass in the containing block height when Box's // TODO: Pass in the containing block height when Box's
// assign-height can handle it correctly. // assign-height can handle it correctly.
box_.assign_replaced_height_if_necessary(); self.box_.assign_replaced_height_if_necessary();
// TODO: Right now, this content height value includes the // TODO: Right now, this content height value includes the
// margin because of erroneous height calculation in Box_. // margin because of erroneous height calculation in Box_.
// Check this when that has been fixed. // Check this when that has been fixed.
let height_used_val = box_.border_box.get().size.height; let height_used_val = self.box_.border_box.get().size.height;
solution = Some(HeightConstraintSolution::solve_vertical_constraints_abs_replaced( solution = Some(HeightConstraintSolution::solve_vertical_constraints_abs_replaced(
height_used_val,
margin_top,
margin_bottom,
top,
bottom,
content_height,
available_height,
static_y_offset));
} else {
let mut candidate_height_iterator =
CandidateHeightIterator::new(style, Some(containing_block_height));
for (height_used_val, new_candidate_height) in candidate_height_iterator {
solution =
Some(HeightConstraintSolution::solve_vertical_constraints_abs_nonreplaced(
height_used_val, height_used_val,
margin_top, margin_top,
margin_bottom, margin_bottom,
@ -1310,43 +1287,27 @@ impl BlockFlow {
content_height, content_height,
available_height, available_height,
static_y_offset)); static_y_offset));
} else {
let mut candidate_height_iterator =
CandidateHeightIterator::new(style, Some(containing_block_height));
for (height_used_val, new_candidate_height) in candidate_height_iterator { *new_candidate_height = solution.unwrap().height
solution =
Some(HeightConstraintSolution::solve_vertical_constraints_abs_nonreplaced(
height_used_val,
margin_top,
margin_bottom,
top,
bottom,
content_height,
available_height,
static_y_offset));
*new_candidate_height = solution.unwrap().height
}
} }
let solution = solution.unwrap();
let mut margin = box_.margin.get();
margin.top = solution.margin_top;
margin.bottom = solution.margin_bottom;
box_.margin.set(margin);
let mut position = box_.border_box.get();
position.origin.y = Au(0);
// Border box height
let border_and_padding = box_.noncontent_height();
position.size.height = solution.height + border_and_padding;
box_.border_box.set(position);
self.base.position.origin.y = solution.top + margin.top;
self.base.position.size.height = solution.height + border_and_padding;
} }
let solution = solution.unwrap();
let mut margin = self.box_.margin.get();
margin.top = solution.margin_top;
margin.bottom = solution.margin_bottom;
self.box_.margin.set(margin);
let mut position = self.box_.border_box.get();
position.origin.y = Au(0);
// Border box height
let border_and_padding = self.box_.noncontent_height();
position.size.height = solution.height + border_and_padding;
self.box_.border_box.set(position);
self.base.position.origin.y = solution.top + margin.top;
self.base.position.size.height = solution.height + border_and_padding;
} }
/// Add display items for Absolutely Positioned flow. /// Add display items for Absolutely Positioned flow.
@ -1439,15 +1400,10 @@ impl BlockFlow {
let kid_abs_cb_x_offset; let kid_abs_cb_x_offset;
if self.is_positioned() { if self.is_positioned() {
match self.box_ { // Pass yourself as a new Containing Block
Some(ref box_) => { // The static x offset for any immediate kid flows will be the
// Pass yourself as a new Containing Block // left padding
// The static x offset for any immediate kid flows will be the kid_abs_cb_x_offset = self.box_.padding.get().left;
// left padding
kid_abs_cb_x_offset = box_.padding.get().left;
}
None => fail!("BlockFlow: no principal box found"),
}
} else { } else {
// For kids, the left margin edge will be at our left content edge. // For kids, the left margin edge will be at our left content edge.
// The current static offset is at our left margin // The current static offset is at our left margin
@ -1565,20 +1521,18 @@ impl Flow for BlockFlow {
} }
// Add in borders, padding, and margins. // Add in borders, padding, and margins.
for box_ in self.box_.iter() { {
{ // Can compute border width here since it doesn't depend on anything.
// Can compute border width here since it doesn't depend on anything. self.box_.compute_borders(self.box_.style())
box_.compute_borders(box_.style())
}
let box_intrinsic_widths = box_.intrinsic_widths();
intrinsic_widths.minimum_width = geometry::max(intrinsic_widths.minimum_width,
box_intrinsic_widths.minimum_width);
intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
box_intrinsic_widths.preferred_width);
intrinsic_widths.surround_width = box_intrinsic_widths.surround_width
} }
let box_intrinsic_widths = self.box_.intrinsic_widths();
intrinsic_widths.minimum_width = geometry::max(intrinsic_widths.minimum_width,
box_intrinsic_widths.minimum_width);
intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
box_intrinsic_widths.preferred_width);
intrinsic_widths.surround_width = box_intrinsic_widths.surround_width;
self.base.intrinsic_widths = intrinsic_widths self.base.intrinsic_widths = intrinsic_widths
} }
@ -1606,25 +1560,21 @@ impl Flow for BlockFlow {
// The position was set to the containing block by the flow's parent. // The position was set to the containing block by the flow's parent.
let containing_block_width = self.base.position.size.width; let containing_block_width = self.base.position.size.width;
let mut left_content_edge = Au::new(0);
let mut content_width = containing_block_width;
self.set_containing_width_if_float(containing_block_width); self.set_containing_width_if_float(containing_block_width);
self.compute_used_width(ctx, containing_block_width); self.compute_used_width(ctx, containing_block_width);
for box_ in self.box_.iter() { // Assign `clear` now so that the assign-heights pass will have the correct value for
// Assign `clear` now so that the assign-heights pass will have the correct value for // it.
// it. self.base.clear = self.box_.style().Box.get().clear;
self.base.clear = box_.style().Box.get().clear;
// Move in from the left border edge // Move in from the left border edge
left_content_edge = box_.border_box.get().origin.x let left_content_edge = self.box_.border_box.get().origin.x
+ box_.padding.get().left + box_.border.get().left; + self.box_.padding.get().left + self.box_.border.get().left;
let padding_and_borders = box_.padding.get().left + box_.padding.get().right + let padding_and_borders = self.box_.padding.get().left + self.box_.padding.get().right +
box_.border.get().left + box_.border.get().right; self.box_.border.get().left + self.box_.border.get().right;
content_width = box_.border_box.get().size.width - padding_and_borders; let content_width = self.box_.border_box.get().size.width - padding_and_borders;
}
if self.is_float() { if self.is_float() {
self.base.position.size.width = content_width; self.base.position.size.width = content_width;
@ -1649,9 +1599,7 @@ impl Flow for BlockFlow {
fn assign_height(&mut self, ctx: &mut LayoutContext) { fn assign_height(&mut self, ctx: &mut LayoutContext) {
// Assign height for box if it is an image box. // Assign height for box if it is an image box.
for box_ in self.box_.iter() { self.box_.assign_replaced_height_if_necessary();
box_.assign_replaced_height_if_necessary();
}
if self.is_float() { if self.is_float() {
debug!("assign_height_float: assigning height for float"); debug!("assign_height_float: assigning height for float");
@ -1689,12 +1637,7 @@ impl Flow for BlockFlow {
/// The 'position' property of this flow. /// The 'position' property of this flow.
fn positioning(&self) -> position::T { fn positioning(&self) -> position::T {
match self.box_ { self.box_.style.get().Box.get().position
Some(ref box_) => {
box_.style.get().Box.get().position
}
None => fail!("BlockFlow does not have a box_")
}
} }
/// Return true if this is the root of an Absolute flow tree. /// Return true if this is the root of an Absolute flow tree.
@ -1708,34 +1651,20 @@ impl Flow for BlockFlow {
/// ///
/// For Blocks, this will be the padding box. /// For Blocks, this will be the padding box.
fn generated_cb_size(&self) -> Size2D<Au> { fn generated_cb_size(&self) -> Size2D<Au> {
match self.box_ { self.box_.padding_box_size()
Some(ref box_) => {
box_.padding_box_size()
}
None => fail!("Containing Block must have a box")
}
} }
/// Return position of the CB generated by this flow from the start of this flow. /// Return position of the CB generated by this flow from the start of this flow.
fn generated_cb_position(&self) -> Point2D<Au> { fn generated_cb_position(&self) -> Point2D<Au> {
match self.box_ { // Border box y coordinate + border top
Some(ref box_) => { self.box_.border_box.get().origin + Point2D(self.box_.border.get().left, self.box_.border.get().top)
// Border box y coordinate + border top
box_.border_box.get().origin + Point2D(box_.border.get().left, box_.border.get().top)}
None => fail!("Containing Block must have a box")
}
} }
fn layer_id(&self, fragment_index: uint) -> LayerId { fn layer_id(&self, fragment_index: uint) -> LayerId {
// FIXME(#2010, pcwalton): This is a hack and is totally bogus in the presence of pseudo- // FIXME(#2010, pcwalton): This is a hack and is totally bogus in the presence of pseudo-
// elements. But until we have incremental reflow we can't do better--we recreate the flow // elements. But until we have incremental reflow we can't do better--we recreate the flow
// for every DOM node so otherwise we nuke layers on every reflow. // for every DOM node so otherwise we nuke layers on every reflow.
match self.box_ { LayerId(self.box_.node.id(), fragment_index)
Some(ref box_) => {
LayerId(box_.node.id(), fragment_index)
}
None => fail!("can't make a layer ID for a flow with no box"),
}
} }
fn debug_str(&self) -> ~str { fn debug_str(&self) -> ~str {
@ -1746,10 +1675,7 @@ impl Flow for BlockFlow {
} else { } else {
~"BlockFlow: " ~"BlockFlow: "
}; };
txt.append(match self.box_ { txt.append(self.box_.debug_str())
Some(ref rb) => rb.debug_str(),
None => ~"",
})
} }
fn is_absolute_containing_block(&self) -> bool { fn is_absolute_containing_block(&self) -> bool {
@ -1841,35 +1767,32 @@ pub trait WidthAndMarginsComputer {
-> WidthConstraintInput { -> WidthConstraintInput {
let containing_block_width = self.containing_block_width(block, parent_flow_width, ctx); let containing_block_width = self.containing_block_width(block, parent_flow_width, ctx);
let computed_width = self.initial_computed_width(block, parent_flow_width, ctx); let computed_width = self.initial_computed_width(block, parent_flow_width, ctx);
for box_ in block.box_.iter() { let style = block.box_.style();
let style = box_.style();
// The text alignment of a block flow is the text alignment of its box's style. // The text alignment of a block flow is the text alignment of its box's style.
block.base.flags_info.flags.set_text_align(style.InheritedText.get().text_align); block.base.flags_info.flags.set_text_align(style.InheritedText.get().text_align);
box_.compute_padding(style, containing_block_width); block.box_.compute_padding(style, containing_block_width);
// We calculate and set margin-top and margin-bottom here // We calculate and set margin-top and margin-bottom here
// because CSS 2.1 defines % on this wrt CB *width*. // because CSS 2.1 defines % on this wrt CB *width*.
box_.compute_margin_top_bottom(containing_block_width); block.box_.compute_margin_top_bottom(containing_block_width);
let (margin_left, margin_right) = let (margin_left, margin_right) =
(MaybeAuto::from_style(style.Margin.get().margin_left, containing_block_width), (MaybeAuto::from_style(style.Margin.get().margin_left, containing_block_width),
MaybeAuto::from_style(style.Margin.get().margin_right, containing_block_width)); MaybeAuto::from_style(style.Margin.get().margin_right, containing_block_width));
let (left, right) = let (left, right) =
(MaybeAuto::from_style(style.PositionOffsets.get().left, containing_block_width), (MaybeAuto::from_style(style.PositionOffsets.get().left, containing_block_width),
MaybeAuto::from_style(style.PositionOffsets.get().right, containing_block_width)); MaybeAuto::from_style(style.PositionOffsets.get().right, containing_block_width));
let available_width = containing_block_width - box_.noncontent_width(); let available_width = containing_block_width - block.box_.noncontent_width();
return WidthConstraintInput::new(computed_width, return WidthConstraintInput::new(computed_width,
margin_left, margin_left,
margin_right, margin_right,
left, left,
right, right,
available_width, available_width,
block.static_x_offset()); block.static_x_offset());
}
fail!("Block doesn't have a principal box")
} }
/// Set the used values for width and margins got from the relevant constraint equation. /// Set the used values for width and margins got from the relevant constraint equation.

View file

@ -241,9 +241,7 @@ impl Flow for TableFlow {
let child_base = flow::mut_base(kid); let child_base = flow::mut_base(kid);
num_floats = num_floats + child_base.num_floats; num_floats = num_floats + child_base.num_floats;
} }
for box_ in self.block_flow.box_.iter() { self.block_flow.box_.compute_borders(self.block_flow.box_.style());
box_.compute_borders(box_.style());
}
self.block_flow.base.num_floats = num_floats; self.block_flow.base.num_floats = num_floats;
self.block_flow.base.intrinsic_widths.minimum_width = min_width; self.block_flow.base.intrinsic_widths.minimum_width = min_width;
self.block_flow.base.intrinsic_widths.preferred_width = geometry::max(min_width, pref_width); self.block_flow.base.intrinsic_widths.preferred_width = geometry::max(min_width, pref_width);
@ -256,8 +254,6 @@ impl Flow for TableFlow {
// The position was set to the containing block by the flow's parent. // The position was set to the containing block by the flow's parent.
let containing_block_width = self.block_flow.base.position.size.width; let containing_block_width = self.block_flow.base.position.size.width;
let mut left_content_edge = Au::new(0);
let mut content_width = containing_block_width;
let mut num_unspecified_widths = 0; let mut num_unspecified_widths = 0;
let mut total_column_width = Au::new(0); let mut total_column_width = Au::new(0);
@ -272,12 +268,10 @@ impl Flow for TableFlow {
let width_computer = InternalTable; let width_computer = InternalTable;
width_computer.compute_used_width(&mut self.block_flow, ctx, containing_block_width); width_computer.compute_used_width(&mut self.block_flow, ctx, containing_block_width);
for box_ in self.block_flow.box_.iter() { let left_content_edge = self.block_flow.box_.padding.get().left + self.block_flow.box_.border.get().left;
left_content_edge = box_.padding.get().left + box_.border.get().left; let padding_and_borders = self.block_flow.box_.padding.get().left + self.block_flow.box_.padding.get().right +
let padding_and_borders = box_.padding.get().left + box_.padding.get().right + self.block_flow.box_.border.get().left + self.block_flow.box_.border.get().right;
box_.border.get().left + box_.border.get().right; let content_width = self.block_flow.box_.border_box.get().size.width - padding_and_borders;
content_width = box_.border_box.get().size.width - padding_and_borders;
}
match self.table_layout { match self.table_layout {
FixedLayout => { FixedLayout => {
@ -319,10 +313,7 @@ impl Flow for TableFlow {
fn debug_str(&self) -> ~str { fn debug_str(&self) -> ~str {
let txt = ~"TableFlow: "; let txt = ~"TableFlow: ";
txt.append(match self.block_flow.box_ { txt.append(self.block_flow.box_.debug_str())
Some(ref rb) => rb.debug_str(),
None => ~"",
})
} }
} }

View file

@ -78,9 +78,6 @@ impl Flow for TableCaptionFlow {
fn debug_str(&self) -> ~str { fn debug_str(&self) -> ~str {
let txt = ~"TableCaptionFlow: "; let txt = ~"TableCaptionFlow: ";
txt.append(match self.block_flow.box_ { txt.append(self.block_flow.box_.debug_str())
Some(ref rb) => rb.debug_str(),
None => ~"",
})
} }
} }

View file

@ -35,7 +35,7 @@ impl TableCellFlow {
self.block_flow.teardown() self.block_flow.teardown()
} }
pub fn box_<'a>(&'a mut self) -> &'a Option<Box>{ pub fn box_<'a>(&'a mut self) -> &'a Box {
&self.block_flow.box_ &self.block_flow.box_
} }
@ -77,17 +77,15 @@ impl Flow for TableCellFlow {
/// Minimum/preferred widths set by this function are used in automatic table layout calculation. /// Minimum/preferred widths set by this function are used in automatic table layout calculation.
fn bubble_widths(&mut self, ctx: &mut LayoutContext) { fn bubble_widths(&mut self, ctx: &mut LayoutContext) {
self.block_flow.bubble_widths(ctx); self.block_flow.bubble_widths(ctx);
for box_ in self.block_flow.box_.iter() { let specified_width = MaybeAuto::from_style(self.block_flow.box_.style().Box.get().width,
let specified_width = MaybeAuto::from_style(box_.style().Box.get().width, Au::new(0)).specified_or_zero();
Au::new(0)).specified_or_zero(); if self.block_flow.base.intrinsic_widths.minimum_width < specified_width {
if self.block_flow.base.intrinsic_widths.minimum_width < specified_width { self.block_flow.base.intrinsic_widths.minimum_width = specified_width;
self.block_flow.base.intrinsic_widths.minimum_width = specified_width; }
} if self.block_flow.base.intrinsic_widths.preferred_width <
if self.block_flow.base.intrinsic_widths.preferred_width < self.block_flow.base.intrinsic_widths.minimum_width {
self.block_flow.base.intrinsic_widths.minimum_width { self.block_flow.base.intrinsic_widths.preferred_width =
self.block_flow.base.intrinsic_widths.preferred_width = self.block_flow.base.intrinsic_widths.minimum_width;
self.block_flow.base.intrinsic_widths.minimum_width;
}
} }
} }
@ -98,18 +96,14 @@ impl Flow for TableCellFlow {
// The position was set to the column width by the parent flow, table row flow. // The position was set to the column width by the parent flow, table row flow.
let containing_block_width = self.block_flow.base.position.size.width; let containing_block_width = self.block_flow.base.position.size.width;
let mut left_content_edge = Au::new(0);
let mut content_width = containing_block_width;
let width_computer = InternalTable; let width_computer = InternalTable;
width_computer.compute_used_width(&mut self.block_flow, ctx, containing_block_width); width_computer.compute_used_width(&mut self.block_flow, ctx, containing_block_width);
for box_ in self.block_flow.box_.iter() { let left_content_edge = self.block_flow.box_.border_box.get().origin.x + self.block_flow.box_.padding.get().left + self.block_flow.box_.border.get().left;
left_content_edge = box_.border_box.get().origin.x + box_.padding.get().left + box_.border.get().left; let padding_and_borders = self.block_flow.box_.padding.get().left + self.block_flow.box_.padding.get().right +
let padding_and_borders = box_.padding.get().left + box_.padding.get().right + self.block_flow.box_.border.get().left + self.block_flow.box_.border.get().right;
box_.border.get().left + box_.border.get().right; let content_width = self.block_flow.box_.border_box.get().size.width - padding_and_borders;
content_width = box_.border_box.get().size.width - padding_and_borders;
}
self.block_flow.propagate_assigned_width_to_children(left_content_edge, content_width, None); self.block_flow.propagate_assigned_width_to_children(left_content_edge, content_width, None);
} }
@ -130,10 +124,7 @@ impl Flow for TableCellFlow {
fn debug_str(&self) -> ~str { fn debug_str(&self) -> ~str {
let txt = ~"TableCellFlow: "; let txt = ~"TableCellFlow: ";
txt.append(match self.block_flow.box_ { txt.append(self.block_flow.box_.debug_str())
Some(ref rb) => rb.debug_str(),
None => ~"",
})
} }
} }

View file

@ -64,7 +64,7 @@ impl TableRowFlow {
self.col_pref_widths = ~[]; self.col_pref_widths = ~[];
} }
pub fn box_<'a>(&'a mut self) -> &'a Option<Box>{ pub fn box_<'a>(&'a mut self) -> &'a Box {
&self.block_flow.box_ &self.block_flow.box_
} }
@ -93,7 +93,8 @@ impl TableRowFlow {
kid.assign_height_inorder(layout_context) kid.assign_height_inorder(layout_context)
} }
for child_box in kid.as_table_cell().box_().iter() { {
let child_box = kid.as_table_cell().box_();
// TODO: Percentage height // TODO: Percentage height
let child_specified_height = MaybeAuto::from_style(child_box.style().Box.get().height, let child_specified_height = MaybeAuto::from_style(child_box.style().Box.get().height,
Au::new(0)).specified_or_zero(); Au::new(0)).specified_or_zero();
@ -105,28 +106,25 @@ impl TableRowFlow {
} }
let mut height = max_y; let mut height = max_y;
for box_ in self.block_flow.box_.iter() { // TODO: Percentage height
// TODO: Percentage height height = match MaybeAuto::from_style(self.block_flow.box_.style().Box.get().height, Au(0)) {
height = match MaybeAuto::from_style(box_.style().Box.get().height, Au(0)) { Auto => height,
Auto => height, Specified(value) => geometry::max(value, height)
Specified(value) => geometry::max(value, height) };
};
}
// cur_y = cur_y + height; // cur_y = cur_y + height;
// Assign the height of own box // Assign the height of own box
// //
// FIXME(pcwalton): Take `cur_y` into account. // FIXME(pcwalton): Take `cur_y` into account.
for box_ in self.block_flow.box_.iter() { let mut position = self.block_flow.box_.border_box.get();
let mut position = box_.border_box.get(); position.size.height = height;
position.size.height = height; self.block_flow.box_.border_box.set(position);
box_.border_box.set(position);
}
self.block_flow.base.position.size.height = height; self.block_flow.base.position.size.height = height;
// Assign the height of kid boxes, which is the same value as own height. // Assign the height of kid boxes, which is the same value as own height.
for kid in self.block_flow.base.child_iter() { for kid in self.block_flow.base.child_iter() {
for kid_box_ in kid.as_table_cell().box_().iter() { {
let kid_box_ = kid.as_table_cell().box_();
let mut position = kid_box_.border_box.get(); let mut position = kid_box_.border_box.get();
position.size.height = height; position.size.height = height;
kid_box_.border_box.set(position); kid_box_.border_box.set(position);
@ -185,7 +183,8 @@ impl Flow for TableRowFlow {
assert!(kid.is_table_cell()); assert!(kid.is_table_cell());
// collect the specified column widths of cells. These are used in fixed table layout calculation. // collect the specified column widths of cells. These are used in fixed table layout calculation.
for child_box in kid.as_table_cell().box_().iter() { {
let child_box = kid.as_table_cell().box_();
let child_specified_width = MaybeAuto::from_style(child_box.style().Box.get().width, let child_specified_width = MaybeAuto::from_style(child_box.style().Box.get().width,
Au::new(0)).specified_or_zero(); Au::new(0)).specified_or_zero();
self.col_widths.push(child_specified_width); self.col_widths.push(child_specified_width);
@ -237,10 +236,7 @@ impl Flow for TableRowFlow {
fn debug_str(&self) -> ~str { fn debug_str(&self) -> ~str {
let txt = ~"TableRowFlow: "; let txt = ~"TableRowFlow: ";
txt.append(match self.block_flow.box_ { txt.append(self.block_flow.box_.debug_str())
Some(ref rb) => rb.debug_str(),
None => ~"",
})
} }
} }

View file

@ -63,7 +63,7 @@ impl TableRowGroupFlow {
self.col_pref_widths = ~[]; self.col_pref_widths = ~[];
} }
pub fn box_<'a>(&'a mut self) -> &'a Option<Box>{ pub fn box_<'a>(&'a mut self) -> &'a Box {
&self.block_flow.box_ &self.block_flow.box_
} }
@ -93,11 +93,9 @@ impl TableRowGroupFlow {
let height = cur_y - top_offset; let height = cur_y - top_offset;
for box_ in self.block_flow.box_.iter() { let mut position = self.block_flow.box_.border_box.get();
let mut position = box_.border_box.get(); position.size.height = height;
position.size.height = height; self.block_flow.box_.border_box.set(position);
box_.border_box.set(position);
}
self.block_flow.base.position.size.height = height; self.block_flow.base.position.size.height = height;
} }
@ -219,10 +217,7 @@ impl Flow for TableRowGroupFlow {
fn debug_str(&self) -> ~str { fn debug_str(&self) -> ~str {
let txt = ~"TableRowGroupFlow: "; let txt = ~"TableRowGroupFlow: ";
txt.append(match self.block_flow.box_ { txt.append(self.block_flow.box_.debug_str())
Some(ref rb) => rb.debug_str(),
None => ~"",
})
} }
} }

View file

@ -166,16 +166,12 @@ impl Flow for TableWrapperFlow {
// The position was set to the containing block by the flow's parent. // The position was set to the containing block by the flow's parent.
let containing_block_width = self.block_flow.base.position.size.width; let containing_block_width = self.block_flow.base.position.size.width;
let mut left_content_edge = Au::new(0);
let mut content_width = containing_block_width;
let width_computer = TableWrapper; let width_computer = TableWrapper;
width_computer.compute_used_width_table_wrapper(self, ctx, containing_block_width); width_computer.compute_used_width_table_wrapper(self, ctx, containing_block_width);
for box_ in self.block_flow.box_.iter() { let left_content_edge = self.block_flow.box_.border_box.get().origin.x;
left_content_edge = box_.border_box.get().origin.x; let content_width = self.block_flow.box_.border_box.get().size.width;
content_width = box_.border_box.get().size.width;
}
match self.table_layout { match self.table_layout {
FixedLayout | _ if self.is_float() => FixedLayout | _ if self.is_float() =>
@ -221,10 +217,7 @@ impl Flow for TableWrapperFlow {
} else { } else {
~"TableWrapperFlow: " ~"TableWrapperFlow: "
}; };
txt.append(match self.block_flow.box_ { txt.append(self.block_flow.box_.debug_str())
Some(ref rb) => rb.debug_str(),
None => ~"",
})
} }
} }
@ -258,23 +251,21 @@ impl TableWrapper {
|sum, width| sum.add(width)); |sum, width| sum.add(width));
let mut computed_width = input.computed_width.specified_or_zero(); let mut computed_width = input.computed_width.specified_or_zero();
for box_ in table_wrapper.block_flow.box_.iter() { let style = table_wrapper.block_flow.box_.style();
let style = box_.style();
// Get left and right paddings, borders for table. // Get left and right paddings, borders for table.
// We get these values from the box's style since table_wrapper doesn't have it's own border or padding. // We get these values from the box's style since table_wrapper doesn't have it's own border or padding.
// input.available_width is same as containing_block_width in table_wrapper. // input.available_width is same as containing_block_width in table_wrapper.
let padding_left = specified(style.Padding.get().padding_left, let padding_left = specified(style.Padding.get().padding_left,
input.available_width); input.available_width);
let padding_right = specified(style.Padding.get().padding_right, let padding_right = specified(style.Padding.get().padding_right,
input.available_width); input.available_width);
let border_left = style.Border.get().border_left_width; let border_left = style.Border.get().border_left_width;
let border_right = style.Border.get().border_right_width; let border_right = style.Border.get().border_right_width;
let padding_and_borders = padding_left + padding_right + border_left + border_right; let padding_and_borders = padding_left + padding_right + border_left + border_right;
// Compare border-edge widths. Because fixed_cells_width indicates content-width, // Compare border-edge widths. Because fixed_cells_width indicates content-width,
// padding and border values are added to fixed_cells_width. // padding and border values are added to fixed_cells_width.
computed_width = geometry::max(fixed_cells_width + padding_and_borders, computed_width); computed_width = geometry::max(fixed_cells_width + padding_and_borders, computed_width);
}
computed_width computed_width
}, },
AutoLayout => { AutoLayout => {