mirror of
https://github.com/servo/servo.git
synced 2025-08-12 17:05:33 +01:00
auto merge of #2497 : bjz/servo/rename-box-type, r=pcwalton
I tried to make sure to keep 'box' where it made sense, and alter comments so they still make sense. r? @pcwalton
This commit is contained in:
commit
547ad2dc48
16 changed files with 1159 additions and 1158 deletions
|
@ -12,13 +12,13 @@
|
|||
//!
|
||||
//! CB: Containing Block of the current flow.
|
||||
|
||||
use layout::box_::{Box, ImageBox, ScannedTextBox};
|
||||
use layout::construct::FlowConstructor;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::floats::{ClearBoth, ClearLeft, ClearRight, FloatKind, Floats, PlacementInfo};
|
||||
use layout::flow::{BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use layout::flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal, mut_base};
|
||||
use layout::flow;
|
||||
use layout::fragment::{Fragment, ImageFragment, ScannedTextFragment};
|
||||
use layout::model::{Auto, IntrinsicWidths, MarginCollapseInfo, MarginsCollapse};
|
||||
use layout::model::{MarginsCollapseThrough, MaybeAuto, NoCollapsibleMargins, Specified, specified};
|
||||
use layout::model::{specified_or_none};
|
||||
|
@ -41,7 +41,6 @@ use servo_util::geometry;
|
|||
use std::fmt;
|
||||
use std::mem;
|
||||
use std::num::Zero;
|
||||
use std::owned;
|
||||
use style::computed_values::{LPA_Auto, LPA_Length, LPA_Percentage, LPN_Length, LPN_None};
|
||||
use style::computed_values::{LPN_Percentage, LP_Length, LP_Percentage, display, float, overflow};
|
||||
use sync::Arc;
|
||||
|
@ -53,7 +52,7 @@ pub struct FloatedBlockInfo {
|
|||
/// Offset relative to where the parent tried to position this flow
|
||||
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>,
|
||||
|
||||
/// Left or right?
|
||||
|
@ -489,8 +488,8 @@ pub struct BlockFlow {
|
|||
/// Data common to all flows.
|
||||
pub base: BaseFlow,
|
||||
|
||||
/// The associated box.
|
||||
pub box_: Box,
|
||||
/// The associated fragment.
|
||||
pub fragment: Fragment,
|
||||
|
||||
/// TODO: is_root should be a bit field to conserve memory.
|
||||
/// Whether this block flow is the root flow.
|
||||
|
@ -504,14 +503,14 @@ pub struct BlockFlow {
|
|||
previous_float_width: Option<Au>,
|
||||
|
||||
/// Additional floating flow members.
|
||||
pub float: Option<owned::Box<FloatedBlockInfo>>
|
||||
pub float: Option<Box<FloatedBlockInfo>>
|
||||
}
|
||||
|
||||
impl BlockFlow {
|
||||
pub fn from_node(constructor: &mut FlowConstructor, node: &ThreadSafeLayoutNode) -> BlockFlow {
|
||||
BlockFlow {
|
||||
base: BaseFlow::new((*node).clone()),
|
||||
box_: Box::new(constructor, node),
|
||||
fragment: Fragment::new(constructor, node),
|
||||
is_root: false,
|
||||
static_y_offset: Au::new(0),
|
||||
previous_float_width: None,
|
||||
|
@ -519,10 +518,10 @@ impl BlockFlow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode, box_: Box) -> BlockFlow {
|
||||
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> BlockFlow {
|
||||
BlockFlow {
|
||||
base: BaseFlow::new((*node).clone()),
|
||||
box_: box_,
|
||||
fragment: fragment,
|
||||
is_root: false,
|
||||
static_y_offset: Au::new(0),
|
||||
previous_float_width: None,
|
||||
|
@ -536,7 +535,7 @@ impl BlockFlow {
|
|||
-> BlockFlow {
|
||||
BlockFlow {
|
||||
base: BaseFlow::new((*node).clone()),
|
||||
box_: Box::new(constructor, node),
|
||||
fragment: Fragment::new(constructor, node),
|
||||
is_root: false,
|
||||
static_y_offset: Au::new(0),
|
||||
previous_float_width: None,
|
||||
|
@ -601,9 +600,9 @@ impl BlockFlow {
|
|||
}
|
||||
}
|
||||
|
||||
/// Return this flow's box.
|
||||
pub fn box_<'a>(&'a mut self) -> &'a mut Box {
|
||||
&mut self.box_
|
||||
/// Return this flow's fragment.
|
||||
pub fn fragment<'a>(&'a mut self) -> &'a mut Fragment {
|
||||
&mut self.fragment
|
||||
}
|
||||
|
||||
/// Return the static x offset from the appropriate Containing Block for this flow.
|
||||
|
@ -699,13 +698,13 @@ impl BlockFlow {
|
|||
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
|
||||
/// image boxes.
|
||||
/// The only two types of replaced fragments currently are text fragments
|
||||
/// and image fragments.
|
||||
fn is_replaced_content(&self) -> bool {
|
||||
match self.box_.specific {
|
||||
ScannedTextBox(_) | ImageBox(_) => true,
|
||||
match self.fragment.specific {
|
||||
ScannedTextFragment(_) | ImageFragment(_) => true,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
@ -766,7 +765,7 @@ impl BlockFlow {
|
|||
///
|
||||
/// TODO(#2017, pcwalton): This is somewhat inefficient (traverses kids twice); can we do
|
||||
/// 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() {
|
||||
return
|
||||
}
|
||||
|
@ -789,7 +788,7 @@ impl BlockFlow {
|
|||
|
||||
self.base.position.size.height = self.base.position.size.height + top_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;
|
||||
}
|
||||
|
||||
|
@ -823,17 +822,17 @@ impl BlockFlow {
|
|||
}
|
||||
|
||||
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.
|
||||
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);
|
||||
|
||||
let can_collapse_top_margin_with_kids =
|
||||
margins_may_collapse == MarginsMayCollapse &&
|
||||
!self.is_absolutely_positioned() &&
|
||||
self.box_.border_padding.top == Au(0);
|
||||
margin_collapse_info.initialize_top_margin(&self.box_,
|
||||
self.fragment.border_padding.top == Au(0);
|
||||
margin_collapse_info.initialize_top_margin(&self.fragment,
|
||||
can_collapse_top_margin_with_kids);
|
||||
|
||||
// At this point, `cur_y` is at the content edge of our box. Now iterate over children.
|
||||
|
@ -935,10 +934,10 @@ impl BlockFlow {
|
|||
let can_collapse_bottom_margin_with_kids =
|
||||
margins_may_collapse == MarginsMayCollapse &&
|
||||
!self.is_absolutely_positioned() &&
|
||||
self.box_.border_padding.bottom == Au(0);
|
||||
self.fragment.border_padding.bottom == Au(0);
|
||||
let (collapsible_margins, delta) =
|
||||
margin_collapse_info.finish_and_compute_collapsible_margins(
|
||||
&self.box_,
|
||||
&self.fragment,
|
||||
can_collapse_bottom_margin_with_kids);
|
||||
self.base.collapsible_margins = collapsible_margins;
|
||||
translate_including_floats(&mut cur_y, delta, &mut floats);
|
||||
|
@ -964,11 +963,11 @@ impl BlockFlow {
|
|||
|
||||
// Store the content height for use in calculating the absolute flow's dimensions
|
||||
// later.
|
||||
self.box_.border_box.size.height = height;
|
||||
self.fragment.border_box.size.height = height;
|
||||
return
|
||||
}
|
||||
|
||||
let mut candidate_height_iterator = CandidateHeightIterator::new(self.box_.style(),
|
||||
let mut candidate_height_iterator = CandidateHeightIterator::new(self.fragment.style(),
|
||||
None);
|
||||
for (candidate_height, new_candidate_height) in candidate_height_iterator {
|
||||
*new_candidate_height = match candidate_height {
|
||||
|
@ -983,17 +982,17 @@ impl BlockFlow {
|
|||
translate_including_floats(&mut cur_y, delta, &mut floats);
|
||||
|
||||
// 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);
|
||||
|
||||
// Now that `cur_y` is at the bottom of the border box, compute the final border box
|
||||
// position.
|
||||
self.box_.border_box.size.height = cur_y;
|
||||
self.box_.border_box.origin.y = Au(0);
|
||||
self.fragment.border_box.size.height = cur_y;
|
||||
self.fragment.border_box.origin.y = Au(0);
|
||||
self.base.position.size.height = cur_y;
|
||||
|
||||
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() {
|
||||
// Assign heights for all flows in this Absolute flow tree.
|
||||
|
@ -1019,16 +1018,16 @@ impl BlockFlow {
|
|||
/// already called on this kid flow by the traversal function. So, the values used are
|
||||
/// well-defined.
|
||||
pub fn place_float(&mut self) {
|
||||
let height = self.box_.border_box.size.height;
|
||||
let clearance = match self.box_.clear() {
|
||||
let height = self.fragment.border_box.size.height;
|
||||
let clearance = match self.fragment.clear() {
|
||||
None => Au(0),
|
||||
Some(clear) => self.base.floats.clearance(clear),
|
||||
};
|
||||
|
||||
let margin_height = self.box_.margin.vertical();
|
||||
let margin_height = self.fragment.margin.vertical();
|
||||
let info = PlacementInfo {
|
||||
size: Size2D(self.base.position.size.width + self.box_.margin.horizontal() +
|
||||
self.box_.border_padding.horizontal(),
|
||||
size: Size2D(self.base.position.size.width + self.fragment.margin.horizontal() +
|
||||
self.fragment.border_padding.horizontal(),
|
||||
height + margin_height),
|
||||
ceiling: clearance + self.base.position.origin.y,
|
||||
max_width: self.float.get_ref().containing_width,
|
||||
|
@ -1061,7 +1060,7 @@ impl BlockFlow {
|
|||
// Floats establish a block formatting context, so we discard the output floats here.
|
||||
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;
|
||||
|
||||
// cur_y is now at the top content edge
|
||||
|
@ -1075,11 +1074,11 @@ impl BlockFlow {
|
|||
|
||||
let content_height = cur_y - top_offset;
|
||||
|
||||
// The associated box is the border box of this flow.
|
||||
self.box_.border_box.origin.y = self.box_.margin.top;
|
||||
// The associated fragment has the border box of this flow.
|
||||
self.fragment.border_box.origin.y = self.fragment.margin.top;
|
||||
|
||||
// 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 {
|
||||
*new_candidate_height = match candidate_height {
|
||||
Auto => content_height,
|
||||
|
@ -1088,9 +1087,9 @@ impl BlockFlow {
|
|||
}
|
||||
|
||||
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);
|
||||
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,
|
||||
|
@ -1098,7 +1097,7 @@ impl BlockFlow {
|
|||
offset: Point2D<Au>,
|
||||
background_border_level: BackgroundAndBorderLevel) {
|
||||
let rel_offset =
|
||||
self.box_.relative_position(&self.base
|
||||
self.fragment.relative_position(&self.base
|
||||
.absolute_position_info
|
||||
.relative_containing_block_size,
|
||||
None);
|
||||
|
@ -1106,11 +1105,11 @@ impl BlockFlow {
|
|||
// Add the box that starts the block context.
|
||||
let mut display_list = DisplayList::new();
|
||||
let mut accumulator =
|
||||
self.box_.build_display_list(&mut display_list,
|
||||
layout_context,
|
||||
self.base.abs_position + rel_offset + offset,
|
||||
background_border_level,
|
||||
None);
|
||||
self.fragment.build_display_list(&mut display_list,
|
||||
layout_context,
|
||||
self.base.abs_position + rel_offset + offset,
|
||||
background_border_level,
|
||||
None);
|
||||
|
||||
let mut child_layers = DList::new();
|
||||
for kid in self.base.child_iter() {
|
||||
|
@ -1177,39 +1176,39 @@ impl BlockFlow {
|
|||
let static_y_offset = self.static_y_offset;
|
||||
|
||||
// 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;
|
||||
{
|
||||
// Non-auto margin-top and margin-bottom values have already been
|
||||
// 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,
|
||||
_ => 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,
|
||||
_ => Specified(self.box_.margin.bottom)
|
||||
_ => Specified(self.fragment.margin.bottom)
|
||||
};
|
||||
|
||||
let top;
|
||||
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);
|
||||
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() {
|
||||
// Calculate used value of height just like we do for inline replaced elements.
|
||||
// TODO: Pass in the containing block height when Box's
|
||||
// TODO: Pass in the containing block height when Fragment's
|
||||
// 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
|
||||
// margin because of erroneous height calculation in Box_.
|
||||
// margin because of erroneous height calculation in fragment.
|
||||
// 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(
|
||||
height_used_val,
|
||||
margin_top,
|
||||
|
@ -1220,7 +1219,7 @@ impl BlockFlow {
|
|||
available_height,
|
||||
static_y_offset));
|
||||
} else {
|
||||
let style = self.box_.style();
|
||||
let style = self.fragment.style();
|
||||
let mut candidate_height_iterator =
|
||||
CandidateHeightIterator::new(style, Some(containing_block_height));
|
||||
|
||||
|
@ -1242,13 +1241,13 @@ impl BlockFlow {
|
|||
}
|
||||
|
||||
let solution = solution.unwrap();
|
||||
self.box_.margin.top = solution.margin_top;
|
||||
self.box_.margin.bottom = solution.margin_bottom;
|
||||
self.box_.border_box.origin.y = Au(0);
|
||||
self.box_.border_box.size.height = solution.height + self.box_.border_padding.vertical();
|
||||
self.fragment.margin.top = solution.margin_top;
|
||||
self.fragment.margin.bottom = solution.margin_bottom;
|
||||
self.fragment.border_box.origin.y = Au(0);
|
||||
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.size.height = solution.height + self.box_.border_padding.vertical();
|
||||
self.base.position.origin.y = solution.top + self.fragment.margin.top;
|
||||
self.base.position.size.height = solution.height + self.fragment.border_padding.vertical();
|
||||
}
|
||||
|
||||
/// Add display items for Absolutely Positioned flow.
|
||||
|
@ -1289,7 +1288,7 @@ impl BlockFlow {
|
|||
self.base.layers.push_back(new_layer)
|
||||
}
|
||||
|
||||
/// Return the top outer edge of the Hypothetical Box for an absolute flow.
|
||||
/// Return the top outer edge of the hypothetical box for an absolute flow.
|
||||
///
|
||||
/// This is wrt its parent flow box.
|
||||
///
|
||||
|
@ -1317,7 +1316,7 @@ impl BlockFlow {
|
|||
let absolute_static_x_offset = if self.is_positioned() {
|
||||
// This flow is the containing block. The static X offset will be the left padding
|
||||
// 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 {
|
||||
// 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.
|
||||
|
@ -1396,7 +1395,7 @@ impl BlockFlow {
|
|||
/// Determines the type of formatting context this is. See the definition of
|
||||
/// `FormattingContextType`.
|
||||
fn formatting_context_type(&self) -> FormattingContextType {
|
||||
let style = self.box_.style();
|
||||
let style = self.fragment.style();
|
||||
if style.get_box().float != float::none {
|
||||
return OtherFormattingContext
|
||||
}
|
||||
|
@ -1404,7 +1403,7 @@ impl BlockFlow {
|
|||
display::table_cell | display::table_caption | display::inline_block => {
|
||||
OtherFormattingContext
|
||||
}
|
||||
_ if style.get_box().position == position::static_ &&
|
||||
_ if style.get_box().position == position::static_ &&
|
||||
style.get_box().overflow != overflow::visible => {
|
||||
BlockFormattingContext
|
||||
}
|
||||
|
@ -1424,7 +1423,7 @@ impl Flow for BlockFlow {
|
|||
|
||||
/// Returns the direction that this flow clears floats in, if any.
|
||||
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.
|
||||
|
@ -1432,7 +1431,7 @@ impl Flow for BlockFlow {
|
|||
/// 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
|
||||
/// 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.
|
||||
fn bubble_widths(&mut self, _: &mut LayoutContext) {
|
||||
|
@ -1458,15 +1457,15 @@ impl Flow for BlockFlow {
|
|||
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,
|
||||
box_intrinsic_widths.minimum_width);
|
||||
fragment_intrinsic_widths.minimum_width);
|
||||
intrinsic_widths.preferred_width = geometry::max(intrinsic_widths.preferred_width,
|
||||
box_intrinsic_widths.preferred_width);
|
||||
intrinsic_widths.surround_width = box_intrinsic_widths.surround_width;
|
||||
fragment_intrinsic_widths.preferred_width);
|
||||
intrinsic_widths.surround_width = fragment_intrinsic_widths.surround_width;
|
||||
self.base.intrinsic_widths = intrinsic_widths;
|
||||
|
||||
match self.box_.style().get_box().float {
|
||||
match self.fragment.style().get_box().float {
|
||||
float::none => {}
|
||||
float::left => flags.set_has_left_floated_descendants(true),
|
||||
float::right => flags.set_has_right_floated_descendants(true),
|
||||
|
@ -1474,10 +1473,10 @@ impl Flow for BlockFlow {
|
|||
self.base.flags = flags
|
||||
}
|
||||
|
||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
||||
/// on this context, the context has had its width set by the parent context.
|
||||
/// 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.
|
||||
///
|
||||
/// 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.
|
||||
fn assign_widths(&mut self, layout_context: &mut LayoutContext) {
|
||||
debug!("assign_widths({}): assigning width for flow",
|
||||
|
@ -1519,8 +1518,8 @@ impl Flow for BlockFlow {
|
|||
match self.previous_float_width {
|
||||
None => {}
|
||||
Some(previous_float_width) => {
|
||||
self.box_.border_box.size.width =
|
||||
self.box_.border_box.size.width - previous_float_width
|
||||
self.fragment.border_box.size.width =
|
||||
self.fragment.border_box.size.width - previous_float_width
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1531,9 +1530,9 @@ impl Flow for BlockFlow {
|
|||
}
|
||||
|
||||
// Move in from the left border edge
|
||||
let left_content_edge = self.box_.border_box.origin.x + self.box_.border_padding.left;
|
||||
let padding_and_borders = self.box_.border_padding.horizontal();
|
||||
let content_width = self.box_.border_box.size.width - padding_and_borders;
|
||||
let left_content_edge = self.fragment.border_box.origin.x + self.fragment.border_padding.left;
|
||||
let padding_and_borders = self.fragment.border_padding.horizontal();
|
||||
let content_width = self.fragment.border_box.size.width - padding_and_borders;
|
||||
|
||||
if self.is_float() {
|
||||
self.base.position.size.width = content_width;
|
||||
|
@ -1563,8 +1562,8 @@ impl Flow for BlockFlow {
|
|||
}
|
||||
|
||||
fn assign_height(&mut self, ctx: &mut LayoutContext) {
|
||||
// Assign height for box if it is an image box.
|
||||
self.box_.assign_replaced_height_if_necessary();
|
||||
// Assign height for fragment if it is an image fragment.
|
||||
self.fragment.assign_replaced_height_if_necessary();
|
||||
|
||||
if self.is_float() {
|
||||
debug!("assign_height_float: assigning height for float");
|
||||
|
@ -1599,10 +1598,10 @@ impl Flow for BlockFlow {
|
|||
// the content box. The containing block for absolutely-positioned descendants, on the
|
||||
// other hand, is only established if we are positioned.
|
||||
let relative_offset =
|
||||
self.box_.relative_position(&self.base
|
||||
.absolute_position_info
|
||||
.relative_containing_block_size,
|
||||
None);
|
||||
self.fragment.relative_position(&self.base
|
||||
.absolute_position_info
|
||||
.relative_containing_block_size,
|
||||
None);
|
||||
if self.is_positioned() {
|
||||
self.base.absolute_position_info.absolute_containing_block_position =
|
||||
self.base.abs_position +
|
||||
|
@ -1618,7 +1617,7 @@ impl Flow for BlockFlow {
|
|||
|
||||
// Compute absolute position info for children.
|
||||
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 =
|
||||
self.base.flags.layers_needed_for_descendants();
|
||||
|
||||
|
@ -1666,7 +1665,7 @@ impl Flow for BlockFlow {
|
|||
|
||||
/// The 'position' property of this flow.
|
||||
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.
|
||||
|
@ -1679,17 +1678,17 @@ impl Flow for BlockFlow {
|
|||
/// Return the dimensions of the containing block generated by this flow for absolutely-
|
||||
/// positioned descendants. For block flows, this is the padding box.
|
||||
fn generated_containing_block_rect(&self) -> Rect<Au> {
|
||||
let border = model::border_from_style(self.box_.style());
|
||||
Rect(self.box_.border_box.origin + Point2D(border.left, border.top),
|
||||
Size2D(self.box_.border_box.size.width - border.horizontal(),
|
||||
self.box_.border_box.size.height - border.vertical()))
|
||||
let border = model::border_from_style(self.fragment.style());
|
||||
Rect(self.fragment.border_box.origin + Point2D(border.left, border.top),
|
||||
Size2D(self.fragment.border_box.size.width - border.horizontal(),
|
||||
self.fragment.border_box.size.height - border.vertical()))
|
||||
}
|
||||
|
||||
fn layer_id(&self, fragment_index: uint) -> LayerId {
|
||||
// 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
|
||||
// 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 {
|
||||
|
@ -1700,11 +1699,11 @@ impl Flow for BlockFlow {
|
|||
impl fmt::Show for BlockFlow {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.is_float() {
|
||||
write!(f.buf, "FloatFlow: {}", self.box_)
|
||||
write!(f.buf, "FloatFlow: {}", self.fragment)
|
||||
} else if self.is_root() {
|
||||
write!(f.buf, "RootFlow: {}", self.box_)
|
||||
write!(f.buf, "RootFlow: {}", self.fragment)
|
||||
} else {
|
||||
write!(f.buf, "BlockFlow: {}", self.box_)
|
||||
write!(f.buf, "BlockFlow: {}", self.fragment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1794,9 +1793,9 @@ pub trait WidthAndMarginsComputer {
|
|||
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);
|
||||
|
||||
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.
|
||||
block.base.flags.set_text_align(style.get_inheritedtext().text_align);
|
||||
|
@ -1808,7 +1807,7 @@ pub trait WidthAndMarginsComputer {
|
|||
let (left, right) =
|
||||
(MaybeAuto::from_style(style.get_positionoffsets().left, 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,
|
||||
margin_left,
|
||||
margin_right,
|
||||
|
@ -1829,15 +1828,15 @@ pub trait WidthAndMarginsComputer {
|
|||
fn set_width_constraint_solutions(&self,
|
||||
block: &mut BlockFlow,
|
||||
solution: WidthConstraintSolution) {
|
||||
let box_ = block.box_();
|
||||
box_.margin.left = solution.margin_left;
|
||||
box_.margin.right = solution.margin_right;
|
||||
let fragment = block.fragment();
|
||||
fragment.margin.left = solution.margin_left;
|
||||
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.
|
||||
box_.border_box.origin.x = box_.margin.left;
|
||||
fragment.border_box.origin.x = fragment.margin.left;
|
||||
// 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.
|
||||
|
@ -1854,7 +1853,7 @@ pub trait WidthAndMarginsComputer {
|
|||
parent_flow_width: Au,
|
||||
ctx: &mut LayoutContext)
|
||||
-> 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))
|
||||
}
|
||||
|
||||
|
@ -1881,7 +1880,7 @@ pub trait WidthAndMarginsComputer {
|
|||
|
||||
// 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'.
|
||||
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 => {
|
||||
input.computed_width = Specified(max_width);
|
||||
solution = self.solve_width_constraints(block, &input);
|
||||
|
@ -1891,7 +1890,7 @@ pub trait WidthAndMarginsComputer {
|
|||
|
||||
// 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'.
|
||||
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);
|
||||
if computed_min_width > solution.width {
|
||||
input.computed_width = Specified(computed_min_width);
|
||||
|
@ -2234,11 +2233,11 @@ impl WidthAndMarginsComputer for AbsoluteReplaced {
|
|||
ctx: &mut LayoutContext)
|
||||
-> MaybeAuto {
|
||||
let containing_block_width = block.containing_block_size(ctx.screen_size).width;
|
||||
let box_ = block.box_();
|
||||
box_.assign_replaced_width_if_necessary(containing_block_width, None);
|
||||
let fragment = block.fragment();
|
||||
fragment.assign_replaced_width_if_necessary(containing_block_width, None);
|
||||
// For replaced absolute flow, the rest of the constraint solving will
|
||||
// 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 {
|
||||
|
@ -2283,11 +2282,11 @@ impl WidthAndMarginsComputer for BlockReplaced {
|
|||
parent_flow_width: Au,
|
||||
_: &mut LayoutContext)
|
||||
-> MaybeAuto {
|
||||
let box_ = block.box_();
|
||||
box_.assign_replaced_width_if_necessary(parent_flow_width, None);
|
||||
let fragment = block.fragment();
|
||||
fragment.assign_replaced_width_if_necessary(parent_flow_width, None);
|
||||
// For replaced block flow, the rest of the constraint solving will
|
||||
// take width to be specified as the value computed here.
|
||||
Specified(box_.content_width())
|
||||
Specified(fragment.content_width())
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -2339,11 +2338,11 @@ impl WidthAndMarginsComputer for FloatReplaced {
|
|||
parent_flow_width: Au,
|
||||
_: &mut LayoutContext)
|
||||
-> MaybeAuto {
|
||||
let box_ = block.box_();
|
||||
box_.assign_replaced_width_if_necessary(parent_flow_width, None);
|
||||
let fragment = block.fragment();
|
||||
fragment.assign_replaced_width_if_necessary(parent_flow_width, None);
|
||||
// For replaced block flow, the rest of the constraint solving will
|
||||
// take width to be specified as the value computed here.
|
||||
Specified(box_.content_width())
|
||||
Specified(fragment.content_width())
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
* 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/. */
|
||||
|
||||
//! 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
|
||||
//! not dirty and an existing flow exists, then the traversal reuses that flow. Otherwise, it
|
||||
|
@ -22,15 +22,15 @@
|
|||
|
||||
use css::node_style::StyledNode;
|
||||
use layout::block::BlockFlow;
|
||||
use layout::box_::{Box, GenericBox, IframeBox, IframeBoxInfo, ImageBox, ImageBoxInfo};
|
||||
use layout::box_::{SpecificBoxInfo, TableBox, TableCellBox, TableColumnBox, TableColumnBoxInfo};
|
||||
use layout::box_::{TableRowBox, TableWrapperBox, UnscannedTextBox, UnscannedTextBoxInfo};
|
||||
use layout::context::LayoutContext;
|
||||
use layout::floats::FloatKind;
|
||||
use layout::flow::{Flow, ImmutableFlowUtils, MutableOwnedFlowUtils};
|
||||
use layout::flow::{Descendants, AbsDescendants};
|
||||
use layout::flow_list::{Rawlink};
|
||||
use layout::inline::{FragmentIndex, InlineBoxes, InlineFlow};
|
||||
use layout::fragment::{Fragment, GenericFragment, IframeFragment, IframeFragmentInfo, ImageFragment, ImageFragmentInfo};
|
||||
use layout::fragment::{SpecificFragmentInfo, TableFragment, TableCellFragment, TableColumnFragment, TableColumnFragmentInfo};
|
||||
use layout::fragment::{TableRowFragment, TableWrapperFragment, UnscannedTextFragment, UnscannedTextFragmentInfo};
|
||||
use layout::inline::{FragmentIndex, InlineFragments, InlineFlow};
|
||||
use layout::table_wrapper::TableWrapperFlow;
|
||||
use layout::table::TableFlow;
|
||||
use layout::table_caption::TableCaptionFlow;
|
||||
|
@ -60,7 +60,6 @@ use servo_util::range::Range;
|
|||
use servo_util::str::is_whitespace;
|
||||
use servo_util::url::{is_image_data, parse_url};
|
||||
use std::mem;
|
||||
use std::owned;
|
||||
use style::ComputedValues;
|
||||
use style::computed_values::{display, position, float, white_space};
|
||||
use sync::Arc;
|
||||
|
@ -75,7 +74,7 @@ pub enum ConstructionResult {
|
|||
/// This node contributed a flow at the proper position in the tree.
|
||||
/// Nothing more needs to be done for this node. It has bubbled up fixed
|
||||
/// and absolute descendant flows that have a CB above it.
|
||||
FlowConstructionResult(owned::Box<Flow:Share>, AbsDescendants),
|
||||
FlowConstructionResult(Box<Flow:Share>, AbsDescendants),
|
||||
|
||||
/// This node contributed some object or objects that will be needed to construct a proper flow
|
||||
/// later up the tree, but these objects have not yet found their home.
|
||||
|
@ -96,35 +95,35 @@ impl ConstructionResult {
|
|||
/// complete flow. Construction items bubble up the tree until they find a `Flow` to be
|
||||
/// attached to.
|
||||
pub enum ConstructionItem {
|
||||
/// Inline boxes and associated {ib} splits that have not yet found flows.
|
||||
InlineBoxesConstructionItem(InlineBoxesConstructionResult),
|
||||
/// Inline fragments and associated {ib} splits that have not yet found flows.
|
||||
InlineFragmentsConstructionItem(InlineFragmentsConstructionResult),
|
||||
/// Potentially ignorable whitespace.
|
||||
WhitespaceConstructionItem(OpaqueNode, Arc<ComputedValues>),
|
||||
/// TableColumn Box
|
||||
TableColumnBoxConstructionItem(Box),
|
||||
/// TableColumn Fragment
|
||||
TableColumnFragmentConstructionItem(Fragment),
|
||||
}
|
||||
|
||||
impl ConstructionItem {
|
||||
fn destroy(&mut self) {
|
||||
match *self {
|
||||
InlineBoxesConstructionItem(ref mut result) => {
|
||||
InlineFragmentsConstructionItem(ref mut result) => {
|
||||
for split in result.splits.mut_iter() {
|
||||
split.destroy()
|
||||
}
|
||||
}
|
||||
WhitespaceConstructionItem(..) => {}
|
||||
TableColumnBoxConstructionItem(_) => {}
|
||||
TableColumnFragmentConstructionItem(_) => {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Represents inline boxes and {ib} splits that are bubbling up from an inline.
|
||||
pub struct InlineBoxesConstructionResult {
|
||||
/// Represents inline fragments and {ib} splits that are bubbling up from an inline.
|
||||
pub struct InlineFragmentsConstructionResult {
|
||||
/// Any {ib} splits that we're bubbling up.
|
||||
pub splits: Vec<InlineBlockSplit>,
|
||||
|
||||
/// Any boxes that succeed the {ib} splits.
|
||||
pub boxes: InlineBoxes,
|
||||
/// Any fragments that succeed the {ib} splits.
|
||||
pub fragments: InlineFragments,
|
||||
|
||||
/// Any absolute descendants that we're bubbling up.
|
||||
pub abs_descendants: AbsDescendants,
|
||||
|
@ -141,9 +140,9 @@ pub struct InlineBoxesConstructionResult {
|
|||
///
|
||||
/// The resulting `ConstructionItem` for the outer `span` will be:
|
||||
///
|
||||
/// InlineBoxesConstructionItem(Some(~[
|
||||
/// InlineFragmentsConstructionItem(Some(~[
|
||||
/// InlineBlockSplit {
|
||||
/// predecessor_boxes: ~[
|
||||
/// predecessor_fragments: ~[
|
||||
/// A
|
||||
/// ],
|
||||
/// block: ~BlockFlow {
|
||||
|
@ -153,11 +152,11 @@ pub struct InlineBoxesConstructionResult {
|
|||
/// C
|
||||
/// ])
|
||||
pub struct InlineBlockSplit {
|
||||
/// The inline boxes that precede the flow.
|
||||
pub predecessors: InlineBoxes,
|
||||
/// The inline fragments that precede the flow.
|
||||
pub predecessors: InlineFragments,
|
||||
|
||||
/// The flow that caused this {ib} split.
|
||||
pub flow: owned::Box<Flow:Share>,
|
||||
pub flow: Box<Flow:Share>,
|
||||
}
|
||||
|
||||
impl InlineBlockSplit {
|
||||
|
@ -166,44 +165,44 @@ impl InlineBlockSplit {
|
|||
}
|
||||
}
|
||||
|
||||
/// Holds inline boxes that we're gathering for children of an inline node.
|
||||
struct InlineBoxAccumulator {
|
||||
/// The list of boxes.
|
||||
boxes: InlineBoxes,
|
||||
/// Holds inline fragments that we're gathering for children of an inline node.
|
||||
struct InlineFragmentsAccumulator {
|
||||
/// The list of fragments.
|
||||
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.
|
||||
has_enclosing_range: bool,
|
||||
}
|
||||
|
||||
impl InlineBoxAccumulator {
|
||||
fn new() -> InlineBoxAccumulator {
|
||||
InlineBoxAccumulator {
|
||||
boxes: InlineBoxes::new(),
|
||||
impl InlineFragmentsAccumulator {
|
||||
fn new() -> InlineFragmentsAccumulator {
|
||||
InlineFragmentsAccumulator {
|
||||
fragments: InlineFragments::new(),
|
||||
has_enclosing_range: false,
|
||||
}
|
||||
}
|
||||
|
||||
fn from_inline_node(node: &ThreadSafeLayoutNode) -> InlineBoxAccumulator {
|
||||
let mut boxes = InlineBoxes::new();
|
||||
boxes.map.push(node.style().clone(), Range::empty());
|
||||
InlineBoxAccumulator {
|
||||
boxes: boxes,
|
||||
fn from_inline_node(node: &ThreadSafeLayoutNode) -> InlineFragmentsAccumulator {
|
||||
let mut fragments = InlineFragments::new();
|
||||
fragments.map.push(node.style().clone(), Range::empty());
|
||||
InlineFragmentsAccumulator {
|
||||
fragments: fragments,
|
||||
has_enclosing_range: true,
|
||||
}
|
||||
}
|
||||
|
||||
fn finish(self) -> InlineBoxes {
|
||||
let InlineBoxAccumulator {
|
||||
boxes: mut boxes,
|
||||
fn finish(self) -> InlineFragments {
|
||||
let InlineFragmentsAccumulator {
|
||||
fragments: mut fragments,
|
||||
has_enclosing_range
|
||||
} = self;
|
||||
|
||||
if has_enclosing_range {
|
||||
let len = FragmentIndex(boxes.len() as int);
|
||||
boxes.map.get_mut(FragmentIndex(0)).range.extend_to(len);
|
||||
let len = FragmentIndex(fragments.len() as int);
|
||||
fragments.map.get_mut(FragmentIndex(0)).range.extend_to(len);
|
||||
}
|
||||
boxes
|
||||
fragments
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,12 +222,12 @@ pub struct FlowConstructor<'a> {
|
|||
///
|
||||
/// FIXME(pcwalton): This is pretty bogus and is basically just a workaround for libgreen
|
||||
/// having slow TLS.
|
||||
pub font_context: Option<owned::Box<FontContext>>,
|
||||
pub font_context: Option<Box<FontContext>>,
|
||||
}
|
||||
|
||||
impl<'a> FlowConstructor<'a> {
|
||||
/// Creates a new flow constructor.
|
||||
pub fn new(layout_context: &'a mut LayoutContext, font_context: Option<owned::Box<FontContext>>)
|
||||
pub fn new(layout_context: &'a mut LayoutContext, font_context: Option<Box<FontContext>>)
|
||||
-> FlowConstructor<'a> {
|
||||
FlowConstructor {
|
||||
layout_context: layout_context,
|
||||
|
@ -247,7 +246,7 @@ impl<'a> FlowConstructor<'a> {
|
|||
}
|
||||
|
||||
/// Destroys this flow constructor and retrieves the font context.
|
||||
pub fn unwrap_font_context(self) -> Option<owned::Box<FontContext>> {
|
||||
pub fn unwrap_font_context(self) -> Option<Box<FontContext>> {
|
||||
let FlowConstructor {
|
||||
font_context,
|
||||
..
|
||||
|
@ -255,82 +254,82 @@ impl<'a> FlowConstructor<'a> {
|
|||
font_context
|
||||
}
|
||||
|
||||
/// Builds the `ImageBoxInfo` 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>)
|
||||
-> SpecificBoxInfo {
|
||||
/// Builds the `ImageFragmentInfo` for the given image. This is out of line to guide inlining.
|
||||
fn build_fragment_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>)
|
||||
-> SpecificFragmentInfo {
|
||||
match url {
|
||||
None => GenericBox,
|
||||
None => GenericFragment,
|
||||
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.
|
||||
ImageBox(ImageBoxInfo::new(node, url, self.layout_context.image_cache.clone()))
|
||||
ImageFragment(ImageFragmentInfo::new(node, url, self.layout_context.image_cache.clone()))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Builds specific `Box` info for the given node.
|
||||
pub fn build_specific_box_info_for_node(&mut self, node: &ThreadSafeLayoutNode)
|
||||
-> SpecificBoxInfo {
|
||||
/// Builds specific `Fragment` info for the given node.
|
||||
pub fn build_specific_fragment_info_for_node(&mut self, node: &ThreadSafeLayoutNode)
|
||||
-> SpecificFragmentInfo {
|
||||
match node.type_id() {
|
||||
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)) => {
|
||||
IframeBox(IframeBoxInfo::new(node))
|
||||
IframeFragment(IframeFragmentInfo::new(node))
|
||||
}
|
||||
Some(ElementNodeTypeId(HTMLObjectElementTypeId)) => {
|
||||
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)) => TableWrapperBox,
|
||||
Some(ElementNodeTypeId(HTMLTableElementTypeId)) => TableWrapperFragment,
|
||||
Some(ElementNodeTypeId(HTMLTableColElementTypeId)) => {
|
||||
TableColumnBox(TableColumnBoxInfo::new(node))
|
||||
TableColumnFragment(TableColumnFragmentInfo::new(node))
|
||||
}
|
||||
Some(ElementNodeTypeId(HTMLTableDataCellElementTypeId)) |
|
||||
Some(ElementNodeTypeId(HTMLTableHeaderCellElementTypeId)) => TableCellBox,
|
||||
Some(ElementNodeTypeId(HTMLTableHeaderCellElementTypeId)) => TableCellFragment,
|
||||
Some(ElementNodeTypeId(HTMLTableRowElementTypeId)) |
|
||||
Some(ElementNodeTypeId(HTMLTableSectionElementTypeId)) => TableRowBox,
|
||||
None | Some(TextNodeTypeId) => UnscannedTextBox(UnscannedTextBoxInfo::new(node)),
|
||||
_ => GenericBox,
|
||||
Some(ElementNodeTypeId(HTMLTableSectionElementTypeId)) => TableRowFragment,
|
||||
None | Some(TextNodeTypeId) => UnscannedTextFragment(UnscannedTextFragmentInfo::new(node)),
|
||||
_ => GenericFragment,
|
||||
}
|
||||
}
|
||||
|
||||
/// 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.
|
||||
///
|
||||
/// `#[inline(always)]` because this is performance critical and LLVM will not inline it
|
||||
/// otherwise.
|
||||
#[inline(always)]
|
||||
fn flush_inline_boxes_to_flow_or_list(&mut self,
|
||||
box_accumulator: InlineBoxAccumulator,
|
||||
flow: &mut owned::Box<Flow:Share>,
|
||||
flow_list: &mut Vec<owned::Box<Flow:Share>>,
|
||||
fn flush_inline_fragments_to_flow_or_list(&mut self,
|
||||
fragment_accumulator: InlineFragmentsAccumulator,
|
||||
flow: &mut Box<Flow:Share>,
|
||||
flow_list: &mut Vec<Box<Flow:Share>>,
|
||||
whitespace_stripping: WhitespaceStrippingMode,
|
||||
node: &ThreadSafeLayoutNode) {
|
||||
let mut boxes = box_accumulator.finish();
|
||||
if boxes.len() == 0 {
|
||||
let mut fragments = fragment_accumulator.finish();
|
||||
if fragments.len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
match whitespace_stripping {
|
||||
NoWhitespaceStripping => {}
|
||||
StripWhitespaceFromStart => {
|
||||
strip_ignorable_whitespace_from_start(&mut boxes);
|
||||
if boxes.len() == 0 {
|
||||
strip_ignorable_whitespace_from_start(&mut fragments);
|
||||
if fragments.len() == 0 {
|
||||
return
|
||||
}
|
||||
}
|
||||
StripWhitespaceFromEnd => {
|
||||
strip_ignorable_whitespace_from_end(&mut boxes);
|
||||
if boxes.len() == 0 {
|
||||
strip_ignorable_whitespace_from_end(&mut fragments);
|
||||
if fragments.len() == 0 {
|
||||
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());
|
||||
let mut inline_flow = inline_flow as owned::Box<Flow:Share>;
|
||||
let mut inline_flow = inline_flow as Box<Flow:Share>;
|
||||
TextRunScanner::new().scan_for_runs(self.font_context(), inline_flow);
|
||||
inline_flow.finish(self.layout_context);
|
||||
|
||||
|
@ -342,15 +341,15 @@ impl<'a> FlowConstructor<'a> {
|
|||
}
|
||||
|
||||
fn build_block_flow_using_children_construction_result(&mut self,
|
||||
flow: &mut owned::Box<Flow:Share>,
|
||||
flow: &mut Box<Flow:Share>,
|
||||
consecutive_siblings:
|
||||
&mut Vec<owned::Box<Flow:Share>>,
|
||||
&mut Vec<Box<Flow:Share>>,
|
||||
node: &ThreadSafeLayoutNode,
|
||||
kid: ThreadSafeLayoutNode,
|
||||
inline_box_accumulator:
|
||||
&mut InlineBoxAccumulator,
|
||||
inline_fragment_accumulator:
|
||||
&mut InlineFragmentsAccumulator,
|
||||
abs_descendants: &mut Descendants,
|
||||
first_box: &mut bool) {
|
||||
first_fragment: &mut bool) {
|
||||
match kid.swap_out_construction_result() {
|
||||
NoConstructionResult => {}
|
||||
FlowConstructionResult(kid_flow, kid_abs_descendants) => {
|
||||
|
@ -365,19 +364,19 @@ impl<'a> FlowConstructor<'a> {
|
|||
} else {
|
||||
// Strip ignorable whitespace from the start of this flow per CSS 2.1 §
|
||||
// 9.2.1.1.
|
||||
let whitespace_stripping = if flow.is_table_kind() || *first_box {
|
||||
*first_box = false;
|
||||
let whitespace_stripping = if flow.is_table_kind() || *first_fragment {
|
||||
*first_fragment = false;
|
||||
StripWhitespaceFromStart
|
||||
} else {
|
||||
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.
|
||||
debug!("flushing {} inline box(es) to flow A",
|
||||
inline_box_accumulator.boxes.len());
|
||||
self.flush_inline_boxes_to_flow_or_list(
|
||||
mem::replace(inline_box_accumulator, InlineBoxAccumulator::new()),
|
||||
inline_fragment_accumulator.fragments.len());
|
||||
self.flush_inline_fragments_to_flow_or_list(
|
||||
mem::replace(inline_fragment_accumulator, InlineFragmentsAccumulator::new()),
|
||||
flow,
|
||||
consecutive_siblings,
|
||||
whitespace_stripping,
|
||||
|
@ -392,37 +391,37 @@ impl<'a> FlowConstructor<'a> {
|
|||
}
|
||||
abs_descendants.push_descendants(kid_abs_descendants);
|
||||
}
|
||||
ConstructionItemConstructionResult(InlineBoxesConstructionItem(
|
||||
InlineBoxesConstructionResult {
|
||||
ConstructionItemConstructionResult(InlineFragmentsConstructionItem(
|
||||
InlineFragmentsConstructionResult {
|
||||
splits: splits,
|
||||
boxes: successor_boxes,
|
||||
fragments: successor_fragments,
|
||||
abs_descendants: kid_abs_descendants,
|
||||
})) => {
|
||||
// Add any {ib} splits.
|
||||
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.
|
||||
let InlineBlockSplit {
|
||||
predecessors: predecessors,
|
||||
flow: kid_flow
|
||||
} = 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.
|
||||
let whitespace_stripping = if *first_box {
|
||||
*first_box = false;
|
||||
let whitespace_stripping = if *first_fragment {
|
||||
*first_fragment = false;
|
||||
StripWhitespaceFromStart
|
||||
} else {
|
||||
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",
|
||||
inline_box_accumulator.boxes.len());
|
||||
self.flush_inline_boxes_to_flow_or_list(
|
||||
mem::replace(inline_box_accumulator,
|
||||
InlineBoxAccumulator::new()),
|
||||
inline_fragment_accumulator.fragments.len());
|
||||
self.flush_inline_fragments_to_flow_or_list(
|
||||
mem::replace(inline_fragment_accumulator,
|
||||
InlineFragmentsAccumulator::new()),
|
||||
flow,
|
||||
consecutive_siblings,
|
||||
whitespace_stripping,
|
||||
|
@ -437,14 +436,14 @@ impl<'a> FlowConstructor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
// Add the boxes to the list we're maintaining.
|
||||
inline_box_accumulator.boxes.push_all(successor_boxes);
|
||||
// Add the fragments to the list we're maintaining.
|
||||
inline_fragment_accumulator.fragments.push_all(successor_fragments);
|
||||
abs_descendants.push_descendants(kid_abs_descendants);
|
||||
}
|
||||
ConstructionItemConstructionResult(WhitespaceConstructionItem(..)) => {
|
||||
// Nothing to do here.
|
||||
}
|
||||
ConstructionItemConstructionResult(TableColumnBoxConstructionItem(_)) => {
|
||||
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => {
|
||||
// TODO: Implement anonymous table objects for missing parents
|
||||
// CSS 2.1 § 17.2.1, step 3-2
|
||||
}
|
||||
|
@ -459,13 +458,13 @@ impl<'a> FlowConstructor<'a> {
|
|||
/// Also, deal with the absolute and fixed descendants bubbled up by
|
||||
/// children nodes.
|
||||
fn build_flow_using_children(&mut self,
|
||||
mut flow: owned::Box<Flow:Share>,
|
||||
mut flow: Box<Flow:Share>,
|
||||
node: &ThreadSafeLayoutNode)
|
||||
-> ConstructionResult {
|
||||
// Gather up boxes for the inline flows we might need to create.
|
||||
let mut inline_box_accumulator = InlineBoxAccumulator::new();
|
||||
// Gather up fragments for the inline flows we might need to create.
|
||||
let mut inline_fragment_accumulator = InlineFragmentsAccumulator::new();
|
||||
let mut consecutive_siblings = vec!();
|
||||
let mut first_box = true;
|
||||
let mut first_fragment = true;
|
||||
|
||||
// List of absolute descendants, in tree order.
|
||||
let mut abs_descendants = Descendants::new();
|
||||
|
@ -478,14 +477,14 @@ impl<'a> FlowConstructor<'a> {
|
|||
&mut consecutive_siblings,
|
||||
node,
|
||||
kid,
|
||||
&mut inline_box_accumulator,
|
||||
&mut inline_fragment_accumulator,
|
||||
&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.
|
||||
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 consecutive_siblings,
|
||||
StripWhitespaceFromEnd,
|
||||
|
@ -517,7 +516,7 @@ impl<'a> FlowConstructor<'a> {
|
|||
/// other `BlockFlow`s or `InlineFlow`s underneath it, depending on whether {ib} splits needed
|
||||
/// to happen.
|
||||
fn build_flow_for_block(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
let flow = box BlockFlow::from_node(self, node) as owned::Box<Flow:Share>;
|
||||
let flow = box BlockFlow::from_node(self, node) as Box<Flow:Share>;
|
||||
self.build_flow_using_children(flow, node)
|
||||
}
|
||||
|
||||
|
@ -525,20 +524,20 @@ impl<'a> FlowConstructor<'a> {
|
|||
/// a `BlockFlow` underneath it.
|
||||
fn build_flow_for_floated_block(&mut self, node: &ThreadSafeLayoutNode, float_kind: FloatKind)
|
||||
-> ConstructionResult {
|
||||
let flow = box BlockFlow::float_from_node(self, node, float_kind) as owned::Box<Flow:Share>;
|
||||
let flow = box BlockFlow::float_from_node(self, node, float_kind) as Box<Flow:Share>;
|
||||
self.build_flow_using_children(flow, node)
|
||||
}
|
||||
|
||||
/// Concatenates the boxes of kids, adding in our own borders/padding/margins if necessary.
|
||||
/// Returns the `InlineBoxesConstructionResult`, if any. There will be no
|
||||
/// `InlineBoxesConstructionResult` if this node consisted entirely of ignorable whitespace.
|
||||
fn build_boxes_for_nonreplaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
||||
/// Concatenates the fragments of kids, adding in our own borders/padding/margins if necessary.
|
||||
/// Returns the `InlineFragmentsConstructionResult`, if any. There will be no
|
||||
/// `InlineFragmentsConstructionResult` if this node consisted entirely of ignorable whitespace.
|
||||
fn build_fragments_for_nonreplaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
||||
-> ConstructionResult {
|
||||
let mut opt_inline_block_splits: Vec<InlineBlockSplit> = Vec::new();
|
||||
let mut box_accumulator = InlineBoxAccumulator::from_inline_node(node);
|
||||
let mut fragment_accumulator = InlineFragmentsAccumulator::from_inline_node(node);
|
||||
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() {
|
||||
if kid.get_pseudo_element_type() != Normal {
|
||||
self.process(&kid);
|
||||
|
@ -547,20 +546,20 @@ impl<'a> FlowConstructor<'a> {
|
|||
NoConstructionResult => {}
|
||||
FlowConstructionResult(flow, kid_abs_descendants) => {
|
||||
// {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 {
|
||||
predecessors:
|
||||
mem::replace(&mut box_accumulator,
|
||||
InlineBoxAccumulator::from_inline_node(node)).finish(),
|
||||
mem::replace(&mut fragment_accumulator,
|
||||
InlineFragmentsAccumulator::from_inline_node(node)).finish(),
|
||||
flow: flow,
|
||||
};
|
||||
opt_inline_block_splits.push(split);
|
||||
abs_descendants.push_descendants(kid_abs_descendants);
|
||||
}
|
||||
ConstructionItemConstructionResult(InlineBoxesConstructionItem(
|
||||
InlineBoxesConstructionResult {
|
||||
ConstructionItemConstructionResult(InlineFragmentsConstructionItem(
|
||||
InlineFragmentsConstructionResult {
|
||||
splits: splits,
|
||||
boxes: successors,
|
||||
fragments: successors,
|
||||
abs_descendants: kid_abs_descendants,
|
||||
})) => {
|
||||
|
||||
|
@ -570,33 +569,33 @@ impl<'a> FlowConstructor<'a> {
|
|||
predecessors: predecessors,
|
||||
flow: kid_flow
|
||||
} = split;
|
||||
box_accumulator.boxes.push_all(predecessors);
|
||||
fragment_accumulator.fragments.push_all(predecessors);
|
||||
|
||||
let split = InlineBlockSplit {
|
||||
predecessors:
|
||||
mem::replace(&mut box_accumulator,
|
||||
InlineBoxAccumulator::from_inline_node(node))
|
||||
mem::replace(&mut fragment_accumulator,
|
||||
InlineFragmentsAccumulator::from_inline_node(node))
|
||||
.finish(),
|
||||
flow: kid_flow,
|
||||
};
|
||||
opt_inline_block_splits.push(split)
|
||||
}
|
||||
|
||||
// Push residual boxes.
|
||||
box_accumulator.boxes.push_all(successors);
|
||||
// Push residual fragments.
|
||||
fragment_accumulator.fragments.push_all(successors);
|
||||
abs_descendants.push_descendants(kid_abs_descendants);
|
||||
}
|
||||
ConstructionItemConstructionResult(WhitespaceConstructionItem(whitespace_node,
|
||||
whitespace_style))
|
||||
=> {
|
||||
// Instantiate the whitespace box.
|
||||
let box_info = UnscannedTextBox(UnscannedTextBoxInfo::from_text(" ".to_owned()));
|
||||
let fragment = Box::from_opaque_node_and_style(whitespace_node,
|
||||
// Instantiate the whitespace fragment.
|
||||
let fragment_info = UnscannedTextFragment(UnscannedTextFragmentInfo::from_text(" ".to_owned()));
|
||||
let fragment = Fragment::from_opaque_node_and_style(whitespace_node,
|
||||
whitespace_style.clone(),
|
||||
box_info);
|
||||
box_accumulator.boxes.push(fragment, whitespace_style)
|
||||
fragment_info);
|
||||
fragment_accumulator.fragments.push(fragment, whitespace_style)
|
||||
}
|
||||
ConstructionItemConstructionResult(TableColumnBoxConstructionItem(_)) => {
|
||||
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(_)) => {
|
||||
// TODO: Implement anonymous table objects for missing parents
|
||||
// CSS 2.1 § 17.2.1, step 3-2
|
||||
}
|
||||
|
@ -604,11 +603,11 @@ impl<'a> FlowConstructor<'a> {
|
|||
}
|
||||
|
||||
// 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 {
|
||||
let construction_item = InlineBoxesConstructionItem(InlineBoxesConstructionResult {
|
||||
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
|
||||
splits: opt_inline_block_splits,
|
||||
boxes: box_accumulator.finish(),
|
||||
fragments: fragment_accumulator.finish(),
|
||||
abs_descendants: abs_descendants,
|
||||
});
|
||||
ConstructionItemConstructionResult(construction_item)
|
||||
|
@ -617,9 +616,9 @@ impl<'a> FlowConstructor<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Creates an `InlineBoxesConstructionResult` for replaced content. Replaced content doesn't
|
||||
/// render its children, so this just nukes a child's boxes and creates a `Box`.
|
||||
fn build_boxes_for_replaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
||||
/// Creates an `InlineFragmentsConstructionResult` for replaced content. Replaced content doesn't
|
||||
/// render its children, so this just nukes a child's fragments and creates a `Fragment`.
|
||||
fn build_fragments_for_replaced_inline_content(&mut self, node: &ThreadSafeLayoutNode)
|
||||
-> ConstructionResult {
|
||||
for kid in node.children() {
|
||||
kid.set_flow_construction_result(NoConstructionResult)
|
||||
|
@ -635,33 +634,34 @@ impl<'a> FlowConstructor<'a> {
|
|||
node.style().clone()))
|
||||
}
|
||||
|
||||
let mut boxes = InlineBoxes::new();
|
||||
boxes.push(Box::new(self, node), node.style().clone());
|
||||
let mut fragments = InlineFragments::new();
|
||||
fragments.push(Fragment::new(self, node), node.style().clone());
|
||||
|
||||
let construction_item = InlineBoxesConstructionItem(InlineBoxesConstructionResult {
|
||||
let construction_item = InlineFragmentsConstructionItem(InlineFragmentsConstructionResult {
|
||||
splits: Vec::new(),
|
||||
boxes: boxes,
|
||||
fragments: fragments,
|
||||
abs_descendants: Descendants::new(),
|
||||
});
|
||||
ConstructionItemConstructionResult(construction_item)
|
||||
}
|
||||
|
||||
/// Builds one or more boxes for a node with `display: inline`. This yields an
|
||||
/// `InlineBoxesConstructionResult`.
|
||||
fn build_boxes_for_inline(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
/// Builds one or more fragments for a node with `display: inline`. This yields an
|
||||
/// `InlineFragmentsConstructionResult`.
|
||||
fn build_fragments_for_inline(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
// Is this node replaced content?
|
||||
if !node.is_replaced_content() {
|
||||
// Go to a path that concatenates our kids' boxes.
|
||||
self.build_boxes_for_nonreplaced_inline_content(node)
|
||||
// Go to a path that concatenates our kids' fragments.
|
||||
self.build_fragments_for_nonreplaced_inline_content(node)
|
||||
} else {
|
||||
// Otherwise, just nuke our kids' boxes, create our box if any, and be done with it.
|
||||
self.build_boxes_for_replaced_inline_content(node)
|
||||
// Otherwise, just nuke our kids' fragments, create our fragment if any, and be done
|
||||
// with it.
|
||||
self.build_fragments_for_replaced_inline_content(node)
|
||||
}
|
||||
}
|
||||
|
||||
/// TableCaptionFlow is populated underneath TableWrapperFlow
|
||||
fn place_table_caption_under_table_wrapper(&mut self,
|
||||
table_wrapper_flow: &mut owned::Box<Flow:Share>,
|
||||
table_wrapper_flow: &mut Box<Flow:Share>,
|
||||
node: &ThreadSafeLayoutNode) {
|
||||
for kid in node.children() {
|
||||
match kid.swap_out_construction_result() {
|
||||
|
@ -678,8 +678,8 @@ impl<'a> FlowConstructor<'a> {
|
|||
/// Generates an anonymous table flow according to CSS 2.1 § 17.2.1, step 2.
|
||||
/// If necessary, generate recursively another anonymous table flow.
|
||||
fn generate_anonymous_missing_child(&mut self,
|
||||
child_flows: Vec<owned::Box<Flow:Share>>,
|
||||
flow: &mut owned::Box<Flow:Share>,
|
||||
child_flows: Vec<Box<Flow:Share>>,
|
||||
flow: &mut Box<Flow:Share>,
|
||||
node: &ThreadSafeLayoutNode) {
|
||||
let mut anonymous_flow = flow.generate_missing_child_flow(node);
|
||||
let mut consecutive_siblings = vec!();
|
||||
|
@ -705,11 +705,11 @@ impl<'a> FlowConstructor<'a> {
|
|||
/// Builds a flow for a node with `display: table`. This yields a `TableWrapperFlow` with possibly
|
||||
/// other `TableCaptionFlow`s or `TableFlow`s underneath it.
|
||||
fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
let box_ = Box::new_from_specific_info(node, TableWrapperBox);
|
||||
let mut wrapper_flow = box TableWrapperFlow::from_node_and_box(node, box_) as owned::Box<Flow:Share>;
|
||||
let fragment = Fragment::new_from_specific_info(node, TableWrapperFragment);
|
||||
let mut wrapper_flow = box TableWrapperFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>;
|
||||
|
||||
let table_box_ = Box::new_from_specific_info(node, TableBox);
|
||||
let table_flow = box TableFlow::from_node_and_box(node, table_box_) as owned::Box<Flow:Share>;
|
||||
let table_fragment = Fragment::new_from_specific_info(node, TableFragment);
|
||||
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 then populate the TableWrapperFlow with TableCaptionFlow, and attach
|
||||
|
@ -755,44 +755,44 @@ impl<'a> FlowConstructor<'a> {
|
|||
/// Builds a flow for a node with `display: table-caption`. This yields a `TableCaptionFlow`
|
||||
/// with possibly other `BlockFlow`s or `InlineFlow`s underneath it.
|
||||
fn build_flow_for_table_caption(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
let flow = box TableCaptionFlow::from_node(self, node) as owned::Box<Flow:Share>;
|
||||
let flow = box TableCaptionFlow::from_node(self, node) as Box<Flow:Share>;
|
||||
self.build_flow_using_children(flow, node)
|
||||
}
|
||||
|
||||
/// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow`
|
||||
/// with possibly other `TableRowFlow`s underneath it.
|
||||
fn build_flow_for_table_rowgroup(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
let box_ = Box::new_from_specific_info(node, TableRowBox);
|
||||
let flow = box TableRowGroupFlow::from_node_and_box(node, box_) as owned::Box<Flow:Share>;
|
||||
let fragment = Fragment::new_from_specific_info(node, TableRowFragment);
|
||||
let flow = box TableRowGroupFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>;
|
||||
self.build_flow_using_children(flow, node)
|
||||
}
|
||||
|
||||
/// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with
|
||||
/// possibly other `TableCellFlow`s underneath it.
|
||||
fn build_flow_for_table_row(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
let box_ = Box::new_from_specific_info(node, TableRowBox);
|
||||
let flow = box TableRowFlow::from_node_and_box(node, box_) as owned::Box<Flow:Share>;
|
||||
let fragment = Fragment::new_from_specific_info(node, TableRowFragment);
|
||||
let flow = box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>;
|
||||
self.build_flow_using_children(flow, node)
|
||||
}
|
||||
|
||||
/// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with
|
||||
/// possibly other `BlockFlow`s or `InlineFlow`s underneath it.
|
||||
fn build_flow_for_table_cell(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
let box_ = Box::new_from_specific_info(node, TableCellBox);
|
||||
let flow = box TableCellFlow::from_node_and_box(node, box_) as owned::Box<Flow:Share>;
|
||||
let fragment = Fragment::new_from_specific_info(node, TableCellFragment);
|
||||
let flow = box TableCellFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>;
|
||||
self.build_flow_using_children(flow, node)
|
||||
}
|
||||
|
||||
/// Creates a box for a node with `display: table-column`.
|
||||
fn build_boxes_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`.
|
||||
/// Creates a fragment for a node with `display: table-column`.
|
||||
fn build_fragments_for_table_column(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
// CSS 2.1 § 17.2.1. Treat all child fragments of a `table-column` as `display: none`.
|
||||
for kid in node.children() {
|
||||
kid.set_flow_construction_result(NoConstructionResult)
|
||||
}
|
||||
|
||||
let specific = TableColumnBox(TableColumnBoxInfo::new(node));
|
||||
let construction_item = TableColumnBoxConstructionItem(
|
||||
Box::new_from_specific_info(node, specific)
|
||||
let specific = TableColumnFragment(TableColumnFragmentInfo::new(node));
|
||||
let construction_item = TableColumnFragmentConstructionItem(
|
||||
Fragment::new_from_specific_info(node, specific)
|
||||
);
|
||||
ConstructionItemConstructionResult(construction_item)
|
||||
}
|
||||
|
@ -800,26 +800,25 @@ impl<'a> FlowConstructor<'a> {
|
|||
/// Builds a flow for a node with `display: table-column-group`.
|
||||
/// This yields a `TableColGroupFlow`.
|
||||
fn build_flow_for_table_colgroup(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
let box_ = Box::new_from_specific_info(node,
|
||||
TableColumnBox(TableColumnBoxInfo::new(node)));
|
||||
let mut col_boxes = vec!();
|
||||
let fragment = Fragment::new_from_specific_info(node,
|
||||
TableColumnFragment(TableColumnFragmentInfo::new(node)));
|
||||
let mut col_fragments = vec!();
|
||||
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`.
|
||||
match kid.swap_out_construction_result() {
|
||||
ConstructionItemConstructionResult(TableColumnBoxConstructionItem(box_)) => {
|
||||
col_boxes.push(box_);
|
||||
ConstructionItemConstructionResult(TableColumnFragmentConstructionItem(fragment)) => {
|
||||
col_fragments.push(fragment);
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
if col_boxes.is_empty() {
|
||||
debug!("add TableColumnBox for empty colgroup");
|
||||
let specific = TableColumnBox(TableColumnBoxInfo::new(node));
|
||||
col_boxes.push( Box::new_from_specific_info(node, specific) );
|
||||
if col_fragments.is_empty() {
|
||||
debug!("add TableColumnFragment for empty colgroup");
|
||||
let specific = TableColumnFragment(TableColumnFragmentInfo::new(node));
|
||||
col_fragments.push(Fragment::new_from_specific_info(node, specific));
|
||||
}
|
||||
let mut flow = box TableColGroupFlow::from_node_and_boxes(node, box_, col_boxes) as
|
||||
owned::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);
|
||||
|
||||
FlowConstructionResult(flow, Descendants::new())
|
||||
|
@ -888,9 +887,9 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
|||
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, _) => {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -908,7 +907,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
|||
|
||||
// Table items contribute table flow construction results.
|
||||
(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)
|
||||
}
|
||||
|
||||
|
@ -1086,57 +1085,57 @@ impl<'ln> ObjectElement for ThreadSafeLayoutNode<'ln> {
|
|||
}
|
||||
}
|
||||
|
||||
/// Strips ignorable whitespace from the start of a list of boxes.
|
||||
fn strip_ignorable_whitespace_from_start(boxes: &mut InlineBoxes) {
|
||||
if boxes.len() == 0 {
|
||||
/// Strips ignorable whitespace from the start of a list of fragments.
|
||||
fn strip_ignorable_whitespace_from_start(fragments: &mut InlineFragments) {
|
||||
if fragments.len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
let InlineBoxes {
|
||||
boxes: old_boxes,
|
||||
let InlineFragments {
|
||||
fragments: old_fragments,
|
||||
map: mut map
|
||||
} = mem::replace(boxes, InlineBoxes::new());
|
||||
} = mem::replace(fragments, InlineFragments::new());
|
||||
|
||||
// FIXME(#2264, pcwalton): This is slow because vector shift is broken. :(
|
||||
let mut found_nonwhitespace = false;
|
||||
let mut new_boxes = Vec::new();
|
||||
for fragment in old_boxes.iter() {
|
||||
let mut new_fragments = Vec::new();
|
||||
for fragment in old_fragments.iter() {
|
||||
if !found_nonwhitespace && fragment.is_whitespace_only() {
|
||||
debug!("stripping ignorable whitespace from start");
|
||||
continue
|
||||
}
|
||||
|
||||
found_nonwhitespace = true;
|
||||
new_boxes.push(fragment.clone())
|
||||
new_fragments.push(fragment.clone())
|
||||
}
|
||||
|
||||
map.fixup(old_boxes.as_slice(), new_boxes.as_slice());
|
||||
*boxes = InlineBoxes {
|
||||
boxes: new_boxes,
|
||||
map.fixup(old_fragments.as_slice(), new_fragments.as_slice());
|
||||
*fragments = InlineFragments {
|
||||
fragments: new_fragments,
|
||||
map: map,
|
||||
}
|
||||
}
|
||||
|
||||
/// Strips ignorable whitespace from the end of a list of boxes.
|
||||
fn strip_ignorable_whitespace_from_end(boxes: &mut InlineBoxes) {
|
||||
if boxes.len() == 0 {
|
||||
/// Strips ignorable whitespace from the end of a list of fragments.
|
||||
fn strip_ignorable_whitespace_from_end(fragments: &mut InlineFragments) {
|
||||
if fragments.len() == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
let InlineBoxes {
|
||||
boxes: old_boxes,
|
||||
let InlineFragments {
|
||||
fragments: old_fragments,
|
||||
map: mut map
|
||||
} = mem::replace(boxes, InlineBoxes::new());
|
||||
} = mem::replace(fragments, InlineFragments::new());
|
||||
|
||||
let mut new_boxes = old_boxes.clone();
|
||||
while new_boxes.len() > 0 && new_boxes.as_slice().last().get_ref().is_whitespace_only() {
|
||||
let mut new_fragments = old_fragments.clone();
|
||||
while new_fragments.len() > 0 && new_fragments.as_slice().last().get_ref().is_whitespace_only() {
|
||||
debug!("stripping ignorable whitespace from end");
|
||||
drop(new_boxes.pop());
|
||||
drop(new_fragments.pop());
|
||||
}
|
||||
|
||||
map.fixup(old_boxes.as_slice(), new_boxes.as_slice());
|
||||
*boxes = InlineBoxes {
|
||||
boxes: new_boxes,
|
||||
map.fixup(old_fragments.as_slice(), new_fragments.as_slice());
|
||||
*fragments = InlineFragments {
|
||||
fragments: new_fragments,
|
||||
map: map,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -18,7 +18,7 @@ pub trait LayoutAuxMethods {
|
|||
impl<'ln> LayoutAuxMethods for LayoutNode<'ln> {
|
||||
/// 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) {
|
||||
let mut layout_data_ref = self.mutate_layout_data();
|
||||
match *layout_data_ref {
|
||||
|
@ -35,7 +35,7 @@ impl<'ln> LayoutAuxMethods for LayoutNode<'ln> {
|
|||
|
||||
/// 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) {
|
||||
for n in self.traverse_preorder() {
|
||||
n.initialize_layout_data(chan.clone());
|
||||
|
|
|
@ -320,7 +320,7 @@ impl Floats {
|
|||
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.
|
||||
pub fn place_between_floats(&self, info: &PlacementInfo) -> Rect<Au> {
|
||||
debug!("place_between_floats: Placing object with width {} and height {}",
|
||||
|
|
|
@ -2,14 +2,14 @@
|
|||
* 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/. */
|
||||
|
||||
//! Servo's experimental layout system builds a tree of `Flow` and `Box` objects and solves
|
||||
//! Servo's experimental layout system builds a tree of `Flow` and `Fragment` objects and solves
|
||||
//! layout constraints to obtain positions and display attributes of tree nodes. Positions are
|
||||
//! computed in several tree traversals driven by the fundamental data dependencies required by
|
||||
/// inline and block layout.
|
||||
///
|
||||
/// 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.
|
||||
/// Flows have purpose-specific fields, such as auxiliary line box structs, out-of-flow child
|
||||
/// CSS specification. Flows are responsible for positioning their child flow contexts and fragments.
|
||||
/// Flows have purpose-specific fields, such as auxiliary line structs, out-of-flow child
|
||||
/// lists, and so on.
|
||||
///
|
||||
/// Currently, the important types of flows are:
|
||||
|
@ -21,16 +21,16 @@
|
|||
/// the viewport.
|
||||
///
|
||||
/// * `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
|
||||
/// similar methods.
|
||||
|
||||
use css::node_style::StyledNode;
|
||||
use layout::block::BlockFlow;
|
||||
use layout::box_::{Box, TableRowBox, TableCellBox};
|
||||
use layout::context::LayoutContext;
|
||||
use layout::floats::Floats;
|
||||
use layout::flow_list::{FlowList, Link, Rawlink, FlowListIterator, MutFlowListIterator};
|
||||
use layout::fragment::{Fragment, TableRowFragment, TableCellFragment};
|
||||
use layout::incremental::RestyleDamage;
|
||||
use layout::inline::InlineFlow;
|
||||
use layout::model::{CollapsibleMargins, IntrinsicWidths, MarginCollapseInfo};
|
||||
|
@ -58,7 +58,6 @@ use std::cast;
|
|||
use std::fmt;
|
||||
use std::iter::Zip;
|
||||
use std::num::Zero;
|
||||
use std::owned;
|
||||
use std::sync::atomics::Relaxed;
|
||||
use std::slice::MutItems;
|
||||
use style::computed_values::{clear, position, text_align};
|
||||
|
@ -338,7 +337,7 @@ pub trait ImmutableFlowUtils {
|
|||
fn need_anonymous_flow(self, child: &Flow) -> bool;
|
||||
|
||||
/// Generates missing child flow of this flow.
|
||||
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> owned::Box<Flow:Share>;
|
||||
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> Box<Flow:Share>;
|
||||
|
||||
/// Returns true if this flow has no children.
|
||||
fn is_leaf(self) -> bool;
|
||||
|
@ -392,7 +391,7 @@ pub trait MutableFlowUtils {
|
|||
pub trait MutableOwnedFlowUtils {
|
||||
/// Adds a new flow as a child of this flow. Removes the flow from the given leaf set if
|
||||
/// it's present.
|
||||
fn add_new_child(&mut self, new_child: owned::Box<Flow:Share>);
|
||||
fn add_new_child(&mut self, new_child: Box<Flow:Share>);
|
||||
|
||||
/// Finishes a flow. Once a flow is finished, no more child flows or boxes may be added to it.
|
||||
/// This will normally run the bubble-widths (minimum and preferred -- i.e. intrinsic -- width)
|
||||
|
@ -842,15 +841,15 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
|
|||
}
|
||||
|
||||
/// Generates missing child flow of this flow.
|
||||
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> owned::Box<Flow:Share> {
|
||||
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> Box<Flow:Share> {
|
||||
match self.class() {
|
||||
TableFlowClass | TableRowGroupFlowClass => {
|
||||
let box_ = Box::new_anonymous_table_box(node, TableRowBox);
|
||||
box TableRowFlow::from_node_and_box(node, box_) as owned::Box<Flow:Share>
|
||||
let fragment = Fragment::new_anonymous_table_fragment(node, TableRowFragment);
|
||||
box TableRowFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>
|
||||
},
|
||||
TableRowFlowClass => {
|
||||
let box_ = Box::new_anonymous_table_box(node, TableCellBox);
|
||||
box TableCellFlow::from_node_and_box(node, box_) as owned::Box<Flow:Share>
|
||||
let fragment = Fragment::new_anonymous_table_fragment(node, TableCellFragment);
|
||||
box TableCellFlow::from_node_and_fragment(node, fragment) as Box<Flow:Share>
|
||||
},
|
||||
_ => {
|
||||
fail!("no need to generate a missing child")
|
||||
|
@ -870,8 +869,8 @@ impl<'a> ImmutableFlowUtils for &'a Flow {
|
|||
|
||||
/// Return true if this flow is a Block Container.
|
||||
///
|
||||
/// Except for table boxes and replaced elements, block-level boxes (`BlockFlow`) are
|
||||
/// also block container boxes.
|
||||
/// Except for table fragments and replaced elements, block-level fragments (`BlockFlow`) are
|
||||
/// also block container fragments.
|
||||
/// Non-replaced inline blocks and non-replaced table cells are also block
|
||||
/// containers.
|
||||
fn is_block_container(self) -> bool {
|
||||
|
@ -1052,9 +1051,9 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
|
|||
}
|
||||
}
|
||||
|
||||
impl MutableOwnedFlowUtils for owned::Box<Flow:Share> {
|
||||
impl MutableOwnedFlowUtils for Box<Flow:Share> {
|
||||
/// Adds a new flow as a child of this flow. Fails if this flow is marked as a leaf.
|
||||
fn add_new_child(&mut self, mut new_child: owned::Box<Flow:Share>) {
|
||||
fn add_new_child(&mut self, mut new_child: Box<Flow:Share>) {
|
||||
{
|
||||
let kid_base = mut_base(new_child);
|
||||
kid_base.parallel.parent = parallel::mut_owned_flow_to_unsafe_flow(self);
|
||||
|
@ -1066,7 +1065,7 @@ impl MutableOwnedFlowUtils for owned::Box<Flow:Share> {
|
|||
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)
|
||||
/// calculation, unless the global `bubble_widths_separately` flag is on.
|
||||
///
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
|
@ -4,7 +4,7 @@
|
|||
|
||||
//! Borders, padding, and margins.
|
||||
|
||||
use layout::box_::Box;
|
||||
use layout::fragment::Fragment;
|
||||
|
||||
use computed = style::computed_values;
|
||||
use geom::SideOffsets2D;
|
||||
|
@ -88,7 +88,7 @@ pub struct 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 {
|
||||
MarginCollapseInfo {
|
||||
state: AccumulatingCollapsibleTopMargin,
|
||||
|
@ -98,7 +98,7 @@ impl MarginCollapseInfo {
|
|||
}
|
||||
|
||||
pub fn initialize_top_margin(&mut self,
|
||||
fragment: &Box,
|
||||
fragment: &Fragment,
|
||||
can_collapse_top_margin_with_kids: bool) {
|
||||
if !can_collapse_top_margin_with_kids {
|
||||
self.state = AccumulatingMarginIn
|
||||
|
@ -108,7 +108,7 @@ impl MarginCollapseInfo {
|
|||
}
|
||||
|
||||
pub fn finish_and_compute_collapsible_margins(mut self,
|
||||
fragment: &Box,
|
||||
fragment: &Fragment,
|
||||
can_collapse_bottom_margin_with_kids: bool)
|
||||
-> (CollapsibleMargins, Au) {
|
||||
let state = match self.state {
|
||||
|
@ -120,15 +120,15 @@ impl MarginCollapseInfo {
|
|||
MarginsCollapseThroughFinalMarginState
|
||||
},
|
||||
_ => {
|
||||
// If the box has non-zero min-height, margins may not collapse
|
||||
// through it.
|
||||
// If the fragment has non-zero min-height, margins may not
|
||||
// collapse through it.
|
||||
BottomMarginCollapsesFinalMarginState
|
||||
}
|
||||
}
|
||||
},
|
||||
_ => {
|
||||
// If the box has an explicitly specified height, margins may not collapse
|
||||
// through it.
|
||||
// If the fragment has an explicitly specified height, margins may not
|
||||
// collapse through it.
|
||||
BottomMarginCollapsesFinalMarginState
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
//! CSS table formatting contexts.
|
||||
|
||||
use layout::box_::Box;
|
||||
use layout::block::{BlockFlow, MarginsMayNotCollapse, WidthAndMarginsComputer};
|
||||
use layout::block::{WidthConstraintInput, WidthConstraintSolution};
|
||||
use layout::construct::FlowConstructor;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::floats::FloatKind;
|
||||
use layout::flow::{TableFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use layout::fragment::Fragment;
|
||||
use layout::table_wrapper::{TableLayout, FixedLayout, AutoLayout};
|
||||
use layout::wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
|
@ -19,9 +19,9 @@ use servo_util::geometry;
|
|||
use std::fmt;
|
||||
use style::computed_values::table_layout;
|
||||
|
||||
/// A table flow corresponded to the table's internal table box under a table wrapper flow.
|
||||
/// The properties `position`, `float`, and `margin-*` are used on the table wrapper box,
|
||||
/// not table box per CSS 2.1 § 10.5.
|
||||
/// 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 fragment,
|
||||
/// not table fragment per CSS 2.1 § 10.5.
|
||||
pub struct TableFlow {
|
||||
pub block_flow: BlockFlow,
|
||||
|
||||
|
@ -39,11 +39,11 @@ pub struct TableFlow {
|
|||
}
|
||||
|
||||
impl TableFlow {
|
||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
||||
box_: Box)
|
||||
-> TableFlow {
|
||||
let mut block_flow = BlockFlow::from_node_and_box(node, box_);
|
||||
let table_layout = if block_flow.box_().style().get_table().table_layout ==
|
||||
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
|
||||
fragment: Fragment)
|
||||
-> TableFlow {
|
||||
let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment);
|
||||
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
|
||||
table_layout::fixed {
|
||||
FixedLayout
|
||||
} else {
|
||||
|
@ -62,7 +62,7 @@ impl TableFlow {
|
|||
node: &ThreadSafeLayoutNode)
|
||||
-> TableFlow {
|
||||
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 {
|
||||
FixedLayout
|
||||
} else {
|
||||
|
@ -82,7 +82,7 @@ impl TableFlow {
|
|||
float_kind: FloatKind)
|
||||
-> TableFlow {
|
||||
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 {
|
||||
FixedLayout
|
||||
} else {
|
||||
|
@ -231,8 +231,8 @@ impl Flow for TableFlow {
|
|||
geometry::max(min_width, pref_width);
|
||||
}
|
||||
|
||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
||||
/// on this context, the context has had its width set by the parent context.
|
||||
/// 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.
|
||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||
debug!("assign_widths({}): assigning width for flow", "table");
|
||||
|
||||
|
@ -252,9 +252,9 @@ impl Flow for TableFlow {
|
|||
let width_computer = InternalTable;
|
||||
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 padding_and_borders = self.block_flow.box_.border_padding.horizontal();
|
||||
let content_width = self.block_flow.box_.border_box.size.width - padding_and_borders;
|
||||
let left_content_edge = self.block_flow.fragment.border_padding.left;
|
||||
let padding_and_borders = self.block_flow.fragment.border_padding.horizontal();
|
||||
let content_width = self.block_flow.fragment.border_box.size.width - padding_and_borders;
|
||||
|
||||
match self.table_layout {
|
||||
FixedLayout => {
|
||||
|
|
|
@ -4,10 +4,10 @@
|
|||
|
||||
//! CSS table formatting contexts.
|
||||
|
||||
use layout::box_::Box;
|
||||
use layout::block::{BlockFlow, MarginsMayNotCollapse, WidthAndMarginsComputer};
|
||||
use layout::context::LayoutContext;
|
||||
use layout::flow::{TableCellFlowClass, FlowClass, Flow};
|
||||
use layout::fragment::Fragment;
|
||||
use layout::model::{MaybeAuto};
|
||||
use layout::table::InternalTable;
|
||||
use layout::wrapper::ThreadSafeLayoutNode;
|
||||
|
@ -22,18 +22,18 @@ pub struct TableCellFlow {
|
|||
}
|
||||
|
||||
impl TableCellFlow {
|
||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode, box_: Box) -> TableCellFlow {
|
||||
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode, fragment: Fragment) -> 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 Box {
|
||||
&self.block_flow.box_
|
||||
pub fn fragment<'a>(&'a mut self) -> &'a Fragment {
|
||||
&self.block_flow.fragment
|
||||
}
|
||||
|
||||
pub fn mut_box<'a>(&'a mut self) -> &'a mut Box {
|
||||
&mut self.block_flow.box_
|
||||
pub fn mut_fragment<'a>(&'a mut self) -> &'a mut Fragment {
|
||||
&mut self.block_flow.fragment
|
||||
}
|
||||
|
||||
/// 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.
|
||||
fn bubble_widths(&mut self, ctx: &mut LayoutContext) {
|
||||
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();
|
||||
if 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
|
||||
/// on this context, the context has had its width set by the parent table row.
|
||||
/// 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 table row.
|
||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||
debug!("assign_widths({}): assigning width for flow", "table_cell");
|
||||
|
||||
|
@ -92,10 +92,10 @@ impl Flow for TableCellFlow {
|
|||
let width_computer = InternalTable;
|
||||
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 +
|
||||
self.block_flow.box_.border_padding.left;
|
||||
let padding_and_borders = self.block_flow.box_.border_padding.horizontal();
|
||||
let content_width = self.block_flow.box_.border_box.size.width - padding_and_borders;
|
||||
let left_content_edge = self.block_flow.fragment.border_box.origin.x +
|
||||
self.block_flow.fragment.border_padding.left;
|
||||
let padding_and_borders = self.block_flow.fragment.border_padding.horizontal();
|
||||
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,
|
||||
content_width,
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
//! CSS table formatting contexts.
|
||||
|
||||
use layout::box_::{Box, TableColumnBox};
|
||||
use layout::context::LayoutContext;
|
||||
use layout::flow::{BaseFlow, TableColGroupFlowClass, FlowClass, Flow};
|
||||
use layout::fragment::{Fragment, TableColumnFragment};
|
||||
use layout::model::{MaybeAuto};
|
||||
use layout::wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
|
@ -18,24 +18,24 @@ pub struct TableColGroupFlow {
|
|||
/// Data common to all flows.
|
||||
pub base: BaseFlow,
|
||||
|
||||
/// The associated box.
|
||||
pub box_: Option<Box>,
|
||||
/// The associated fragment.
|
||||
pub fragment: Option<Fragment>,
|
||||
|
||||
/// The table column boxes
|
||||
pub cols: Vec<Box>,
|
||||
/// The table column fragments
|
||||
pub cols: Vec<Fragment>,
|
||||
|
||||
/// The specified widths of table columns
|
||||
pub widths: Vec<Au>,
|
||||
}
|
||||
|
||||
impl TableColGroupFlow {
|
||||
pub fn from_node_and_boxes(node: &ThreadSafeLayoutNode,
|
||||
box_: Box,
|
||||
boxes: Vec<Box>) -> TableColGroupFlow {
|
||||
pub fn from_node_and_fragments(node: &ThreadSafeLayoutNode,
|
||||
fragment: Fragment,
|
||||
fragments: Vec<Fragment>) -> TableColGroupFlow {
|
||||
TableColGroupFlow {
|
||||
base: BaseFlow::new((*node).clone()),
|
||||
box_: Some(box_),
|
||||
cols: boxes,
|
||||
fragment: Some(fragment),
|
||||
cols: fragments,
|
||||
widths: vec!(),
|
||||
}
|
||||
}
|
||||
|
@ -51,14 +51,14 @@ impl Flow for TableColGroupFlow {
|
|||
}
|
||||
|
||||
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
|
||||
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();
|
||||
|
||||
let span: int = match box_.specific {
|
||||
TableColumnBox(col_box) => col_box.span.unwrap_or(1),
|
||||
_ => fail!("Other box come out in TableColGroupFlow. {:?}", box_.specific)
|
||||
let span: int = match fragment.specific {
|
||||
TableColumnFragment(col_fragment) => col_fragment.span.unwrap_or(1),
|
||||
_ => fail!("Other fragment come out in TableColGroupFlow. {:?}", fragment.specific)
|
||||
};
|
||||
for _ in range(0, span) {
|
||||
self.widths.push(width);
|
||||
|
@ -78,7 +78,7 @@ impl Flow for TableColGroupFlow {
|
|||
|
||||
impl fmt::Show for TableColGroupFlow {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self.box_ {
|
||||
match self.fragment {
|
||||
Some(ref rb) => write!(f.buf, "TableColGroupFlow: {}", rb),
|
||||
None => write!(f.buf, "TableColGroupFlow"),
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
//! CSS table formatting contexts.
|
||||
|
||||
use layout::box_::Box;
|
||||
use layout::block::BlockFlow;
|
||||
use layout::block::WidthAndMarginsComputer;
|
||||
use layout::construct::FlowConstructor;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::flow::{TableRowFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use layout::flow;
|
||||
use layout::fragment::Fragment;
|
||||
use layout::table::InternalTable;
|
||||
use layout::model::{MaybeAuto, Specified, Auto};
|
||||
use layout::wrapper::ThreadSafeLayoutNode;
|
||||
|
@ -34,11 +34,11 @@ pub struct TableRowFlow {
|
|||
}
|
||||
|
||||
impl TableRowFlow {
|
||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
||||
box_: Box)
|
||||
-> TableRowFlow {
|
||||
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
|
||||
fragment: Fragment)
|
||||
-> TableRowFlow {
|
||||
TableRowFlow {
|
||||
block_flow: BlockFlow::from_node_and_box(node, box_),
|
||||
block_flow: BlockFlow::from_node_and_fragment(node, fragment),
|
||||
col_widths: vec!(),
|
||||
col_min_widths: vec!(),
|
||||
col_pref_widths: vec!(),
|
||||
|
@ -56,8 +56,8 @@ impl TableRowFlow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn box_<'a>(&'a mut self) -> &'a Box {
|
||||
&self.block_flow.box_
|
||||
pub fn fragment<'a>(&'a mut self) -> &'a Fragment {
|
||||
&self.block_flow.fragment
|
||||
}
|
||||
|
||||
fn initialize_offsets(&mut self) -> (Au, Au, Au) {
|
||||
|
@ -84,13 +84,13 @@ impl TableRowFlow {
|
|||
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
|
||||
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();
|
||||
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);
|
||||
child_node.position.origin.y = cur_y;
|
||||
|
@ -99,27 +99,27 @@ impl TableRowFlow {
|
|||
|
||||
let mut height = max_y;
|
||||
// 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,
|
||||
Specified(value) => geometry::max(value, 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.
|
||||
let mut position = self.block_flow.box_.border_box;
|
||||
let mut position = self.block_flow.fragment.border_box;
|
||||
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;
|
||||
|
||||
// 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() {
|
||||
{
|
||||
let kid_box_ = kid.as_table_cell().mut_box();
|
||||
let mut position = kid_box_.border_box;
|
||||
let kid_fragment = kid.as_table_cell().mut_fragment();
|
||||
let mut position = kid_fragment.border_box;
|
||||
position.size.height = height;
|
||||
kid_box_.border_box = position;
|
||||
kid_fragment.border_box = position;
|
||||
}
|
||||
let child_node = flow::mut_base(kid);
|
||||
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
|
||||
/// 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.
|
||||
/// 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.
|
||||
|
@ -172,8 +172,8 @@ impl Flow for TableRowFlow {
|
|||
|
||||
// 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_specified_width = MaybeAuto::from_style(child_box.style().get_box().width,
|
||||
let child_fragment = kid.as_table_cell().fragment();
|
||||
let child_specified_width = MaybeAuto::from_style(child_fragment.style().get_box().width,
|
||||
Au::new(0)).specified_or_zero();
|
||||
self.col_widths.push(child_specified_width);
|
||||
}
|
||||
|
@ -190,7 +190,7 @@ impl Flow for TableRowFlow {
|
|||
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.
|
||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||
debug!("assign_widths({}): assigning width for flow", "table_row");
|
||||
|
@ -218,6 +218,6 @@ impl Flow for TableRowFlow {
|
|||
|
||||
impl fmt::Show for TableRowFlow {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
//! CSS table formatting contexts.
|
||||
|
||||
use layout::box_::Box;
|
||||
use layout::block::BlockFlow;
|
||||
use layout::block::WidthAndMarginsComputer;
|
||||
use layout::construct::FlowConstructor;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::flow::{TableRowGroupFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use layout::flow;
|
||||
use layout::fragment::Fragment;
|
||||
use layout::table::{InternalTable, TableFlow};
|
||||
use layout::wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
|
@ -33,11 +33,11 @@ pub struct TableRowGroupFlow {
|
|||
}
|
||||
|
||||
impl TableRowGroupFlow {
|
||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
||||
box_: Box)
|
||||
-> TableRowGroupFlow {
|
||||
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
|
||||
fragment: Fragment)
|
||||
-> TableRowGroupFlow {
|
||||
TableRowGroupFlow {
|
||||
block_flow: BlockFlow::from_node_and_box(node, box_),
|
||||
block_flow: BlockFlow::from_node_and_fragment(node, fragment),
|
||||
col_widths: vec!(),
|
||||
col_min_widths: vec!(),
|
||||
col_pref_widths: vec!(),
|
||||
|
@ -55,8 +55,8 @@ impl TableRowGroupFlow {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn box_<'a>(&'a mut self) -> &'a Box {
|
||||
&self.block_flow.box_
|
||||
pub fn fragment<'a>(&'a mut self) -> &'a Fragment {
|
||||
&self.block_flow.fragment
|
||||
}
|
||||
|
||||
fn initialize_offsets(&mut self) -> (Au, Au, Au) {
|
||||
|
@ -87,9 +87,9 @@ impl TableRowGroupFlow {
|
|||
|
||||
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;
|
||||
self.block_flow.box_.border_box = position;
|
||||
self.block_flow.fragment.border_box = position;
|
||||
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
|
||||
/// 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.
|
||||
/// 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.
|
||||
|
@ -171,8 +171,8 @@ impl Flow for TableRowGroupFlow {
|
|||
pref_width);
|
||||
}
|
||||
|
||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
||||
/// on this context, the context has had its width set by the parent context.
|
||||
/// 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.
|
||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||
debug!("assign_widths({}): assigning width for flow", "table_rowgroup");
|
||||
|
||||
|
@ -200,6 +200,6 @@ impl Flow for TableRowGroupFlow {
|
|||
|
||||
impl fmt::Show for TableRowGroupFlow {
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,13 +4,13 @@
|
|||
|
||||
//! CSS table formatting contexts.
|
||||
|
||||
use layout::box_::Box;
|
||||
use layout::block::{BlockFlow, MarginsMayNotCollapse, WidthAndMarginsComputer};
|
||||
use layout::block::{WidthConstraintInput, WidthConstraintSolution};
|
||||
use layout::construct::FlowConstructor;
|
||||
use layout::context::LayoutContext;
|
||||
use layout::floats::FloatKind;
|
||||
use layout::flow::{TableWrapperFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||
use layout::fragment::Fragment;
|
||||
use layout::model::{Specified, Auto, specified};
|
||||
use layout::wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
|
@ -36,11 +36,11 @@ pub struct TableWrapperFlow {
|
|||
}
|
||||
|
||||
impl TableWrapperFlow {
|
||||
pub fn from_node_and_box(node: &ThreadSafeLayoutNode,
|
||||
box_: Box)
|
||||
-> TableWrapperFlow {
|
||||
let mut block_flow = BlockFlow::from_node_and_box(node, box_);
|
||||
let table_layout = if block_flow.box_().style().get_table().table_layout ==
|
||||
pub fn from_node_and_fragment(node: &ThreadSafeLayoutNode,
|
||||
fragment: Fragment)
|
||||
-> TableWrapperFlow {
|
||||
let mut block_flow = BlockFlow::from_node_and_fragment(node, fragment);
|
||||
let table_layout = if block_flow.fragment().style().get_table().table_layout ==
|
||||
table_layout::fixed {
|
||||
FixedLayout
|
||||
} else {
|
||||
|
@ -57,7 +57,7 @@ impl TableWrapperFlow {
|
|||
node: &ThreadSafeLayoutNode)
|
||||
-> TableWrapperFlow {
|
||||
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 {
|
||||
FixedLayout
|
||||
} else {
|
||||
|
@ -75,7 +75,7 @@ impl TableWrapperFlow {
|
|||
float_kind: FloatKind)
|
||||
-> TableWrapperFlow {
|
||||
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 {
|
||||
FixedLayout
|
||||
} else {
|
||||
|
@ -125,7 +125,7 @@ impl Flow for TableWrapperFlow {
|
|||
minimum widths. When called 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 responsible for flowing. */
|
||||
any fragments it is responsible for flowing. */
|
||||
|
||||
fn bubble_widths(&mut self, ctx: &mut LayoutContext) {
|
||||
// get column widths info from table flow
|
||||
|
@ -140,10 +140,10 @@ impl Flow for TableWrapperFlow {
|
|||
self.block_flow.bubble_widths(ctx);
|
||||
}
|
||||
|
||||
/// Recursively (top-down) determines the actual width of child contexts and boxes. When called
|
||||
/// on this context, the context has had its width set by the parent context.
|
||||
/// 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.
|
||||
///
|
||||
/// 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.
|
||||
fn assign_widths(&mut self, ctx: &mut LayoutContext) {
|
||||
debug!("assign_widths({}): assigning width for flow",
|
||||
|
@ -159,8 +159,8 @@ impl Flow for TableWrapperFlow {
|
|||
let width_computer = TableWrapper;
|
||||
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 content_width = self.block_flow.box_.border_box.size.width;
|
||||
let left_content_edge = self.block_flow.fragment.border_box.origin.x;
|
||||
let content_width = self.block_flow.fragment.border_box.size.width;
|
||||
|
||||
match self.table_layout {
|
||||
FixedLayout | _ if self.is_float() =>
|
||||
|
@ -194,9 +194,9 @@ impl Flow for TableWrapperFlow {
|
|||
impl fmt::Show for TableWrapperFlow {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
if self.is_float() {
|
||||
write!(f.buf, "TableWrapperFlow(Float): {}", self.block_flow.box_)
|
||||
write!(f.buf, "TableWrapperFlow(Float): {}", self.block_flow.fragment)
|
||||
} 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));
|
||||
|
||||
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.
|
||||
// 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.
|
||||
let padding_left = specified(style.get_padding().padding_left,
|
||||
input.available_width);
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
//! Text layout.
|
||||
|
||||
use layout::box_::{Box, ScannedTextBox, ScannedTextBoxInfo, UnscannedTextBox};
|
||||
use layout::flow::Flow;
|
||||
use layout::inline::InlineBoxes;
|
||||
use layout::fragment::{Fragment, ScannedTextFragment, ScannedTextFragmentInfo, UnscannedTextFragment};
|
||||
use layout::inline::InlineFragments;
|
||||
|
||||
use gfx::font::{FontMetrics, FontStyle};
|
||||
use gfx::font_context::FontContext;
|
||||
|
@ -25,12 +25,12 @@ struct NewLinePositions {
|
|||
}
|
||||
|
||||
// A helper function.
|
||||
fn can_coalesce_text_nodes(boxes: &[Box], 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);
|
||||
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 `TextBox`es.
|
||||
/// A stack-allocated object for scanning an inline flow into `TextRun`-containing `TextFragment`s.
|
||||
pub struct TextRunScanner {
|
||||
pub clump: Range<CharIndex>,
|
||||
}
|
||||
|
@ -45,22 +45,22 @@ impl TextRunScanner {
|
|||
pub fn scan_for_runs(&mut self, font_context: &mut FontContext, flow: &mut Flow) {
|
||||
{
|
||||
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 InlineBoxes {
|
||||
boxes: old_boxes,
|
||||
let InlineFragments {
|
||||
fragments: old_fragments,
|
||||
map: mut map
|
||||
} = mem::replace(&mut flow.as_inline().boxes, InlineBoxes::new());
|
||||
} = mem::replace(&mut flow.as_inline().fragments, InlineFragments::new());
|
||||
|
||||
let mut last_whitespace = true;
|
||||
let mut new_boxes = Vec::new();
|
||||
for box_i in range(0, old_boxes.len()) {
|
||||
debug!("TextRunScanner: considering box: {:u}", box_i);
|
||||
if box_i > 0 && !can_coalesce_text_nodes(old_boxes.as_slice(), box_i - 1, box_i) {
|
||||
let mut new_fragments = Vec::new();
|
||||
for fragment_i in range(0, old_fragments.len()) {
|
||||
debug!("TextRunScanner: considering fragment: {:u}", fragment_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,
|
||||
old_boxes.as_slice(),
|
||||
&mut new_boxes,
|
||||
old_fragments.as_slice(),
|
||||
&mut new_fragments,
|
||||
last_whitespace);
|
||||
}
|
||||
|
||||
|
@ -70,43 +70,43 @@ impl TextRunScanner {
|
|||
// Handle remaining clumps.
|
||||
if self.clump.length() > CharIndex(0) {
|
||||
drop(self.flush_clump_to_list(font_context,
|
||||
old_boxes.as_slice(),
|
||||
&mut new_boxes,
|
||||
old_fragments.as_slice(),
|
||||
&mut new_fragments,
|
||||
last_whitespace))
|
||||
}
|
||||
|
||||
debug!("TextRunScanner: swapping out boxes.");
|
||||
debug!("TextRunScanner: swapping out fragments.");
|
||||
|
||||
// Swap out the old and new box list of the flow.
|
||||
map.fixup(old_boxes.as_slice(), new_boxes.as_slice());
|
||||
flow.as_inline().boxes = InlineBoxes {
|
||||
boxes: new_boxes,
|
||||
// Swap out the old and new fragment list of the flow.
|
||||
map.fixup(old_fragments.as_slice(), new_fragments.as_slice());
|
||||
flow.as_inline().fragments = InlineFragments {
|
||||
fragments: new_fragments,
|
||||
map: map,
|
||||
}
|
||||
}
|
||||
|
||||
/// A "clump" is a range of inline flow leaves that can be merged together into a single box.
|
||||
/// Adjacent text with the same style can be merged, and nothing else can.
|
||||
/// A "clump" is a range of inline flow leaves that can be merged together into a single
|
||||
/// 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
|
||||
/// for correct painting order. Since we compress several leaf boxes here, the mapping must be
|
||||
/// adjusted.
|
||||
/// 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 fragments here, the mapping must
|
||||
/// be adjusted.
|
||||
///
|
||||
/// FIXME(#2267, pcwalton): Stop cloning boxes. Instead we will need to replace each `in_box`
|
||||
/// with some smaller stub.
|
||||
/// FIXME(#2267, pcwalton): Stop cloning fragments. Instead we will need to replace each
|
||||
/// `in_fragment` with some smaller stub.
|
||||
pub fn flush_clump_to_list(&mut self,
|
||||
font_context: &mut FontContext,
|
||||
in_boxes: &[Box],
|
||||
out_boxes: &mut Vec<Box>,
|
||||
in_fragments: &[Fragment],
|
||||
out_fragments: &mut Vec<Fragment>,
|
||||
last_whitespace: bool)
|
||||
-> bool {
|
||||
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_text_clump = match in_boxes[self.clump.begin().to_uint()].specific {
|
||||
UnscannedTextBox(_) => true,
|
||||
let is_text_clump = match in_fragments[self.clump.begin().to_uint()].specific {
|
||||
UnscannedTextFragment(_) => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
|
@ -116,23 +116,23 @@ impl TextRunScanner {
|
|||
fail!("WAT: can't coalesce non-text nodes in flush_clump_to_list()!")
|
||||
}
|
||||
(true, false) => {
|
||||
// FIXME(pcwalton): Stop cloning boxes, as above.
|
||||
debug!("TextRunScanner: pushing single non-text box in range: {}", self.clump);
|
||||
let new_box = in_boxes[self.clump.begin().to_uint()].clone();
|
||||
out_boxes.push(new_box)
|
||||
// FIXME(pcwalton): Stop cloning fragments, as above.
|
||||
debug!("TextRunScanner: pushing single non-text fragment in range: {}", self.clump);
|
||||
let new_fragment = in_fragments[self.clump.begin().to_uint()].clone();
|
||||
out_fragments.push(new_fragment)
|
||||
},
|
||||
(true, true) => {
|
||||
let old_box = &in_boxes[self.clump.begin().to_uint()];
|
||||
let text = match old_box.specific {
|
||||
UnscannedTextBox(ref text_box_info) => &text_box_info.text,
|
||||
_ => fail!("Expected an unscanned text box!"),
|
||||
let old_fragment = &in_fragments[self.clump.begin().to_uint()];
|
||||
let text = match old_fragment.specific {
|
||||
UnscannedTextFragment(ref text_fragment_info) => &text_fragment_info.text,
|
||||
_ => fail!("Expected an unscanned text fragment!"),
|
||||
};
|
||||
|
||||
let font_style = old_box.font_style();
|
||||
let decoration = old_box.text_decoration();
|
||||
let font_style = old_fragment.font_style();
|
||||
let decoration = old_fragment.text_decoration();
|
||||
|
||||
// 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::pre => CompressNone,
|
||||
};
|
||||
|
@ -154,29 +154,29 @@ impl TextRunScanner {
|
|||
let run = box fontgroup.borrow().create_textrun(
|
||||
transformed_text.clone(), decoration);
|
||||
|
||||
debug!("TextRunScanner: pushing single text box in range: {} ({})",
|
||||
debug!("TextRunScanner: pushing single text fragment in range: {} ({})",
|
||||
self.clump,
|
||||
*text);
|
||||
let range = Range::new(CharIndex(0), run.char_len());
|
||||
let new_metrics = run.metrics_for_range(&range);
|
||||
let new_text_box_info = ScannedTextBoxInfo::new(Arc::new(run), range);
|
||||
let mut new_box = old_box.transform(new_metrics.bounding_box.size,
|
||||
ScannedTextBox(new_text_box_info));
|
||||
new_box.new_line_pos = new_line_pos;
|
||||
out_boxes.push(new_box)
|
||||
let new_text_fragment_info = ScannedTextFragmentInfo::new(Arc::new(run), range);
|
||||
let mut new_fragment = old_fragment.transform(new_metrics.bounding_box.size,
|
||||
ScannedTextFragment(new_text_fragment_info));
|
||||
new_fragment.new_line_pos = new_line_pos;
|
||||
out_fragments.push(new_fragment)
|
||||
}
|
||||
},
|
||||
(false, true) => {
|
||||
// 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
|
||||
// and then letting `FontGroup` decide which `Font` to stick into the text run.
|
||||
let in_box = &in_boxes[self.clump.begin().to_uint()];
|
||||
let font_style = in_box.font_style();
|
||||
let in_fragment = &in_fragments[self.clump.begin().to_uint()];
|
||||
let font_style = in_fragment.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.
|
||||
let compression = match in_box.white_space() {
|
||||
let compression = match in_fragment.white_space() {
|
||||
white_space::normal => CompressWhitespaceNewline,
|
||||
white_space::pre => CompressNone,
|
||||
};
|
||||
|
@ -187,17 +187,17 @@ impl TextRunScanner {
|
|||
let mut last_whitespace_in_clump = new_whitespace;
|
||||
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
|
||||
// `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.
|
||||
let idx = CharIndex(i as int) + self.clump.begin();
|
||||
let in_box = match in_boxes[idx.to_uint()].specific {
|
||||
UnscannedTextBox(ref text_box_info) => &text_box_info.text,
|
||||
_ => fail!("Expected an unscanned text box!"),
|
||||
let in_fragment = match in_fragments[idx.to_uint()].specific {
|
||||
UnscannedTextFragment(ref text_fragment_info) => &text_fragment_info.text,
|
||||
_ => fail!("Expected an unscanned text fragment!"),
|
||||
};
|
||||
|
||||
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,
|
||||
last_whitespace_in_clump,
|
||||
&mut new_line_pos);
|
||||
|
@ -232,23 +232,23 @@ impl TextRunScanner {
|
|||
None
|
||||
};
|
||||
|
||||
// Make new boxes with the run and adjusted text indices.
|
||||
debug!("TextRunScanner: pushing box(es) in range: {}", self.clump);
|
||||
// Make new fragments with the run and adjusted text indices.
|
||||
debug!("TextRunScanner: pushing fragment(s) in range: {}", self.clump);
|
||||
for i in clump.each_index() {
|
||||
let logical_offset = i - self.clump.begin();
|
||||
let range = new_ranges.get(logical_offset.to_uint());
|
||||
if range.length() == CharIndex(0) {
|
||||
debug!("Elided an `UnscannedTextbox` because it was zero-length after \
|
||||
compression; {}", in_boxes[i.to_uint()]);
|
||||
debug!("Elided an `UnscannedTextFragment` because it was zero-length after \
|
||||
compression; {}", in_fragments[i.to_uint()]);
|
||||
continue
|
||||
}
|
||||
|
||||
let new_text_box_info = ScannedTextBoxInfo::new(run.get_ref().clone(), *range);
|
||||
let new_metrics = new_text_box_info.run.metrics_for_range(range);
|
||||
let mut new_box = in_boxes[i.to_uint()].transform(new_metrics.bounding_box.size,
|
||||
ScannedTextBox(new_text_box_info));
|
||||
new_box.new_line_pos = new_line_positions.get(logical_offset.to_uint()).new_line_pos.clone();
|
||||
out_boxes.push(new_box)
|
||||
let new_text_fragment_info = ScannedTextFragmentInfo::new(run.get_ref().clone(), *range);
|
||||
let new_metrics = new_text_fragment_info.run.metrics_for_range(range);
|
||||
let mut new_fragment = in_fragments[i.to_uint()].transform(new_metrics.bounding_box.size,
|
||||
ScannedTextFragment(new_text_fragment_info));
|
||||
new_fragment.new_line_pos = new_line_positions.get(logical_offset.to_uint()).new_line_pos.clone();
|
||||
out_fragments.push(new_fragment)
|
||||
}
|
||||
}
|
||||
} // End of match.
|
||||
|
|
|
@ -95,12 +95,12 @@ pub mod pipeline;
|
|||
|
||||
pub mod layout {
|
||||
pub mod block;
|
||||
pub mod box_;
|
||||
pub mod construct;
|
||||
pub mod context;
|
||||
pub mod floats;
|
||||
pub mod flow;
|
||||
pub mod flow_list;
|
||||
pub mod fragment;
|
||||
pub mod layout_task;
|
||||
pub mod inline;
|
||||
pub mod model;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue