mirror of
https://github.com/servo/servo.git
synced 2025-06-21 23:59:00 +01:00
Rename functions, fields and adjust comments to use fragment
instead of box
I tried to make sure to keep 'box' where it made sense, and alter comments so they still make sense.
This commit is contained in:
parent
c5fced4390
commit
3ffce02b88
15 changed files with 847 additions and 849 deletions
|
@ -52,7 +52,7 @@ pub struct FloatedBlockInfo {
|
||||||
/// Offset relative to where the parent tried to position this flow
|
/// Offset relative to where the parent tried to position this flow
|
||||||
pub rel_pos: Point2D<Au>,
|
pub rel_pos: Point2D<Au>,
|
||||||
|
|
||||||
/// Index into the box list for inline floats
|
/// Index into the fragment list for inline floats
|
||||||
pub index: Option<uint>,
|
pub index: Option<uint>,
|
||||||
|
|
||||||
/// Left or right?
|
/// Left or right?
|
||||||
|
@ -488,8 +488,8 @@ pub struct BlockFlow {
|
||||||
/// Data common to all flows.
|
/// Data common to all flows.
|
||||||
pub base: BaseFlow,
|
pub base: BaseFlow,
|
||||||
|
|
||||||
/// The associated box.
|
/// The associated fragment.
|
||||||
pub box_: Fragment,
|
pub fragment: Fragment,
|
||||||
|
|
||||||
/// 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.
|
||||||
|
@ -510,7 +510,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_: Fragment::new(constructor, node),
|
fragment: Fragment::new(constructor, node),
|
||||||
is_root: false,
|
is_root: false,
|
||||||
static_y_offset: Au::new(0),
|
static_y_offset: Au::new(0),
|
||||||
previous_float_width: None,
|
previous_float_width: None,
|
||||||
|
@ -518,10 +518,10 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode, box_: Fragment) -> BlockFlow {
|
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> BlockFlow {
|
||||||
BlockFlow {
|
BlockFlow {
|
||||||
base: BaseFlow::new((*node).clone()),
|
base: BaseFlow::new((*node).clone()),
|
||||||
box_: box_,
|
fragment: fragment,
|
||||||
is_root: false,
|
is_root: false,
|
||||||
static_y_offset: Au::new(0),
|
static_y_offset: Au::new(0),
|
||||||
previous_float_width: None,
|
previous_float_width: None,
|
||||||
|
@ -535,7 +535,7 @@ impl BlockFlow {
|
||||||
-> BlockFlow {
|
-> BlockFlow {
|
||||||
BlockFlow {
|
BlockFlow {
|
||||||
base: BaseFlow::new((*node).clone()),
|
base: BaseFlow::new((*node).clone()),
|
||||||
box_: Fragment::new(constructor, node),
|
fragment: Fragment::new(constructor, node),
|
||||||
is_root: false,
|
is_root: false,
|
||||||
static_y_offset: Au::new(0),
|
static_y_offset: Au::new(0),
|
||||||
previous_float_width: None,
|
previous_float_width: None,
|
||||||
|
@ -600,9 +600,9 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return this flow's box.
|
/// Return this flow's fragment.
|
||||||
pub fn box_<'a>(&'a mut self) -> &'a mut Fragment {
|
pub fn fragment<'a>(&'a mut self) -> &'a mut Fragment {
|
||||||
&mut self.box_
|
&mut self.fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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.
|
||||||
|
@ -698,12 +698,12 @@ impl BlockFlow {
|
||||||
traversal.process(flow)
|
traversal.process(flow)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if this has a replaced box.
|
/// Return true if this has a replaced fragment.
|
||||||
///
|
///
|
||||||
/// The only two types of replaced boxes currently are text boxes and
|
/// The only two types of replaced fragments currently are text fragments
|
||||||
/// image boxes.
|
/// and image fragments.
|
||||||
fn is_replaced_content(&self) -> bool {
|
fn is_replaced_content(&self) -> bool {
|
||||||
match self.box_.specific {
|
match self.fragment.specific {
|
||||||
ScannedTextFragment(_) | ImageFragment(_) => true,
|
ScannedTextFragment(_) | ImageFragment(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
|
@ -765,7 +765,7 @@ impl BlockFlow {
|
||||||
///
|
///
|
||||||
/// TODO(#2017, pcwalton): This is somewhat inefficient (traverses kids twice); can we do
|
/// TODO(#2017, pcwalton): This is somewhat inefficient (traverses kids twice); can we do
|
||||||
/// better?
|
/// better?
|
||||||
fn adjust_boxes_for_collapsed_margins_if_root(&mut self) {
|
fn adjust_fragments_for_collapsed_margins_if_root(&mut self) {
|
||||||
if !self.is_root() {
|
if !self.is_root() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -788,7 +788,7 @@ 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;
|
||||||
self.box_.border_box.size.height = self.box_.border_box.size.height + top_margin_value +
|
self.fragment.border_box.size.height = self.fragment.border_box.size.height + top_margin_value +
|
||||||
bottom_margin_value;
|
bottom_margin_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -822,17 +822,17 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut margin_collapse_info = MarginCollapseInfo::new();
|
let mut margin_collapse_info = MarginCollapseInfo::new();
|
||||||
self.base.floats.translate(Point2D(-self.box_.left_offset(), Au(0)));
|
self.base.floats.translate(Point2D(-self.fragment.left_offset(), Au(0)));
|
||||||
|
|
||||||
// The sum of our top border and top padding.
|
// The sum of our top border and top padding.
|
||||||
let top_offset = self.box_.border_padding.top;
|
let top_offset = self.fragment.border_padding.top;
|
||||||
translate_including_floats(&mut cur_y, top_offset, &mut self.base.floats);
|
translate_including_floats(&mut cur_y, top_offset, &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() &&
|
||||||
self.box_.border_padding.top == Au(0);
|
self.fragment.border_padding.top == Au(0);
|
||||||
margin_collapse_info.initialize_top_margin(&self.box_,
|
margin_collapse_info.initialize_top_margin(&self.fragment,
|
||||||
can_collapse_top_margin_with_kids);
|
can_collapse_top_margin_with_kids);
|
||||||
|
|
||||||
// At this point, `cur_y` is at the content edge of our box. Now iterate over children.
|
// At this point, `cur_y` is at the content edge of our box. Now iterate over children.
|
||||||
|
@ -934,10 +934,10 @@ impl BlockFlow {
|
||||||
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_padding.bottom == Au(0);
|
self.fragment.border_padding.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_,
|
&self.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, &mut floats);
|
translate_including_floats(&mut cur_y, delta, &mut floats);
|
||||||
|
@ -963,11 +963,11 @@ 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.
|
||||||
self.box_.border_box.size.height = height;
|
self.fragment.border_box.size.height = height;
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut candidate_height_iterator = CandidateHeightIterator::new(self.box_.style(),
|
let mut candidate_height_iterator = CandidateHeightIterator::new(self.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 {
|
||||||
|
@ -982,17 +982,17 @@ impl BlockFlow {
|
||||||
translate_including_floats(&mut cur_y, delta, &mut floats);
|
translate_including_floats(&mut cur_y, delta, &mut floats);
|
||||||
|
|
||||||
// Compute content height and noncontent height.
|
// Compute content height and noncontent height.
|
||||||
let bottom_offset = self.box_.border_padding.bottom;
|
let bottom_offset = self.fragment.border_padding.bottom;
|
||||||
translate_including_floats(&mut cur_y, bottom_offset, &mut floats);
|
translate_including_floats(&mut cur_y, bottom_offset, &mut floats);
|
||||||
|
|
||||||
// Now that `cur_y` is at the bottom of the border box, compute the final border box
|
// Now that `cur_y` is at the bottom of the border box, compute the final border box
|
||||||
// position.
|
// position.
|
||||||
self.box_.border_box.size.height = cur_y;
|
self.fragment.border_box.size.height = cur_y;
|
||||||
self.box_.border_box.origin.y = Au(0);
|
self.fragment.border_box.origin.y = Au(0);
|
||||||
self.base.position.size.height = cur_y;
|
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_fragments_for_collapsed_margins_if_root();
|
||||||
|
|
||||||
if self.is_root_of_absolute_flow_tree() {
|
if self.is_root_of_absolute_flow_tree() {
|
||||||
// Assign heights for all flows in this Absolute flow tree.
|
// Assign heights for all flows in this Absolute flow tree.
|
||||||
|
@ -1018,16 +1018,16 @@ impl BlockFlow {
|
||||||
/// already called on this kid flow by the traversal function. So, the values used are
|
/// already called on this kid flow by the traversal function. So, the values used are
|
||||||
/// well-defined.
|
/// well-defined.
|
||||||
pub fn place_float(&mut self) {
|
pub fn place_float(&mut self) {
|
||||||
let height = self.box_.border_box.size.height;
|
let height = self.fragment.border_box.size.height;
|
||||||
let clearance = match self.box_.clear() {
|
let clearance = match self.fragment.clear() {
|
||||||
None => Au(0),
|
None => Au(0),
|
||||||
Some(clear) => self.base.floats.clearance(clear),
|
Some(clear) => self.base.floats.clearance(clear),
|
||||||
};
|
};
|
||||||
|
|
||||||
let margin_height = self.box_.margin.vertical();
|
let margin_height = self.fragment.margin.vertical();
|
||||||
let info = PlacementInfo {
|
let info = PlacementInfo {
|
||||||
size: Size2D(self.base.position.size.width + self.box_.margin.horizontal() +
|
size: Size2D(self.base.position.size.width + self.fragment.margin.horizontal() +
|
||||||
self.box_.border_padding.horizontal(),
|
self.fragment.border_padding.horizontal(),
|
||||||
height + margin_height),
|
height + margin_height),
|
||||||
ceiling: clearance + self.base.position.origin.y,
|
ceiling: clearance + self.base.position.origin.y,
|
||||||
max_width: self.float.get_ref().containing_width,
|
max_width: self.float.get_ref().containing_width,
|
||||||
|
@ -1060,7 +1060,7 @@ impl BlockFlow {
|
||||||
// Floats establish a block formatting context, so we discard the output floats here.
|
// Floats establish a block formatting context, so we discard the output floats here.
|
||||||
drop(floats);
|
drop(floats);
|
||||||
|
|
||||||
let top_offset = self.box_.margin.top + self.box_.border_padding.top;
|
let top_offset = self.fragment.margin.top + self.fragment.border_padding.top;
|
||||||
let mut cur_y = top_offset;
|
let mut cur_y = top_offset;
|
||||||
|
|
||||||
// cur_y is now at the top content edge
|
// cur_y is now at the top content edge
|
||||||
|
@ -1074,11 +1074,11 @@ impl BlockFlow {
|
||||||
|
|
||||||
let content_height = cur_y - top_offset;
|
let content_height = cur_y - top_offset;
|
||||||
|
|
||||||
// The associated box is the border box of this flow.
|
// The associated fragment has the border box of this flow.
|
||||||
self.box_.border_box.origin.y = self.box_.margin.top;
|
self.fragment.border_box.origin.y = self.fragment.margin.top;
|
||||||
|
|
||||||
// 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(self.box_.style(), None);
|
let mut candidate_height_iterator = CandidateHeightIterator::new(self.fragment.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,
|
||||||
|
@ -1087,9 +1087,9 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
let content_height = candidate_height_iterator.candidate_value;
|
let content_height = candidate_height_iterator.candidate_value;
|
||||||
let noncontent_height = self.box_.border_padding.vertical();
|
let noncontent_height = self.fragment.border_padding.vertical();
|
||||||
debug!("assign_height_float -- height: {}", content_height + noncontent_height);
|
debug!("assign_height_float -- height: {}", content_height + noncontent_height);
|
||||||
self.box_.border_box.size.height = content_height + noncontent_height;
|
self.fragment.border_box.size.height = content_height + noncontent_height;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_display_list_block_common(&mut self,
|
fn build_display_list_block_common(&mut self,
|
||||||
|
@ -1097,7 +1097,7 @@ impl BlockFlow {
|
||||||
offset: Point2D<Au>,
|
offset: Point2D<Au>,
|
||||||
background_border_level: BackgroundAndBorderLevel) {
|
background_border_level: BackgroundAndBorderLevel) {
|
||||||
let rel_offset =
|
let rel_offset =
|
||||||
self.box_.relative_position(&self.base
|
self.fragment.relative_position(&self.base
|
||||||
.absolute_position_info
|
.absolute_position_info
|
||||||
.relative_containing_block_size,
|
.relative_containing_block_size,
|
||||||
None);
|
None);
|
||||||
|
@ -1105,11 +1105,11 @@ impl BlockFlow {
|
||||||
// Add the box that starts the block context.
|
// Add the box that starts the block context.
|
||||||
let mut display_list = DisplayList::new();
|
let mut display_list = DisplayList::new();
|
||||||
let mut accumulator =
|
let mut accumulator =
|
||||||
self.box_.build_display_list(&mut display_list,
|
self.fragment.build_display_list(&mut display_list,
|
||||||
layout_context,
|
layout_context,
|
||||||
self.base.abs_position + rel_offset + offset,
|
self.base.abs_position + rel_offset + offset,
|
||||||
background_border_level,
|
background_border_level,
|
||||||
None);
|
None);
|
||||||
|
|
||||||
let mut child_layers = DList::new();
|
let mut child_layers = DList::new();
|
||||||
for kid in self.base.child_iter() {
|
for kid in self.base.child_iter() {
|
||||||
|
@ -1176,39 +1176,39 @@ impl BlockFlow {
|
||||||
let static_y_offset = self.static_y_offset;
|
let static_y_offset = self.static_y_offset;
|
||||||
|
|
||||||
// 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_.content_box().size.height;
|
let content_height = self.fragment.content_box().size.height;
|
||||||
|
|
||||||
let mut solution = None;
|
let mut solution = None;
|
||||||
{
|
{
|
||||||
// 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_top = match self.box_.style().get_margin().margin_top {
|
let margin_top = match self.fragment.style().get_margin().margin_top {
|
||||||
LPA_Auto => Auto,
|
LPA_Auto => Auto,
|
||||||
_ => Specified(self.box_.margin.top)
|
_ => Specified(self.fragment.margin.top)
|
||||||
};
|
};
|
||||||
let margin_bottom = match self.box_.style().get_margin().margin_bottom {
|
let margin_bottom = match self.fragment.style().get_margin().margin_bottom {
|
||||||
LPA_Auto => Auto,
|
LPA_Auto => Auto,
|
||||||
_ => Specified(self.box_.margin.bottom)
|
_ => Specified(self.fragment.margin.bottom)
|
||||||
};
|
};
|
||||||
|
|
||||||
let top;
|
let top;
|
||||||
let bottom;
|
let bottom;
|
||||||
{
|
{
|
||||||
let position_style = self.box_.style().get_positionoffsets();
|
let position_style = self.fragment.style().get_positionoffsets();
|
||||||
top = MaybeAuto::from_style(position_style.top, containing_block_height);
|
top = MaybeAuto::from_style(position_style.top, containing_block_height);
|
||||||
bottom = MaybeAuto::from_style(position_style.bottom, containing_block_height);
|
bottom = MaybeAuto::from_style(position_style.bottom, containing_block_height);
|
||||||
}
|
}
|
||||||
|
|
||||||
let available_height = containing_block_height - self.box_.border_padding.vertical();
|
let available_height = containing_block_height - self.fragment.border_padding.vertical();
|
||||||
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 Fragment's
|
// TODO: Pass in the containing block height when Fragment's
|
||||||
// assign-height can handle it correctly.
|
// assign-height can handle it correctly.
|
||||||
self.box_.assign_replaced_height_if_necessary();
|
self.fragment.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 fragment.
|
||||||
// Check this when that has been fixed.
|
// Check this when that has been fixed.
|
||||||
let height_used_val = self.box_.border_box.size.height;
|
let height_used_val = self.fragment.border_box.size.height;
|
||||||
solution = Some(HeightConstraintSolution::solve_vertical_constraints_abs_replaced(
|
solution = Some(HeightConstraintSolution::solve_vertical_constraints_abs_replaced(
|
||||||
height_used_val,
|
height_used_val,
|
||||||
margin_top,
|
margin_top,
|
||||||
|
@ -1219,7 +1219,7 @@ impl BlockFlow {
|
||||||
available_height,
|
available_height,
|
||||||
static_y_offset));
|
static_y_offset));
|
||||||
} else {
|
} else {
|
||||||
let style = self.box_.style();
|
let style = self.fragment.style();
|
||||||
let mut candidate_height_iterator =
|
let mut candidate_height_iterator =
|
||||||
CandidateHeightIterator::new(style, Some(containing_block_height));
|
CandidateHeightIterator::new(style, Some(containing_block_height));
|
||||||
|
|
||||||
|
@ -1241,13 +1241,13 @@ impl BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
let solution = solution.unwrap();
|
let solution = solution.unwrap();
|
||||||
self.box_.margin.top = solution.margin_top;
|
self.fragment.margin.top = solution.margin_top;
|
||||||
self.box_.margin.bottom = solution.margin_bottom;
|
self.fragment.margin.bottom = solution.margin_bottom;
|
||||||
self.box_.border_box.origin.y = Au(0);
|
self.fragment.border_box.origin.y = Au(0);
|
||||||
self.box_.border_box.size.height = solution.height + self.box_.border_padding.vertical();
|
self.fragment.border_box.size.height = solution.height + self.fragment.border_padding.vertical();
|
||||||
|
|
||||||
self.base.position.origin.y = solution.top + self.box_.margin.top;
|
self.base.position.origin.y = solution.top + self.fragment.margin.top;
|
||||||
self.base.position.size.height = solution.height + self.box_.border_padding.vertical();
|
self.base.position.size.height = solution.height + self.fragment.border_padding.vertical();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add display items for Absolutely Positioned flow.
|
/// Add display items for Absolutely Positioned flow.
|
||||||
|
@ -1288,7 +1288,7 @@ impl BlockFlow {
|
||||||
self.base.layers.push_back(new_layer)
|
self.base.layers.push_back(new_layer)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return the top outer edge of the Hypothetical Fragment for an absolute flow.
|
/// Return the top outer edge of the hypothetical box for an absolute flow.
|
||||||
///
|
///
|
||||||
/// This is wrt its parent flow box.
|
/// This is wrt its parent flow box.
|
||||||
///
|
///
|
||||||
|
@ -1316,7 +1316,7 @@ impl BlockFlow {
|
||||||
let absolute_static_x_offset = if self.is_positioned() {
|
let absolute_static_x_offset = if self.is_positioned() {
|
||||||
// This flow is the containing block. The static X offset will be the left padding
|
// This flow is the containing block. The static X offset will be the left padding
|
||||||
// edge.
|
// edge.
|
||||||
self.box_.border_padding.left - model::border_from_style(self.box_.style()).left
|
self.fragment.border_padding.left - model::border_from_style(self.fragment.style()).left
|
||||||
} else {
|
} else {
|
||||||
// For kids, the left margin edge will be at our left content edge. The current static
|
// 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.
|
// offset is at our left margin edge. So move in to the left content edge.
|
||||||
|
@ -1395,7 +1395,7 @@ impl BlockFlow {
|
||||||
/// Determines the type of formatting context this is. See the definition of
|
/// Determines the type of formatting context this is. See the definition of
|
||||||
/// `FormattingContextType`.
|
/// `FormattingContextType`.
|
||||||
fn formatting_context_type(&self) -> FormattingContextType {
|
fn formatting_context_type(&self) -> FormattingContextType {
|
||||||
let style = self.box_.style();
|
let style = self.fragment.style();
|
||||||
if style.get_box().float != float::none {
|
if style.get_box().float != float::none {
|
||||||
return OtherFormattingContext
|
return OtherFormattingContext
|
||||||
}
|
}
|
||||||
|
@ -1423,7 +1423,7 @@ impl Flow for BlockFlow {
|
||||||
|
|
||||||
/// Returns the direction that this flow clears floats in, if any.
|
/// Returns the direction that this flow clears floats in, if any.
|
||||||
fn float_clearance(&self) -> clear::T {
|
fn float_clearance(&self) -> clear::T {
|
||||||
self.box_.style().get_box().clear
|
self.fragment.style().get_box().clear
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pass 1 of reflow: computes minimum and preferred widths.
|
/// Pass 1 of reflow: computes minimum and preferred widths.
|
||||||
|
@ -1431,7 +1431,7 @@ impl Flow for BlockFlow {
|
||||||
/// Recursively (bottom-up) determine the flow's minimum and preferred widths. When called on
|
/// Recursively (bottom-up) determine the flow's minimum and preferred widths. When called on
|
||||||
/// this flow, all child flows have had their minimum and preferred widths set. This function
|
/// this flow, all child flows have had their minimum and preferred widths set. This function
|
||||||
/// must decide minimum/preferred widths based on its children's widths and the dimensions of
|
/// must decide minimum/preferred widths based on its children's widths and the dimensions of
|
||||||
/// any boxes it is responsible for flowing.
|
/// any fragments it is responsible for flowing.
|
||||||
///
|
///
|
||||||
/// TODO(pcwalton): Inline blocks.
|
/// TODO(pcwalton): Inline blocks.
|
||||||
fn bubble_widths(&mut self, _: &mut LayoutContext) {
|
fn bubble_widths(&mut self, _: &mut LayoutContext) {
|
||||||
|
@ -1457,15 +1457,15 @@ impl Flow for BlockFlow {
|
||||||
flags.union_floated_descendants_flags(child_base.flags);
|
flags.union_floated_descendants_flags(child_base.flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
let box_intrinsic_widths = self.box_.intrinsic_widths(None);
|
let fragment_intrinsic_widths = self.fragment.intrinsic_widths(None);
|
||||||
intrinsic_widths.minimum_width = geometry::max(intrinsic_widths.minimum_width,
|
intrinsic_widths.minimum_width = geometry::max(intrinsic_widths.minimum_width,
|
||||||
box_intrinsic_widths.minimum_width);
|
fragment_intrinsic_widths.minimum_width);
|
||||||
intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
|
intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
|
||||||
box_intrinsic_widths.preferred_width);
|
fragment_intrinsic_widths.preferred_width);
|
||||||
intrinsic_widths.surround_width = box_intrinsic_widths.surround_width;
|
intrinsic_widths.surround_width = fragment_intrinsic_widths.surround_width;
|
||||||
self.base.intrinsic_widths = intrinsic_widths;
|
self.base.intrinsic_widths = intrinsic_widths;
|
||||||
|
|
||||||
match self.box_.style().get_box().float {
|
match self.fragment.style().get_box().float {
|
||||||
float::none => {}
|
float::none => {}
|
||||||
float::left => flags.set_has_left_floated_descendants(true),
|
float::left => flags.set_has_left_floated_descendants(true),
|
||||||
float::right => flags.set_has_right_floated_descendants(true),
|
float::right => flags.set_has_right_floated_descendants(true),
|
||||||
|
@ -1473,10 +1473,10 @@ impl Flow for BlockFlow {
|
||||||
self.base.flags = flags
|
self.base.flags = flags
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
/// Recursively (top-down) determines the actual width of child contexts and fragments. When
|
||||||
/// on this context, the context has had its width set by the parent context.
|
/// called on this context, the context has had its width set by the parent context.
|
||||||
///
|
///
|
||||||
/// Dual boxes consume some width first, and the remainder is assigned to all child (block)
|
/// Dual fragments consume some width first, and the remainder is assigned to all child (block)
|
||||||
/// contexts.
|
/// contexts.
|
||||||
fn assign_widths(&mut self, layout_context: &mut LayoutContext) {
|
fn assign_widths(&mut self, layout_context: &mut LayoutContext) {
|
||||||
debug!("assign_widths({}): assigning width for flow",
|
debug!("assign_widths({}): assigning width for flow",
|
||||||
|
@ -1518,8 +1518,8 @@ impl Flow for BlockFlow {
|
||||||
match self.previous_float_width {
|
match self.previous_float_width {
|
||||||
None => {}
|
None => {}
|
||||||
Some(previous_float_width) => {
|
Some(previous_float_width) => {
|
||||||
self.box_.border_box.size.width =
|
self.fragment.border_box.size.width =
|
||||||
self.box_.border_box.size.width - previous_float_width
|
self.fragment.border_box.size.width - previous_float_width
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1530,9 +1530,9 @@ impl Flow for BlockFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move in from the left border edge
|
// Move in from the left border edge
|
||||||
let left_content_edge = self.box_.border_box.origin.x + self.box_.border_padding.left;
|
let left_content_edge = self.fragment.border_box.origin.x + self.fragment.border_padding.left;
|
||||||
let padding_and_borders = self.box_.border_padding.horizontal();
|
let padding_and_borders = self.fragment.border_padding.horizontal();
|
||||||
let content_width = self.box_.border_box.size.width - padding_and_borders;
|
let content_width = self.fragment.border_box.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;
|
||||||
|
@ -1562,8 +1562,8 @@ 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 fragment if it is an image fragment.
|
||||||
self.box_.assign_replaced_height_if_necessary();
|
self.fragment.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");
|
||||||
|
@ -1598,10 +1598,10 @@ impl Flow for BlockFlow {
|
||||||
// the content box. The containing block for absolutely-positioned descendants, on the
|
// the content box. The containing block for absolutely-positioned descendants, on the
|
||||||
// other hand, is only established if we are positioned.
|
// other hand, is only established if we are positioned.
|
||||||
let relative_offset =
|
let relative_offset =
|
||||||
self.box_.relative_position(&self.base
|
self.fragment.relative_position(&self.base
|
||||||
.absolute_position_info
|
.absolute_position_info
|
||||||
.relative_containing_block_size,
|
.relative_containing_block_size,
|
||||||
None);
|
None);
|
||||||
if self.is_positioned() {
|
if self.is_positioned() {
|
||||||
self.base.absolute_position_info.absolute_containing_block_position =
|
self.base.absolute_position_info.absolute_containing_block_position =
|
||||||
self.base.abs_position +
|
self.base.abs_position +
|
||||||
|
@ -1617,7 +1617,7 @@ impl Flow for BlockFlow {
|
||||||
|
|
||||||
// Compute absolute position info for children.
|
// Compute absolute position info for children.
|
||||||
let mut absolute_position_info = self.base.absolute_position_info;
|
let mut absolute_position_info = self.base.absolute_position_info;
|
||||||
absolute_position_info.relative_containing_block_size = self.box_.content_box().size;
|
absolute_position_info.relative_containing_block_size = self.fragment.content_box().size;
|
||||||
absolute_position_info.layers_needed_for_positioned_flows =
|
absolute_position_info.layers_needed_for_positioned_flows =
|
||||||
self.base.flags.layers_needed_for_descendants();
|
self.base.flags.layers_needed_for_descendants();
|
||||||
|
|
||||||
|
@ -1665,7 +1665,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 {
|
||||||
self.box_.style.get_box().position
|
self.fragment.style.get_box().position
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Return true if this is the root of an Absolute flow tree.
|
/// Return true if this is the root of an Absolute flow tree.
|
||||||
|
@ -1678,17 +1678,17 @@ impl Flow for BlockFlow {
|
||||||
/// Return the dimensions of the containing block generated by this flow for absolutely-
|
/// Return the dimensions of the containing block generated by this flow for absolutely-
|
||||||
/// positioned descendants. For block flows, this is the padding box.
|
/// positioned descendants. For block flows, this is the padding box.
|
||||||
fn generated_containing_block_rect(&self) -> Rect<Au> {
|
fn generated_containing_block_rect(&self) -> Rect<Au> {
|
||||||
let border = model::border_from_style(self.box_.style());
|
let border = model::border_from_style(self.fragment.style());
|
||||||
Rect(self.box_.border_box.origin + Point2D(border.left, border.top),
|
Rect(self.fragment.border_box.origin + Point2D(border.left, border.top),
|
||||||
Size2D(self.box_.border_box.size.width - border.horizontal(),
|
Size2D(self.fragment.border_box.size.width - border.horizontal(),
|
||||||
self.box_.border_box.size.height - border.vertical()))
|
self.fragment.border_box.size.height - border.vertical()))
|
||||||
}
|
}
|
||||||
|
|
||||||
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.
|
||||||
LayerId(self.box_.node.id(), fragment_index)
|
LayerId(self.fragment.node.id(), fragment_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn is_absolute_containing_block(&self) -> bool {
|
fn is_absolute_containing_block(&self) -> bool {
|
||||||
|
@ -1699,11 +1699,11 @@ impl Flow for BlockFlow {
|
||||||
impl fmt::Show for BlockFlow {
|
impl fmt::Show for BlockFlow {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.is_float() {
|
if self.is_float() {
|
||||||
write!(f.buf, "FloatFlow: {}", self.box_)
|
write!(f.buf, "FloatFlow: {}", self.fragment)
|
||||||
} else if self.is_root() {
|
} else if self.is_root() {
|
||||||
write!(f.buf, "RootFlow: {}", self.box_)
|
write!(f.buf, "RootFlow: {}", self.fragment)
|
||||||
} else {
|
} else {
|
||||||
write!(f.buf, "BlockFlow: {}", self.box_)
|
write!(f.buf, "BlockFlow: {}", self.fragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1793,9 +1793,9 @@ pub trait WidthAndMarginsComputer {
|
||||||
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);
|
||||||
|
|
||||||
block.box_.compute_border_padding_margins(containing_block_width, None);
|
block.fragment.compute_border_padding_margins(containing_block_width, None);
|
||||||
|
|
||||||
let style = block.box_.style();
|
let style = block.fragment.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.set_text_align(style.get_inheritedtext().text_align);
|
block.base.flags.set_text_align(style.get_inheritedtext().text_align);
|
||||||
|
@ -1807,7 +1807,7 @@ pub trait WidthAndMarginsComputer {
|
||||||
let (left, right) =
|
let (left, right) =
|
||||||
(MaybeAuto::from_style(style.get_positionoffsets().left, containing_block_width),
|
(MaybeAuto::from_style(style.get_positionoffsets().left, containing_block_width),
|
||||||
MaybeAuto::from_style(style.get_positionoffsets().right, containing_block_width));
|
MaybeAuto::from_style(style.get_positionoffsets().right, containing_block_width));
|
||||||
let available_width = containing_block_width - block.box_.border_padding.horizontal();
|
let available_width = containing_block_width - block.fragment.border_padding.horizontal();
|
||||||
return WidthConstraintInput::new(computed_width,
|
return WidthConstraintInput::new(computed_width,
|
||||||
margin_left,
|
margin_left,
|
||||||
margin_right,
|
margin_right,
|
||||||
|
@ -1828,15 +1828,15 @@ pub trait WidthAndMarginsComputer {
|
||||||
fn set_width_constraint_solutions(&self,
|
fn set_width_constraint_solutions(&self,
|
||||||
block: &mut BlockFlow,
|
block: &mut BlockFlow,
|
||||||
solution: WidthConstraintSolution) {
|
solution: WidthConstraintSolution) {
|
||||||
let box_ = block.box_();
|
let fragment = block.fragment();
|
||||||
box_.margin.left = solution.margin_left;
|
fragment.margin.left = solution.margin_left;
|
||||||
box_.margin.right = solution.margin_right;
|
fragment.margin.right = solution.margin_right;
|
||||||
|
|
||||||
// The associated box is the border box of this flow.
|
// The associated fragment has the border box of this flow.
|
||||||
// Left border edge.
|
// Left border edge.
|
||||||
box_.border_box.origin.x = box_.margin.left;
|
fragment.border_box.origin.x = fragment.margin.left;
|
||||||
// Border box width.
|
// Border box width.
|
||||||
box_.border_box.size.width = solution.width + box_.border_padding.horizontal();
|
fragment.border_box.size.width = solution.width + fragment.border_padding.horizontal();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set the x coordinate of the given flow if it is absolutely positioned.
|
/// Set the x coordinate of the given flow if it is absolutely positioned.
|
||||||
|
@ -1853,7 +1853,7 @@ pub trait WidthAndMarginsComputer {
|
||||||
parent_flow_width: Au,
|
parent_flow_width: Au,
|
||||||
ctx: &mut LayoutContext)
|
ctx: &mut LayoutContext)
|
||||||
-> MaybeAuto {
|
-> MaybeAuto {
|
||||||
MaybeAuto::from_style(block.box_().style().get_box().width,
|
MaybeAuto::from_style(block.fragment().style().get_box().width,
|
||||||
self.containing_block_width(block, parent_flow_width, ctx))
|
self.containing_block_width(block, parent_flow_width, ctx))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1880,7 +1880,7 @@ pub trait WidthAndMarginsComputer {
|
||||||
|
|
||||||
// If the tentative used width is greater than 'max-width', width should be recalculated,
|
// If the tentative used width is greater than 'max-width', width should be recalculated,
|
||||||
// but this time using the computed value of 'max-width' as the computed value for 'width'.
|
// but this time using the computed value of 'max-width' as the computed value for 'width'.
|
||||||
match specified_or_none(block.box_().style().get_box().max_width, containing_block_width) {
|
match specified_or_none(block.fragment().style().get_box().max_width, containing_block_width) {
|
||||||
Some(max_width) if max_width < solution.width => {
|
Some(max_width) if max_width < solution.width => {
|
||||||
input.computed_width = Specified(max_width);
|
input.computed_width = Specified(max_width);
|
||||||
solution = self.solve_width_constraints(block, &input);
|
solution = self.solve_width_constraints(block, &input);
|
||||||
|
@ -1890,7 +1890,7 @@ pub trait WidthAndMarginsComputer {
|
||||||
|
|
||||||
// If the resulting width is smaller than 'min-width', width should be recalculated,
|
// If the resulting width is smaller than 'min-width', width should be recalculated,
|
||||||
// but this time using the value of 'min-width' as the computed value for 'width'.
|
// but this time using the value of 'min-width' as the computed value for 'width'.
|
||||||
let computed_min_width = specified(block.box_().style().get_box().min_width,
|
let computed_min_width = specified(block.fragment().style().get_box().min_width,
|
||||||
containing_block_width);
|
containing_block_width);
|
||||||
if computed_min_width > solution.width {
|
if computed_min_width > solution.width {
|
||||||
input.computed_width = Specified(computed_min_width);
|
input.computed_width = Specified(computed_min_width);
|
||||||
|
@ -2233,11 +2233,11 @@ impl WidthAndMarginsComputer for AbsoluteReplaced {
|
||||||
ctx: &mut LayoutContext)
|
ctx: &mut LayoutContext)
|
||||||
-> MaybeAuto {
|
-> MaybeAuto {
|
||||||
let containing_block_width = block.containing_block_size(ctx.screen_size).width;
|
let containing_block_width = block.containing_block_size(ctx.screen_size).width;
|
||||||
let box_ = block.box_();
|
let fragment = block.fragment();
|
||||||
box_.assign_replaced_width_if_necessary(containing_block_width, None);
|
fragment.assign_replaced_width_if_necessary(containing_block_width, None);
|
||||||
// For replaced absolute flow, the rest of the constraint solving will
|
// For replaced absolute flow, the rest of the constraint solving will
|
||||||
// take width to be specified as the value computed here.
|
// take width to be specified as the value computed here.
|
||||||
Specified(box_.content_width())
|
Specified(fragment.content_width())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn containing_block_width(&self, block: &mut BlockFlow, _: Au, ctx: &mut LayoutContext) -> Au {
|
fn containing_block_width(&self, block: &mut BlockFlow, _: Au, ctx: &mut LayoutContext) -> Au {
|
||||||
|
@ -2282,11 +2282,11 @@ impl WidthAndMarginsComputer for BlockReplaced {
|
||||||
parent_flow_width: Au,
|
parent_flow_width: Au,
|
||||||
_: &mut LayoutContext)
|
_: &mut LayoutContext)
|
||||||
-> MaybeAuto {
|
-> MaybeAuto {
|
||||||
let box_ = block.box_();
|
let fragment = block.fragment();
|
||||||
box_.assign_replaced_width_if_necessary(parent_flow_width, None);
|
fragment.assign_replaced_width_if_necessary(parent_flow_width, None);
|
||||||
// For replaced block flow, the rest of the constraint solving will
|
// For replaced block flow, the rest of the constraint solving will
|
||||||
// take width to be specified as the value computed here.
|
// take width to be specified as the value computed here.
|
||||||
Specified(box_.content_width())
|
Specified(fragment.content_width())
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -2338,11 +2338,11 @@ impl WidthAndMarginsComputer for FloatReplaced {
|
||||||
parent_flow_width: Au,
|
parent_flow_width: Au,
|
||||||
_: &mut LayoutContext)
|
_: &mut LayoutContext)
|
||||||
-> MaybeAuto {
|
-> MaybeAuto {
|
||||||
let box_ = block.box_();
|
let fragment = block.fragment();
|
||||||
box_.assign_replaced_width_if_necessary(parent_flow_width, None);
|
fragment.assign_replaced_width_if_necessary(parent_flow_width, None);
|
||||||
// For replaced block flow, the rest of the constraint solving will
|
// For replaced block flow, the rest of the constraint solving will
|
||||||
// take width to be specified as the value computed here.
|
// take width to be specified as the value computed here.
|
||||||
Specified(box_.content_width())
|
Specified(fragment.content_width())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -51,24 +51,24 @@ use style::computed_values::{text_decoration, vertical_align, visibility, white_
|
||||||
use sync::Arc;
|
use sync::Arc;
|
||||||
use url::Url;
|
use url::Url;
|
||||||
|
|
||||||
/// Boxes (`struct Box`) are the leaves of the layout tree. They cannot position themselves. In
|
/// Fragments (`struct Fragment`) are the leaves of the layout tree. They cannot position themselves. In
|
||||||
/// general, boxes do not have a simple correspondence with CSS boxes in the specification:
|
/// general, fragments do not have a simple correspondence with CSS fragments in the specification:
|
||||||
///
|
///
|
||||||
/// * Several boxes may correspond to the same CSS box or DOM node. For example, a CSS text box
|
/// * Several fragments may correspond to the same CSS box or DOM node. For example, a CSS text box
|
||||||
/// broken across two lines is represented by two boxes.
|
/// broken across two lines is represented by two fragments.
|
||||||
///
|
///
|
||||||
/// * Some CSS boxes are not created at all, such as some anonymous block boxes induced by inline
|
/// * Some CSS fragments are not created at all, such as some anonymous block fragments induced by inline
|
||||||
/// boxes with block-level sibling boxes. In that case, Servo uses an `InlineFlow` with
|
/// fragments with block-level sibling fragments. In that case, Servo uses an `InlineFlow` with
|
||||||
/// `BlockFlow` siblings; the `InlineFlow` is block-level, but not a block container. It is
|
/// `BlockFlow` siblings; the `InlineFlow` is block-level, but not a block container. It is
|
||||||
/// positioned as if it were a block box, but its children are positioned according to inline
|
/// positioned as if it were a block fragment, but its children are positioned according to inline
|
||||||
/// flow.
|
/// flow.
|
||||||
///
|
///
|
||||||
/// A `GenericFragment` is an empty box that contributes only borders, margins, padding, and
|
/// A `GenericFragment` is an empty fragment that contributes only borders, margins, padding, and
|
||||||
/// backgrounds. It is analogous to a CSS nonreplaced content box.
|
/// backgrounds. It is analogous to a CSS nonreplaced content box.
|
||||||
///
|
///
|
||||||
/// A box's type influences how its styles are interpreted during layout. For example, replaced
|
/// A fragment's type influences how its styles are interpreted during layout. For example, replaced
|
||||||
/// content such as images are resized differently from tables, text, or other content. Different
|
/// content such as images are resized differently from tables, text, or other content. Different
|
||||||
/// types of boxes may also contain custom data; for example, text boxes contain text.
|
/// types of fragments may also contain custom data; for example, text fragments contain text.
|
||||||
///
|
///
|
||||||
/// FIXME(#2260, pcwalton): This can be slimmed down some.
|
/// FIXME(#2260, pcwalton): This can be slimmed down some.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
|
@ -76,21 +76,21 @@ pub struct Fragment {
|
||||||
/// An opaque reference to the DOM node that this `Fragment` originates from.
|
/// An opaque reference to the DOM node that this `Fragment` originates from.
|
||||||
pub node: OpaqueNode,
|
pub node: OpaqueNode,
|
||||||
|
|
||||||
/// The CSS style of this box.
|
/// The CSS style of this fragment.
|
||||||
pub style: Arc<ComputedValues>,
|
pub style: Arc<ComputedValues>,
|
||||||
|
|
||||||
/// The position of this box relative to its owning flow.
|
/// The position of this fragment relative to its owning flow.
|
||||||
/// The size includes padding and border, but not margin.
|
/// The size includes padding and border, but not margin.
|
||||||
pub border_box: Rect<Au>,
|
pub border_box: Rect<Au>,
|
||||||
|
|
||||||
/// The sum of border and padding; i.e. the distance from the edge of the border box to the
|
/// The sum of border and padding; i.e. the distance from the edge of the border box to the
|
||||||
/// content edge of the box.
|
/// content edge of the fragment.
|
||||||
pub border_padding: SideOffsets2D<Au>,
|
pub border_padding: SideOffsets2D<Au>,
|
||||||
|
|
||||||
/// The margin of the content box.
|
/// The margin of the content box.
|
||||||
pub margin: SideOffsets2D<Au>,
|
pub margin: SideOffsets2D<Au>,
|
||||||
|
|
||||||
/// Info specific to the kind of box. Keep this enum small.
|
/// Info specific to the kind of fragment. Keep this enum small.
|
||||||
pub specific: SpecificFragmentInfo,
|
pub specific: SpecificFragmentInfo,
|
||||||
|
|
||||||
/// New-line chracter(\n)'s positions(relative, not absolute)
|
/// New-line chracter(\n)'s positions(relative, not absolute)
|
||||||
|
@ -99,7 +99,7 @@ pub struct Fragment {
|
||||||
pub new_line_pos: Vec<CharIndex>,
|
pub new_line_pos: Vec<CharIndex>,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Info specific to the kind of box. Keep this enum small.
|
/// Info specific to the kind of fragment. Keep this enum small.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub enum SpecificFragmentInfo {
|
pub enum SpecificFragmentInfo {
|
||||||
GenericFragment,
|
GenericFragment,
|
||||||
|
@ -114,10 +114,10 @@ pub enum SpecificFragmentInfo {
|
||||||
UnscannedTextFragment(UnscannedTextFragmentInfo),
|
UnscannedTextFragment(UnscannedTextFragmentInfo),
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A box that represents a replaced content image and its accompanying borders, shadows, etc.
|
/// A fragment that represents a replaced content image and its accompanying borders, shadows, etc.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct ImageFragmentInfo {
|
pub struct ImageFragmentInfo {
|
||||||
/// The image held within this box.
|
/// The image held within this fragment.
|
||||||
pub image: ImageHolder,
|
pub image: ImageHolder,
|
||||||
pub computed_width: Option<Au>,
|
pub computed_width: Option<Au>,
|
||||||
pub computed_height: Option<Au>,
|
pub computed_height: Option<Au>,
|
||||||
|
@ -126,9 +126,9 @@ pub struct ImageFragmentInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ImageFragmentInfo {
|
impl ImageFragmentInfo {
|
||||||
/// Creates a new image box from the given URL and local image cache.
|
/// Creates a new image fragment from the given URL and local image cache.
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): The fact that image boxes store the cache in the box makes little sense to
|
/// FIXME(pcwalton): The fact that image fragments store the cache in the fragment makes little sense to
|
||||||
/// me.
|
/// me.
|
||||||
pub fn new(node: &ThreadSafeLayoutNode,
|
pub fn new(node: &ThreadSafeLayoutNode,
|
||||||
image_url: Url,
|
image_url: Url,
|
||||||
|
@ -196,7 +196,7 @@ impl ImageFragmentInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A box that represents an inline frame (iframe). This stores the pipeline ID so that the size
|
/// A fragment that represents an inline frame (iframe). This stores the pipeline ID so that the size
|
||||||
/// of this iframe can be communicated via the constellation to the iframe's own layout task.
|
/// of this iframe can be communicated via the constellation to the iframe's own layout task.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct IframeFragmentInfo {
|
pub struct IframeFragmentInfo {
|
||||||
|
@ -207,7 +207,7 @@ pub struct IframeFragmentInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl IframeFragmentInfo {
|
impl IframeFragmentInfo {
|
||||||
/// Creates the information specific to an iframe box.
|
/// Creates the information specific to an iframe fragment.
|
||||||
pub fn new(node: &ThreadSafeLayoutNode) -> IframeFragmentInfo {
|
pub fn new(node: &ThreadSafeLayoutNode) -> IframeFragmentInfo {
|
||||||
let (pipeline_id, subpage_id) = node.iframe_pipeline_and_subpage_ids();
|
let (pipeline_id, subpage_id) = node.iframe_pipeline_and_subpage_ids();
|
||||||
IframeFragmentInfo {
|
IframeFragmentInfo {
|
||||||
|
@ -217,10 +217,10 @@ impl IframeFragmentInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A scanned text box represents a single run of text with a distinct style. A `TextBox` may be
|
/// A scanned text fragment represents a single run of text with a distinct style. A `TextFragment`
|
||||||
/// split into two or more boxes across line breaks. Several `TextBox`es may correspond to a single
|
/// may be split into two or more fragments across line breaks. Several `TextFragment`s may
|
||||||
/// DOM text node. Split text boxes are implemented by referring to subsets of a single `TextRun`
|
/// correspond to a single DOM text node. Split text fragments are implemented by referring to
|
||||||
/// object.
|
/// subsets of a single `TextRun` object.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct ScannedTextFragmentInfo {
|
pub struct ScannedTextFragmentInfo {
|
||||||
/// The text run that this represents.
|
/// The text run that this represents.
|
||||||
|
@ -231,7 +231,7 @@ pub struct ScannedTextFragmentInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ScannedTextFragmentInfo {
|
impl ScannedTextFragmentInfo {
|
||||||
/// Creates the information specific to a scanned text box from a range and a text run.
|
/// Creates the information specific to a scanned text fragment from a range and a text run.
|
||||||
pub fn new(run: Arc<Box<TextRun>>, range: Range<CharIndex>) -> ScannedTextFragmentInfo {
|
pub fn new(run: Arc<Box<TextRun>>, range: Range<CharIndex>) -> ScannedTextFragmentInfo {
|
||||||
ScannedTextFragmentInfo {
|
ScannedTextFragmentInfo {
|
||||||
run: run,
|
run: run,
|
||||||
|
@ -257,11 +257,11 @@ impl SplitInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Data for an unscanned text box. Unscanned text boxes are the results of flow construction that
|
/// Data for an unscanned text fragment. Unscanned text fragments are the results of flow construction that
|
||||||
/// have not yet had their width determined.
|
/// have not yet had their width determined.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct UnscannedTextFragmentInfo {
|
pub struct UnscannedTextFragmentInfo {
|
||||||
/// The text inside the box.
|
/// The text inside the fragment.
|
||||||
pub text: ~str,
|
pub text: ~str,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ impl UnscannedTextFragmentInfo {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A box that represents a table column.
|
/// A fragment that represents a table column.
|
||||||
#[deriving(Clone)]
|
#[deriving(Clone)]
|
||||||
pub struct TableColumnFragmentInfo {
|
pub struct TableColumnFragmentInfo {
|
||||||
/// the number of columns a <col> element should span
|
/// the number of columns a <col> element should span
|
||||||
|
@ -291,7 +291,7 @@ pub struct TableColumnFragmentInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableColumnFragmentInfo {
|
impl TableColumnFragmentInfo {
|
||||||
/// Create the information specific to an table column box.
|
/// Create the information specific to an table column fragment.
|
||||||
pub fn new(node: &ThreadSafeLayoutNode) -> TableColumnFragmentInfo {
|
pub fn new(node: &ThreadSafeLayoutNode) -> TableColumnFragmentInfo {
|
||||||
let span = {
|
let span = {
|
||||||
let element = node.as_element();
|
let element = node.as_element();
|
||||||
|
@ -313,7 +313,7 @@ impl Fragment {
|
||||||
///
|
///
|
||||||
/// * `constructor`: The flow constructor.
|
/// * `constructor`: The flow constructor.
|
||||||
///
|
///
|
||||||
/// * `node`: The node to create a box for.
|
/// * `node`: The node to create a fragment for.
|
||||||
pub fn new(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> Fragment {
|
pub fn new(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> Fragment {
|
||||||
Fragment {
|
Fragment {
|
||||||
node: OpaqueNodeMethods::from_thread_safe_layout_node(node),
|
node: OpaqueNodeMethods::from_thread_safe_layout_node(node),
|
||||||
|
@ -321,7 +321,7 @@ impl Fragment {
|
||||||
border_box: Rect::zero(),
|
border_box: Rect::zero(),
|
||||||
border_padding: Zero::zero(),
|
border_padding: Zero::zero(),
|
||||||
margin: Zero::zero(),
|
margin: Zero::zero(),
|
||||||
specific: constructor.build_specific_box_info_for_node(node),
|
specific: constructor.build_specific_fragment_info_for_node(node),
|
||||||
new_line_pos: vec!(),
|
new_line_pos: vec!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -340,15 +340,15 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Constructs a new `Fragment` instance for an anonymous table object.
|
/// Constructs a new `Fragment` instance for an anonymous table object.
|
||||||
pub fn new_anonymous_table_box(node: &ThreadSafeLayoutNode, specific: SpecificFragmentInfo) -> Fragment {
|
pub fn new_anonymous_table_fragment(node: &ThreadSafeLayoutNode, specific: SpecificFragmentInfo) -> Fragment {
|
||||||
// CSS 2.1 § 17.2.1 This is for non-inherited properties on anonymous table boxes
|
// CSS 2.1 § 17.2.1 This is for non-inherited properties on anonymous table fragments
|
||||||
// example:
|
// example:
|
||||||
//
|
//
|
||||||
// <div style="display: table">
|
// <div style="display: table">
|
||||||
// Foo
|
// Foo
|
||||||
// </div>
|
// </div>
|
||||||
//
|
//
|
||||||
// Anonymous table boxes, TableRowFragment and TableCellFragment, are generated around `Foo`, but it shouldn't inherit the border.
|
// Anonymous table fragments, TableRowFragment and TableCellFragment, are generated around `Foo`, but it shouldn't inherit the border.
|
||||||
|
|
||||||
let node_style = cascade_anonymous(&**node.style());
|
let node_style = cascade_anonymous(&**node.style());
|
||||||
Fragment {
|
Fragment {
|
||||||
|
@ -378,15 +378,15 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns a debug ID of this box. This ID should not be considered stable across multiple
|
/// Returns a debug ID of this fragment. This ID should not be considered stable across multiple
|
||||||
/// layouts or box manipulations.
|
/// layouts or fragment manipulations.
|
||||||
pub fn debug_id(&self) -> uint {
|
pub fn debug_id(&self) -> uint {
|
||||||
unsafe {
|
unsafe {
|
||||||
cast::transmute(self)
|
cast::transmute(self)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Transforms this box into another box of the given type, with the given size, preserving all
|
/// Transforms this fragment into another fragment of the given type, with the given size, preserving all
|
||||||
/// the other data.
|
/// the other data.
|
||||||
pub fn transform(&self, size: Size2D<Au>, specific: SpecificFragmentInfo) -> Fragment {
|
pub fn transform(&self, size: Size2D<Au>, specific: SpecificFragmentInfo) -> Fragment {
|
||||||
Fragment {
|
Fragment {
|
||||||
|
@ -409,7 +409,7 @@ impl Fragment {
|
||||||
TableWrapperFragment => (true, false),
|
TableWrapperFragment => (true, false),
|
||||||
TableRowFragment => (false, false),
|
TableRowFragment => (false, false),
|
||||||
ScannedTextFragment(_) | TableColumnFragment(_) | UnscannedTextFragment(_) => {
|
ScannedTextFragment(_) | TableColumnFragment(_) | UnscannedTextFragment(_) => {
|
||||||
// Styles are irrelevant for these kinds of boxes.
|
// Styles are irrelevant for these kinds of fragments.
|
||||||
return IntrinsicWidths::new()
|
return IntrinsicWidths::new()
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -541,7 +541,7 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Go over the ancestor boxes and add all relative offsets (if any).
|
// Go over the ancestor fragments and add all relative offsets (if any).
|
||||||
let mut rel_pos: Point2D<Au> = Zero::zero();
|
let mut rel_pos: Point2D<Au> = Zero::zero();
|
||||||
match inline_fragment_context {
|
match inline_fragment_context {
|
||||||
None => {
|
None => {
|
||||||
|
@ -603,7 +603,7 @@ impl Fragment {
|
||||||
self.style().get_inheritedtext().white_space
|
self.style().get_inheritedtext().white_space
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the text decoration of this box, according to the style of the nearest ancestor
|
/// Returns the text decoration of this fragment, according to the style of the nearest ancestor
|
||||||
/// element.
|
/// element.
|
||||||
///
|
///
|
||||||
/// NB: This may not be the actual text decoration, because of the override rules specified in
|
/// NB: This may not be the actual text decoration, because of the override rules specified in
|
||||||
|
@ -627,7 +627,7 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this element can be split. This is true for text boxes.
|
/// Returns true if this element can be split. This is true for text fragments.
|
||||||
pub fn can_split(&self) -> bool {
|
pub fn can_split(&self) -> bool {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
ScannedTextFragment(..) => true,
|
ScannedTextFragment(..) => true,
|
||||||
|
@ -635,8 +635,8 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the background of this box to the display list if
|
/// Adds the display items necessary to paint the background of this fragment to the display
|
||||||
/// necessary.
|
/// list if necessary.
|
||||||
pub fn build_display_list_for_background_if_applicable(&self,
|
pub fn build_display_list_for_background_if_applicable(&self,
|
||||||
list: &mut DisplayList,
|
list: &mut DisplayList,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
@ -645,7 +645,7 @@ impl Fragment {
|
||||||
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
// FIXME: This causes a lot of background colors to be displayed when they are clearly not
|
||||||
// needed. We could use display list optimization to clean this up, but it still seems
|
// needed. We could use display list optimization to clean this up, but it still seems
|
||||||
// inefficient. What we really want is something like "nearest ancestor element that
|
// inefficient. What we really want is something like "nearest ancestor element that
|
||||||
// doesn't have a box".
|
// doesn't have a fragment".
|
||||||
let style = self.style();
|
let style = self.style();
|
||||||
let background_color = style.resolve_color(style.get_background().background_color);
|
let background_color = style.resolve_color(style.get_background().background_color);
|
||||||
if !background_color.alpha.approx_eq(&0.0) {
|
if !background_color.alpha.approx_eq(&0.0) {
|
||||||
|
@ -741,7 +741,7 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the display items necessary to paint the borders of this box to a display list if
|
/// Adds the display items necessary to paint the borders of this fragment to a display list if
|
||||||
/// necessary.
|
/// necessary.
|
||||||
pub fn build_display_list_for_borders_if_applicable(&self,
|
pub fn build_display_list_for_borders_if_applicable(&self,
|
||||||
list: &mut DisplayList,
|
list: &mut DisplayList,
|
||||||
|
@ -778,18 +778,18 @@ impl Fragment {
|
||||||
list.push(BorderDisplayItemClass(border_display_item))
|
list.push(BorderDisplayItemClass(border_display_item))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_debug_borders_around_text_boxes(&self,
|
fn build_debug_borders_around_text_fragments(&self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
flow_origin: Point2D<Au>,
|
flow_origin: Point2D<Au>,
|
||||||
text_box: &ScannedTextFragmentInfo) {
|
text_fragment: &ScannedTextFragmentInfo) {
|
||||||
let box_bounds = self.border_box;
|
let fragment_bounds = self.border_box;
|
||||||
let absolute_box_bounds = box_bounds.translate(&flow_origin);
|
let absolute_fragment_bounds = fragment_bounds.translate(&flow_origin);
|
||||||
|
|
||||||
// Compute the text box bounds and draw a border surrounding them.
|
// Compute the text fragment bounds and draw a border surrounding them.
|
||||||
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
||||||
|
|
||||||
let border_display_item = box BorderDisplayItem {
|
let border_display_item = box BorderDisplayItem {
|
||||||
base: BaseDisplayItem::new(absolute_box_bounds, self.node, ContentStackingLevel),
|
base: BaseDisplayItem::new(absolute_fragment_bounds, self.node, ContentStackingLevel),
|
||||||
border: debug_border,
|
border: debug_border,
|
||||||
color: SideOffsets2D::new_all_same(rgb(0, 0, 200)),
|
color: SideOffsets2D::new_all_same(rgb(0, 0, 200)),
|
||||||
style: SideOffsets2D::new_all_same(border_style::solid)
|
style: SideOffsets2D::new_all_same(border_style::solid)
|
||||||
|
@ -797,9 +797,9 @@ impl Fragment {
|
||||||
display_list.push(BorderDisplayItemClass(border_display_item));
|
display_list.push(BorderDisplayItemClass(border_display_item));
|
||||||
|
|
||||||
// Draw a rectangle representing the baselines.
|
// Draw a rectangle representing the baselines.
|
||||||
let ascent = text_box.run.ascent();
|
let ascent = text_fragment.run.ascent();
|
||||||
let baseline = Rect(absolute_box_bounds.origin + Point2D(Au(0), ascent),
|
let baseline = Rect(absolute_fragment_bounds.origin + Point2D(Au(0), ascent),
|
||||||
Size2D(absolute_box_bounds.size.width, Au(0)));
|
Size2D(absolute_fragment_bounds.size.width, Au(0)));
|
||||||
|
|
||||||
let line_display_item = box LineDisplayItem {
|
let line_display_item = box LineDisplayItem {
|
||||||
base: BaseDisplayItem::new(baseline, self.node, ContentStackingLevel),
|
base: BaseDisplayItem::new(baseline, self.node, ContentStackingLevel),
|
||||||
|
@ -809,17 +809,17 @@ impl Fragment {
|
||||||
display_list.push(LineDisplayItemClass(line_display_item));
|
display_list.push(LineDisplayItemClass(line_display_item));
|
||||||
}
|
}
|
||||||
|
|
||||||
fn build_debug_borders_around_box(&self,
|
fn build_debug_borders_around_fragment(&self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
flow_origin: Point2D<Au>) {
|
flow_origin: Point2D<Au>) {
|
||||||
let box_bounds = self.border_box;
|
let fragment_bounds = self.border_box;
|
||||||
let absolute_box_bounds = box_bounds.translate(&flow_origin);
|
let absolute_fragment_bounds = fragment_bounds.translate(&flow_origin);
|
||||||
|
|
||||||
// This prints a debug border around the border of this box.
|
// This prints a debug border around the border of this fragment.
|
||||||
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
let debug_border = SideOffsets2D::new_all_same(Au::from_px(1));
|
||||||
|
|
||||||
let border_display_item = box BorderDisplayItem {
|
let border_display_item = box BorderDisplayItem {
|
||||||
base: BaseDisplayItem::new(absolute_box_bounds, self.node, ContentStackingLevel),
|
base: BaseDisplayItem::new(absolute_fragment_bounds, self.node, ContentStackingLevel),
|
||||||
border: debug_border,
|
border: debug_border,
|
||||||
color: SideOffsets2D::new_all_same(rgb(0, 0, 200)),
|
color: SideOffsets2D::new_all_same(rgb(0, 0, 200)),
|
||||||
style: SideOffsets2D::new_all_same(border_style::solid)
|
style: SideOffsets2D::new_all_same(border_style::solid)
|
||||||
|
@ -827,7 +827,7 @@ impl Fragment {
|
||||||
display_list.push(BorderDisplayItemClass(border_display_item))
|
display_list.push(BorderDisplayItemClass(border_display_item))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Adds the display items for this box to the given stacking context.
|
/// Adds the display items for this fragment to the given stacking context.
|
||||||
///
|
///
|
||||||
/// Arguments:
|
/// Arguments:
|
||||||
///
|
///
|
||||||
|
@ -835,7 +835,6 @@ impl Fragment {
|
||||||
/// * `layout_context`: The layout context.
|
/// * `layout_context`: The layout context.
|
||||||
/// * `dirty`: The dirty rectangle in the coordinate system of the owning flow.
|
/// * `dirty`: The dirty rectangle in the coordinate system of the owning flow.
|
||||||
/// * `flow_origin`: Position of the origin of the owning flow wrt the display list root flow.
|
/// * `flow_origin`: Position of the origin of the owning flow wrt the display list root flow.
|
||||||
/// box.
|
|
||||||
pub fn build_display_list(&self,
|
pub fn build_display_list(&self,
|
||||||
display_list: &mut DisplayList,
|
display_list: &mut DisplayList,
|
||||||
layout_context: &LayoutContext,
|
layout_context: &LayoutContext,
|
||||||
|
@ -844,25 +843,25 @@ impl Fragment {
|
||||||
inline_fragment_context: Option<InlineFragmentContext>)
|
inline_fragment_context: Option<InlineFragmentContext>)
|
||||||
-> ChildDisplayListAccumulator {
|
-> ChildDisplayListAccumulator {
|
||||||
// Fragment position wrt to the owning flow.
|
// Fragment position wrt to the owning flow.
|
||||||
let box_bounds = self.border_box;
|
let fragment_bounds = self.border_box;
|
||||||
let absolute_box_bounds = box_bounds.translate(&flow_origin);
|
let absolute_fragment_bounds = fragment_bounds.translate(&flow_origin);
|
||||||
debug!("Fragment::build_display_list at rel={}, abs={}: {}",
|
debug!("Fragment::build_display_list at rel={}, abs={}: {}",
|
||||||
box_bounds,
|
fragment_bounds,
|
||||||
absolute_box_bounds,
|
absolute_fragment_bounds,
|
||||||
self);
|
self);
|
||||||
debug!("Fragment::build_display_list: dirty={}, flow_origin={}",
|
debug!("Fragment::build_display_list: dirty={}, flow_origin={}",
|
||||||
layout_context.dirty,
|
layout_context.dirty,
|
||||||
flow_origin);
|
flow_origin);
|
||||||
|
|
||||||
let mut accumulator = ChildDisplayListAccumulator::new(self.style(),
|
let mut accumulator = ChildDisplayListAccumulator::new(self.style(),
|
||||||
absolute_box_bounds,
|
absolute_fragment_bounds,
|
||||||
self.node,
|
self.node,
|
||||||
ContentStackingLevel);
|
ContentStackingLevel);
|
||||||
if self.style().get_inheritedbox().visibility != visibility::visible {
|
if self.style().get_inheritedbox().visibility != visibility::visible {
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
|
|
||||||
if !absolute_box_bounds.intersects(&layout_context.dirty) {
|
if !absolute_fragment_bounds.intersects(&layout_context.dirty) {
|
||||||
debug!("Fragment::build_display_list: Did not intersect...");
|
debug!("Fragment::build_display_list: Did not intersect...");
|
||||||
return accumulator
|
return accumulator
|
||||||
}
|
}
|
||||||
|
@ -874,29 +873,29 @@ impl Fragment {
|
||||||
StackingLevel::from_background_and_border_level(background_and_border_level);
|
StackingLevel::from_background_and_border_level(background_and_border_level);
|
||||||
|
|
||||||
// Add a pseudo-display item for content box queries. This is a very bogus thing to do.
|
// Add a pseudo-display item for content box queries. This is a very bogus thing to do.
|
||||||
let base_display_item = box BaseDisplayItem::new(absolute_box_bounds, self.node, level);
|
let base_display_item = box BaseDisplayItem::new(absolute_fragment_bounds, self.node, level);
|
||||||
display_list.push(PseudoDisplayItemClass(base_display_item));
|
display_list.push(PseudoDisplayItemClass(base_display_item));
|
||||||
|
|
||||||
// Add the background to the list, if applicable.
|
// Add the background to the list, if applicable.
|
||||||
self.build_display_list_for_background_if_applicable(display_list,
|
self.build_display_list_for_background_if_applicable(display_list,
|
||||||
layout_context,
|
layout_context,
|
||||||
level,
|
level,
|
||||||
&absolute_box_bounds);
|
&absolute_fragment_bounds);
|
||||||
|
|
||||||
// Add a border, if applicable.
|
// Add a border, if applicable.
|
||||||
//
|
//
|
||||||
// TODO: Outlines.
|
// TODO: Outlines.
|
||||||
self.build_display_list_for_borders_if_applicable(display_list,
|
self.build_display_list_for_borders_if_applicable(display_list,
|
||||||
&absolute_box_bounds,
|
&absolute_fragment_bounds,
|
||||||
level,
|
level,
|
||||||
inline_fragment_context);
|
inline_fragment_context);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a clip, if applicable.
|
// Add a clip, if applicable.
|
||||||
match self.specific {
|
match self.specific {
|
||||||
UnscannedTextFragment(_) => fail!("Shouldn't see unscanned boxes here."),
|
UnscannedTextFragment(_) => fail!("Shouldn't see unscanned fragments here."),
|
||||||
TableColumnFragment(_) => fail!("Shouldn't see table column boxes here."),
|
TableColumnFragment(_) => fail!("Shouldn't see table column fragments here."),
|
||||||
ScannedTextFragment(ref text_box) => {
|
ScannedTextFragment(ref text_fragment) => {
|
||||||
// Compute text color.
|
// Compute text color.
|
||||||
let text_color = self.style().get_color().color.to_gfx_color();
|
let text_color = self.style().get_color().color.to_gfx_color();
|
||||||
|
|
||||||
|
@ -911,15 +910,15 @@ impl Fragment {
|
||||||
.map(|c| c.to_gfx_color()),
|
.map(|c| c.to_gfx_color()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut bounds = absolute_box_bounds.clone();
|
let mut bounds = absolute_fragment_bounds.clone();
|
||||||
bounds.origin.x = bounds.origin.x + self.border_padding.left;
|
bounds.origin.x = bounds.origin.x + self.border_padding.left;
|
||||||
bounds.size.width = bounds.size.width - self.border_padding.horizontal();
|
bounds.size.width = bounds.size.width - self.border_padding.horizontal();
|
||||||
|
|
||||||
// Create the text box.
|
// Create the text fragment.
|
||||||
let text_display_item = box TextDisplayItem {
|
let text_display_item = box TextDisplayItem {
|
||||||
base: BaseDisplayItem::new(bounds, self.node, ContentStackingLevel),
|
base: BaseDisplayItem::new(bounds, self.node, ContentStackingLevel),
|
||||||
text_run: text_box.run.clone(),
|
text_run: text_fragment.run.clone(),
|
||||||
range: text_box.range,
|
range: text_fragment.range,
|
||||||
text_color: text_color,
|
text_color: text_color,
|
||||||
text_decorations: text_decorations,
|
text_decorations: text_decorations,
|
||||||
};
|
};
|
||||||
|
@ -929,29 +928,29 @@ impl Fragment {
|
||||||
//
|
//
|
||||||
// FIXME(#2263, pcwalton): This is a bit of an abuse of the logging infrastructure.
|
// FIXME(#2263, pcwalton): This is a bit of an abuse of the logging infrastructure.
|
||||||
// We should have a real `SERVO_DEBUG` system.
|
// We should have a real `SERVO_DEBUG` system.
|
||||||
debug!("{:?}", self.build_debug_borders_around_text_boxes(display_list,
|
debug!("{:?}", self.build_debug_borders_around_text_fragments(display_list,
|
||||||
flow_origin,
|
flow_origin,
|
||||||
text_box))
|
text_fragment))
|
||||||
},
|
},
|
||||||
GenericFragment | IframeFragment(..) | TableFragment | TableCellFragment | TableRowFragment |
|
GenericFragment | IframeFragment(..) | TableFragment | TableCellFragment | TableRowFragment |
|
||||||
TableWrapperFragment => {
|
TableWrapperFragment => {
|
||||||
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
// FIXME(pcwalton): This is a bit of an abuse of the logging infrastructure. We
|
||||||
// should have a real `SERVO_DEBUG` system.
|
// should have a real `SERVO_DEBUG` system.
|
||||||
debug!("{:?}", self.build_debug_borders_around_box(display_list, flow_origin))
|
debug!("{:?}", self.build_debug_borders_around_fragment(display_list, flow_origin))
|
||||||
},
|
},
|
||||||
ImageFragment(_) => {
|
ImageFragment(_) => {
|
||||||
let mut bounds = absolute_box_bounds.clone();
|
let mut bounds = absolute_fragment_bounds.clone();
|
||||||
bounds.origin.x = bounds.origin.x + self.border_padding.left;
|
bounds.origin.x = bounds.origin.x + self.border_padding.left;
|
||||||
bounds.origin.y = bounds.origin.y + self.border_padding.top;
|
bounds.origin.y = bounds.origin.y + self.border_padding.top;
|
||||||
bounds.size.width = bounds.size.width - self.border_padding.horizontal();
|
bounds.size.width = bounds.size.width - self.border_padding.horizontal();
|
||||||
bounds.size.height = bounds.size.height - self.border_padding.vertical();
|
bounds.size.height = bounds.size.height - self.border_padding.vertical();
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
ImageFragment(ref image_box) => {
|
ImageFragment(ref image_fragment) => {
|
||||||
let image_ref = &image_box.image;
|
let image_ref = &image_fragment.image;
|
||||||
match image_ref.get_image_if_present() {
|
match image_ref.get_image_if_present() {
|
||||||
Some(image) => {
|
Some(image) => {
|
||||||
debug!("(building display list) building image box");
|
debug!("(building display list) building image fragment");
|
||||||
|
|
||||||
// Place the image into the display list.
|
// Place the image into the display list.
|
||||||
let image_display_item = box ImageDisplayItem {
|
let image_display_item = box ImageDisplayItem {
|
||||||
|
@ -977,7 +976,7 @@ impl Fragment {
|
||||||
|
|
||||||
// FIXME(pcwalton): This is a bit of an abuse of the logging
|
// FIXME(pcwalton): This is a bit of an abuse of the logging
|
||||||
// infrastructure. We should have a real `SERVO_DEBUG` system.
|
// infrastructure. We should have a real `SERVO_DEBUG` system.
|
||||||
debug!("{:?}", self.build_debug_borders_around_box(display_list, flow_origin))
|
debug!("{:?}", self.build_debug_borders_around_fragment(display_list, flow_origin))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -992,8 +991,8 @@ impl Fragment {
|
||||||
// layout for the iframe only needs to know size, and origin is only relevant if the
|
// layout for the iframe only needs to know size, and origin is only relevant if the
|
||||||
// iframe is actually going to be displayed.
|
// iframe is actually going to be displayed.
|
||||||
match self.specific {
|
match self.specific {
|
||||||
IframeFragment(ref iframe_box) => {
|
IframeFragment(ref iframe_fragment) => {
|
||||||
self.finalize_position_and_size_of_iframe(iframe_box, flow_origin, layout_context)
|
self.finalize_position_and_size_of_iframe(iframe_fragment, flow_origin, layout_context)
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
|
@ -1009,28 +1008,28 @@ impl Fragment {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableColumnFragment(_) | TableRowFragment |
|
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableColumnFragment(_) | TableRowFragment |
|
||||||
TableWrapperFragment => {}
|
TableWrapperFragment => {}
|
||||||
ImageFragment(ref mut image_box_info) => {
|
ImageFragment(ref mut image_fragment_info) => {
|
||||||
let image_width = image_box_info.image_width();
|
let image_width = image_fragment_info.image_width();
|
||||||
result.minimum_width = geometry::max(result.minimum_width, image_width);
|
result.minimum_width = geometry::max(result.minimum_width, image_width);
|
||||||
result.preferred_width = geometry::max(result.preferred_width, image_width);
|
result.preferred_width = geometry::max(result.preferred_width, image_width);
|
||||||
}
|
}
|
||||||
ScannedTextFragment(ref text_box_info) => {
|
ScannedTextFragment(ref text_fragment_info) => {
|
||||||
let range = &text_box_info.range;
|
let range = &text_fragment_info.range;
|
||||||
let min_line_width = text_box_info.run.min_width_for_range(range);
|
let min_line_width = text_fragment_info.run.min_width_for_range(range);
|
||||||
|
|
||||||
let mut max_line_width = Au::new(0);
|
let mut max_line_width = Au::new(0);
|
||||||
for line_range in text_box_info.run.iter_natural_lines_for_range(range) {
|
for line_range in text_fragment_info.run.iter_natural_lines_for_range(range) {
|
||||||
let line_metrics = text_box_info.run.metrics_for_range(&line_range);
|
let line_metrics = text_fragment_info.run.metrics_for_range(&line_range);
|
||||||
max_line_width = Au::max(max_line_width, line_metrics.advance_width);
|
max_line_width = Au::max(max_line_width, line_metrics.advance_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
result.minimum_width = geometry::max(result.minimum_width, min_line_width);
|
result.minimum_width = geometry::max(result.minimum_width, min_line_width);
|
||||||
result.preferred_width = geometry::max(result.preferred_width, max_line_width);
|
result.preferred_width = geometry::max(result.preferred_width, max_line_width);
|
||||||
}
|
}
|
||||||
UnscannedTextFragment(..) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextFragment(..) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
}
|
}
|
||||||
|
|
||||||
// Take borders and padding for parent inline boxes into account, if necessary.
|
// Take borders and padding for parent inline fragments into account, if necessary.
|
||||||
match inline_fragment_context {
|
match inline_fragment_context {
|
||||||
None => {}
|
None => {}
|
||||||
Some(context) => {
|
Some(context) => {
|
||||||
|
@ -1052,39 +1051,39 @@ impl Fragment {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
||||||
TableWrapperFragment => Au(0),
|
TableWrapperFragment => Au(0),
|
||||||
ImageFragment(ref image_box_info) => {
|
ImageFragment(ref image_fragment_info) => {
|
||||||
image_box_info.computed_width()
|
image_fragment_info.computed_width()
|
||||||
}
|
}
|
||||||
ScannedTextFragment(ref text_box_info) => {
|
ScannedTextFragment(ref text_fragment_info) => {
|
||||||
let (range, run) = (&text_box_info.range, &text_box_info.run);
|
let (range, run) = (&text_fragment_info.range, &text_fragment_info.run);
|
||||||
let text_bounds = run.metrics_for_range(range).bounding_box;
|
let text_bounds = run.metrics_for_range(range).bounding_box;
|
||||||
text_bounds.size.width
|
text_bounds.size.width
|
||||||
}
|
}
|
||||||
TableColumnFragment(_) => fail!("Table column boxes do not have width"),
|
TableColumnFragment(_) => fail!("Table column fragments do not have width"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns, and computes, the height of this box.
|
/// Returns, and computes, the height of this fragment.
|
||||||
pub fn content_height(&self) -> Au {
|
pub fn content_height(&self) -> Au {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
||||||
TableWrapperFragment => Au(0),
|
TableWrapperFragment => Au(0),
|
||||||
ImageFragment(ref image_box_info) => {
|
ImageFragment(ref image_fragment_info) => {
|
||||||
image_box_info.computed_height()
|
image_fragment_info.computed_height()
|
||||||
}
|
}
|
||||||
ScannedTextFragment(ref text_box_info) => {
|
ScannedTextFragment(ref text_fragment_info) => {
|
||||||
// Compute the height based on the line-height and font size.
|
// Compute the height based on the line-height and font size.
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): Shouldn't we use the value of the `font-size` property below
|
// FIXME(pcwalton): Shouldn't we use the value of the `font-size` property below
|
||||||
// instead of the bounding box of the text run?
|
// instead of the bounding box of the text run?
|
||||||
let (range, run) = (&text_box_info.range, &text_box_info.run);
|
let (range, run) = (&text_fragment_info.range, &text_fragment_info.run);
|
||||||
let text_bounds = run.metrics_for_range(range).bounding_box;
|
let text_bounds = run.metrics_for_range(range).bounding_box;
|
||||||
let em_size = text_bounds.size.height;
|
let em_size = text_bounds.size.height;
|
||||||
self.calculate_line_height(em_size)
|
self.calculate_line_height(em_size)
|
||||||
}
|
}
|
||||||
TableColumnFragment(_) => fail!("Table column boxes do not have height"),
|
TableColumnFragment(_) => fail!("Table column fragments do not have height"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1102,82 +1101,81 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Find the split of a box that includes a new-line character.
|
/// Find the split of a fragment that includes a new-line character.
|
||||||
///
|
///
|
||||||
/// A return value of `None` indicates that the box is not splittable.
|
/// A return value of `None` indicates that the fragment is not splittable.
|
||||||
/// Otherwise the split information is returned. The right information is
|
/// Otherwise the split information is returned. The right information is
|
||||||
/// optional due to the possibility of it being whitespace.
|
/// optional due to the possibility of it being whitespace.
|
||||||
//
|
//
|
||||||
// TODO(bjz): The text run should be removed in the future, but it is currently needed for
|
// TODO(bjz): The text run should be removed in the future, but it is currently needed for
|
||||||
// the current method of box splitting in the `inline::try_append_*` functions.
|
// the current method of fragment splitting in the `inline::try_append_*` functions.
|
||||||
pub fn find_split_info_by_new_line(&self)
|
pub fn find_split_info_by_new_line(&self)
|
||||||
-> Option<(SplitInfo, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
|
-> Option<(SplitInfo, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | ImageFragment(_) | TableFragment | TableCellFragment |
|
GenericFragment | IframeFragment(_) | ImageFragment(_) | TableFragment | TableCellFragment |
|
||||||
TableRowFragment | TableWrapperFragment => None,
|
TableRowFragment | TableWrapperFragment => None,
|
||||||
TableColumnFragment(_) => fail!("Table column boxes do not need to split"),
|
TableColumnFragment(_) => fail!("Table column fragments do not need to split"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
ScannedTextFragment(ref text_box_info) => {
|
ScannedTextFragment(ref text_fragment_info) => {
|
||||||
let mut new_line_pos = self.new_line_pos.clone();
|
let mut new_line_pos = self.new_line_pos.clone();
|
||||||
let cur_new_line_pos = new_line_pos.shift().unwrap();
|
let cur_new_line_pos = new_line_pos.shift().unwrap();
|
||||||
|
|
||||||
let left_range = Range::new(text_box_info.range.begin(), cur_new_line_pos);
|
let left_range = Range::new(text_fragment_info.range.begin(), cur_new_line_pos);
|
||||||
let right_range = Range::new(text_box_info.range.begin() + cur_new_line_pos + CharIndex(1),
|
let right_range = Range::new(text_fragment_info.range.begin() + cur_new_line_pos + CharIndex(1),
|
||||||
text_box_info.range.length() - (cur_new_line_pos + CharIndex(1)));
|
text_fragment_info.range.length() - (cur_new_line_pos + CharIndex(1)));
|
||||||
|
|
||||||
// Left box is for left text of first founded new-line character.
|
// Left fragment is for left text of first founded new-line character.
|
||||||
let left_box = SplitInfo::new(left_range, text_box_info);
|
let left_fragment = SplitInfo::new(left_range, text_fragment_info);
|
||||||
|
|
||||||
// Right box is for right text of first founded new-line character.
|
// Right fragment is for right text of first founded new-line character.
|
||||||
let right_box = if right_range.length() > CharIndex(0) {
|
let right_fragment = if right_range.length() > CharIndex(0) {
|
||||||
Some(SplitInfo::new(right_range, text_box_info))
|
Some(SplitInfo::new(right_range, text_fragment_info))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
Some((left_box, right_box, text_box_info.run.clone()))
|
Some((left_fragment, right_fragment, text_fragment_info.run.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Attempts to find the split positions of a text box so that its width is
|
/// Attempts to find the split positions of a text fragment so that its width is
|
||||||
/// no more than `max_width`.
|
/// no more than `max_width`.
|
||||||
///
|
///
|
||||||
/// A return value of `None` indicates that the box could not be split.
|
/// A return value of `None` indicates that the fragment could not be split.
|
||||||
/// Otherwise the information pertaining to the split is returned. The left
|
/// Otherwise the information pertaining to the split is returned. The left
|
||||||
/// and right split information are both optional due to the possibility of
|
/// and right split information are both optional due to the possibility of
|
||||||
/// them being whitespace.
|
/// them being whitespace.
|
||||||
//
|
//
|
||||||
// TODO(bjz): The text run should be removed in the future, but it is currently needed for
|
// TODO(bjz): The text run should be removed in the future, but it is currently needed for
|
||||||
// the current method of box splitting in the `inline::try_append_*` functions.
|
// the current method of fragment splitting in the `inline::try_append_*` functions.
|
||||||
pub fn find_split_info_for_width(&self, start: CharIndex, max_width: Au, starts_line: bool)
|
pub fn find_split_info_for_width(&self, start: CharIndex, max_width: Au, starts_line: bool)
|
||||||
-> Option<(Option<SplitInfo>, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
|
-> Option<(Option<SplitInfo>, Option<SplitInfo>, Arc<Box<TextRun>> /* TODO(bjz): remove */)> {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | ImageFragment(_) | TableFragment | TableCellFragment |
|
GenericFragment | IframeFragment(_) | ImageFragment(_) | TableFragment | TableCellFragment |
|
||||||
TableRowFragment | TableWrapperFragment => None,
|
TableRowFragment | TableWrapperFragment => None,
|
||||||
TableColumnFragment(_) => fail!("Table column boxes do not have width"),
|
TableColumnFragment(_) => fail!("Table column fragments do not have width"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
ScannedTextFragment(ref text_box_info) => {
|
ScannedTextFragment(ref text_fragment_info) => {
|
||||||
let mut pieces_processed_count: uint = 0;
|
let mut pieces_processed_count: uint = 0;
|
||||||
let mut remaining_width: Au = max_width;
|
let mut remaining_width: Au = max_width;
|
||||||
let mut left_range = Range::new(text_box_info.range.begin() + start, CharIndex(0));
|
let mut left_range = Range::new(text_fragment_info.range.begin() + start, CharIndex(0));
|
||||||
let mut right_range: Option<Range<CharIndex>> = None;
|
let mut right_range: Option<Range<CharIndex>> = None;
|
||||||
|
|
||||||
debug!("split_to_width: splitting text box (strlen={:u}, range={}, \
|
debug!("split_to_width: splitting text fragment (strlen={}, range={}, avail_width={})",
|
||||||
avail_width={})",
|
text_fragment_info.run.text.len(),
|
||||||
text_box_info.run.text.len(),
|
text_fragment_info.range,
|
||||||
text_box_info.range,
|
|
||||||
max_width);
|
max_width);
|
||||||
|
|
||||||
for (glyphs, offset, slice_range) in text_box_info.run.iter_slices_for_range(
|
for (glyphs, offset, slice_range) in text_fragment_info.run.iter_slices_for_range(
|
||||||
&text_box_info.range) {
|
&text_fragment_info.range) {
|
||||||
debug!("split_to_width: considering slice (offset={}, range={}, \
|
debug!("split_to_width: considering slice (offset={}, range={}, \
|
||||||
remain_width={})",
|
remain_width={})",
|
||||||
offset,
|
offset,
|
||||||
slice_range,
|
slice_range,
|
||||||
remaining_width);
|
remaining_width);
|
||||||
|
|
||||||
let metrics = text_box_info.run.metrics_for_slice(glyphs, &slice_range);
|
let metrics = text_fragment_info.run.metrics_for_slice(glyphs, &slice_range);
|
||||||
let advance = metrics.advance_width;
|
let advance = metrics.advance_width;
|
||||||
|
|
||||||
let should_continue;
|
let should_continue;
|
||||||
|
@ -1201,19 +1199,19 @@ impl Fragment {
|
||||||
if glyphs.is_whitespace() {
|
if glyphs.is_whitespace() {
|
||||||
// If there are still things after the trimmable whitespace, create the
|
// If there are still things after the trimmable whitespace, create the
|
||||||
// right chunk.
|
// right chunk.
|
||||||
if slice_end < text_box_info.range.end() {
|
if slice_end < text_fragment_info.range.end() {
|
||||||
debug!("split_to_width: case=skipping trimmable trailing \
|
debug!("split_to_width: case=skipping trimmable trailing \
|
||||||
whitespace, then split remainder");
|
whitespace, then split remainder");
|
||||||
let right_range_end = text_box_info.range.end() - slice_end;
|
let right_range_end = text_fragment_info.range.end() - slice_end;
|
||||||
right_range = Some(Range::new(slice_end, right_range_end));
|
right_range = Some(Range::new(slice_end, right_range_end));
|
||||||
} else {
|
} else {
|
||||||
debug!("split_to_width: case=skipping trimmable trailing \
|
debug!("split_to_width: case=skipping trimmable trailing \
|
||||||
whitespace");
|
whitespace");
|
||||||
}
|
}
|
||||||
} else if slice_begin < text_box_info.range.end() {
|
} else if slice_begin < text_fragment_info.range.end() {
|
||||||
// There are still some things left over at the end of the line. Create
|
// There are still some things left over at the end of the line. Create
|
||||||
// the right chunk.
|
// the right chunk.
|
||||||
let right_range_end = text_box_info.range.end() - slice_begin;
|
let right_range_end = text_fragment_info.range.end() - slice_begin;
|
||||||
right_range = Some(Range::new(slice_begin, right_range_end));
|
right_range = Some(Range::new(slice_begin, right_range_end));
|
||||||
debug!("split_to_width: case=splitting remainder with right range={:?}",
|
debug!("split_to_width: case=splitting remainder with right range={:?}",
|
||||||
right_range);
|
right_range);
|
||||||
|
@ -1233,28 +1231,28 @@ impl Fragment {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
let left = if left_is_some {
|
let left = if left_is_some {
|
||||||
Some(SplitInfo::new(left_range, text_box_info))
|
Some(SplitInfo::new(left_range, text_fragment_info))
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
let right = right_range.map(|right_range| SplitInfo::new(right_range, text_box_info));
|
let right = right_range.map(|right_range| SplitInfo::new(right_range, text_fragment_info));
|
||||||
|
|
||||||
Some((left, right, text_box_info.run.clone()))
|
Some((left, right, text_fragment_info.run.clone()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this box is an unscanned text box that consists entirely of whitespace.
|
/// Returns true if this fragment is an unscanned text fragment that consists entirely of whitespace.
|
||||||
pub fn is_whitespace_only(&self) -> bool {
|
pub fn is_whitespace_only(&self) -> bool {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
UnscannedTextFragment(ref text_box_info) => is_whitespace(text_box_info.text),
|
UnscannedTextFragment(ref text_fragment_info) => is_whitespace(text_fragment_info.text),
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assigns replaced width, padding, and margins for this box only if it is replaced content
|
/// Assigns replaced width, padding, and margins for this fragment only if it is replaced
|
||||||
/// per CSS 2.1 § 10.3.2.
|
/// content per CSS 2.1 § 10.3.2.
|
||||||
pub fn assign_replaced_width_if_necessary(&mut self,
|
pub fn assign_replaced_width_if_necessary(&mut self,
|
||||||
container_width: Au,
|
container_width: Au,
|
||||||
inline_fragment_context:
|
inline_fragment_context:
|
||||||
|
@ -1262,8 +1260,8 @@ impl Fragment {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
||||||
TableWrapperFragment => return,
|
TableWrapperFragment => return,
|
||||||
TableColumnFragment(_) => fail!("Table column boxes do not have width"),
|
TableColumnFragment(_) => fail!("Table column fragments do not have width"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
ImageFragment(_) | ScannedTextFragment(_) => {}
|
ImageFragment(_) | ScannedTextFragment(_) => {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -1275,37 +1273,37 @@ impl Fragment {
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
ScannedTextFragment(_) => {
|
ScannedTextFragment(_) => {
|
||||||
// Scanned text boxes will have already had their content widths assigned by this
|
// Scanned text fragments will have already had their content widths assigned by this
|
||||||
// point.
|
// point.
|
||||||
self.border_box.size.width = self.border_box.size.width + noncontent_width
|
self.border_box.size.width = self.border_box.size.width + noncontent_width
|
||||||
}
|
}
|
||||||
ImageFragment(ref mut image_box_info) => {
|
ImageFragment(ref mut image_fragment_info) => {
|
||||||
// TODO(ksh8281): compute border,margin
|
// TODO(ksh8281): compute border,margin
|
||||||
let width = ImageFragmentInfo::style_length(style_width,
|
let width = ImageFragmentInfo::style_length(style_width,
|
||||||
image_box_info.dom_width,
|
image_fragment_info.dom_width,
|
||||||
container_width);
|
container_width);
|
||||||
let height = ImageFragmentInfo::style_length(style_height,
|
let height = ImageFragmentInfo::style_length(style_height,
|
||||||
image_box_info.dom_height,
|
image_fragment_info.dom_height,
|
||||||
Au(0));
|
Au(0));
|
||||||
|
|
||||||
let width = match (width,height) {
|
let width = match (width,height) {
|
||||||
(Auto, Auto) => image_box_info.image_width(),
|
(Auto, Auto) => image_fragment_info.image_width(),
|
||||||
(Auto,Specified(h)) => {
|
(Auto,Specified(h)) => {
|
||||||
let scale = image_box_info.
|
let scale = image_fragment_info.
|
||||||
image_height().to_f32().unwrap() / h.to_f32().unwrap();
|
image_height().to_f32().unwrap() / h.to_f32().unwrap();
|
||||||
Au::new((image_box_info.image_width().to_f32().unwrap() / scale) as i32)
|
Au::new((image_fragment_info.image_width().to_f32().unwrap() / scale) as i32)
|
||||||
},
|
},
|
||||||
(Specified(w), _) => w,
|
(Specified(w), _) => w,
|
||||||
};
|
};
|
||||||
|
|
||||||
self.border_box.size.width = width + noncontent_width;
|
self.border_box.size.width = width + noncontent_width;
|
||||||
image_box_info.computed_width = Some(width);
|
image_fragment_info.computed_width = Some(width);
|
||||||
}
|
}
|
||||||
_ => fail!("this case should have been handled above"),
|
_ => fail!("this case should have been handled above"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign height for this box if it is replaced content. The width must have been assigned
|
/// Assign height for this fragment if it is replaced content. The width must have been assigned
|
||||||
/// first.
|
/// first.
|
||||||
///
|
///
|
||||||
/// Ideally, this should follow CSS 2.1 § 10.6.2.
|
/// Ideally, this should follow CSS 2.1 § 10.6.2.
|
||||||
|
@ -1313,8 +1311,8 @@ impl Fragment {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
GenericFragment | IframeFragment(_) | TableFragment | TableCellFragment | TableRowFragment |
|
||||||
TableWrapperFragment => return,
|
TableWrapperFragment => return,
|
||||||
TableColumnFragment(_) => fail!("Table column boxes do not have height"),
|
TableColumnFragment(_) => fail!("Table column fragments do not have height"),
|
||||||
UnscannedTextFragment(_) => fail!("Unscanned text boxes should have been scanned by now!"),
|
UnscannedTextFragment(_) => fail!("Unscanned text fragments should have been scanned by now!"),
|
||||||
ImageFragment(_) | ScannedTextFragment(_) => {}
|
ImageFragment(_) | ScannedTextFragment(_) => {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1323,34 +1321,34 @@ impl Fragment {
|
||||||
let noncontent_height = self.border_padding.vertical();
|
let noncontent_height = self.border_padding.vertical();
|
||||||
|
|
||||||
match self.specific {
|
match self.specific {
|
||||||
ImageFragment(ref mut image_box_info) => {
|
ImageFragment(ref mut image_fragment_info) => {
|
||||||
// TODO(ksh8281): compute border,margin,padding
|
// TODO(ksh8281): compute border,margin,padding
|
||||||
let width = image_box_info.computed_width();
|
let width = image_fragment_info.computed_width();
|
||||||
// FIXME(ksh8281): we shouldn't assign height this way
|
// FIXME(ksh8281): we shouldn't assign height this way
|
||||||
// we don't know about size of parent's height
|
// we don't know about size of parent's height
|
||||||
let height = ImageFragmentInfo::style_length(style_height,
|
let height = ImageFragmentInfo::style_length(style_height,
|
||||||
image_box_info.dom_height,
|
image_fragment_info.dom_height,
|
||||||
Au(0));
|
Au(0));
|
||||||
|
|
||||||
let height = match (style_width, image_box_info.dom_width, height) {
|
let height = match (style_width, image_fragment_info.dom_width, height) {
|
||||||
(LPA_Auto, None, Auto) => {
|
(LPA_Auto, None, Auto) => {
|
||||||
image_box_info.image_height()
|
image_fragment_info.image_height()
|
||||||
},
|
},
|
||||||
(_,_,Auto) => {
|
(_,_,Auto) => {
|
||||||
let scale = image_box_info.image_width().to_f32().unwrap()
|
let scale = image_fragment_info.image_width().to_f32().unwrap()
|
||||||
/ width.to_f32().unwrap();
|
/ width.to_f32().unwrap();
|
||||||
Au::new((image_box_info.image_height().to_f32().unwrap() / scale) as i32)
|
Au::new((image_fragment_info.image_height().to_f32().unwrap() / scale) as i32)
|
||||||
},
|
},
|
||||||
(_,_,Specified(h)) => {
|
(_,_,Specified(h)) => {
|
||||||
h
|
h
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
image_box_info.computed_height = Some(height);
|
image_fragment_info.computed_height = Some(height);
|
||||||
self.border_box.size.height = height + noncontent_height
|
self.border_box.size.height = height + noncontent_height
|
||||||
}
|
}
|
||||||
ScannedTextFragment(_) => {
|
ScannedTextFragment(_) => {
|
||||||
// Scanned text boxes' content heights are calculated by the text run scanner
|
// Scanned text fragments' content heights are calculated by the text run scanner
|
||||||
// during flow construction.
|
// during flow construction.
|
||||||
self.border_box.size.height = self.border_box.size.height + noncontent_height
|
self.border_box.size.height = self.border_box.size.height + noncontent_height
|
||||||
}
|
}
|
||||||
|
@ -1362,19 +1360,19 @@ impl Fragment {
|
||||||
/// used in an inline formatting context. See CSS 2.1 § 10.8.1.
|
/// used in an inline formatting context. See CSS 2.1 § 10.8.1.
|
||||||
pub fn inline_metrics(&self) -> InlineMetrics {
|
pub fn inline_metrics(&self) -> InlineMetrics {
|
||||||
match self.specific {
|
match self.specific {
|
||||||
ImageFragment(ref image_box_info) => {
|
ImageFragment(ref image_fragment_info) => {
|
||||||
let computed_height = image_box_info.computed_height();
|
let computed_height = image_fragment_info.computed_height();
|
||||||
InlineMetrics {
|
InlineMetrics {
|
||||||
height_above_baseline: computed_height + self.border_padding.vertical(),
|
height_above_baseline: computed_height + self.border_padding.vertical(),
|
||||||
depth_below_baseline: Au(0),
|
depth_below_baseline: Au(0),
|
||||||
ascent: computed_height + self.border_padding.bottom,
|
ascent: computed_height + self.border_padding.bottom,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ScannedTextFragment(ref text_box) => {
|
ScannedTextFragment(ref text_fragment) => {
|
||||||
// See CSS 2.1 § 10.8.1.
|
// See CSS 2.1 § 10.8.1.
|
||||||
let font_size = self.style().get_font().font_size;
|
let font_size = self.style().get_font().font_size;
|
||||||
let line_height = self.calculate_line_height(font_size);
|
let line_height = self.calculate_line_height(font_size);
|
||||||
InlineMetrics::from_font_metrics(&text_box.run.font_metrics, line_height)
|
InlineMetrics::from_font_metrics(&text_fragment.run.font_metrics, line_height)
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
InlineMetrics {
|
InlineMetrics {
|
||||||
|
@ -1386,8 +1384,8 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this box can merge with another adjacent box or false otherwise.
|
/// Returns true if this fragment can merge with another adjacent fragment or false otherwise.
|
||||||
pub fn can_merge_with_box(&self, other: &Fragment) -> bool {
|
pub fn can_merge_with_fragment(&self, other: &Fragment) -> bool {
|
||||||
match (&self.specific, &other.specific) {
|
match (&self.specific, &other.specific) {
|
||||||
(&UnscannedTextFragment(_), &UnscannedTextFragment(_)) => {
|
(&UnscannedTextFragment(_), &UnscannedTextFragment(_)) => {
|
||||||
self.font_style() == other.font_style() &&
|
self.font_style() == other.font_style() &&
|
||||||
|
@ -1419,11 +1417,11 @@ impl Fragment {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sends the size and position of this iframe box to the constellation. This is out of line to
|
/// Sends the size and position of this iframe fragment to the constellation. This is out of
|
||||||
/// guide inlining.
|
/// line to guide inlining.
|
||||||
#[inline(never)]
|
#[inline(never)]
|
||||||
fn finalize_position_and_size_of_iframe(&self,
|
fn finalize_position_and_size_of_iframe(&self,
|
||||||
iframe_box: &IframeFragmentInfo,
|
iframe_fragment: &IframeFragmentInfo,
|
||||||
offset: Point2D<Au>,
|
offset: Point2D<Au>,
|
||||||
layout_context: &LayoutContext) {
|
layout_context: &LayoutContext) {
|
||||||
let left = offset.x + self.margin.left + self.border_padding.left;
|
let left = offset.x + self.margin.left + self.border_padding.left;
|
||||||
|
@ -1435,16 +1433,16 @@ impl Fragment {
|
||||||
let rect = Rect(origin, size);
|
let rect = Rect(origin, size);
|
||||||
|
|
||||||
debug!("finalizing position and size of iframe for {:?},{:?}",
|
debug!("finalizing position and size of iframe for {:?},{:?}",
|
||||||
iframe_box.pipeline_id,
|
iframe_fragment.pipeline_id,
|
||||||
iframe_box.subpage_id);
|
iframe_fragment.subpage_id);
|
||||||
let msg = FrameRectMsg(iframe_box.pipeline_id, iframe_box.subpage_id, rect);
|
let msg = FrameRectMsg(iframe_fragment.pipeline_id, iframe_fragment.subpage_id, rect);
|
||||||
let ConstellationChan(ref chan) = layout_context.constellation_chan;
|
let ConstellationChan(ref chan) = layout_context.constellation_chan;
|
||||||
chan.send(msg)
|
chan.send(msg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl fmt::Show for Fragment {
|
impl fmt::Show for Fragment {
|
||||||
/// Outputs a debugging string describing this box.
|
/// Outputs a debugging string describing this fragment.
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
try!(write!(f.buf, "({} ",
|
try!(write!(f.buf, "({} ",
|
||||||
match self.specific {
|
match self.specific {
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
//! Creates flows and boxes from a DOM tree via a bottom-up, incremental traversal of the DOM.
|
//! Creates flows and fragments from a DOM tree via a bottom-up, incremental traversal of the DOM.
|
||||||
//!
|
//!
|
||||||
//! Each step of the traversal considers the node and existing flow, if there is one. If a node is
|
//! Each step of the traversal considers the node and existing flow, if there is one. If a node is
|
||||||
//! not dirty and an existing flow exists, then the traversal reuses that flow. Otherwise, it
|
//! not dirty and an existing flow exists, then the traversal reuses that flow. Otherwise, it
|
||||||
|
@ -95,7 +95,7 @@ impl ConstructionResult {
|
||||||
/// complete flow. Construction items bubble up the tree until they find a `Flow` to be
|
/// complete flow. Construction items bubble up the tree until they find a `Flow` to be
|
||||||
/// attached to.
|
/// attached to.
|
||||||
pub enum ConstructionItem {
|
pub enum ConstructionItem {
|
||||||
/// Inline boxes and associated {ib} splits that have not yet found flows.
|
/// Inline fragments and associated {ib} splits that have not yet found flows.
|
||||||
InlineFragmentsConstructionItem(InlineFragmentsConstructionResult),
|
InlineFragmentsConstructionItem(InlineFragmentsConstructionResult),
|
||||||
/// Potentially ignorable whitespace.
|
/// Potentially ignorable whitespace.
|
||||||
WhitespaceConstructionItem(OpaqueNode, Arc<ComputedValues>),
|
WhitespaceConstructionItem(OpaqueNode, Arc<ComputedValues>),
|
||||||
|
@ -117,13 +117,13 @@ impl ConstructionItem {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents inline boxes and {ib} splits that are bubbling up from an inline.
|
/// Represents inline fragments and {ib} splits that are bubbling up from an inline.
|
||||||
pub struct InlineFragmentsConstructionResult {
|
pub struct InlineFragmentsConstructionResult {
|
||||||
/// Any {ib} splits that we're bubbling up.
|
/// Any {ib} splits that we're bubbling up.
|
||||||
pub splits: Vec<InlineBlockSplit>,
|
pub splits: Vec<InlineBlockSplit>,
|
||||||
|
|
||||||
/// Any boxes that succeed the {ib} splits.
|
/// Any fragments that succeed the {ib} splits.
|
||||||
pub boxes: InlineFragments,
|
pub fragments: InlineFragments,
|
||||||
|
|
||||||
/// Any absolute descendants that we're bubbling up.
|
/// Any absolute descendants that we're bubbling up.
|
||||||
pub abs_descendants: AbsDescendants,
|
pub abs_descendants: AbsDescendants,
|
||||||
|
@ -142,7 +142,7 @@ pub struct InlineFragmentsConstructionResult {
|
||||||
///
|
///
|
||||||
/// InlineFragmentsConstructionItem(Some(~[
|
/// InlineFragmentsConstructionItem(Some(~[
|
||||||
/// InlineBlockSplit {
|
/// InlineBlockSplit {
|
||||||
/// predecessor_boxes: ~[
|
/// predecessor_fragments: ~[
|
||||||
/// A
|
/// A
|
||||||
/// ],
|
/// ],
|
||||||
/// block: ~BlockFlow {
|
/// block: ~BlockFlow {
|
||||||
|
@ -152,7 +152,7 @@ pub struct InlineFragmentsConstructionResult {
|
||||||
/// C
|
/// C
|
||||||
/// ])
|
/// ])
|
||||||
pub struct InlineBlockSplit {
|
pub struct InlineBlockSplit {
|
||||||
/// The inline boxes that precede the flow.
|
/// The inline fragments that precede the flow.
|
||||||
pub predecessors: InlineFragments,
|
pub predecessors: InlineFragments,
|
||||||
|
|
||||||
/// The flow that caused this {ib} split.
|
/// The flow that caused this {ib} split.
|
||||||
|
@ -165,12 +165,12 @@ impl InlineBlockSplit {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Holds inline boxes that we're gathering for children of an inline node.
|
/// Holds inline fragments that we're gathering for children of an inline node.
|
||||||
struct InlineFragmentsAccumulator {
|
struct InlineFragmentsAccumulator {
|
||||||
/// The list of boxes.
|
/// The list of fragments.
|
||||||
boxes: InlineFragments,
|
fragments: InlineFragments,
|
||||||
|
|
||||||
/// Whether we've created a range to enclose all the boxes. This will be true if the outer node
|
/// Whether we've created a range to enclose all the fragments. This will be true if the outer node
|
||||||
/// is an inline and false otherwise.
|
/// is an inline and false otherwise.
|
||||||
has_enclosing_range: bool,
|
has_enclosing_range: bool,
|
||||||
}
|
}
|
||||||
|
@ -178,31 +178,31 @@ struct InlineFragmentsAccumulator {
|
||||||
impl InlineFragmentsAccumulator {
|
impl InlineFragmentsAccumulator {
|
||||||
fn new() -> InlineFragmentsAccumulator {
|
fn new() -> InlineFragmentsAccumulator {
|
||||||
InlineFragmentsAccumulator {
|
InlineFragmentsAccumulator {
|
||||||
boxes: InlineFragments::new(),
|
fragments: InlineFragments::new(),
|
||||||
has_enclosing_range: false,
|
has_enclosing_range: false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn from_inline_node(node: &ThreadSafeLayoutNode) -> InlineFragmentsAccumulator {
|
fn from_inline_node(node: &ThreadSafeLayoutNode) -> InlineFragmentsAccumulator {
|
||||||
let mut boxes = InlineFragments::new();
|
let mut fragments = InlineFragments::new();
|
||||||
boxes.map.push(node.style().clone(), Range::empty());
|
fragments.map.push(node.style().clone(), Range::empty());
|
||||||
InlineFragmentsAccumulator {
|
InlineFragmentsAccumulator {
|
||||||
boxes: boxes,
|
fragments: fragments,
|
||||||
has_enclosing_range: true,
|
has_enclosing_range: true,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn finish(self) -> InlineFragments {
|
fn finish(self) -> InlineFragments {
|
||||||
let InlineFragmentsAccumulator {
|
let InlineFragmentsAccumulator {
|
||||||
boxes: mut boxes,
|
fragments: mut fragments,
|
||||||
has_enclosing_range
|
has_enclosing_range
|
||||||
} = self;
|
} = self;
|
||||||
|
|
||||||
if has_enclosing_range {
|
if has_enclosing_range {
|
||||||
let len = FragmentIndex(boxes.len() as int);
|
let len = FragmentIndex(fragments.len() as int);
|
||||||
boxes.map.get_mut(FragmentIndex(0)).range.extend_to(len);
|
fragments.map.get_mut(FragmentIndex(0)).range.extend_to(len);
|
||||||
}
|
}
|
||||||
boxes
|
fragments
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,12 +255,12 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds the `ImageFragmentInfo` for the given image. This is out of line to guide inlining.
|
/// Builds the `ImageFragmentInfo` for the given image. This is out of line to guide inlining.
|
||||||
fn build_box_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>)
|
fn build_fragment_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>)
|
||||||
-> SpecificFragmentInfo {
|
-> SpecificFragmentInfo {
|
||||||
match url {
|
match url {
|
||||||
None => GenericFragment,
|
None => GenericFragment,
|
||||||
Some(url) => {
|
Some(url) => {
|
||||||
// FIXME(pcwalton): The fact that image boxes store the cache within them makes
|
// FIXME(pcwalton): The fact that image fragments store the cache within them makes
|
||||||
// little sense to me.
|
// little sense to me.
|
||||||
ImageFragment(ImageFragmentInfo::new(node, url, self.layout_context.image_cache.clone()))
|
ImageFragment(ImageFragmentInfo::new(node, url, self.layout_context.image_cache.clone()))
|
||||||
}
|
}
|
||||||
|
@ -268,18 +268,18 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds specific `Fragment` info for the given node.
|
/// Builds specific `Fragment` info for the given node.
|
||||||
pub fn build_specific_box_info_for_node(&mut self, node: &ThreadSafeLayoutNode)
|
pub fn build_specific_fragment_info_for_node(&mut self, node: &ThreadSafeLayoutNode)
|
||||||
-> SpecificFragmentInfo {
|
-> SpecificFragmentInfo {
|
||||||
match node.type_id() {
|
match node.type_id() {
|
||||||
Some(ElementNodeTypeId(HTMLImageElementTypeId)) => {
|
Some(ElementNodeTypeId(HTMLImageElementTypeId)) => {
|
||||||
self.build_box_info_for_image(node, node.image_url())
|
self.build_fragment_info_for_image(node, node.image_url())
|
||||||
}
|
}
|
||||||
Some(ElementNodeTypeId(HTMLIFrameElementTypeId)) => {
|
Some(ElementNodeTypeId(HTMLIFrameElementTypeId)) => {
|
||||||
IframeFragment(IframeFragmentInfo::new(node))
|
IframeFragment(IframeFragmentInfo::new(node))
|
||||||
}
|
}
|
||||||
Some(ElementNodeTypeId(HTMLObjectElementTypeId)) => {
|
Some(ElementNodeTypeId(HTMLObjectElementTypeId)) => {
|
||||||
let data = node.get_object_data(&self.layout_context.url);
|
let data = node.get_object_data(&self.layout_context.url);
|
||||||
self.build_box_info_for_image(node, data)
|
self.build_fragment_info_for_image(node, data)
|
||||||
}
|
}
|
||||||
Some(ElementNodeTypeId(HTMLTableElementTypeId)) => TableWrapperFragment,
|
Some(ElementNodeTypeId(HTMLTableElementTypeId)) => TableWrapperFragment,
|
||||||
Some(ElementNodeTypeId(HTMLTableColElementTypeId)) => {
|
Some(ElementNodeTypeId(HTMLTableColElementTypeId)) => {
|
||||||
|
@ -294,40 +294,40 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an inline flow from a set of inline boxes, then adds it as a child of the given flow
|
/// Creates an inline flow from a set of inline fragments, then adds it as a child of the given flow
|
||||||
/// or pushes it onto the given flow list.
|
/// or pushes it onto the given flow list.
|
||||||
///
|
///
|
||||||
/// `#[inline(always)]` because this is performance critical and LLVM will not inline it
|
/// `#[inline(always)]` because this is performance critical and LLVM will not inline it
|
||||||
/// otherwise.
|
/// otherwise.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn flush_inline_boxes_to_flow_or_list(&mut self,
|
fn flush_inline_fragments_to_flow_or_list(&mut self,
|
||||||
box_accumulator: InlineFragmentsAccumulator,
|
fragment_accumulator: InlineFragmentsAccumulator,
|
||||||
flow: &mut Box<Flow:Share>,
|
flow: &mut Box<Flow:Share>,
|
||||||
flow_list: &mut Vec<Box<Flow:Share>>,
|
flow_list: &mut Vec<Box<Flow:Share>>,
|
||||||
whitespace_stripping: WhitespaceStrippingMode,
|
whitespace_stripping: WhitespaceStrippingMode,
|
||||||
node: &ThreadSafeLayoutNode) {
|
node: &ThreadSafeLayoutNode) {
|
||||||
let mut boxes = box_accumulator.finish();
|
let mut fragments = fragment_accumulator.finish();
|
||||||
if boxes.len() == 0 {
|
if fragments.len() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
match whitespace_stripping {
|
match whitespace_stripping {
|
||||||
NoWhitespaceStripping => {}
|
NoWhitespaceStripping => {}
|
||||||
StripWhitespaceFromStart => {
|
StripWhitespaceFromStart => {
|
||||||
strip_ignorable_whitespace_from_start(&mut boxes);
|
strip_ignorable_whitespace_from_start(&mut fragments);
|
||||||
if boxes.len() == 0 {
|
if fragments.len() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
StripWhitespaceFromEnd => {
|
StripWhitespaceFromEnd => {
|
||||||
strip_ignorable_whitespace_from_end(&mut boxes);
|
strip_ignorable_whitespace_from_end(&mut fragments);
|
||||||
if boxes.len() == 0 {
|
if fragments.len() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut inline_flow = box InlineFlow::from_boxes((*node).clone(), boxes);
|
let mut inline_flow = box InlineFlow::from_fragments((*node).clone(), fragments);
|
||||||
inline_flow.compute_minimum_ascent_and_descent(self.font_context(), &**node.style());
|
inline_flow.compute_minimum_ascent_and_descent(self.font_context(), &**node.style());
|
||||||
let mut inline_flow = inline_flow as Box<Flow:Share>;
|
let mut inline_flow = inline_flow as Box<Flow:Share>;
|
||||||
TextRunScanner::new().scan_for_runs(self.font_context(), inline_flow);
|
TextRunScanner::new().scan_for_runs(self.font_context(), inline_flow);
|
||||||
|
@ -343,13 +343,13 @@ impl<'a> FlowConstructor<'a> {
|
||||||
fn build_block_flow_using_children_construction_result(&mut self,
|
fn build_block_flow_using_children_construction_result(&mut self,
|
||||||
flow: &mut Box<Flow:Share>,
|
flow: &mut Box<Flow:Share>,
|
||||||
consecutive_siblings:
|
consecutive_siblings:
|
||||||
&mut Vec<Box<Flow:Share>>,
|
&mut Vec<Box<Flow:Share>>,
|
||||||
node: &ThreadSafeLayoutNode,
|
node: &ThreadSafeLayoutNode,
|
||||||
kid: ThreadSafeLayoutNode,
|
kid: ThreadSafeLayoutNode,
|
||||||
inline_box_accumulator:
|
inline_fragment_accumulator:
|
||||||
&mut InlineFragmentsAccumulator,
|
&mut InlineFragmentsAccumulator,
|
||||||
abs_descendants: &mut Descendants,
|
abs_descendants: &mut Descendants,
|
||||||
first_box: &mut bool) {
|
first_fragment: &mut bool) {
|
||||||
match kid.swap_out_construction_result() {
|
match kid.swap_out_construction_result() {
|
||||||
NoConstructionResult => {}
|
NoConstructionResult => {}
|
||||||
FlowConstructionResult(kid_flow, kid_abs_descendants) => {
|
FlowConstructionResult(kid_flow, kid_abs_descendants) => {
|
||||||
|
@ -364,19 +364,19 @@ impl<'a> FlowConstructor<'a> {
|
||||||
} else {
|
} else {
|
||||||
// Strip ignorable whitespace from the start of this flow per CSS 2.1 §
|
// Strip ignorable whitespace from the start of this flow per CSS 2.1 §
|
||||||
// 9.2.1.1.
|
// 9.2.1.1.
|
||||||
let whitespace_stripping = if flow.is_table_kind() || *first_box {
|
let whitespace_stripping = if flow.is_table_kind() || *first_fragment {
|
||||||
*first_box = false;
|
*first_fragment = false;
|
||||||
StripWhitespaceFromStart
|
StripWhitespaceFromStart
|
||||||
} else {
|
} else {
|
||||||
NoWhitespaceStripping
|
NoWhitespaceStripping
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flush any inline boxes that we were gathering up. This allows us to handle
|
// Flush any inline fragments that we were gathering up. This allows us to handle
|
||||||
// {ib} splits.
|
// {ib} splits.
|
||||||
debug!("flushing {} inline box(es) to flow A",
|
debug!("flushing {} inline box(es) to flow A",
|
||||||
inline_box_accumulator.boxes.len());
|
inline_fragment_accumulator.fragments.len());
|
||||||
self.flush_inline_boxes_to_flow_or_list(
|
self.flush_inline_fragments_to_flow_or_list(
|
||||||
mem::replace(inline_box_accumulator, InlineFragmentsAccumulator::new()),
|
mem::replace(inline_fragment_accumulator, InlineFragmentsAccumulator::new()),
|
||||||
flow,
|
flow,
|
||||||
consecutive_siblings,
|
consecutive_siblings,
|
||||||
whitespace_stripping,
|
whitespace_stripping,
|
||||||
|
@ -394,33 +394,33 @@ impl<'a> FlowConstructor<'a> {
|
||||||
ConstructionItemConstructionResult(InlineFragmentsConstructionItem(
|
ConstructionItemConstructionResult(InlineFragmentsConstructionItem(
|
||||||
InlineFragmentsConstructionResult {
|
InlineFragmentsConstructionResult {
|
||||||
splits: splits,
|
splits: splits,
|
||||||
boxes: successor_boxes,
|
fragments: successor_fragments,
|
||||||
abs_descendants: kid_abs_descendants,
|
abs_descendants: kid_abs_descendants,
|
||||||
})) => {
|
})) => {
|
||||||
// Add any {ib} splits.
|
// Add any {ib} splits.
|
||||||
for split in splits.move_iter() {
|
for split in splits.move_iter() {
|
||||||
// Pull apart the {ib} split object and push its predecessor boxes
|
// Pull apart the {ib} split object and push its predecessor fragments
|
||||||
// onto the list.
|
// onto the list.
|
||||||
let InlineBlockSplit {
|
let InlineBlockSplit {
|
||||||
predecessors: predecessors,
|
predecessors: predecessors,
|
||||||
flow: kid_flow
|
flow: kid_flow
|
||||||
} = split;
|
} = split;
|
||||||
inline_box_accumulator.boxes.push_all(predecessors);
|
inline_fragment_accumulator.fragments.push_all(predecessors);
|
||||||
|
|
||||||
// If this is the first box in flow, then strip ignorable
|
// If this is the first fragment in flow, then strip ignorable
|
||||||
// whitespace per CSS 2.1 § 9.2.1.1.
|
// whitespace per CSS 2.1 § 9.2.1.1.
|
||||||
let whitespace_stripping = if *first_box {
|
let whitespace_stripping = if *first_fragment {
|
||||||
*first_box = false;
|
*first_fragment = false;
|
||||||
StripWhitespaceFromStart
|
StripWhitespaceFromStart
|
||||||
} else {
|
} else {
|
||||||
NoWhitespaceStripping
|
NoWhitespaceStripping
|
||||||
};
|
};
|
||||||
|
|
||||||
// Flush any inline boxes that we were gathering up.
|
// Flush any inline fragments that we were gathering up.
|
||||||
debug!("flushing {} inline box(es) to flow A",
|
debug!("flushing {} inline box(es) to flow A",
|
||||||
inline_box_accumulator.boxes.len());
|
inline_fragment_accumulator.fragments.len());
|
||||||
self.flush_inline_boxes_to_flow_or_list(
|
self.flush_inline_fragments_to_flow_or_list(
|
||||||
mem::replace(inline_box_accumulator,
|
mem::replace(inline_fragment_accumulator,
|
||||||
InlineFragmentsAccumulator::new()),
|
InlineFragmentsAccumulator::new()),
|
||||||
flow,
|
flow,
|
||||||
consecutive_siblings,
|
consecutive_siblings,
|
||||||
|
@ -436,8 +436,8 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add the boxes to the list we're maintaining.
|
// Add the fragments to the list we're maintaining.
|
||||||
inline_box_accumulator.boxes.push_all(successor_boxes);
|
inline_fragment_accumulator.fragments.push_all(successor_fragments);
|
||||||
abs_descendants.push_descendants(kid_abs_descendants);
|
abs_descendants.push_descendants(kid_abs_descendants);
|
||||||
}
|
}
|
||||||
ConstructionItemConstructionResult(WhitespaceConstructionItem(..)) => {
|
ConstructionItemConstructionResult(WhitespaceConstructionItem(..)) => {
|
||||||
|
@ -461,10 +461,10 @@ impl<'a> FlowConstructor<'a> {
|
||||||
mut flow: Box<Flow:Share>,
|
mut flow: Box<Flow:Share>,
|
||||||
node: &ThreadSafeLayoutNode)
|
node: &ThreadSafeLayoutNode)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
// Gather up boxes for the inline flows we might need to create.
|
// Gather up fragments for the inline flows we might need to create.
|
||||||
let mut inline_box_accumulator = InlineFragmentsAccumulator::new();
|
let mut inline_fragment_accumulator = InlineFragmentsAccumulator::new();
|
||||||
let mut consecutive_siblings = vec!();
|
let mut consecutive_siblings = vec!();
|
||||||
let mut first_box = true;
|
let mut first_fragment = true;
|
||||||
|
|
||||||
// List of absolute descendants, in tree order.
|
// List of absolute descendants, in tree order.
|
||||||
let mut abs_descendants = Descendants::new();
|
let mut abs_descendants = Descendants::new();
|
||||||
|
@ -477,14 +477,14 @@ impl<'a> FlowConstructor<'a> {
|
||||||
&mut consecutive_siblings,
|
&mut consecutive_siblings,
|
||||||
node,
|
node,
|
||||||
kid,
|
kid,
|
||||||
&mut inline_box_accumulator,
|
&mut inline_fragment_accumulator,
|
||||||
&mut abs_descendants,
|
&mut abs_descendants,
|
||||||
&mut first_box);
|
&mut first_fragment);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform a final flush of any inline boxes that we were gathering up to handle {ib}
|
// Perform a final flush of any inline fragments that we were gathering up to handle {ib}
|
||||||
// splits, after stripping ignorable whitespace.
|
// splits, after stripping ignorable whitespace.
|
||||||
self.flush_inline_boxes_to_flow_or_list(inline_box_accumulator,
|
self.flush_inline_fragments_to_flow_or_list(inline_fragment_accumulator,
|
||||||
&mut flow,
|
&mut flow,
|
||||||
&mut consecutive_siblings,
|
&mut consecutive_siblings,
|
||||||
StripWhitespaceFromEnd,
|
StripWhitespaceFromEnd,
|
||||||
|
@ -528,16 +528,16 @@ impl<'a> FlowConstructor<'a> {
|
||||||
self.build_flow_using_children(flow, node)
|
self.build_flow_using_children(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Concatenates the boxes of kids, adding in our own borders/padding/margins if necessary.
|
/// Concatenates the fragments of kids, adding in our own borders/padding/margins if necessary.
|
||||||
/// Returns the `InlineFragmentsConstructionResult`, if any. There will be no
|
/// Returns the `InlineFragmentsConstructionResult`, if any. There will be no
|
||||||
/// `InlineFragmentsConstructionResult` if this node consisted entirely of ignorable whitespace.
|
/// `InlineFragmentsConstructionResult` if this node consisted entirely of ignorable whitespace.
|
||||||
fn build_boxes_for_nonreplaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
fn build_fragments_for_nonreplaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
let mut opt_inline_block_splits: Vec<InlineBlockSplit> = Vec::new();
|
let mut opt_inline_block_splits: Vec<InlineBlockSplit> = Vec::new();
|
||||||
let mut box_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
|
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
|
||||||
let mut abs_descendants = Descendants::new();
|
let mut abs_descendants = Descendants::new();
|
||||||
|
|
||||||
// Concatenate all the boxes of our kids, creating {ib} splits as necessary.
|
// Concatenate all the fragments of our kids, creating {ib} splits as necessary.
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
if kid.get_pseudo_element_type() != Normal {
|
if kid.get_pseudo_element_type() != Normal {
|
||||||
self.process(&kid);
|
self.process(&kid);
|
||||||
|
@ -546,10 +546,10 @@ impl<'a> FlowConstructor<'a> {
|
||||||
NoConstructionResult => {}
|
NoConstructionResult => {}
|
||||||
FlowConstructionResult(flow, kid_abs_descendants) => {
|
FlowConstructionResult(flow, kid_abs_descendants) => {
|
||||||
// {ib} split. Flush the accumulator to our new split and make a new
|
// {ib} split. Flush the accumulator to our new split and make a new
|
||||||
// accumulator to hold any subsequent boxes we come across.
|
// accumulator to hold any subsequent fragments we come across.
|
||||||
let split = InlineBlockSplit {
|
let split = InlineBlockSplit {
|
||||||
predecessors:
|
predecessors:
|
||||||
mem::replace(&mut box_accumulator,
|
mem::replace(&mut fragment_accumulator,
|
||||||
InlineFragmentsAccumulator::from_inline_node(node)).finish(),
|
InlineFragmentsAccumulator::from_inline_node(node)).finish(),
|
||||||
flow: flow,
|
flow: flow,
|
||||||
};
|
};
|
||||||
|
@ -559,7 +559,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
ConstructionItemConstructionResult(InlineFragmentsConstructionItem(
|
ConstructionItemConstructionResult(InlineFragmentsConstructionItem(
|
||||||
InlineFragmentsConstructionResult {
|
InlineFragmentsConstructionResult {
|
||||||
splits: splits,
|
splits: splits,
|
||||||
boxes: successors,
|
fragments: successors,
|
||||||
abs_descendants: kid_abs_descendants,
|
abs_descendants: kid_abs_descendants,
|
||||||
})) => {
|
})) => {
|
||||||
|
|
||||||
|
@ -569,11 +569,11 @@ impl<'a> FlowConstructor<'a> {
|
||||||
predecessors: predecessors,
|
predecessors: predecessors,
|
||||||
flow: kid_flow
|
flow: kid_flow
|
||||||
} = split;
|
} = split;
|
||||||
box_accumulator.boxes.push_all(predecessors);
|
fragment_accumulator.fragments.push_all(predecessors);
|
||||||
|
|
||||||
let split = InlineBlockSplit {
|
let split = InlineBlockSplit {
|
||||||
predecessors:
|
predecessors:
|
||||||
mem::replace(&mut box_accumulator,
|
mem::replace(&mut fragment_accumulator,
|
||||||
InlineFragmentsAccumulator::from_inline_node(node))
|
InlineFragmentsAccumulator::from_inline_node(node))
|
||||||
.finish(),
|
.finish(),
|
||||||
flow: kid_flow,
|
flow: kid_flow,
|
||||||
|
@ -581,19 +581,19 @@ impl<'a> FlowConstructor<'a> {
|
||||||
opt_inline_block_splits.push(split)
|
opt_inline_block_splits.push(split)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Push residual boxes.
|
// Push residual fragments.
|
||||||
box_accumulator.boxes.push_all(successors);
|
fragment_accumulator.fragments.push_all(successors);
|
||||||
abs_descendants.push_descendants(kid_abs_descendants);
|
abs_descendants.push_descendants(kid_abs_descendants);
|
||||||
}
|
}
|
||||||
ConstructionItemConstructionResult(WhitespaceConstructionItem(whitespace_node,
|
ConstructionItemConstructionResult(WhitespaceConstructionItem(whitespace_node,
|
||||||
whitespace_style))
|
whitespace_style))
|
||||||
=> {
|
=> {
|
||||||
// Instantiate the whitespace box.
|
// Instantiate the whitespace fragment.
|
||||||
let box_info = UnscannedTextFragment(UnscannedTextFragmentInfo::from_text(" ".to_owned()));
|
let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::from_text(" ".to_owned()));
|
||||||
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
|
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
|
||||||
whitespace_style.clone(),
|
whitespace_style.clone(),
|
||||||
box_info);
|
fragment_info);
|
||||||
box_accumulator.boxes.push(fragment, whitespace_style)
|
fragment_accumulator.fragments.push(fragment, whitespace_style)
|
||||||
}
|
}
|
||||||
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => {
|
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => {
|
||||||
// TODO: Implement anonymous table objects for missing parents
|
// TODO: Implement anonymous table objects for missing parents
|
||||||
|
@ -603,11 +603,11 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Finally, make a new construction result.
|
// Finally, make a new construction result.
|
||||||
if opt_inline_block_splits.len() > 0 || box_accumulator.boxes.len() > 0
|
if opt_inline_block_splits.len() > 0 || fragment_accumulator.fragments.len() > 0
|
||||||
|| abs_descendants.len() > 0 {
|
|| abs_descendants.len() > 0 {
|
||||||
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
|
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
|
||||||
splits: opt_inline_block_splits,
|
splits: opt_inline_block_splits,
|
||||||
boxes: box_accumulator.finish(),
|
fragments: fragment_accumulator.finish(),
|
||||||
abs_descendants: abs_descendants,
|
abs_descendants: abs_descendants,
|
||||||
});
|
});
|
||||||
ConstructionItemConstructionResult(construction_item)
|
ConstructionItemConstructionResult(construction_item)
|
||||||
|
@ -617,8 +617,8 @@ impl<'a> FlowConstructor<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates an `InlineFragmentsConstructionResult` for replaced content. Replaced content doesn't
|
/// Creates an `InlineFragmentsConstructionResult` for replaced content. Replaced content doesn't
|
||||||
/// render its children, so this just nukes a child's boxes and creates a `Fragment`.
|
/// render its children, so this just nukes a child's fragments and creates a `Fragment`.
|
||||||
fn build_boxes_for_replaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
fn build_fragments_for_replaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
kid.set_flow_construction_result(NoConstructionResult)
|
kid.set_flow_construction_result(NoConstructionResult)
|
||||||
|
@ -634,27 +634,28 @@ impl<'a> FlowConstructor<'a> {
|
||||||
node.style().clone()))
|
node.style().clone()))
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut boxes = InlineFragments::new();
|
let mut fragments = InlineFragments::new();
|
||||||
boxes.push(Fragment::new(self, node), node.style().clone());
|
fragments.push(Fragment::new(self, node), node.style().clone());
|
||||||
|
|
||||||
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
|
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
|
||||||
splits: Vec::new(),
|
splits: Vec::new(),
|
||||||
boxes: boxes,
|
fragments: fragments,
|
||||||
abs_descendants: Descendants::new(),
|
abs_descendants: Descendants::new(),
|
||||||
});
|
});
|
||||||
ConstructionItemConstructionResult(construction_item)
|
ConstructionItemConstructionResult(construction_item)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds one or more boxes for a node with `display: inline`. This yields an
|
/// Builds one or more fragments for a node with `display: inline`. This yields an
|
||||||
/// `InlineFragmentsConstructionResult`.
|
/// `InlineFragmentsConstructionResult`.
|
||||||
fn build_boxes_for_inline(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_fragments_for_inline(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
// Is this node replaced content?
|
// Is this node replaced content?
|
||||||
if !node.is_replaced_content() {
|
if !node.is_replaced_content() {
|
||||||
// Go to a path that concatenates our kids' boxes.
|
// Go to a path that concatenates our kids' fragments.
|
||||||
self.build_boxes_for_nonreplaced_inline_content(node)
|
self.build_fragments_for_nonreplaced_inline_content(node)
|
||||||
} else {
|
} else {
|
||||||
// Otherwise, just nuke our kids' boxes, create our box if any, and be done with it.
|
// Otherwise, just nuke our kids' fragments, create our fragment if any, and be done
|
||||||
self.build_boxes_for_replaced_inline_content(node)
|
// with it.
|
||||||
|
self.build_fragments_for_replaced_inline_content(node)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -704,11 +705,11 @@ impl<'a> FlowConstructor<'a> {
|
||||||
/// Builds a flow for a node with `display: table`. This yields a `TableWrapperFlow` with possibly
|
/// Builds a flow for a node with `display: table`. This yields a `TableWrapperFlow` with possibly
|
||||||
/// other `TableCaptionFlow`s or `TableFlow`s underneath it.
|
/// other `TableCaptionFlow`s or `TableFlow`s underneath it.
|
||||||
fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
let box_ = Fragment::new_from_specific_info(node, TableWrapperFragment);
|
let fragment = Fragment::new_from_specific_info(node, TableWrapperFragment);
|
||||||
let mut wrapper_flow = box TableWrapperFlow::from_node_and_box(node, box_) as Box<Flow:Share>;
|
let mut wrapper_flow = box TableWrapperFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>;
|
||||||
|
|
||||||
let table_box_ = Fragment::new_from_specific_info(node, TableFragment);
|
let table_fragment = Fragment::new_from_specific_info(node, TableFragment);
|
||||||
let table_flow = box TableFlow::from_node_and_box(node, table_box_) as Box<Flow:Share>;
|
let table_flow = box TableFlow::from_node_and_fragment(node, table_fragment) as Box<Flow:Share>;
|
||||||
|
|
||||||
// We first populate the TableFlow with other flows than TableCaptionFlow.
|
// We first populate the TableFlow with other flows than TableCaptionFlow.
|
||||||
// We then populate the TableWrapperFlow with TableCaptionFlow, and attach
|
// We then populate the TableWrapperFlow with TableCaptionFlow, and attach
|
||||||
|
@ -761,30 +762,30 @@ impl<'a> FlowConstructor<'a> {
|
||||||
/// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow`
|
/// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow`
|
||||||
/// with possibly other `TableRowFlow`s underneath it.
|
/// with possibly other `TableRowFlow`s underneath it.
|
||||||
fn build_flow_for_table_rowgroup(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_flow_for_table_rowgroup(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
let box_ = Fragment::new_from_specific_info(node, TableRowFragment);
|
let fragment = Fragment::new_from_specific_info(node, TableRowFragment);
|
||||||
let flow = box TableRowGroupFlow::from_node_and_box(node, box_) as Box<Flow:Share>;
|
let flow = box TableRowGroupFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>;
|
||||||
self.build_flow_using_children(flow, node)
|
self.build_flow_using_children(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with
|
/// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with
|
||||||
/// possibly other `TableCellFlow`s underneath it.
|
/// possibly other `TableCellFlow`s underneath it.
|
||||||
fn build_flow_for_table_row(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_flow_for_table_row(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
let box_ = Fragment::new_from_specific_info(node, TableRowFragment);
|
let fragment = Fragment::new_from_specific_info(node, TableRowFragment);
|
||||||
let flow = box TableRowFlow::from_node_and_box(node, box_) as Box<Flow:Share>;
|
let flow = box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>;
|
||||||
self.build_flow_using_children(flow, node)
|
self.build_flow_using_children(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with
|
/// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with
|
||||||
/// possibly other `BlockFlow`s or `InlineFlow`s underneath it.
|
/// possibly other `BlockFlow`s or `InlineFlow`s underneath it.
|
||||||
fn build_flow_for_table_cell(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_flow_for_table_cell(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
let box_ = Fragment::new_from_specific_info(node, TableCellFragment);
|
let fragment = Fragment::new_from_specific_info(node, TableCellFragment);
|
||||||
let flow = box TableCellFlow::from_node_and_box(node, box_) as Box<Flow:Share>;
|
let flow = box TableCellFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>;
|
||||||
self.build_flow_using_children(flow, node)
|
self.build_flow_using_children(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a box for a node with `display: table-column`.
|
/// Creates a fragment for a node with `display: table-column`.
|
||||||
fn build_boxes_for_table_column(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_fragments_for_table_column(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
// CSS 2.1 § 17.2.1. Treat all child boxes of a `table-column` as `display: none`.
|
// CSS 2.1 § 17.2.1. Treat all child fragments of a `table-column` as `display: none`.
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
kid.set_flow_construction_result(NoConstructionResult)
|
kid.set_flow_construction_result(NoConstructionResult)
|
||||||
}
|
}
|
||||||
|
@ -799,25 +800,25 @@ impl<'a> FlowConstructor<'a> {
|
||||||
/// Builds a flow for a node with `display: table-column-group`.
|
/// Builds a flow for a node with `display: table-column-group`.
|
||||||
/// This yields a `TableColGroupFlow`.
|
/// This yields a `TableColGroupFlow`.
|
||||||
fn build_flow_for_table_colgroup(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_flow_for_table_colgroup(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
let box_ = Fragment::new_from_specific_info(node,
|
let fragment = Fragment::new_from_specific_info(node,
|
||||||
TableColumnFragment(TableColumnFragmentInfo::new(node)));
|
TableColumnFragment(TableColumnFragmentInfo::new(node)));
|
||||||
let mut col_boxes = vec!();
|
let mut col_fragments = vec!();
|
||||||
for kid in node.children() {
|
for kid in node.children() {
|
||||||
// CSS 2.1 § 17.2.1. Treat all non-column child boxes of `table-column-group`
|
// CSS 2.1 § 17.2.1. Treat all non-column child fragments of `table-column-group`
|
||||||
// as `display: none`.
|
// as `display: none`.
|
||||||
match kid.swap_out_construction_result() {
|
match kid.swap_out_construction_result() {
|
||||||
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(box_)) => {
|
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(fragment)) => {
|
||||||
col_boxes.push(box_);
|
col_fragments.push(fragment);
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if col_boxes.is_empty() {
|
if col_fragments.is_empty() {
|
||||||
debug!("add TableColumnFragment for empty colgroup");
|
debug!("add TableColumnFragment for empty colgroup");
|
||||||
let specific = TableColumnFragment(TableColumnFragmentInfo::new(node));
|
let specific = TableColumnFragment(TableColumnFragmentInfo::new(node));
|
||||||
col_boxes.push(Fragment::new_from_specific_info(node, specific));
|
col_fragments.push(Fragment::new_from_specific_info(node, specific));
|
||||||
}
|
}
|
||||||
let mut flow = box TableColGroupFlow::from_node_and_boxes(node, box_, col_boxes) as Box<Flow:Share>;
|
let mut flow = box TableColGroupFlow::from_node_and_fragments(node, fragment, col_fragments) as Box<Flow:Share>;
|
||||||
flow.finish(self.layout_context);
|
flow.finish(self.layout_context);
|
||||||
|
|
||||||
FlowConstructionResult(flow, Descendants::new())
|
FlowConstructionResult(flow, Descendants::new())
|
||||||
|
@ -886,9 +887,9 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
node.set_flow_construction_result(self.build_flow_for_block(node))
|
node.set_flow_construction_result(self.build_flow_for_block(node))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Inline items contribute inline box construction results.
|
// Inline items contribute inline fragment construction results.
|
||||||
(display::inline, float::none, _) => {
|
(display::inline, float::none, _) => {
|
||||||
let construction_result = self.build_boxes_for_inline(node);
|
let construction_result = self.build_fragments_for_inline(node);
|
||||||
node.set_flow_construction_result(construction_result)
|
node.set_flow_construction_result(construction_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -906,7 +907,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
||||||
|
|
||||||
// Table items contribute table flow construction results.
|
// Table items contribute table flow construction results.
|
||||||
(display::table_column, _, _) => {
|
(display::table_column, _, _) => {
|
||||||
let construction_result = self.build_boxes_for_table_column(node);
|
let construction_result = self.build_fragments_for_table_column(node);
|
||||||
node.set_flow_construction_result(construction_result)
|
node.set_flow_construction_result(construction_result)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1084,57 +1085,57 @@ impl<'ln> ObjectElement for ThreadSafeLayoutNode<'ln> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Strips ignorable whitespace from the start of a list of boxes.
|
/// Strips ignorable whitespace from the start of a list of fragments.
|
||||||
fn strip_ignorable_whitespace_from_start(boxes: &mut InlineFragments) {
|
fn strip_ignorable_whitespace_from_start(fragments: &mut InlineFragments) {
|
||||||
if boxes.len() == 0 {
|
if fragments.len() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let InlineFragments {
|
let InlineFragments {
|
||||||
boxes: old_boxes,
|
fragments: old_fragments,
|
||||||
map: mut map
|
map: mut map
|
||||||
} = mem::replace(boxes, InlineFragments::new());
|
} = mem::replace(fragments, InlineFragments::new());
|
||||||
|
|
||||||
// FIXME(#2264, pcwalton): This is slow because vector shift is broken. :(
|
// FIXME(#2264, pcwalton): This is slow because vector shift is broken. :(
|
||||||
let mut found_nonwhitespace = false;
|
let mut found_nonwhitespace = false;
|
||||||
let mut new_boxes = Vec::new();
|
let mut new_fragments = Vec::new();
|
||||||
for fragment in old_boxes.iter() {
|
for fragment in old_fragments.iter() {
|
||||||
if !found_nonwhitespace && fragment.is_whitespace_only() {
|
if !found_nonwhitespace && fragment.is_whitespace_only() {
|
||||||
debug!("stripping ignorable whitespace from start");
|
debug!("stripping ignorable whitespace from start");
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
found_nonwhitespace = true;
|
found_nonwhitespace = true;
|
||||||
new_boxes.push(fragment.clone())
|
new_fragments.push(fragment.clone())
|
||||||
}
|
}
|
||||||
|
|
||||||
map.fixup(old_boxes.as_slice(), new_boxes.as_slice());
|
map.fixup(old_fragments.as_slice(), new_fragments.as_slice());
|
||||||
*boxes = InlineFragments {
|
*fragments = InlineFragments {
|
||||||
boxes: new_boxes,
|
fragments: new_fragments,
|
||||||
map: map,
|
map: map,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Strips ignorable whitespace from the end of a list of boxes.
|
/// Strips ignorable whitespace from the end of a list of fragments.
|
||||||
fn strip_ignorable_whitespace_from_end(boxes: &mut InlineFragments) {
|
fn strip_ignorable_whitespace_from_end(fragments: &mut InlineFragments) {
|
||||||
if boxes.len() == 0 {
|
if fragments.len() == 0 {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
let InlineFragments {
|
let InlineFragments {
|
||||||
boxes: old_boxes,
|
fragments: old_fragments,
|
||||||
map: mut map
|
map: mut map
|
||||||
} = mem::replace(boxes, InlineFragments::new());
|
} = mem::replace(fragments, InlineFragments::new());
|
||||||
|
|
||||||
let mut new_boxes = old_boxes.clone();
|
let mut new_fragments = old_fragments.clone();
|
||||||
while new_boxes.len() > 0 && new_boxes.as_slice().last().get_ref().is_whitespace_only() {
|
while new_fragments.len() > 0 && new_fragments.as_slice().last().get_ref().is_whitespace_only() {
|
||||||
debug!("stripping ignorable whitespace from end");
|
debug!("stripping ignorable whitespace from end");
|
||||||
drop(new_boxes.pop());
|
drop(new_fragments.pop());
|
||||||
}
|
}
|
||||||
|
|
||||||
map.fixup(old_boxes.as_slice(), new_boxes.as_slice());
|
map.fixup(old_fragments.as_slice(), new_fragments.as_slice());
|
||||||
*boxes = InlineFragments {
|
*fragments = InlineFragments {
|
||||||
boxes: new_boxes,
|
fragments: new_fragments,
|
||||||
map: map,
|
map: map,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@ pub trait LayoutAuxMethods {
|
||||||
impl<'ln> LayoutAuxMethods for LayoutNode<'ln> {
|
impl<'ln> LayoutAuxMethods for LayoutNode<'ln> {
|
||||||
/// Resets layout data and styles for the node.
|
/// Resets layout data and styles for the node.
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): Do this as part of box building instead of in a traversal.
|
/// FIXME(pcwalton): Do this as part of fragment building instead of in a traversal.
|
||||||
fn initialize_layout_data(&self, chan: LayoutChan) {
|
fn initialize_layout_data(&self, chan: LayoutChan) {
|
||||||
let mut layout_data_ref = self.mutate_layout_data();
|
let mut layout_data_ref = self.mutate_layout_data();
|
||||||
match *layout_data_ref {
|
match *layout_data_ref {
|
||||||
|
@ -35,7 +35,7 @@ impl<'ln> LayoutAuxMethods for LayoutNode<'ln> {
|
||||||
|
|
||||||
/// Resets layout data and styles for a Node tree.
|
/// Resets layout data and styles for a Node tree.
|
||||||
///
|
///
|
||||||
/// FIXME(pcwalton): Do this as part of box building instead of in a traversal.
|
/// FIXME(pcwalton): Do this as part of fragment building instead of in a traversal.
|
||||||
fn initialize_style_for_subtree(&self, chan: LayoutChan) {
|
fn initialize_style_for_subtree(&self, chan: LayoutChan) {
|
||||||
for n in self.traverse_preorder() {
|
for n in self.traverse_preorder() {
|
||||||
n.initialize_layout_data(chan.clone());
|
n.initialize_layout_data(chan.clone());
|
||||||
|
|
|
@ -320,7 +320,7 @@ impl Floats {
|
||||||
max_height.map(|h| h + self.offset.y)
|
max_height.map(|h| h + self.offset.y)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given placement information, finds the closest place a box can be positioned without
|
/// Given placement information, finds the closest place a fragment can be positioned without
|
||||||
/// colliding with any floats.
|
/// colliding with any floats.
|
||||||
pub fn place_between_floats(&self, info: &PlacementInfo) -> Rect<Au> {
|
pub fn place_between_floats(&self, info: &PlacementInfo) -> Rect<Au> {
|
||||||
debug!("place_between_floats: Placing object with width {} and height {}",
|
debug!("place_between_floats: Placing object with width {} and height {}",
|
||||||
|
|
|
@ -8,8 +8,8 @@
|
||||||
/// inline and block layout.
|
/// inline and block layout.
|
||||||
///
|
///
|
||||||
/// Flows are interior nodes in the layout tree and correspond closely to *flow contexts* in the
|
/// Flows are interior nodes in the layout tree and correspond closely to *flow contexts* in the
|
||||||
/// CSS specification. Flows are responsible for positioning their child flow contexts and boxes.
|
/// CSS specification. Flows are responsible for positioning their child flow contexts and fragments.
|
||||||
/// Flows have purpose-specific fields, such as auxiliary line box structs, out-of-flow child
|
/// Flows have purpose-specific fields, such as auxiliary line fragment structs, out-of-flow child
|
||||||
/// lists, and so on.
|
/// lists, and so on.
|
||||||
///
|
///
|
||||||
/// Currently, the important types of flows are:
|
/// Currently, the important types of flows are:
|
||||||
|
@ -21,7 +21,7 @@
|
||||||
/// the viewport.
|
/// the viewport.
|
||||||
///
|
///
|
||||||
/// * `InlineFlow`: A flow that establishes an inline context. It has a flat list of child
|
/// * `InlineFlow`: A flow that establishes an inline context. It has a flat list of child
|
||||||
/// boxes/flows that are subject to inline layout and line breaking and structs to represent
|
/// fragments/flows that are subject to inline layout and line breaking and structs to represent
|
||||||
/// line breaks and mapping to CSS boxes, for the purpose of handling `getClientRects()` and
|
/// line breaks and mapping to CSS boxes, for the purpose of handling `getClientRects()` and
|
||||||
/// similar methods.
|
/// similar methods.
|
||||||
|
|
||||||
|
@ -844,12 +844,12 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
|
||||||
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> Box<Flow:Share> {
|
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> Box<Flow:Share> {
|
||||||
match self.class() {
|
match self.class() {
|
||||||
TableFlowClass | TableRowGroupFlowClass => {
|
TableFlowClass | TableRowGroupFlowClass => {
|
||||||
let box_ = Fragment::new_anonymous_table_box(node, TableRowFragment);
|
let fragment = Fragment::new_anonymous_table_fragment(node, TableRowFragment);
|
||||||
box TableRowFlow::from_node_and_box(node, box_) as Box<Flow:Share>
|
box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>
|
||||||
},
|
},
|
||||||
TableRowFlowClass => {
|
TableRowFlowClass => {
|
||||||
let box_ = Fragment::new_anonymous_table_box(node, TableCellFragment);
|
let fragment = Fragment::new_anonymous_table_fragment(node, TableCellFragment);
|
||||||
box TableCellFlow::from_node_and_box(node, box_) as Box<Flow:Share>
|
box TableCellFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
fail!("no need to generate a missing child")
|
fail!("no need to generate a missing child")
|
||||||
|
@ -869,8 +869,8 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
|
||||||
|
|
||||||
/// Return true if this flow is a Block Container.
|
/// Return true if this flow is a Block Container.
|
||||||
///
|
///
|
||||||
/// Except for table boxes and replaced elements, block-level boxes (`BlockFlow`) are
|
/// Except for table fragments and replaced elements, block-level fragments (`BlockFlow`) are
|
||||||
/// also block container boxes.
|
/// also block container fragments.
|
||||||
/// Non-replaced inline blocks and non-replaced table cells are also block
|
/// Non-replaced inline blocks and non-replaced table cells are also block
|
||||||
/// containers.
|
/// containers.
|
||||||
fn is_block_container(self) -> bool {
|
fn is_block_container(self) -> bool {
|
||||||
|
@ -1065,7 +1065,7 @@ impl MutableOwnedFlowUtils for Box<Flow:Share> {
|
||||||
let _ = base.parallel.children_and_absolute_descendant_count.fetch_add(1, Relaxed);
|
let _ = base.parallel.children_and_absolute_descendant_count.fetch_add(1, Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finishes a flow. Once a flow is finished, no more child flows or boxes may be added to it.
|
/// Finishes a flow. Once a flow is finished, no more child flows or fragments may be added to it.
|
||||||
/// This will normally run the bubble-widths (minimum and preferred -- i.e. intrinsic -- width)
|
/// This will normally run the bubble-widths (minimum and preferred -- i.e. intrinsic -- width)
|
||||||
/// calculation, unless the global `bubble_widths_separately` flag is on.
|
/// calculation, unless the global `bubble_widths_separately` flag is on.
|
||||||
///
|
///
|
||||||
|
|
|
@ -33,39 +33,39 @@ use style::computed_values::{text_align, vertical_align, white_space};
|
||||||
use style::ComputedValues;
|
use style::ComputedValues;
|
||||||
use sync::Arc;
|
use sync::Arc;
|
||||||
|
|
||||||
/// Lineboxes are represented as offsets into the child list, rather than
|
/// `LineFragment`s are represented as offsets into the child list, rather than
|
||||||
/// as an object that "owns" boxes. Choosing a different set of line
|
/// as an object that "owns" fragments. Choosing a different set of line
|
||||||
/// breaks requires a new list of offsets, and possibly some splitting and
|
/// breaks requires a new list of offsets, and possibly some splitting and
|
||||||
/// merging of TextFragments.
|
/// merging of TextFragments.
|
||||||
///
|
///
|
||||||
/// A similar list will keep track of the mapping between CSS boxes and
|
/// A similar list will keep track of the mapping between CSS fragments and
|
||||||
/// the corresponding boxes in the inline flow.
|
/// the corresponding fragments in the inline flow.
|
||||||
///
|
///
|
||||||
/// After line breaks are determined, render boxes in the inline flow may
|
/// After line breaks are determined, render fragments in the inline flow may
|
||||||
/// overlap visually. For example, in the case of nested inline CSS boxes,
|
/// overlap visually. For example, in the case of nested inline CSS fragments,
|
||||||
/// outer inlines must be at least as large as the inner inlines, for
|
/// outer inlines must be at least as large as the inner inlines, for
|
||||||
/// purposes of drawing noninherited things like backgrounds, borders,
|
/// purposes of drawing noninherited things like backgrounds, borders,
|
||||||
/// outlines.
|
/// outlines.
|
||||||
///
|
///
|
||||||
/// N.B. roc has an alternative design where the list instead consists of
|
/// N.B. roc has an alternative design where the list instead consists of
|
||||||
/// things like "start outer box, text, start inner box, text, end inner
|
/// things like "start outer fragment, text, start inner fragment, text, end inner
|
||||||
/// box, text, end outer box, text". This seems a little complicated to
|
/// fragment, text, end outer fragment, text". This seems a little complicated to
|
||||||
/// serve as the starting point, but the current design doesn't make it
|
/// serve as the starting point, but the current design doesn't make it
|
||||||
/// hard to try out that alternative.
|
/// hard to try out that alternative.
|
||||||
///
|
///
|
||||||
/// Line boxes also contain some metadata used during line breaking. The
|
/// Line fragments also contain some metadata used during line breaking. The
|
||||||
/// green zone is the area that the line can expand to before it collides
|
/// green zone is the area that the line can expand to before it collides
|
||||||
/// with a float or a horizontal wall of the containing block. The top
|
/// with a float or a horizontal wall of the containing block. The top
|
||||||
/// left corner of the green zone is the same as that of the line, but
|
/// left corner of the green zone is the same as that of the line, but
|
||||||
/// the green zone can be taller and wider than the line itself.
|
/// the green zone can be taller and wider than the line itself.
|
||||||
pub struct LineBox {
|
pub struct LineFragment {
|
||||||
pub range: Range<LineIndices>,
|
pub range: Range<LineIndices>,
|
||||||
pub bounds: Rect<Au>,
|
pub bounds: Rect<Au>,
|
||||||
pub green_zone: Size2D<Au>
|
pub green_zone: Size2D<Au>
|
||||||
}
|
}
|
||||||
|
|
||||||
int_range_index! {
|
int_range_index! {
|
||||||
#[doc = "The index of a box fragment in a flattened vector of DOM elements."]
|
#[doc = "The index of a fragment in a flattened vector of DOM elements."]
|
||||||
struct FragmentIndex(int)
|
struct FragmentIndex(int)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,8 +97,7 @@ int_range_index! {
|
||||||
/// ~~~
|
/// ~~~
|
||||||
#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Zero)]
|
#[deriving(Clone, Eq, Ord, TotalEq, TotalOrd, Zero)]
|
||||||
pub struct LineIndices {
|
pub struct LineIndices {
|
||||||
/// The index of a box fragment into the flattened vector of DOM
|
/// The index of a fragment into the flattened vector of DOM elements.
|
||||||
/// elements.
|
|
||||||
///
|
///
|
||||||
/// For example, given the HTML below:
|
/// For example, given the HTML below:
|
||||||
///
|
///
|
||||||
|
@ -199,22 +198,22 @@ pub fn each_char_index(range: &Range<LineIndices>) -> EachIndex<int, CharIndex>
|
||||||
range::each_index(range.begin().char_index, range.end().char_index)
|
range::each_index(range.begin().char_index, range.end().char_index)
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LineboxScanner {
|
struct LineFragmentScanner {
|
||||||
pub floats: Floats,
|
pub floats: Floats,
|
||||||
pub new_boxes: Vec<Fragment>,
|
pub new_fragments: Vec<Fragment>,
|
||||||
pub work_list: RingBuf<Fragment>,
|
pub work_list: RingBuf<Fragment>,
|
||||||
pub pending_line: LineBox,
|
pub pending_line: LineFragment,
|
||||||
pub lines: Vec<LineBox>,
|
pub lines: Vec<LineFragment>,
|
||||||
pub cur_y: Au,
|
pub cur_y: Au,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LineboxScanner {
|
impl LineFragmentScanner {
|
||||||
pub fn new(float_ctx: Floats) -> LineboxScanner {
|
pub fn new(float_ctx: Floats) -> LineFragmentScanner {
|
||||||
LineboxScanner {
|
LineFragmentScanner {
|
||||||
floats: float_ctx,
|
floats: float_ctx,
|
||||||
new_boxes: Vec::new(),
|
new_fragments: Vec::new(),
|
||||||
work_list: RingBuf::new(),
|
work_list: RingBuf::new(),
|
||||||
pending_line: LineBox {
|
pending_line: LineFragment {
|
||||||
range: Range::empty(),
|
range: Range::empty(),
|
||||||
bounds: Rect(Point2D(Au::new(0), Au::new(0)), Size2D(Au::new(0), Au::new(0))),
|
bounds: Rect(Point2D(Au::new(0), Au::new(0)), Size2D(Au::new(0), Au::new(0))),
|
||||||
green_zone: Size2D(Au::new(0), Au::new(0))
|
green_zone: Size2D(Au::new(0), Au::new(0))
|
||||||
|
@ -229,14 +228,14 @@ impl LineboxScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_scanner(&mut self) {
|
fn reset_scanner(&mut self) {
|
||||||
debug!("Resetting line box scanner's state for flow.");
|
debug!("Resetting LineFragmentScanner's state for flow.");
|
||||||
self.lines = Vec::new();
|
self.lines = Vec::new();
|
||||||
self.new_boxes = Vec::new();
|
self.new_fragments = Vec::new();
|
||||||
self.cur_y = Au(0);
|
self.cur_y = Au(0);
|
||||||
self.reset_linebox();
|
self.reset_line_fragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn reset_linebox(&mut self) {
|
fn reset_line_fragment(&mut self) {
|
||||||
self.pending_line.range.reset(num::zero(), num::zero());
|
self.pending_line.range.reset(num::zero(), num::zero());
|
||||||
self.pending_line.bounds = Rect(Point2D(Au::new(0), self.cur_y), Size2D(Au::new(0), Au::new(0)));
|
self.pending_line.bounds = Rect(Point2D(Au::new(0), self.cur_y), Size2D(Au::new(0), Au::new(0)));
|
||||||
self.pending_line.green_zone = Size2D(Au::new(0), Au::new(0))
|
self.pending_line.green_zone = Size2D(Au::new(0), Au::new(0))
|
||||||
|
@ -247,52 +246,52 @@ impl LineboxScanner {
|
||||||
|
|
||||||
// Swap out temporarily.
|
// Swap out temporarily.
|
||||||
let InlineFragments {
|
let InlineFragments {
|
||||||
boxes: old_boxes,
|
fragments: old_fragments,
|
||||||
map: mut map
|
map: mut map
|
||||||
} = mem::replace(&mut flow.boxes, InlineFragments::new());
|
} = mem::replace(&mut flow.fragments, InlineFragments::new());
|
||||||
|
|
||||||
let mut old_box_iter = old_boxes.iter();
|
let mut old_fragment_iter = old_fragments.iter();
|
||||||
loop {
|
loop {
|
||||||
// acquire the next box to lay out from work list or box list
|
// acquire the next fragment to lay out from work list or fragment list
|
||||||
let cur_box = if self.work_list.is_empty() {
|
let cur_fragment = if self.work_list.is_empty() {
|
||||||
match old_box_iter.next() {
|
match old_fragment_iter.next() {
|
||||||
None => break,
|
None => break,
|
||||||
Some(fragment) => {
|
Some(fragment) => {
|
||||||
debug!("LineboxScanner: Working with fragment from flow: b{}",
|
debug!("LineFragmentScanner: Working with fragment from flow: b{}",
|
||||||
fragment.debug_id());
|
fragment.debug_id());
|
||||||
(*fragment).clone()
|
(*fragment).clone()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
let fragment = self.work_list.pop_front().unwrap();
|
let fragment = self.work_list.pop_front().unwrap();
|
||||||
debug!("LineboxScanner: Working with box from work list: b{}",
|
debug!("LineFragmentScanner: Working with fragment from work list: b{}",
|
||||||
fragment.debug_id());
|
fragment.debug_id());
|
||||||
fragment
|
fragment
|
||||||
};
|
};
|
||||||
|
|
||||||
let box_was_appended = match cur_box.white_space() {
|
let fragment_was_appended = match cur_fragment.white_space() {
|
||||||
white_space::normal => self.try_append_to_line(cur_box, flow),
|
white_space::normal => self.try_append_to_line(cur_fragment, flow),
|
||||||
white_space::pre => self.try_append_to_line_by_new_line(cur_box),
|
white_space::pre => self.try_append_to_line_by_new_line(cur_fragment),
|
||||||
};
|
};
|
||||||
|
|
||||||
if !box_was_appended {
|
if !fragment_was_appended {
|
||||||
debug!("LineboxScanner: Fragment wasn't appended, because line {:u} was full.",
|
debug!("LineFragmentScanner: Fragment wasn't appended, because line {:u} was full.",
|
||||||
self.lines.len());
|
self.lines.len());
|
||||||
self.flush_current_line();
|
self.flush_current_line();
|
||||||
} else {
|
} else {
|
||||||
debug!("LineboxScanner: appended a box to line {:u}", self.lines.len());
|
debug!("LineFragmentScanner: appended a fragment to line {:u}", self.lines.len());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if self.pending_line.range.length() > num::zero() {
|
if self.pending_line.range.length() > num::zero() {
|
||||||
debug!("LineboxScanner: Partially full linebox {:u} left at end of scanning.",
|
debug!("LineFragmentScanner: Partially full line_fragment {:u} left at end of scanning.",
|
||||||
self.lines.len());
|
self.lines.len());
|
||||||
self.flush_current_line();
|
self.flush_current_line();
|
||||||
}
|
}
|
||||||
|
|
||||||
map.fixup(old_boxes.as_slice(), self.new_boxes.as_slice());
|
map.fixup(old_fragments.as_slice(), self.new_fragments.as_slice());
|
||||||
flow.boxes = InlineFragments {
|
flow.fragments = InlineFragments {
|
||||||
boxes: mem::replace(&mut self.new_boxes, Vec::new()),
|
fragments: mem::replace(&mut self.new_fragments, Vec::new()),
|
||||||
map: map,
|
map: map,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -300,49 +299,49 @@ impl LineboxScanner {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn flush_current_line(&mut self) {
|
fn flush_current_line(&mut self) {
|
||||||
debug!("LineboxScanner: Flushing line {:u}: {:?}",
|
debug!("LineFragmentScanner: Flushing line {:u}: {:?}",
|
||||||
self.lines.len(), self.pending_line);
|
self.lines.len(), self.pending_line);
|
||||||
|
|
||||||
// clear line and add line mapping
|
// clear line and add line mapping
|
||||||
debug!("LineboxScanner: Saving information for flushed line {:u}.", self.lines.len());
|
debug!("LineFragmentScanner: Saving information for flushed line {:u}.", self.lines.len());
|
||||||
self.lines.push(self.pending_line);
|
self.lines.push(self.pending_line);
|
||||||
self.cur_y = self.pending_line.bounds.origin.y + self.pending_line.bounds.size.height;
|
self.cur_y = self.pending_line.bounds.origin.y + self.pending_line.bounds.size.height;
|
||||||
self.reset_linebox();
|
self.reset_line_fragment();
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(eatkinson): this assumes that the tallest box in the line determines the line height
|
// FIXME(eatkinson): this assumes that the tallest fragment in the line determines the line height
|
||||||
// This might not be the case with some weird text fonts.
|
// This might not be the case with some weird text fonts.
|
||||||
fn new_height_for_line(&self, new_box: &Fragment) -> Au {
|
fn new_height_for_line(&self, new_fragment: &Fragment) -> Au {
|
||||||
let box_height = new_box.content_height();
|
let fragment_height = new_fragment.content_height();
|
||||||
if box_height > self.pending_line.bounds.size.height {
|
if fragment_height > self.pending_line.bounds.size.height {
|
||||||
box_height
|
fragment_height
|
||||||
} else {
|
} else {
|
||||||
self.pending_line.bounds.size.height
|
self.pending_line.bounds.size.height
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes the position of a line that has only the provided box. Returns the bounding rect
|
/// Computes the position of a line that has only the provided fragment. Returns the bounding
|
||||||
/// of the line's green zone (whose origin coincides with the line's origin) and the actual
|
/// rect of the line's green zone (whose origin coincides with the line's origin) and the actual
|
||||||
/// width of the first box after splitting.
|
/// width of the first fragment after splitting.
|
||||||
fn initial_line_placement(&self, first_box: &Fragment, ceiling: Au, flow: &mut InlineFlow)
|
fn initial_line_placement(&self, first_fragment: &Fragment, ceiling: Au, flow: &mut InlineFlow)
|
||||||
-> (Rect<Au>, Au) {
|
-> (Rect<Au>, Au) {
|
||||||
debug!("LineboxScanner: Trying to place first box of line {}", self.lines.len());
|
debug!("LineFragmentScanner: Trying to place first fragment of line {}", self.lines.len());
|
||||||
|
|
||||||
let first_box_size = first_box.border_box.size;
|
let first_fragment_size = first_fragment.border_box.size;
|
||||||
let splittable = first_box.can_split();
|
let splittable = first_fragment.can_split();
|
||||||
debug!("LineboxScanner: box size: {}, splittable: {}", first_box_size, splittable);
|
debug!("LineFragmentScanner: fragment size: {}, splittable: {}", first_fragment_size, splittable);
|
||||||
|
|
||||||
// Initally, pretend a splittable box has 0 width.
|
// Initally, pretend a splittable fragment has 0 width.
|
||||||
// We will move it later if it has nonzero width
|
// We will move it later if it has nonzero width
|
||||||
// and that causes problems.
|
// and that causes problems.
|
||||||
let placement_width = if splittable {
|
let placement_width = if splittable {
|
||||||
Au::new(0)
|
Au::new(0)
|
||||||
} else {
|
} else {
|
||||||
first_box_size.width
|
first_fragment_size.width
|
||||||
};
|
};
|
||||||
|
|
||||||
let info = PlacementInfo {
|
let info = PlacementInfo {
|
||||||
size: Size2D(placement_width, first_box_size.height),
|
size: Size2D(placement_width, first_fragment_size.height),
|
||||||
ceiling: ceiling,
|
ceiling: ceiling,
|
||||||
max_width: flow.base.position.size.width,
|
max_width: flow.base.position.size.width,
|
||||||
kind: FloatLeft,
|
kind: FloatLeft,
|
||||||
|
@ -350,33 +349,33 @@ impl LineboxScanner {
|
||||||
|
|
||||||
let line_bounds = self.floats.place_between_floats(&info);
|
let line_bounds = self.floats.place_between_floats(&info);
|
||||||
|
|
||||||
debug!("LineboxScanner: found position for line: {} using placement_info: {:?}",
|
debug!("LineFragmentScanner: found position for line: {} using placement_info: {:?}",
|
||||||
line_bounds,
|
line_bounds,
|
||||||
info);
|
info);
|
||||||
|
|
||||||
// Simple case: if the box fits, then we can stop here
|
// Simple case: if the fragment fits, then we can stop here
|
||||||
if line_bounds.size.width > first_box_size.width {
|
if line_bounds.size.width > first_fragment_size.width {
|
||||||
debug!("LineboxScanner: case=box fits");
|
debug!("LineFragmentScanner: case=fragment fits");
|
||||||
return (line_bounds, first_box_size.width);
|
return (line_bounds, first_fragment_size.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not, but we can't split the box, then we'll place
|
// If not, but we can't split the fragment, then we'll place
|
||||||
// the line here and it will overflow.
|
// the line here and it will overflow.
|
||||||
if !splittable {
|
if !splittable {
|
||||||
debug!("LineboxScanner: case=line doesn't fit, but is unsplittable");
|
debug!("LineFragmentScanner: case=line doesn't fit, but is unsplittable");
|
||||||
return (line_bounds, first_box_size.width);
|
return (line_bounds, first_fragment_size.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("LineboxScanner: used to call split_to_width here");
|
debug!("LineFragmentScanner: used to call split_to_width here");
|
||||||
return (line_bounds, first_box_size.width);
|
return (line_bounds, first_fragment_size.width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Performs float collision avoidance. This is called when adding a box is going to increase
|
/// Performs float collision avoidance. This is called when adding a fragment is going to increase
|
||||||
/// the height, and because of that we will collide with some floats.
|
/// the height, and because of that we will collide with some floats.
|
||||||
///
|
///
|
||||||
/// We have two options here:
|
/// We have two options here:
|
||||||
/// 1) Move the entire line so that it doesn't collide any more.
|
/// 1) Move the entire line so that it doesn't collide any more.
|
||||||
/// 2) Break the line and put the new box on the next line.
|
/// 2) Break the line and put the new fragment on the next line.
|
||||||
///
|
///
|
||||||
/// The problem with option 1 is that we might move the line and then wind up breaking anyway,
|
/// The problem with option 1 is that we might move the line and then wind up breaking anyway,
|
||||||
/// which violates the standard.
|
/// which violates the standard.
|
||||||
|
@ -386,93 +385,93 @@ impl LineboxScanner {
|
||||||
///
|
///
|
||||||
/// Returns false if and only if we should break the line.
|
/// Returns false if and only if we should break the line.
|
||||||
fn avoid_floats(&mut self,
|
fn avoid_floats(&mut self,
|
||||||
in_box: Fragment,
|
in_fragment: Fragment,
|
||||||
flow: &mut InlineFlow,
|
flow: &mut InlineFlow,
|
||||||
new_height: Au,
|
new_height: Au,
|
||||||
line_is_empty: bool)
|
line_is_empty: bool)
|
||||||
-> bool {
|
-> bool {
|
||||||
debug!("LineboxScanner: entering float collision avoider!");
|
debug!("LineFragmentScanner: entering float collision avoider!");
|
||||||
|
|
||||||
// First predict where the next line is going to be.
|
// First predict where the next line is going to be.
|
||||||
let this_line_y = self.pending_line.bounds.origin.y;
|
let this_line_y = self.pending_line.bounds.origin.y;
|
||||||
let (next_line, first_box_width) = self.initial_line_placement(&in_box, this_line_y, flow);
|
let (next_line, first_fragment_width) = self.initial_line_placement(&in_fragment, this_line_y, flow);
|
||||||
let next_green_zone = next_line.size;
|
let next_green_zone = next_line.size;
|
||||||
|
|
||||||
let new_width = self.pending_line.bounds.size.width + first_box_width;
|
let new_width = self.pending_line.bounds.size.width + first_fragment_width;
|
||||||
|
|
||||||
// Now, see if everything can fit at the new location.
|
// Now, see if everything can fit at the new location.
|
||||||
if next_green_zone.width >= new_width && next_green_zone.height >= new_height {
|
if next_green_zone.width >= new_width && next_green_zone.height >= new_height {
|
||||||
debug!("LineboxScanner: case=adding box collides vertically with floats: moving line");
|
debug!("LineFragmentScanner: case=adding fragment collides vertically with floats: moving line");
|
||||||
|
|
||||||
self.pending_line.bounds.origin = next_line.origin;
|
self.pending_line.bounds.origin = next_line.origin;
|
||||||
self.pending_line.green_zone = next_green_zone;
|
self.pending_line.green_zone = next_green_zone;
|
||||||
|
|
||||||
assert!(!line_is_empty, "Non-terminating line breaking");
|
assert!(!line_is_empty, "Non-terminating line breaking");
|
||||||
self.work_list.push_front(in_box);
|
self.work_list.push_front(in_fragment);
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("LineboxScanner: case=adding box collides vertically with floats: breaking line");
|
debug!("LineFragmentScanner: case=adding fragment collides vertically with floats: breaking line");
|
||||||
self.work_list.push_front(in_box);
|
self.work_list.push_front(in_fragment);
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn try_append_to_line_by_new_line(&mut self, in_box: Fragment) -> bool {
|
fn try_append_to_line_by_new_line(&mut self, in_fragment: Fragment) -> bool {
|
||||||
if in_box.new_line_pos.len() == 0 {
|
if in_fragment.new_line_pos.len() == 0 {
|
||||||
debug!("LineboxScanner: Did not find a new-line character, so pushing the box to \
|
debug!("LineFragmentScanner: Did not find a new-line character, so pushing the fragment to \
|
||||||
the line without splitting.");
|
the line without splitting.");
|
||||||
self.push_box_to_line(in_box);
|
self.push_fragment_to_line(in_fragment);
|
||||||
true
|
true
|
||||||
} else {
|
} else {
|
||||||
debug!("LineboxScanner: Found a new-line character, so splitting theline.");
|
debug!("LineFragmentScanner: Found a new-line character, so splitting theline.");
|
||||||
match in_box.find_split_info_by_new_line() {
|
match in_fragment.find_split_info_by_new_line() {
|
||||||
Some((left, right, run)) => {
|
Some((left, right, run)) => {
|
||||||
// TODO(bjz): Remove box splitting
|
// TODO(bjz): Remove fragment splitting
|
||||||
let split_box = |split: SplitInfo| {
|
let split_fragment = |split: SplitInfo| {
|
||||||
let info = ScannedTextFragmentInfo::new(run.clone(), split.range);
|
let info = ScannedTextFragmentInfo::new(run.clone(), split.range);
|
||||||
let specific = ScannedTextFragment(info);
|
let specific = ScannedTextFragment(info);
|
||||||
let size = Size2D(split.width, in_box.border_box.size.height);
|
let size = Size2D(split.width, in_fragment.border_box.size.height);
|
||||||
in_box.transform(size, specific)
|
in_fragment.transform(size, specific)
|
||||||
};
|
};
|
||||||
|
|
||||||
debug!("LineboxScanner: Pushing the box to the left of the new-line character \
|
debug!("LineFragmentScanner: Pushing the fragment to the left of the new-line character \
|
||||||
to the line.");
|
to the line.");
|
||||||
let mut left = split_box(left);
|
let mut left = split_fragment(left);
|
||||||
left.new_line_pos = vec!();
|
left.new_line_pos = vec!();
|
||||||
self.push_box_to_line(left);
|
self.push_fragment_to_line(left);
|
||||||
|
|
||||||
for right in right.move_iter() {
|
for right in right.move_iter() {
|
||||||
debug!("LineboxScanner: Deferring the box to the right of the new-line \
|
debug!("LineFragmentScanner: Deferring the fragment to the right of the new-line \
|
||||||
character to the line.");
|
character to the line.");
|
||||||
let mut right = split_box(right);
|
let mut right = split_fragment(right);
|
||||||
right.new_line_pos = in_box.new_line_pos.clone();
|
right.new_line_pos = in_fragment.new_line_pos.clone();
|
||||||
self.work_list.push_front(right);
|
self.work_list.push_front(right);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
None => {
|
None => {
|
||||||
error!("LineboxScanner: This split case makes no sense!")
|
error!("LineFragmentScanner: This split case makes no sense!")
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tries to append the given box to the line, splitting it if necessary. Returns false only if
|
/// Tries to append the given fragment to the line, splitting it if necessary. Returns false only if
|
||||||
/// we should break the line.
|
/// we should break the line.
|
||||||
fn try_append_to_line(&mut self, in_box: Fragment, flow: &mut InlineFlow) -> bool {
|
fn try_append_to_line(&mut self, in_fragment: Fragment, flow: &mut InlineFlow) -> bool {
|
||||||
let line_is_empty = self.pending_line.range.length() == num::zero();
|
let line_is_empty = self.pending_line.range.length() == num::zero();
|
||||||
if line_is_empty {
|
if line_is_empty {
|
||||||
let (line_bounds, _) = self.initial_line_placement(&in_box, self.cur_y, flow);
|
let (line_bounds, _) = self.initial_line_placement(&in_fragment, self.cur_y, flow);
|
||||||
self.pending_line.bounds.origin = line_bounds.origin;
|
self.pending_line.bounds.origin = line_bounds.origin;
|
||||||
self.pending_line.green_zone = line_bounds.size;
|
self.pending_line.green_zone = line_bounds.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("LineboxScanner: Trying to append box to line {:u} (box size: {}, green zone: \
|
debug!("LineFragmentScanner: Trying to append fragment to line {:u} (fragment size: {}, green zone: \
|
||||||
{}): {}",
|
{}): {}",
|
||||||
self.lines.len(),
|
self.lines.len(),
|
||||||
in_box.border_box.size,
|
in_fragment.border_box.size,
|
||||||
self.pending_line.green_zone,
|
self.pending_line.green_zone,
|
||||||
in_box);
|
in_fragment);
|
||||||
|
|
||||||
let green_zone = self.pending_line.green_zone;
|
let green_zone = self.pending_line.green_zone;
|
||||||
|
|
||||||
|
@ -480,87 +479,87 @@ impl LineboxScanner {
|
||||||
// `green_zone.height < self.pending_line.bounds.size.height`, then we committed a line
|
// `green_zone.height < self.pending_line.bounds.size.height`, then we committed a line
|
||||||
// that overlaps with floats.
|
// that overlaps with floats.
|
||||||
|
|
||||||
let new_height = self.new_height_for_line(&in_box);
|
let new_height = self.new_height_for_line(&in_fragment);
|
||||||
if new_height > green_zone.height {
|
if new_height > green_zone.height {
|
||||||
// Uh-oh. Float collision imminent. Enter the float collision avoider
|
// Uh-oh. Float collision imminent. Enter the float collision avoider
|
||||||
return self.avoid_floats(in_box, flow, new_height, line_is_empty)
|
return self.avoid_floats(in_fragment, flow, new_height, line_is_empty)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're not going to overflow the green zone vertically, we might still do so
|
// If we're not going to overflow the green zone vertically, we might still do so
|
||||||
// horizontally. We'll try to place the whole box on this line and break somewhere if it
|
// horizontally. We'll try to place the whole fragment on this line and break somewhere if it
|
||||||
// doesn't fit.
|
// doesn't fit.
|
||||||
|
|
||||||
let new_width = self.pending_line.bounds.size.width + in_box.border_box.size.width;
|
let new_width = self.pending_line.bounds.size.width + in_fragment.border_box.size.width;
|
||||||
if new_width <= green_zone.width {
|
if new_width <= green_zone.width {
|
||||||
debug!("LineboxScanner: case=box fits without splitting");
|
debug!("LineFragmentScanner: case=fragment fits without splitting");
|
||||||
self.push_box_to_line(in_box);
|
self.push_fragment_to_line(in_fragment);
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
if !in_box.can_split() {
|
if !in_fragment.can_split() {
|
||||||
// TODO(eatkinson, issue #224): Signal that horizontal overflow happened?
|
// TODO(eatkinson, issue #224): Signal that horizontal overflow happened?
|
||||||
if line_is_empty {
|
if line_is_empty {
|
||||||
debug!("LineboxScanner: case=box can't split and line {:u} is empty, so \
|
debug!("LineFragmentScanner: case=fragment can't split and line {:u} is empty, so \
|
||||||
overflowing.",
|
overflowing.",
|
||||||
self.lines.len());
|
self.lines.len());
|
||||||
self.push_box_to_line(in_box);
|
self.push_fragment_to_line(in_fragment);
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let available_width = green_zone.width - self.pending_line.bounds.size.width;
|
let available_width = green_zone.width - self.pending_line.bounds.size.width;
|
||||||
let split = in_box.find_split_info_for_width(CharIndex(0), available_width, line_is_empty);
|
let split = in_fragment.find_split_info_for_width(CharIndex(0), available_width, line_is_empty);
|
||||||
match split.map(|(left, right, run)| {
|
match split.map(|(left, right, run)| {
|
||||||
// TODO(bjz): Remove box splitting
|
// TODO(bjz): Remove fragment splitting
|
||||||
let split_box = |split: SplitInfo| {
|
let split_fragment = |split: SplitInfo| {
|
||||||
let info = ScannedTextFragmentInfo::new(run.clone(), split.range);
|
let info = ScannedTextFragmentInfo::new(run.clone(), split.range);
|
||||||
let specific = ScannedTextFragment(info);
|
let specific = ScannedTextFragment(info);
|
||||||
let size = Size2D(split.width, in_box.border_box.size.height);
|
let size = Size2D(split.width, in_fragment.border_box.size.height);
|
||||||
in_box.transform(size, specific)
|
in_fragment.transform(size, specific)
|
||||||
};
|
};
|
||||||
|
|
||||||
(left.map(|x| { debug!("LineboxScanner: Left split {}", x); split_box(x) }),
|
(left.map(|x| { debug!("LineFragmentScanner: Left split {}", x); split_fragment(x) }),
|
||||||
right.map(|x| { debug!("LineboxScanner: Right split {}", x); split_box(x) }))
|
right.map(|x| { debug!("LineFragmentScanner: Right split {}", x); split_fragment(x) }))
|
||||||
}) {
|
}) {
|
||||||
None => {
|
None => {
|
||||||
debug!("LineboxScanner: Tried to split unsplittable render box! Deferring to next \
|
debug!("LineFragmentScanner: Tried to split unsplittable render fragment! Deferring to next \
|
||||||
line. {}", in_box);
|
line. {}", in_fragment);
|
||||||
self.work_list.push_front(in_box);
|
self.work_list.push_front(in_fragment);
|
||||||
false
|
false
|
||||||
},
|
},
|
||||||
Some((Some(left_box), Some(right_box))) => {
|
Some((Some(left_fragment), Some(right_fragment))) => {
|
||||||
debug!("LineboxScanner: Line break found! Pushing left box to line and deferring \
|
debug!("LineFragmentScanner: Line break found! Pushing left fragment to line and deferring \
|
||||||
right box to next line.");
|
right fragment to next line.");
|
||||||
self.push_box_to_line(left_box);
|
self.push_fragment_to_line(left_fragment);
|
||||||
self.work_list.push_front(right_box);
|
self.work_list.push_front(right_fragment);
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
Some((Some(left_box), None)) => {
|
Some((Some(left_fragment), None)) => {
|
||||||
debug!("LineboxScanner: Pushing left box to line.");
|
debug!("LineFragmentScanner: Pushing left fragment to line.");
|
||||||
self.push_box_to_line(left_box);
|
self.push_fragment_to_line(left_fragment);
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
Some((None, Some(right_box))) => {
|
Some((None, Some(right_fragment))) => {
|
||||||
debug!("LineboxScanner: Pushing right box to line.");
|
debug!("LineFragmentScanner: Pushing right fragment to line.");
|
||||||
self.push_box_to_line(right_box);
|
self.push_fragment_to_line(right_fragment);
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
Some((None, None)) => {
|
Some((None, None)) => {
|
||||||
error!("LineboxScanner: This split case makes no sense!");
|
error!("LineFragmentScanner: This split case makes no sense!");
|
||||||
true
|
true
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// An unconditional push
|
// An unconditional push
|
||||||
fn push_box_to_line(&mut self, box_: Fragment) {
|
fn push_fragment_to_line(&mut self, fragment: Fragment) {
|
||||||
debug!("LineboxScanner: Pushing box {} to line {:u}", box_.debug_id(), self.lines.len());
|
debug!("LineFragmentScanner: Pushing fragment {} to line {:u}", fragment.debug_id(), self.lines.len());
|
||||||
|
|
||||||
if self.pending_line.range.length() == num::zero() {
|
if self.pending_line.range.length() == num::zero() {
|
||||||
assert!(self.new_boxes.len() <= (u16::MAX as uint));
|
assert!(self.new_fragments.len() <= (u16::MAX as uint));
|
||||||
self.pending_line.range.reset(
|
self.pending_line.range.reset(
|
||||||
LineIndices {
|
LineIndices {
|
||||||
fragment_index: FragmentIndex(self.new_boxes.len() as int),
|
fragment_index: FragmentIndex(self.new_fragments.len() as int),
|
||||||
char_index: CharIndex(0) /* unused for now */,
|
char_index: CharIndex(0) /* unused for now */,
|
||||||
},
|
},
|
||||||
num::zero()
|
num::zero()
|
||||||
|
@ -571,14 +570,14 @@ impl LineboxScanner {
|
||||||
char_index: CharIndex(0) /* unused for now */ ,
|
char_index: CharIndex(0) /* unused for now */ ,
|
||||||
});
|
});
|
||||||
self.pending_line.bounds.size.width = self.pending_line.bounds.size.width +
|
self.pending_line.bounds.size.width = self.pending_line.bounds.size.width +
|
||||||
box_.border_box.size.width;
|
fragment.border_box.size.width;
|
||||||
self.pending_line.bounds.size.height = Au::max(self.pending_line.bounds.size.height,
|
self.pending_line.bounds.size.height = Au::max(self.pending_line.bounds.size.height,
|
||||||
box_.border_box.size.height);
|
fragment.border_box.size.height);
|
||||||
self.new_boxes.push(box_);
|
self.new_fragments.push(fragment);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterator over boxes.
|
/// Iterator over fragments.
|
||||||
pub struct FragmentIterator<'a> {
|
pub struct FragmentIterator<'a> {
|
||||||
iter: Enumerate<Items<'a,Fragment>>,
|
iter: Enumerate<Items<'a,Fragment>>,
|
||||||
map: &'a InlineFragmentMap,
|
map: &'a InlineFragmentMap,
|
||||||
|
@ -597,7 +596,7 @@ impl<'a> Iterator<(&'a Fragment, InlineFragmentContext<'a>)> for FragmentIterato
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Mutable iterator over boxes.
|
/// Mutable iterator over fragments.
|
||||||
pub struct MutFragmentIterator<'a> {
|
pub struct MutFragmentIterator<'a> {
|
||||||
iter: Enumerate<MutItems<'a,Fragment>>,
|
iter: Enumerate<MutItems<'a,Fragment>>,
|
||||||
map: &'a InlineFragmentMap,
|
map: &'a InlineFragmentMap,
|
||||||
|
@ -616,75 +615,75 @@ impl<'a> Iterator<(&'a mut Fragment, InlineFragmentContext<'a>)> for MutFragment
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a list of inline boxes, including element ranges.
|
/// Represents a list of inline fragments, including element ranges.
|
||||||
pub struct InlineFragments {
|
pub struct InlineFragments {
|
||||||
/// The boxes themselves.
|
/// The fragments themselves.
|
||||||
pub boxes: Vec<Fragment>,
|
pub fragments: Vec<Fragment>,
|
||||||
/// Tracks the elements that made up the boxes above.
|
/// Tracks the elements that made up the fragments above.
|
||||||
pub map: InlineFragmentMap,
|
pub map: InlineFragmentMap,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineFragments {
|
impl InlineFragments {
|
||||||
/// Creates an empty set of inline boxes.
|
/// Creates an empty set of inline fragments.
|
||||||
pub fn new() -> InlineFragments {
|
pub fn new() -> InlineFragments {
|
||||||
InlineFragments {
|
InlineFragments {
|
||||||
boxes: Vec::new(),
|
fragments: Vec::new(),
|
||||||
map: InlineFragmentMap::new(),
|
map: InlineFragmentMap::new(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the number of inline boxes.
|
/// Returns the number of inline fragments.
|
||||||
pub fn len(&self) -> uint {
|
pub fn len(&self) -> uint {
|
||||||
self.boxes.len()
|
self.fragments.len()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this list contains no boxes and false if it contains at least one box.
|
/// Returns true if this list contains no fragments and false if it contains at least one fragment.
|
||||||
pub fn is_empty(&self) -> bool {
|
pub fn is_empty(&self) -> bool {
|
||||||
self.len() == 0
|
self.len() == 0
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Pushes a new inline box.
|
/// Pushes a new inline fragment.
|
||||||
pub fn push(&mut self, fragment: Fragment, style: Arc<ComputedValues>) {
|
pub fn push(&mut self, fragment: Fragment, style: Arc<ComputedValues>) {
|
||||||
self.map.push(style, Range::new(FragmentIndex(self.boxes.len() as int), FragmentIndex(1)));
|
self.map.push(style, Range::new(FragmentIndex(self.fragments.len() as int), FragmentIndex(1)));
|
||||||
self.boxes.push(fragment)
|
self.fragments.push(fragment)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Merges another set of inline boxes with this one.
|
/// Merges another set of inline fragments with this one.
|
||||||
pub fn push_all(&mut self, other: InlineFragments) {
|
pub fn push_all(&mut self, other: InlineFragments) {
|
||||||
let InlineFragments {
|
let InlineFragments {
|
||||||
boxes: other_boxes,
|
fragments: other_fragments,
|
||||||
map: other_map
|
map: other_map
|
||||||
} = other;
|
} = other;
|
||||||
let adjustment = FragmentIndex(self.boxes.len() as int);
|
let adjustment = FragmentIndex(self.fragments.len() as int);
|
||||||
self.map.push_all(other_map, adjustment);
|
self.map.push_all(other_map, adjustment);
|
||||||
self.boxes.push_all_move(other_boxes);
|
self.fragments.push_all_move(other_fragments);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator that iterates over all boxes along with the appropriate context.
|
/// Returns an iterator that iterates over all fragments along with the appropriate context.
|
||||||
pub fn iter<'a>(&'a self) -> FragmentIterator<'a> {
|
pub fn iter<'a>(&'a self) -> FragmentIterator<'a> {
|
||||||
FragmentIterator {
|
FragmentIterator {
|
||||||
iter: self.boxes.as_slice().iter().enumerate(),
|
iter: self.fragments.as_slice().iter().enumerate(),
|
||||||
map: &self.map,
|
map: &self.map,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns an iterator that iterates over all boxes along with the appropriate context and
|
/// Returns an iterator that iterates over all fragments along with the appropriate context and
|
||||||
/// allows those boxes to be mutated.
|
/// allows those fragments to be mutated.
|
||||||
pub fn mut_iter<'a>(&'a mut self) -> MutFragmentIterator<'a> {
|
pub fn mut_iter<'a>(&'a mut self) -> MutFragmentIterator<'a> {
|
||||||
MutFragmentIterator {
|
MutFragmentIterator {
|
||||||
iter: self.boxes.as_mut_slice().mut_iter().enumerate(),
|
iter: self.fragments.as_mut_slice().mut_iter().enumerate(),
|
||||||
map: &self.map,
|
map: &self.map,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function to return the box at a given index.
|
/// A convenience function to return the fragment at a given index.
|
||||||
pub fn get<'a>(&'a self, index: uint) -> &'a Fragment {
|
pub fn get<'a>(&'a self, index: uint) -> &'a Fragment {
|
||||||
self.boxes.get(index)
|
self.fragments.get(index)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A convenience function to return a mutable reference to the box at a given index.
|
/// A convenience function to return a mutable reference to the fragment at a given index.
|
||||||
pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut Fragment {
|
pub fn get_mut<'a>(&'a mut self, index: uint) -> &'a mut Fragment {
|
||||||
self.boxes.get_mut(index)
|
self.fragments.get_mut(index)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -694,12 +693,12 @@ pub struct InlineFlow {
|
||||||
pub base: BaseFlow,
|
pub base: BaseFlow,
|
||||||
|
|
||||||
/// A vector of all inline fragments. Several fragments may correspond to one node/element.
|
/// A vector of all inline fragments. Several fragments may correspond to one node/element.
|
||||||
pub boxes: InlineFragments,
|
pub fragments: InlineFragments,
|
||||||
|
|
||||||
/// A vector of ranges into boxes that represents line positions. These ranges are disjoint and
|
/// A vector of ranges into fragments that represents line positions. These ranges are disjoint and
|
||||||
/// are the result of inline layout. This also includes some metadata used for positioning
|
/// are the result of inline layout. This also includes some metadata used for positioning
|
||||||
/// lines.
|
/// lines.
|
||||||
pub lines: Vec<LineBox>,
|
pub lines: Vec<LineFragment>,
|
||||||
|
|
||||||
/// The minimum height above the baseline for each line, as specified by the line height and
|
/// The minimum height above the baseline for each line, as specified by the line height and
|
||||||
/// font style.
|
/// font style.
|
||||||
|
@ -711,10 +710,10 @@ pub struct InlineFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InlineFlow {
|
impl InlineFlow {
|
||||||
pub fn from_boxes(node: ThreadSafeLayoutNode, boxes: InlineFragments) -> InlineFlow {
|
pub fn from_fragments(node: ThreadSafeLayoutNode, fragments: InlineFragments) -> InlineFlow {
|
||||||
InlineFlow {
|
InlineFlow {
|
||||||
base: BaseFlow::new(node),
|
base: BaseFlow::new(node),
|
||||||
boxes: boxes,
|
fragments: fragments,
|
||||||
lines: Vec::new(),
|
lines: Vec::new(),
|
||||||
minimum_height_above_baseline: Au(0),
|
minimum_height_above_baseline: Au(0),
|
||||||
minimum_depth_below_baseline: Au(0),
|
minimum_depth_below_baseline: Au(0),
|
||||||
|
@ -727,11 +726,11 @@ impl InlineFlow {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#228): Once we form line boxes and have their cached bounds, we can be smarter and
|
// TODO(#228): Once we form line fragments and have their cached bounds, we can be smarter and
|
||||||
// not recurse on a line if nothing in it can intersect the dirty region.
|
// not recurse on a line if nothing in it can intersect the dirty region.
|
||||||
debug!("Flow: building display list for {:u} inline boxes", self.boxes.len());
|
debug!("Flow: building display list for {:u} inline fragments", self.fragments.len());
|
||||||
|
|
||||||
for (fragment, context) in self.boxes.mut_iter() {
|
for (fragment, context) in self.fragments.mut_iter() {
|
||||||
let rel_offset = fragment.relative_position(&self.base
|
let rel_offset = fragment.relative_position(&self.base
|
||||||
.absolute_position_info
|
.absolute_position_info
|
||||||
.relative_containing_block_size,
|
.relative_containing_block_size,
|
||||||
|
@ -744,7 +743,7 @@ impl InlineFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
|
// TODO(#225): Should `inline-block` elements have flows as children of the inline flow or
|
||||||
// should the flow be nested inside the box somehow?
|
// should the flow be nested inside the fragment somehow?
|
||||||
|
|
||||||
// For now, don't traverse the subtree rooted here.
|
// For now, don't traverse the subtree rooted here.
|
||||||
}
|
}
|
||||||
|
@ -784,17 +783,17 @@ impl InlineFlow {
|
||||||
(-super_offset - ascent, false)
|
(-super_offset - ascent, false)
|
||||||
},
|
},
|
||||||
vertical_align::text_top => {
|
vertical_align::text_top => {
|
||||||
let box_height = *height_above_baseline + *depth_below_baseline;
|
let fragment_height = *height_above_baseline + *depth_below_baseline;
|
||||||
let prev_depth_below_baseline = *depth_below_baseline;
|
let prev_depth_below_baseline = *depth_below_baseline;
|
||||||
*height_above_baseline = parent_text_top;
|
*height_above_baseline = parent_text_top;
|
||||||
*depth_below_baseline = box_height - *height_above_baseline;
|
*depth_below_baseline = fragment_height - *height_above_baseline;
|
||||||
(*depth_below_baseline - prev_depth_below_baseline - ascent, false)
|
(*depth_below_baseline - prev_depth_below_baseline - ascent, false)
|
||||||
},
|
},
|
||||||
vertical_align::text_bottom => {
|
vertical_align::text_bottom => {
|
||||||
let box_height = *height_above_baseline + *depth_below_baseline;
|
let fragment_height = *height_above_baseline + *depth_below_baseline;
|
||||||
let prev_depth_below_baseline = *depth_below_baseline;
|
let prev_depth_below_baseline = *depth_below_baseline;
|
||||||
*depth_below_baseline = parent_text_bottom;
|
*depth_below_baseline = parent_text_bottom;
|
||||||
*height_above_baseline = box_height - *depth_below_baseline;
|
*height_above_baseline = fragment_height - *depth_below_baseline;
|
||||||
(*depth_below_baseline - prev_depth_below_baseline - ascent, false)
|
(*depth_below_baseline - prev_depth_below_baseline - ascent, false)
|
||||||
},
|
},
|
||||||
vertical_align::top => {
|
vertical_align::top => {
|
||||||
|
@ -821,17 +820,17 @@ impl InlineFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Sets box X positions based on alignment for one line.
|
/// Sets fragment X positions based on alignment for one line.
|
||||||
fn set_horizontal_box_positions(boxes: &mut InlineFragments,
|
fn set_horizontal_fragment_positions(fragments: &mut InlineFragments,
|
||||||
line: &LineBox,
|
line: &LineFragment,
|
||||||
linebox_align: text_align::T) {
|
line_fragment_align: text_align::T) {
|
||||||
// Figure out how much width we have.
|
// Figure out how much width we have.
|
||||||
let slack_width = Au::max(Au(0), line.green_zone.width - line.bounds.size.width);
|
let slack_width = Au::max(Au(0), line.green_zone.width - line.bounds.size.width);
|
||||||
|
|
||||||
// Set the box x positions based on that alignment.
|
// Set the fragment x positions based on that alignment.
|
||||||
let mut offset_x = line.bounds.origin.x;
|
let mut offset_x = line.bounds.origin.x;
|
||||||
offset_x = offset_x + match linebox_align {
|
offset_x = offset_x + match line_fragment_align {
|
||||||
// So sorry, but justified text is more complicated than shuffling linebox
|
// So sorry, but justified text is more complicated than shuffling line_fragment
|
||||||
// coordinates.
|
// coordinates.
|
||||||
//
|
//
|
||||||
// TODO(burg, issue #213): Implement `text-align: justify`.
|
// TODO(burg, issue #213): Implement `text-align: justify`.
|
||||||
|
@ -841,9 +840,9 @@ impl InlineFlow {
|
||||||
};
|
};
|
||||||
|
|
||||||
for i in each_fragment_index(&line.range) {
|
for i in each_fragment_index(&line.range) {
|
||||||
let box_ = boxes.get_mut(i.to_uint());
|
let fragment = fragments.get_mut(i.to_uint());
|
||||||
let size = box_.border_box.size;
|
let size = fragment.border_box.size;
|
||||||
box_.border_box = Rect(Point2D(offset_x, box_.border_box.origin.y), size);
|
fragment.border_box = Rect(Point2D(offset_x, fragment.border_box.origin.y), size);
|
||||||
offset_x = offset_x + size.width;
|
offset_x = offset_x + size.width;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -883,31 +882,31 @@ impl Flow for InlineFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut intrinsic_widths = IntrinsicWidths::new();
|
let mut intrinsic_widths = IntrinsicWidths::new();
|
||||||
for (fragment, context) in self.boxes.mut_iter() {
|
for (fragment, context) in self.fragments.mut_iter() {
|
||||||
debug!("Flow: measuring {}", *fragment);
|
debug!("Flow: measuring {}", *fragment);
|
||||||
|
|
||||||
let box_intrinsic_widths = fragment.intrinsic_widths(Some(context));
|
let fragment_intrinsic_widths = fragment.intrinsic_widths(Some(context));
|
||||||
intrinsic_widths.minimum_width = geometry::max(intrinsic_widths.minimum_width,
|
intrinsic_widths.minimum_width = geometry::max(intrinsic_widths.minimum_width,
|
||||||
box_intrinsic_widths.minimum_width);
|
fragment_intrinsic_widths.minimum_width);
|
||||||
intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
|
intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
|
||||||
box_intrinsic_widths.preferred_width);
|
fragment_intrinsic_widths.preferred_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.base.intrinsic_widths = intrinsic_widths;
|
self.base.intrinsic_widths = intrinsic_widths;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
/// Recursively (top-down) determines the actual width of child contexts and fragments. When called
|
||||||
/// on this context, the context has had its width set by the parent context.
|
/// on this context, the context has had its width set by the parent context.
|
||||||
fn assign_widths(&mut self, _: &mut LayoutContext) {
|
fn assign_widths(&mut self, _: &mut LayoutContext) {
|
||||||
// Initialize content box widths if they haven't been initialized already.
|
// Initialize content fragment widths if they haven't been initialized already.
|
||||||
//
|
//
|
||||||
// TODO: Combine this with `LineboxScanner`'s walk in the box list, or put this into `Fragment`.
|
// TODO: Combine this with `LineFragmentScanner`'s walk in the fragment list, or put this into `Fragment`.
|
||||||
|
|
||||||
debug!("InlineFlow::assign_widths: floats in: {:?}", self.base.floats);
|
debug!("InlineFlow::assign_widths: floats in: {:?}", self.base.floats);
|
||||||
|
|
||||||
{
|
{
|
||||||
let this = &mut *self;
|
let this = &mut *self;
|
||||||
for (fragment, context) in this.boxes.mut_iter() {
|
for (fragment, context) in this.fragments.mut_iter() {
|
||||||
fragment.assign_replaced_width_if_necessary(self.base.position.size.width,
|
fragment.assign_replaced_width_if_necessary(self.base.position.size.width,
|
||||||
Some(context))
|
Some(context))
|
||||||
}
|
}
|
||||||
|
@ -922,57 +921,57 @@ impl Flow for InlineFlow {
|
||||||
// true. In that case, set the InlineBlockFragment's width to the
|
// true. In that case, set the InlineBlockFragment's width to the
|
||||||
// shrink-to-fit width, perform inline flow, and set the block
|
// shrink-to-fit width, perform inline flow, and set the block
|
||||||
// flow context's width as the assigned width of the
|
// flow context's width as the assigned width of the
|
||||||
// 'inline-block' box that created this flow before recursing.
|
// 'inline-block' fragment that created this flow before recursing.
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Calculate and set the height of this flow. See CSS 2.1 § 10.6.1.
|
/// Calculate and set the height of this flow. See CSS 2.1 § 10.6.1.
|
||||||
fn assign_height(&mut self, _: &mut LayoutContext) {
|
fn assign_height(&mut self, _: &mut LayoutContext) {
|
||||||
debug!("assign_height_inline: assigning height for flow");
|
debug!("assign_height_inline: assigning height for flow");
|
||||||
|
|
||||||
// Divide the boxes into lines.
|
// Divide the fragments into lines.
|
||||||
//
|
//
|
||||||
// TODO(#226): Get the CSS `line-height` property from the containing block's style to
|
// TODO(#226): Get the CSS `line-height` property from the containing block's style to
|
||||||
// determine minimum linebox height.
|
// determine minimum line_fragment height.
|
||||||
//
|
//
|
||||||
// TODO(#226): Get the CSS `line-height` property from each non-replaced inline element to
|
// TODO(#226): Get the CSS `line-height` property from each non-replaced inline element to
|
||||||
// determine its height for computing linebox height.
|
// determine its height for computing line_fragment height.
|
||||||
//
|
//
|
||||||
// TODO(pcwalton): Cache the linebox scanner?
|
// TODO(pcwalton): Cache the line_fragment scanner?
|
||||||
debug!("assign_height_inline: floats in: {:?}", self.base.floats);
|
debug!("assign_height_inline: floats in: {:?}", self.base.floats);
|
||||||
|
|
||||||
// assign height for inline boxes
|
// assign height for inline fragments
|
||||||
for (fragment, _) in self.boxes.mut_iter() {
|
for (fragment, _) in self.fragments.mut_iter() {
|
||||||
fragment.assign_replaced_height_if_necessary();
|
fragment.assign_replaced_height_if_necessary();
|
||||||
}
|
}
|
||||||
|
|
||||||
let scanner_floats = self.base.floats.clone();
|
let scanner_floats = self.base.floats.clone();
|
||||||
let mut scanner = LineboxScanner::new(scanner_floats);
|
let mut scanner = LineFragmentScanner::new(scanner_floats);
|
||||||
scanner.scan_for_lines(self);
|
scanner.scan_for_lines(self);
|
||||||
|
|
||||||
// All lines use text alignment of the flow.
|
// All lines use text alignment of the flow.
|
||||||
let text_align = self.base.flags.text_align();
|
let text_align = self.base.flags.text_align();
|
||||||
|
|
||||||
// Now, go through each line and lay out the boxes inside.
|
// Now, go through each line and lay out the fragments inside.
|
||||||
let mut line_distance_from_flow_top = Au(0);
|
let mut line_distance_from_flow_top = Au(0);
|
||||||
for line in self.lines.mut_iter() {
|
for line in self.lines.mut_iter() {
|
||||||
// Lay out boxes horizontally.
|
// Lay out fragments horizontally.
|
||||||
InlineFlow::set_horizontal_box_positions(&mut self.boxes, line, text_align);
|
InlineFlow::set_horizontal_fragment_positions(&mut self.fragments, line, text_align);
|
||||||
|
|
||||||
// Set the top y position of the current line box.
|
// Set the top y position of the current line fragment.
|
||||||
// `line_height_offset` is updated at the end of the previous loop.
|
// `line_height_offset` is updated at the end of the previous loop.
|
||||||
line.bounds.origin.y = line_distance_from_flow_top;
|
line.bounds.origin.y = line_distance_from_flow_top;
|
||||||
|
|
||||||
// Calculate the distance from the baseline to the top and bottom of the line box.
|
// Calculate the distance from the baseline to the top and bottom of the line fragment.
|
||||||
let mut largest_height_above_baseline = self.minimum_height_above_baseline;
|
let mut largest_height_above_baseline = self.minimum_height_above_baseline;
|
||||||
let mut largest_depth_below_baseline = self.minimum_depth_below_baseline;
|
let mut largest_depth_below_baseline = self.minimum_depth_below_baseline;
|
||||||
|
|
||||||
// Calculate the largest height among boxes with 'top' and 'bottom' values
|
// Calculate the largest height among fragments with 'top' and 'bottom' values
|
||||||
// respectively.
|
// respectively.
|
||||||
let (mut largest_height_for_top_fragments, mut largest_height_for_bottom_fragments) =
|
let (mut largest_height_for_top_fragments, mut largest_height_for_bottom_fragments) =
|
||||||
(Au(0), Au(0));
|
(Au(0), Au(0));
|
||||||
|
|
||||||
for box_i in each_fragment_index(&line.range) {
|
for fragment_i in each_fragment_index(&line.range) {
|
||||||
let fragment = self.boxes.boxes.get_mut(box_i.to_uint());
|
let fragment = self.fragments.fragments.get_mut(fragment_i.to_uint());
|
||||||
|
|
||||||
let InlineMetrics {
|
let InlineMetrics {
|
||||||
height_above_baseline: mut height_above_baseline,
|
height_above_baseline: mut height_above_baseline,
|
||||||
|
@ -981,7 +980,7 @@ impl Flow for InlineFlow {
|
||||||
} = fragment.inline_metrics();
|
} = fragment.inline_metrics();
|
||||||
|
|
||||||
// To calculate text-top and text-bottom value when `vertical-align` is involved,
|
// To calculate text-top and text-bottom value when `vertical-align` is involved,
|
||||||
// we should find the top and bottom of the content area of the parent box.
|
// we should find the top and bottom of the content area of the parent fragment.
|
||||||
// "Content area" is defined in CSS 2.1 § 10.6.1.
|
// "Content area" is defined in CSS 2.1 § 10.6.1.
|
||||||
//
|
//
|
||||||
// TODO: We should extract em-box info from the font size of the parent and
|
// TODO: We should extract em-box info from the font size of the parent and
|
||||||
|
@ -999,7 +998,7 @@ impl Flow for InlineFlow {
|
||||||
// content area. But for now we assume it's zero.
|
// content area. But for now we assume it's zero.
|
||||||
let parent_text_bottom = Au(0);
|
let parent_text_bottom = Au(0);
|
||||||
|
|
||||||
// Calculate the final height above the baseline for this box.
|
// Calculate the final height above the baseline for this fragment.
|
||||||
//
|
//
|
||||||
// The no-update flag decides whether `largest_height_for_top_fragments` and
|
// The no-update flag decides whether `largest_height_for_top_fragments` and
|
||||||
// `largest_height_for_bottom_fragments` are to be updated or not. This will be set
|
// `largest_height_for_bottom_fragments` are to be updated or not. This will be set
|
||||||
|
@ -1029,26 +1028,26 @@ impl Flow for InlineFlow {
|
||||||
fragment.border_box.origin.y = distance_from_baseline
|
fragment.border_box.origin.y = distance_from_baseline
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate the distance from the baseline to the top of the largest box with a
|
// Calculate the distance from the baseline to the top of the largest fragment with a
|
||||||
// value for `bottom`. Then, if necessary, update `largest_height_above_baseline`.
|
// value for `bottom`. Then, if necessary, update `largest_height_above_baseline`.
|
||||||
largest_height_above_baseline =
|
largest_height_above_baseline =
|
||||||
Au::max(largest_height_above_baseline,
|
Au::max(largest_height_above_baseline,
|
||||||
largest_height_for_bottom_fragments - largest_depth_below_baseline);
|
largest_height_for_bottom_fragments - largest_depth_below_baseline);
|
||||||
|
|
||||||
// Calculate the distance from baseline to the bottom of the largest box with a value
|
// Calculate the distance from baseline to the bottom of the largest fragment with a value
|
||||||
// for `top`. Then, if necessary, update `largest_depth_below_baseline`.
|
// for `top`. Then, if necessary, update `largest_depth_below_baseline`.
|
||||||
largest_depth_below_baseline =
|
largest_depth_below_baseline =
|
||||||
Au::max(largest_depth_below_baseline,
|
Au::max(largest_depth_below_baseline,
|
||||||
largest_height_for_top_fragments - largest_height_above_baseline);
|
largest_height_for_top_fragments - largest_height_above_baseline);
|
||||||
|
|
||||||
// Now, the distance from the logical top of the line box to the baseline can be
|
// Now, the distance from the logical top of the line fragment to the baseline can be
|
||||||
// computed as `largest_height_above_baseline`.
|
// computed as `largest_height_above_baseline`.
|
||||||
let baseline_distance_from_top = largest_height_above_baseline;
|
let baseline_distance_from_top = largest_height_above_baseline;
|
||||||
|
|
||||||
// Compute the final positions in the block direction of each fragment. Recall that
|
// Compute the final positions in the block direction of each fragment. Recall that
|
||||||
// `fragment.border_box.origin.y` was set to the distance from the baseline above.
|
// `fragment.border_box.origin.y` was set to the distance from the baseline above.
|
||||||
for box_i in each_fragment_index(&line.range) {
|
for fragment_i in each_fragment_index(&line.range) {
|
||||||
let fragment = self.boxes.get_mut(box_i.to_uint());
|
let fragment = self.fragments.get_mut(fragment_i.to_uint());
|
||||||
match fragment.vertical_align() {
|
match fragment.vertical_align() {
|
||||||
vertical_align::top => {
|
vertical_align::top => {
|
||||||
fragment.border_box.origin.y = fragment.border_box.origin.y +
|
fragment.border_box.origin.y = fragment.border_box.origin.y +
|
||||||
|
@ -1066,7 +1065,7 @@ impl Flow for InlineFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is used to set the top y position of the next line box in the next loop.
|
// This is used to set the top y position of the next line fragment in the next loop.
|
||||||
line.bounds.size.height = largest_height_above_baseline + largest_depth_below_baseline;
|
line.bounds.size.height = largest_height_above_baseline + largest_depth_below_baseline;
|
||||||
line_distance_from_flow_top = line_distance_from_flow_top + line.bounds.size.height;
|
line_distance_from_flow_top = line_distance_from_flow_top + line.bounds.size.height;
|
||||||
} // End of `lines.each` loop.
|
} // End of `lines.each` loop.
|
||||||
|
@ -1087,7 +1086,7 @@ impl Flow for InlineFlow {
|
||||||
impl fmt::Show for InlineFlow {
|
impl fmt::Show for InlineFlow {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
try!(write!(f.buf, "InlineFlow"));
|
try!(write!(f.buf, "InlineFlow"));
|
||||||
for (i, (fragment, _)) in self.boxes.iter().enumerate() {
|
for (i, (fragment, _)) in self.fragments.iter().enumerate() {
|
||||||
if i == 0 {
|
if i == 0 {
|
||||||
try!(write!(f.buf, ": {}", fragment))
|
try!(write!(f.buf, ": {}", fragment))
|
||||||
} else {
|
} else {
|
||||||
|
@ -1099,7 +1098,7 @@ impl fmt::Show for InlineFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information that inline flows keep about a single nested element. This is used to recover the
|
/// Information that inline flows keep about a single nested element. This is used to recover the
|
||||||
/// DOM structure from the flat box list when it's needed.
|
/// DOM structure from the flat fragment list when it's needed.
|
||||||
pub struct InlineFragmentRange {
|
pub struct InlineFragmentRange {
|
||||||
/// The style of the DOM node that this range refers to.
|
/// The style of the DOM node that this range refers to.
|
||||||
pub style: Arc<ComputedValues>,
|
pub style: Arc<ComputedValues>,
|
||||||
|
@ -1166,7 +1165,7 @@ impl<'a> Iterator<&'a InlineFragmentRange> for RangeIterator<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Information that inline flows keep about nested elements. This is used to recover the DOM
|
/// Information that inline flows keep about nested elements. This is used to recover the DOM
|
||||||
/// structure from the flat box list when it's needed.
|
/// structure from the flat fragment list when it's needed.
|
||||||
pub struct InlineFragmentMap {
|
pub struct InlineFragmentMap {
|
||||||
list: Vec<InlineFragmentRange>,
|
list: Vec<InlineFragmentRange>,
|
||||||
}
|
}
|
||||||
|
@ -1207,7 +1206,7 @@ impl InlineFragmentMap {
|
||||||
&mut self.list.as_mut_slice()[index.to_uint()]
|
&mut self.list.as_mut_slice()[index.to_uint()]
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Iterates over all ranges that contain the box with the given index, outermost first.
|
/// Iterates over all ranges that contain the fragment with the given index, outermost first.
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn ranges_for_index<'a>(&'a self, index: FragmentIndex) -> RangeIterator<'a> {
|
fn ranges_for_index<'a>(&'a self, index: FragmentIndex) -> RangeIterator<'a> {
|
||||||
RangeIterator {
|
RangeIterator {
|
||||||
|
@ -1222,10 +1221,10 @@ impl InlineFragmentMap {
|
||||||
/// DOM has changed, then the flow constructor will need to do more complicated surgery than
|
/// DOM has changed, then the flow constructor will need to do more complicated surgery than
|
||||||
/// this function can provide.
|
/// this function can provide.
|
||||||
///
|
///
|
||||||
/// FIXME(#2267, pcwalton): It would be more efficient to not have to clone boxes all the time;
|
/// FIXME(#2267, pcwalton): It would be more efficient to not have to clone fragments all the time;
|
||||||
/// i.e. if `old_boxes` contained less info than the entire range of boxes. See
|
/// i.e. if `old_fragments` contained less info than the entire range of fragments. See
|
||||||
/// `layout::construct::strip_ignorable_whitespace_from_start` for an example of some code that
|
/// `layout::construct::strip_ignorable_whitespace_from_start` for an example of some code that
|
||||||
/// needlessly has to clone boxes.
|
/// needlessly has to clone fragments.
|
||||||
pub fn fixup(&mut self, old_fragments: &[Fragment], new_fragments: &[Fragment]) {
|
pub fn fixup(&mut self, old_fragments: &[Fragment], new_fragments: &[Fragment]) {
|
||||||
// TODO(pcwalton): Post Rust upgrade, use `with_capacity` here.
|
// TODO(pcwalton): Post Rust upgrade, use `with_capacity` here.
|
||||||
let old_list = mem::replace(&mut self.list, Vec::new());
|
let old_list = mem::replace(&mut self.list, Vec::new());
|
||||||
|
|
|
@ -88,7 +88,7 @@ pub struct MarginCollapseInfo {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl MarginCollapseInfo {
|
impl MarginCollapseInfo {
|
||||||
/// TODO(#2012, pcwalton): Remove this method once `box_` is not an `Option`.
|
/// TODO(#2012, pcwalton): Remove this method once `fragment` is not an `Option`.
|
||||||
pub fn new() -> MarginCollapseInfo {
|
pub fn new() -> MarginCollapseInfo {
|
||||||
MarginCollapseInfo {
|
MarginCollapseInfo {
|
||||||
state: AccumulatingCollapsibleTopMargin,
|
state: AccumulatingCollapsibleTopMargin,
|
||||||
|
@ -120,15 +120,15 @@ impl MarginCollapseInfo {
|
||||||
MarginsCollapseThroughFinalMarginState
|
MarginsCollapseThroughFinalMarginState
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
// If the box has non-zero min-height, margins may not collapse
|
// If the fragment has non-zero min-height, margins may not
|
||||||
// through it.
|
// collapse through it.
|
||||||
BottomMarginCollapsesFinalMarginState
|
BottomMarginCollapsesFinalMarginState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
// If the box has an explicitly specified height, margins may not collapse
|
// If the fragment has an explicitly specified height, margins may not
|
||||||
// through it.
|
// collapse through it.
|
||||||
BottomMarginCollapsesFinalMarginState
|
BottomMarginCollapsesFinalMarginState
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,9 @@ use servo_util::geometry;
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
use style::computed_values::table_layout;
|
use style::computed_values::table_layout;
|
||||||
|
|
||||||
/// A table flow corresponded to the table's internal table box under a table wrapper flow.
|
/// A table flow corresponded to the table's internal table fragment under a table wrapper flow.
|
||||||
/// The properties `position`, `float`, and `margin-*` are used on the table wrapper box,
|
/// The properties `position`, `float`, and `margin-*` are used on the table wrapper fragment,
|
||||||
/// not table box per CSS 2.1 § 10.5.
|
/// not table fragment per CSS 2.1 § 10.5.
|
||||||
pub struct TableFlow {
|
pub struct TableFlow {
|
||||||
pub block_flow: BlockFlow,
|
pub block_flow: BlockFlow,
|
||||||
|
|
||||||
|
@ -39,11 +39,11 @@ pub struct TableFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableFlow {
|
impl TableFlow {
|
||||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
|
||||||
box_: Fragment)
|
fragment: Fragment)
|
||||||
-> TableFlow {
|
-> TableFlow {
|
||||||
let mut block_flow = BlockFlow::from_node_and_box(node, box_);
|
let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment);
|
||||||
let table_layout = if block_flow.box_().style().get_table().table_layout ==
|
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
|
||||||
table_layout::fixed {
|
table_layout::fixed {
|
||||||
FixedLayout
|
FixedLayout
|
||||||
} else {
|
} else {
|
||||||
|
@ -62,7 +62,7 @@ impl TableFlow {
|
||||||
node: &ThreadSafeLayoutNode)
|
node: &ThreadSafeLayoutNode)
|
||||||
-> TableFlow {
|
-> TableFlow {
|
||||||
let mut block_flow = BlockFlow::from_node(constructor, node);
|
let mut block_flow = BlockFlow::from_node(constructor, node);
|
||||||
let table_layout = if block_flow.box_().style().get_table().table_layout ==
|
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
|
||||||
table_layout::fixed {
|
table_layout::fixed {
|
||||||
FixedLayout
|
FixedLayout
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,7 +82,7 @@ impl TableFlow {
|
||||||
float_kind: FloatKind)
|
float_kind: FloatKind)
|
||||||
-> TableFlow {
|
-> TableFlow {
|
||||||
let mut block_flow = BlockFlow::float_from_node(constructor, node, float_kind);
|
let mut block_flow = BlockFlow::float_from_node(constructor, node, float_kind);
|
||||||
let table_layout = if block_flow.box_().style().get_table().table_layout ==
|
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
|
||||||
table_layout::fixed {
|
table_layout::fixed {
|
||||||
FixedLayout
|
FixedLayout
|
||||||
} else {
|
} else {
|
||||||
|
@ -231,8 +231,8 @@ impl Flow for TableFlow {
|
||||||
geometry::max(min_width, pref_width);
|
geometry::max(min_width, pref_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
/// Recursively (top-down) determines the actual width of child contexts and fragments. When
|
||||||
/// on this context, the context has had its width set by the parent context.
|
/// called on this context, the context has had its width set by the parent context.
|
||||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||||
debug!("assign_widths({}): assigning width for flow", "table");
|
debug!("assign_widths({}): assigning width for flow", "table");
|
||||||
|
|
||||||
|
@ -252,9 +252,9 @@ 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);
|
||||||
|
|
||||||
let left_content_edge = self.block_flow.box_.border_padding.left;
|
let left_content_edge = self.block_flow.fragment.border_padding.left;
|
||||||
let padding_and_borders = self.block_flow.box_.border_padding.horizontal();
|
let padding_and_borders = self.block_flow.fragment.border_padding.horizontal();
|
||||||
let content_width = self.block_flow.box_.border_box.size.width - padding_and_borders;
|
let content_width = self.block_flow.fragment.border_box.size.width - padding_and_borders;
|
||||||
|
|
||||||
match self.table_layout {
|
match self.table_layout {
|
||||||
FixedLayout => {
|
FixedLayout => {
|
||||||
|
|
|
@ -22,18 +22,18 @@ pub struct TableCellFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableCellFlow {
|
impl TableCellFlow {
|
||||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode, box_: Fragment) -> TableCellFlow {
|
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> TableCellFlow {
|
||||||
TableCellFlow {
|
TableCellFlow {
|
||||||
block_flow: BlockFlow::from_node_and_box(node, box_)
|
block_flow: BlockFlow::from_node_and_fragment(node, fragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn box_<'a>(&'a mut self) -> &'a Fragment {
|
pub fn fragment<'a>(&'a mut self) -> &'a Fragment {
|
||||||
&self.block_flow.box_
|
&self.block_flow.fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mut_box<'a>(&'a mut self) -> &'a mut Fragment {
|
pub fn mut_fragment<'a>(&'a mut self) -> &'a mut Fragment {
|
||||||
&mut self.block_flow.box_
|
&mut self.block_flow.fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Assign height for table-cell flow.
|
/// Assign height for table-cell flow.
|
||||||
|
@ -69,7 +69,7 @@ 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);
|
||||||
let specified_width = MaybeAuto::from_style(self.block_flow.box_.style().get_box().width,
|
let specified_width = MaybeAuto::from_style(self.block_flow.fragment.style().get_box().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;
|
||||||
|
@ -81,8 +81,8 @@ impl Flow for TableCellFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
/// Recursively (top-down) determines the actual width of child contexts and fragments. When
|
||||||
/// on this context, the context has had its width set by the parent table row.
|
/// called on this context, the context has had its width set by the parent table row.
|
||||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||||
debug!("assign_widths({}): assigning width for flow", "table_cell");
|
debug!("assign_widths({}): assigning width for flow", "table_cell");
|
||||||
|
|
||||||
|
@ -92,10 +92,10 @@ impl Flow for TableCellFlow {
|
||||||
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);
|
||||||
|
|
||||||
let left_content_edge = self.block_flow.box_.border_box.origin.x +
|
let left_content_edge = self.block_flow.fragment.border_box.origin.x +
|
||||||
self.block_flow.box_.border_padding.left;
|
self.block_flow.fragment.border_padding.left;
|
||||||
let padding_and_borders = self.block_flow.box_.border_padding.horizontal();
|
let padding_and_borders = self.block_flow.fragment.border_padding.horizontal();
|
||||||
let content_width = self.block_flow.box_.border_box.size.width - padding_and_borders;
|
let content_width = self.block_flow.fragment.border_box.size.width - padding_and_borders;
|
||||||
|
|
||||||
self.block_flow.propagate_assigned_width_to_children(left_content_edge,
|
self.block_flow.propagate_assigned_width_to_children(left_content_edge,
|
||||||
content_width,
|
content_width,
|
||||||
|
|
|
@ -18,10 +18,10 @@ pub struct TableColGroupFlow {
|
||||||
/// Data common to all flows.
|
/// Data common to all flows.
|
||||||
pub base: BaseFlow,
|
pub base: BaseFlow,
|
||||||
|
|
||||||
/// The associated box.
|
/// The associated fragment.
|
||||||
pub box_: Option<Fragment>,
|
pub fragment: Option<Fragment>,
|
||||||
|
|
||||||
/// The table column boxes
|
/// The table column fragments
|
||||||
pub cols: Vec<Fragment>,
|
pub cols: Vec<Fragment>,
|
||||||
|
|
||||||
/// The specified widths of table columns
|
/// The specified widths of table columns
|
||||||
|
@ -29,13 +29,13 @@ pub struct TableColGroupFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableColGroupFlow {
|
impl TableColGroupFlow {
|
||||||
pub fn from_node_and_boxes(node: &ThreadSafeLayoutNode,
|
pub fn from_node_and_fragments(node: &ThreadSafeLayoutNode,
|
||||||
box_: Fragment,
|
fragment: Fragment,
|
||||||
boxes: Vec<Fragment>) -> TableColGroupFlow {
|
fragments: Vec<Fragment>) -> TableColGroupFlow {
|
||||||
TableColGroupFlow {
|
TableColGroupFlow {
|
||||||
base: BaseFlow::new((*node).clone()),
|
base: BaseFlow::new((*node).clone()),
|
||||||
box_: Some(box_),
|
fragment: Some(fragment),
|
||||||
cols: boxes,
|
cols: fragments,
|
||||||
widths: vec!(),
|
widths: vec!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,14 +51,14 @@ impl Flow for TableColGroupFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn bubble_widths(&mut self, _: &mut LayoutContext) {
|
fn bubble_widths(&mut self, _: &mut LayoutContext) {
|
||||||
for box_ in self.cols.iter() {
|
for fragment in self.cols.iter() {
|
||||||
// get the specified value from width property
|
// get the specified value from width property
|
||||||
let width = MaybeAuto::from_style(box_.style().get_box().width,
|
let width = MaybeAuto::from_style(fragment.style().get_box().width,
|
||||||
Au::new(0)).specified_or_zero();
|
Au::new(0)).specified_or_zero();
|
||||||
|
|
||||||
let span: int = match box_.specific {
|
let span: int = match fragment.specific {
|
||||||
TableColumnFragment(col_box) => col_box.span.unwrap_or(1),
|
TableColumnFragment(col_fragment) => col_fragment.span.unwrap_or(1),
|
||||||
_ => fail!("Other box come out in TableColGroupFlow. {:?}", box_.specific)
|
_ => fail!("Other fragment come out in TableColGroupFlow. {:?}", fragment.specific)
|
||||||
};
|
};
|
||||||
for _ in range(0, span) {
|
for _ in range(0, span) {
|
||||||
self.widths.push(width);
|
self.widths.push(width);
|
||||||
|
@ -78,7 +78,7 @@ impl Flow for TableColGroupFlow {
|
||||||
|
|
||||||
impl fmt::Show for TableColGroupFlow {
|
impl fmt::Show for TableColGroupFlow {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
match self.box_ {
|
match self.fragment {
|
||||||
Some(ref rb) => write!(f.buf, "TableColGroupFlow: {}", rb),
|
Some(ref rb) => write!(f.buf, "TableColGroupFlow: {}", rb),
|
||||||
None => write!(f.buf, "TableColGroupFlow"),
|
None => write!(f.buf, "TableColGroupFlow"),
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,11 +34,11 @@ pub struct TableRowFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableRowFlow {
|
impl TableRowFlow {
|
||||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
|
||||||
box_: Fragment)
|
fragment: Fragment)
|
||||||
-> TableRowFlow {
|
-> TableRowFlow {
|
||||||
TableRowFlow {
|
TableRowFlow {
|
||||||
block_flow: BlockFlow::from_node_and_box(node, box_),
|
block_flow: BlockFlow::from_node_and_fragment(node, fragment),
|
||||||
col_widths: vec!(),
|
col_widths: vec!(),
|
||||||
col_min_widths: vec!(),
|
col_min_widths: vec!(),
|
||||||
col_pref_widths: vec!(),
|
col_pref_widths: vec!(),
|
||||||
|
@ -56,8 +56,8 @@ impl TableRowFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn box_<'a>(&'a mut self) -> &'a Fragment {
|
pub fn fragment<'a>(&'a mut self) -> &'a Fragment {
|
||||||
&self.block_flow.box_
|
&self.block_flow.fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_offsets(&mut self) -> (Au, Au, Au) {
|
fn initialize_offsets(&mut self) -> (Au, Au, Au) {
|
||||||
|
@ -84,13 +84,13 @@ impl TableRowFlow {
|
||||||
kid.assign_height_for_inorder_child_if_necessary(layout_context);
|
kid.assign_height_for_inorder_child_if_necessary(layout_context);
|
||||||
|
|
||||||
{
|
{
|
||||||
let child_box = kid.as_table_cell().box_();
|
let child_fragment = kid.as_table_cell().fragment();
|
||||||
// TODO: Percentage height
|
// TODO: Percentage height
|
||||||
let child_specified_height = MaybeAuto::from_style(child_box.style().get_box().height,
|
let child_specified_height = MaybeAuto::from_style(child_fragment.style().get_box().height,
|
||||||
Au::new(0)).specified_or_zero();
|
Au::new(0)).specified_or_zero();
|
||||||
max_y =
|
max_y =
|
||||||
geometry::max(max_y,
|
geometry::max(max_y,
|
||||||
child_specified_height + child_box.border_padding.vertical());
|
child_specified_height + child_fragment.border_padding.vertical());
|
||||||
}
|
}
|
||||||
let child_node = flow::mut_base(kid);
|
let child_node = flow::mut_base(kid);
|
||||||
child_node.position.origin.y = cur_y;
|
child_node.position.origin.y = cur_y;
|
||||||
|
@ -99,27 +99,27 @@ impl TableRowFlow {
|
||||||
|
|
||||||
let mut height = max_y;
|
let mut height = max_y;
|
||||||
// TODO: Percentage height
|
// TODO: Percentage height
|
||||||
height = match MaybeAuto::from_style(self.block_flow.box_.style().get_box().height, Au(0)) {
|
height = match MaybeAuto::from_style(self.block_flow.fragment.style().get_box().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 fragment
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): Take `cur_y` into account.
|
// FIXME(pcwalton): Take `cur_y` into account.
|
||||||
let mut position = self.block_flow.box_.border_box;
|
let mut position = self.block_flow.fragment.border_box;
|
||||||
position.size.height = height;
|
position.size.height = height;
|
||||||
self.block_flow.box_.border_box = position;
|
self.block_flow.fragment.border_box = 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 fragments, 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() {
|
||||||
{
|
{
|
||||||
let kid_box_ = kid.as_table_cell().mut_box();
|
let kid_fragment = kid.as_table_cell().mut_fragment();
|
||||||
let mut position = kid_box_.border_box;
|
let mut position = kid_fragment.border_box;
|
||||||
position.size.height = height;
|
position.size.height = height;
|
||||||
kid_box_.border_box = position;
|
kid_fragment.border_box = position;
|
||||||
}
|
}
|
||||||
let child_node = flow::mut_base(kid);
|
let child_node = flow::mut_base(kid);
|
||||||
child_node.position.size.height = height;
|
child_node.position.size.height = height;
|
||||||
|
@ -159,7 +159,7 @@ impl Flow for TableRowFlow {
|
||||||
|
|
||||||
/// Recursively (bottom-up) determines the context's preferred and minimum widths. When called
|
/// Recursively (bottom-up) determines the context's preferred and minimum widths. When called
|
||||||
/// on this context, all child contexts have had their min/pref widths set. This function must
|
/// on this context, all child contexts have had their min/pref widths set. This function must
|
||||||
/// decide min/pref widths based on child context widths and dimensions of any boxes it is
|
/// decide min/pref widths based on child context widths and dimensions of any fragments it is
|
||||||
/// responsible for flowing.
|
/// responsible for flowing.
|
||||||
/// Min/pref widths set by this function are used in automatic table layout calculation.
|
/// Min/pref widths set by this function are used in automatic table layout calculation.
|
||||||
/// The specified column widths of children cells are used in fixed table layout calculation.
|
/// The specified column widths of children cells are used in fixed table layout calculation.
|
||||||
|
@ -172,8 +172,8 @@ impl Flow for TableRowFlow {
|
||||||
|
|
||||||
// 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.
|
||||||
{
|
{
|
||||||
let child_box = kid.as_table_cell().box_();
|
let child_fragment = kid.as_table_cell().fragment();
|
||||||
let child_specified_width = MaybeAuto::from_style(child_box.style().get_box().width,
|
let child_specified_width = MaybeAuto::from_style(child_fragment.style().get_box().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);
|
||||||
}
|
}
|
||||||
|
@ -190,7 +190,7 @@ impl Flow for TableRowFlow {
|
||||||
pref_width);
|
pref_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
/// Recursively (top-down) determines the actual width of child contexts and fragments. When called
|
||||||
/// on this context, the context has had its width set by the parent context.
|
/// on this context, the context has had its width set by the parent context.
|
||||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||||
debug!("assign_widths({}): assigning width for flow", "table_row");
|
debug!("assign_widths({}): assigning width for flow", "table_row");
|
||||||
|
@ -218,6 +218,6 @@ impl Flow for TableRowFlow {
|
||||||
|
|
||||||
impl fmt::Show for TableRowFlow {
|
impl fmt::Show for TableRowFlow {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f.buf, "TableRowFlow: {}", self.block_flow.box_)
|
write!(f.buf, "TableRowFlow: {}", self.block_flow.fragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,11 +33,11 @@ pub struct TableRowGroupFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableRowGroupFlow {
|
impl TableRowGroupFlow {
|
||||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
|
||||||
box_: Fragment)
|
fragment: Fragment)
|
||||||
-> TableRowGroupFlow {
|
-> TableRowGroupFlow {
|
||||||
TableRowGroupFlow {
|
TableRowGroupFlow {
|
||||||
block_flow: BlockFlow::from_node_and_box(node, box_),
|
block_flow: BlockFlow::from_node_and_fragment(node, fragment),
|
||||||
col_widths: vec!(),
|
col_widths: vec!(),
|
||||||
col_min_widths: vec!(),
|
col_min_widths: vec!(),
|
||||||
col_pref_widths: vec!(),
|
col_pref_widths: vec!(),
|
||||||
|
@ -55,8 +55,8 @@ impl TableRowGroupFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn box_<'a>(&'a mut self) -> &'a Fragment {
|
pub fn fragment<'a>(&'a mut self) -> &'a Fragment {
|
||||||
&self.block_flow.box_
|
&self.block_flow.fragment
|
||||||
}
|
}
|
||||||
|
|
||||||
fn initialize_offsets(&mut self) -> (Au, Au, Au) {
|
fn initialize_offsets(&mut self) -> (Au, Au, Au) {
|
||||||
|
@ -87,9 +87,9 @@ impl TableRowGroupFlow {
|
||||||
|
|
||||||
let height = cur_y - top_offset;
|
let height = cur_y - top_offset;
|
||||||
|
|
||||||
let mut position = self.block_flow.box_.border_box;
|
let mut position = self.block_flow.fragment.border_box;
|
||||||
position.size.height = height;
|
position.size.height = height;
|
||||||
self.block_flow.box_.border_box = position;
|
self.block_flow.fragment.border_box = position;
|
||||||
self.block_flow.base.position.size.height = height;
|
self.block_flow.base.position.size.height = height;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -126,7 +126,7 @@ impl Flow for TableRowGroupFlow {
|
||||||
|
|
||||||
/// Recursively (bottom-up) determines the context's preferred and minimum widths. When called
|
/// Recursively (bottom-up) determines the context's preferred and minimum widths. When called
|
||||||
/// on this context, all child contexts have had their min/pref widths set. This function must
|
/// on this context, all child contexts have had their min/pref widths set. This function must
|
||||||
/// decide min/pref widths based on child context widths and dimensions of any boxes it is
|
/// decide min/pref widths based on child context widths and dimensions of any fragments it is
|
||||||
/// responsible for flowing.
|
/// responsible for flowing.
|
||||||
/// Min/pref widths set by this function are used in automatic table layout calculation.
|
/// Min/pref widths set by this function are used in automatic table layout calculation.
|
||||||
/// Also, this function finds the specified column widths from the first row.
|
/// Also, this function finds the specified column widths from the first row.
|
||||||
|
@ -171,8 +171,8 @@ impl Flow for TableRowGroupFlow {
|
||||||
pref_width);
|
pref_width);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
/// Recursively (top-down) determines the actual width of child contexts and fragments. When
|
||||||
/// on this context, the context has had its width set by the parent context.
|
/// called on this context, the context has had its width set by the parent context.
|
||||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||||
debug!("assign_widths({}): assigning width for flow", "table_rowgroup");
|
debug!("assign_widths({}): assigning width for flow", "table_rowgroup");
|
||||||
|
|
||||||
|
@ -200,6 +200,6 @@ impl Flow for TableRowGroupFlow {
|
||||||
|
|
||||||
impl fmt::Show for TableRowGroupFlow {
|
impl fmt::Show for TableRowGroupFlow {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
write!(f.buf, "TableRowGroupFlow: {}", self.block_flow.box_)
|
write!(f.buf, "TableRowGroupFlow: {}", self.block_flow.fragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,11 +36,11 @@ pub struct TableWrapperFlow {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TableWrapperFlow {
|
impl TableWrapperFlow {
|
||||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
|
||||||
box_: Fragment)
|
fragment: Fragment)
|
||||||
-> TableWrapperFlow {
|
-> TableWrapperFlow {
|
||||||
let mut block_flow = BlockFlow::from_node_and_box(node, box_);
|
let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment);
|
||||||
let table_layout = if block_flow.box_().style().get_table().table_layout ==
|
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
|
||||||
table_layout::fixed {
|
table_layout::fixed {
|
||||||
FixedLayout
|
FixedLayout
|
||||||
} else {
|
} else {
|
||||||
|
@ -57,7 +57,7 @@ impl TableWrapperFlow {
|
||||||
node: &ThreadSafeLayoutNode)
|
node: &ThreadSafeLayoutNode)
|
||||||
-> TableWrapperFlow {
|
-> TableWrapperFlow {
|
||||||
let mut block_flow = BlockFlow::from_node(constructor, node);
|
let mut block_flow = BlockFlow::from_node(constructor, node);
|
||||||
let table_layout = if block_flow.box_().style().get_table().table_layout ==
|
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
|
||||||
table_layout::fixed {
|
table_layout::fixed {
|
||||||
FixedLayout
|
FixedLayout
|
||||||
} else {
|
} else {
|
||||||
|
@ -75,7 +75,7 @@ impl TableWrapperFlow {
|
||||||
float_kind: FloatKind)
|
float_kind: FloatKind)
|
||||||
-> TableWrapperFlow {
|
-> TableWrapperFlow {
|
||||||
let mut block_flow = BlockFlow::float_from_node(constructor, node, float_kind);
|
let mut block_flow = BlockFlow::float_from_node(constructor, node, float_kind);
|
||||||
let table_layout = if block_flow.box_().style().get_table().table_layout ==
|
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
|
||||||
table_layout::fixed {
|
table_layout::fixed {
|
||||||
FixedLayout
|
FixedLayout
|
||||||
} else {
|
} else {
|
||||||
|
@ -125,7 +125,7 @@ impl Flow for TableWrapperFlow {
|
||||||
minimum widths. When called on this context, all child contexts
|
minimum widths. When called on this context, all child contexts
|
||||||
have had their min/pref widths set. This function must decide
|
have had their min/pref widths set. This function must decide
|
||||||
min/pref widths based on child context widths and dimensions of
|
min/pref widths based on child context widths and dimensions of
|
||||||
any boxes it is responsible for flowing. */
|
any fragments it is responsible for flowing. */
|
||||||
|
|
||||||
fn bubble_widths(&mut self, ctx: &mut LayoutContext) {
|
fn bubble_widths(&mut self, ctx: &mut LayoutContext) {
|
||||||
// get column widths info from table flow
|
// get column widths info from table flow
|
||||||
|
@ -140,10 +140,10 @@ impl Flow for TableWrapperFlow {
|
||||||
self.block_flow.bubble_widths(ctx);
|
self.block_flow.bubble_widths(ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
/// Recursively (top-down) determines the actual width of child contexts and fragments. When
|
||||||
/// on this context, the context has had its width set by the parent context.
|
/// called on this context, the context has had its width set by the parent context.
|
||||||
///
|
///
|
||||||
/// Dual boxes consume some width first, and the remainder is assigned to all child (block)
|
/// Dual fragments consume some width first, and the remainder is assigned to all child (block)
|
||||||
/// contexts.
|
/// contexts.
|
||||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||||
debug!("assign_widths({}): assigning width for flow",
|
debug!("assign_widths({}): assigning width for flow",
|
||||||
|
@ -159,8 +159,8 @@ impl Flow for TableWrapperFlow {
|
||||||
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);
|
||||||
|
|
||||||
let left_content_edge = self.block_flow.box_.border_box.origin.x;
|
let left_content_edge = self.block_flow.fragment.border_box.origin.x;
|
||||||
let content_width = self.block_flow.box_.border_box.size.width;
|
let content_width = self.block_flow.fragment.border_box.size.width;
|
||||||
|
|
||||||
match self.table_layout {
|
match self.table_layout {
|
||||||
FixedLayout | _ if self.is_float() =>
|
FixedLayout | _ if self.is_float() =>
|
||||||
|
@ -194,9 +194,9 @@ impl Flow for TableWrapperFlow {
|
||||||
impl fmt::Show for TableWrapperFlow {
|
impl fmt::Show for TableWrapperFlow {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.is_float() {
|
if self.is_float() {
|
||||||
write!(f.buf, "TableWrapperFlow(Float): {}", self.block_flow.box_)
|
write!(f.buf, "TableWrapperFlow(Float): {}", self.block_flow.fragment)
|
||||||
} else {
|
} else {
|
||||||
write!(f.buf, "TableWrapperFlow: {}", self.block_flow.box_)
|
write!(f.buf, "TableWrapperFlow: {}", self.block_flow.fragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -232,10 +232,10 @@ 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();
|
||||||
let style = table_wrapper.block_flow.box_.style();
|
let style = table_wrapper.block_flow.fragment.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 fragment'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.get_padding().padding_left,
|
let padding_left = specified(style.get_padding().padding_left,
|
||||||
input.available_width);
|
input.available_width);
|
||||||
|
|
|
@ -25,12 +25,12 @@ struct NewLinePositions {
|
||||||
}
|
}
|
||||||
|
|
||||||
// A helper function.
|
// A helper function.
|
||||||
fn can_coalesce_text_nodes(boxes: &[Fragment], left_i: uint, right_i: uint) -> bool {
|
fn can_coalesce_text_nodes(fragments: &[Fragment], left_i: uint, right_i: uint) -> bool {
|
||||||
assert!(left_i != right_i);
|
assert!(left_i != right_i);
|
||||||
boxes[left_i].can_merge_with_box(&boxes[right_i])
|
fragments[left_i].can_merge_with_fragment(&fragments[right_i])
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextFragment`es.
|
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextFragment`s.
|
||||||
pub struct TextRunScanner {
|
pub struct TextRunScanner {
|
||||||
pub clump: Range<CharIndex>,
|
pub clump: Range<CharIndex>,
|
||||||
}
|
}
|
||||||
|
@ -45,22 +45,22 @@ impl TextRunScanner {
|
||||||
pub fn scan_for_runs(&mut self, font_context: &mut FontContext, flow: &mut Flow) {
|
pub fn scan_for_runs(&mut self, font_context: &mut FontContext, flow: &mut Flow) {
|
||||||
{
|
{
|
||||||
let inline = flow.as_immutable_inline();
|
let inline = flow.as_immutable_inline();
|
||||||
debug!("TextRunScanner: scanning {:u} boxes for text runs...", inline.boxes.len());
|
debug!("TextRunScanner: scanning {:u} fragments for text runs...", inline.fragments.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
let InlineFragments {
|
let InlineFragments {
|
||||||
boxes: old_boxes,
|
fragments: old_fragments,
|
||||||
map: mut map
|
map: mut map
|
||||||
} = mem::replace(&mut flow.as_inline().boxes, InlineFragments::new());
|
} = mem::replace(&mut flow.as_inline().fragments, InlineFragments::new());
|
||||||
|
|
||||||
let mut last_whitespace = true;
|
let mut last_whitespace = true;
|
||||||
let mut new_boxes = Vec::new();
|
let mut new_fragments = Vec::new();
|
||||||
for box_i in range(0, old_boxes.len()) {
|
for fragment_i in range(0, old_fragments.len()) {
|
||||||
debug!("TextRunScanner: considering box: {:u}", box_i);
|
debug!("TextRunScanner: considering fragment: {:u}", fragment_i);
|
||||||
if box_i > 0 && !can_coalesce_text_nodes(old_boxes.as_slice(), box_i - 1, box_i) {
|
if fragment_i > 0 && !can_coalesce_text_nodes(old_fragments.as_slice(), fragment_i - 1, fragment_i) {
|
||||||
last_whitespace = self.flush_clump_to_list(font_context,
|
last_whitespace = self.flush_clump_to_list(font_context,
|
||||||
old_boxes.as_slice(),
|
old_fragments.as_slice(),
|
||||||
&mut new_boxes,
|
&mut new_fragments,
|
||||||
last_whitespace);
|
last_whitespace);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,42 +70,42 @@ impl TextRunScanner {
|
||||||
// Handle remaining clumps.
|
// Handle remaining clumps.
|
||||||
if self.clump.length() > CharIndex(0) {
|
if self.clump.length() > CharIndex(0) {
|
||||||
drop(self.flush_clump_to_list(font_context,
|
drop(self.flush_clump_to_list(font_context,
|
||||||
old_boxes.as_slice(),
|
old_fragments.as_slice(),
|
||||||
&mut new_boxes,
|
&mut new_fragments,
|
||||||
last_whitespace))
|
last_whitespace))
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("TextRunScanner: swapping out boxes.");
|
debug!("TextRunScanner: swapping out fragments.");
|
||||||
|
|
||||||
// Swap out the old and new box list of the flow.
|
// Swap out the old and new fragment list of the flow.
|
||||||
map.fixup(old_boxes.as_slice(), new_boxes.as_slice());
|
map.fixup(old_fragments.as_slice(), new_fragments.as_slice());
|
||||||
flow.as_inline().boxes = InlineFragments {
|
flow.as_inline().fragments = InlineFragments {
|
||||||
boxes: new_boxes,
|
fragments: new_fragments,
|
||||||
map: map,
|
map: map,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// A "clump" is a range of inline flow leaves that can be merged together into a single box.
|
/// A "clump" is a range of inline flow leaves that can be merged together into a single
|
||||||
/// Adjacent text with the same style can be merged, and nothing else can.
|
/// fragment. Adjacent text with the same style can be merged, and nothing else can.
|
||||||
///
|
///
|
||||||
/// The flow keeps track of the boxes contained by all non-leaf DOM nodes. This is necessary
|
/// The flow keeps track of the fragments contained by all non-leaf DOM nodes. This is necessary
|
||||||
/// for correct painting order. Since we compress several leaf boxes here, the mapping must be
|
/// for correct painting order. Since we compress several leaf fragments here, the mapping must
|
||||||
/// adjusted.
|
/// be adjusted.
|
||||||
///
|
///
|
||||||
/// FIXME(#2267, pcwalton): Stop cloning boxes. Instead we will need to replace each `in_box`
|
/// FIXME(#2267, pcwalton): Stop cloning fragments. Instead we will need to replace each
|
||||||
/// with some smaller stub.
|
/// `in_fragment` with some smaller stub.
|
||||||
pub fn flush_clump_to_list(&mut self,
|
pub fn flush_clump_to_list(&mut self,
|
||||||
font_context: &mut FontContext,
|
font_context: &mut FontContext,
|
||||||
in_boxes: &[Fragment],
|
in_fragments: &[Fragment],
|
||||||
out_boxes: &mut Vec<Fragment>,
|
out_fragments: &mut Vec<Fragment>,
|
||||||
last_whitespace: bool)
|
last_whitespace: bool)
|
||||||
-> bool {
|
-> bool {
|
||||||
assert!(self.clump.length() > CharIndex(0));
|
assert!(self.clump.length() > CharIndex(0));
|
||||||
|
|
||||||
debug!("TextRunScanner: flushing boxes in range={}", self.clump);
|
debug!("TextRunScanner: flushing fragments in range={}", self.clump);
|
||||||
let is_singleton = self.clump.length() == CharIndex(1);
|
let is_singleton = self.clump.length() == CharIndex(1);
|
||||||
|
|
||||||
let is_text_clump = match in_boxes[self.clump.begin().to_uint()].specific {
|
let is_text_clump = match in_fragments[self.clump.begin().to_uint()].specific {
|
||||||
UnscannedTextFragment(_) => true,
|
UnscannedTextFragment(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
};
|
};
|
||||||
|
@ -116,23 +116,23 @@ impl TextRunScanner {
|
||||||
fail!("WAT: can't coalesce non-text nodes in flush_clump_to_list()!")
|
fail!("WAT: can't coalesce non-text nodes in flush_clump_to_list()!")
|
||||||
}
|
}
|
||||||
(true, false) => {
|
(true, false) => {
|
||||||
// FIXME(pcwalton): Stop cloning boxes, as above.
|
// FIXME(pcwalton): Stop cloning fragments, as above.
|
||||||
debug!("TextRunScanner: pushing single non-text box in range: {}", self.clump);
|
debug!("TextRunScanner: pushing single non-text fragment in range: {}", self.clump);
|
||||||
let new_box = in_boxes[self.clump.begin().to_uint()].clone();
|
let new_fragment = in_fragments[self.clump.begin().to_uint()].clone();
|
||||||
out_boxes.push(new_box)
|
out_fragments.push(new_fragment)
|
||||||
},
|
},
|
||||||
(true, true) => {
|
(true, true) => {
|
||||||
let old_box = &in_boxes[self.clump.begin().to_uint()];
|
let old_fragment = &in_fragments[self.clump.begin().to_uint()];
|
||||||
let text = match old_box.specific {
|
let text = match old_fragment.specific {
|
||||||
UnscannedTextFragment(ref text_box_info) => &text_box_info.text,
|
UnscannedTextFragment(ref text_fragment_info) => &text_fragment_info.text,
|
||||||
_ => fail!("Expected an unscanned text box!"),
|
_ => fail!("Expected an unscanned text fragment!"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let font_style = old_box.font_style();
|
let font_style = old_fragment.font_style();
|
||||||
let decoration = old_box.text_decoration();
|
let decoration = old_fragment.text_decoration();
|
||||||
|
|
||||||
// TODO(#115): Use the actual CSS `white-space` property of the relevant style.
|
// TODO(#115): Use the actual CSS `white-space` property of the relevant style.
|
||||||
let compression = match old_box.white_space() {
|
let compression = match old_fragment.white_space() {
|
||||||
white_space::normal => CompressWhitespaceNewline,
|
white_space::normal => CompressWhitespaceNewline,
|
||||||
white_space::pre => CompressNone,
|
white_space::pre => CompressNone,
|
||||||
};
|
};
|
||||||
|
@ -154,29 +154,29 @@ impl TextRunScanner {
|
||||||
let run = box fontgroup.borrow().create_textrun(
|
let run = box fontgroup.borrow().create_textrun(
|
||||||
transformed_text.clone(), decoration);
|
transformed_text.clone(), decoration);
|
||||||
|
|
||||||
debug!("TextRunScanner: pushing single text box in range: {} ({})",
|
debug!("TextRunScanner: pushing single text fragment in range: {} ({})",
|
||||||
self.clump,
|
self.clump,
|
||||||
*text);
|
*text);
|
||||||
let range = Range::new(CharIndex(0), run.char_len());
|
let range = Range::new(CharIndex(0), run.char_len());
|
||||||
let new_metrics = run.metrics_for_range(&range);
|
let new_metrics = run.metrics_for_range(&range);
|
||||||
let new_text_box_info = ScannedTextFragmentInfo::new(Arc::new(run), range);
|
let new_text_fragment_info = ScannedTextFragmentInfo::new(Arc::new(run), range);
|
||||||
let mut new_box = old_box.transform(new_metrics.bounding_box.size,
|
let mut new_fragment = old_fragment.transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextFragment(new_text_box_info));
|
ScannedTextFragment(new_text_fragment_info));
|
||||||
new_box.new_line_pos = new_line_pos;
|
new_fragment.new_line_pos = new_line_pos;
|
||||||
out_boxes.push(new_box)
|
out_fragments.push(new_fragment)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
(false, true) => {
|
(false, true) => {
|
||||||
// TODO(#177): Text run creation must account for the renderability of text by
|
// TODO(#177): Text run creation must account for the renderability of text by
|
||||||
// font group fonts. This is probably achieved by creating the font group above
|
// font group fonts. This is probably achieved by creating the font group above
|
||||||
// and then letting `FontGroup` decide which `Font` to stick into the text run.
|
// and then letting `FontGroup` decide which `Font` to stick into the text run.
|
||||||
let in_box = &in_boxes[self.clump.begin().to_uint()];
|
let in_fragment = &in_fragments[self.clump.begin().to_uint()];
|
||||||
let font_style = in_box.font_style();
|
let font_style = in_fragment.font_style();
|
||||||
let fontgroup = font_context.get_resolved_font_for_style(&font_style);
|
let fontgroup = font_context.get_resolved_font_for_style(&font_style);
|
||||||
let decoration = in_box.text_decoration();
|
let decoration = in_fragment.text_decoration();
|
||||||
|
|
||||||
// TODO(#115): Use the actual CSS `white-space` property of the relevant style.
|
// TODO(#115): Use the actual CSS `white-space` property of the relevant style.
|
||||||
let compression = match in_box.white_space() {
|
let compression = match in_fragment.white_space() {
|
||||||
white_space::normal => CompressWhitespaceNewline,
|
white_space::normal => CompressWhitespaceNewline,
|
||||||
white_space::pre => CompressNone,
|
white_space::pre => CompressNone,
|
||||||
};
|
};
|
||||||
|
@ -187,17 +187,17 @@ impl TextRunScanner {
|
||||||
let mut last_whitespace_in_clump = new_whitespace;
|
let mut last_whitespace_in_clump = new_whitespace;
|
||||||
let transformed_strs: Vec<~str> = Vec::from_fn(self.clump.length().to_uint(), |i| {
|
let transformed_strs: Vec<~str> = Vec::from_fn(self.clump.length().to_uint(), |i| {
|
||||||
// TODO(#113): We should be passing the compression context between calls to
|
// TODO(#113): We should be passing the compression context between calls to
|
||||||
// `transform_text`, so that boxes starting and/or ending with whitespace can
|
// `transform_text`, so that fragments starting and/or ending with whitespace can
|
||||||
// be compressed correctly with respect to the text run.
|
// be compressed correctly with respect to the text run.
|
||||||
let idx = CharIndex(i as int) + self.clump.begin();
|
let idx = CharIndex(i as int) + self.clump.begin();
|
||||||
let in_box = match in_boxes[idx.to_uint()].specific {
|
let in_fragment = match in_fragments[idx.to_uint()].specific {
|
||||||
UnscannedTextFragment(ref text_box_info) => &text_box_info.text,
|
UnscannedTextFragment(ref text_fragment_info) => &text_fragment_info.text,
|
||||||
_ => fail!("Expected an unscanned text box!"),
|
_ => fail!("Expected an unscanned text fragment!"),
|
||||||
};
|
};
|
||||||
|
|
||||||
let mut new_line_pos = vec![];
|
let mut new_line_pos = vec![];
|
||||||
|
|
||||||
let (new_str, new_whitespace) = transform_text(*in_box,
|
let (new_str, new_whitespace) = transform_text(*in_fragment,
|
||||||
compression,
|
compression,
|
||||||
last_whitespace_in_clump,
|
last_whitespace_in_clump,
|
||||||
&mut new_line_pos);
|
&mut new_line_pos);
|
||||||
|
@ -232,23 +232,23 @@ impl TextRunScanner {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
|
||||||
// Make new boxes with the run and adjusted text indices.
|
// Make new fragments with the run and adjusted text indices.
|
||||||
debug!("TextRunScanner: pushing box(es) in range: {}", self.clump);
|
debug!("TextRunScanner: pushing fragment(s) in range: {}", self.clump);
|
||||||
for i in clump.each_index() {
|
for i in clump.each_index() {
|
||||||
let logical_offset = i - self.clump.begin();
|
let logical_offset = i - self.clump.begin();
|
||||||
let range = new_ranges.get(logical_offset.to_uint());
|
let range = new_ranges.get(logical_offset.to_uint());
|
||||||
if range.length() == CharIndex(0) {
|
if range.length() == CharIndex(0) {
|
||||||
debug!("Elided an `UnscannedTextbox` because it was zero-length after \
|
debug!("Elided an `UnscannedTextFragment` because it was zero-length after \
|
||||||
compression; {}", in_boxes[i.to_uint()]);
|
compression; {}", in_fragments[i.to_uint()]);
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_text_box_info = ScannedTextFragmentInfo::new(run.get_ref().clone(), *range);
|
let new_text_fragment_info = ScannedTextFragmentInfo::new(run.get_ref().clone(), *range);
|
||||||
let new_metrics = new_text_box_info.run.metrics_for_range(range);
|
let new_metrics = new_text_fragment_info.run.metrics_for_range(range);
|
||||||
let mut new_box = in_boxes[i.to_uint()].transform(new_metrics.bounding_box.size,
|
let mut new_fragment = in_fragments[i.to_uint()].transform(new_metrics.bounding_box.size,
|
||||||
ScannedTextFragment(new_text_box_info));
|
ScannedTextFragment(new_text_fragment_info));
|
||||||
new_box.new_line_pos = new_line_positions.get(logical_offset.to_uint()).new_line_pos.clone();
|
new_fragment.new_line_pos = new_line_positions.get(logical_offset.to_uint()).new_line_pos.clone();
|
||||||
out_boxes.push(new_box)
|
out_fragments.push(new_fragment)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} // End of match.
|
} // End of match.
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue