mirror of
https://github.com/servo/servo.git
synced 2025-06-18 13:24:29 +00:00
Added floats to the flow tree
This commit is contained in:
parent
d3fe4f4e3a
commit
94e7a86b7e
10 changed files with 398 additions and 51 deletions
|
@ -8,9 +8,10 @@ use layout::box::{RenderBox};
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||||
use layout::display_list_builder::{FlowDisplayListBuilderMethods};
|
use layout::display_list_builder::{FlowDisplayListBuilderMethods};
|
||||||
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow};
|
use layout::flow::{BlockFlow, FlowContext, FlowData, InlineBlockFlow, FloatFlow};
|
||||||
use layout::inline::InlineLayout;
|
use layout::inline::InlineLayout;
|
||||||
use layout::model::{MaybeAuto, Specified, Auto};
|
use layout::model::{MaybeAuto, Specified, Auto};
|
||||||
|
use layout::float_context::FloatContext;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
|
@ -72,7 +73,7 @@ impl BlockLayout for FlowContext {
|
||||||
|
|
||||||
fn starts_block_flow(&self) -> bool {
|
fn starts_block_flow(&self) -> bool {
|
||||||
match *self {
|
match *self {
|
||||||
BlockFlow(*) | InlineBlockFlow(*) => true,
|
BlockFlow(*) | InlineBlockFlow(*) | FloatFlow(*) => true,
|
||||||
_ => false
|
_ => false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -91,14 +92,17 @@ impl BlockFlowData {
|
||||||
pub fn bubble_widths_block(@mut self, ctx: &LayoutContext) {
|
pub fn bubble_widths_block(@mut self, ctx: &LayoutContext) {
|
||||||
let mut min_width = Au(0);
|
let mut min_width = Au(0);
|
||||||
let mut pref_width = Au(0);
|
let mut pref_width = Au(0);
|
||||||
|
let mut num_floats = 0;
|
||||||
|
|
||||||
/* find max width from child block contexts */
|
/* find max width from child block contexts */
|
||||||
for BlockFlow(self).each_child |child_ctx| {
|
for BlockFlow(self).each_child |child_ctx| {
|
||||||
assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
|
assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
|
||||||
|
|
||||||
do child_ctx.with_base |child_node| {
|
do child_ctx.with_mut_base |child_node| {
|
||||||
min_width = geometry::max(min_width, child_node.min_width);
|
min_width = geometry::max(min_width, child_node.min_width);
|
||||||
pref_width = geometry::max(pref_width, child_node.pref_width);
|
pref_width = geometry::max(pref_width, child_node.pref_width);
|
||||||
|
|
||||||
|
num_floats = num_floats + child_node.num_floats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -116,6 +120,7 @@ impl BlockFlowData {
|
||||||
|
|
||||||
self.common.min_width = min_width;
|
self.common.min_width = min_width;
|
||||||
self.common.pref_width = pref_width;
|
self.common.pref_width = pref_width;
|
||||||
|
self.common.num_floats = num_floats;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes left and right margins and width based on CSS 2.1 secion 10.3.3.
|
/// Computes left and right margins and width based on CSS 2.1 secion 10.3.3.
|
||||||
|
@ -180,6 +185,7 @@ impl BlockFlowData {
|
||||||
debug!("Setting root position");
|
debug!("Setting root position");
|
||||||
self.common.position.origin = Au::zero_point();
|
self.common.position.origin = Au::zero_point();
|
||||||
self.common.position.size.width = ctx.screen_size.size.width;
|
self.common.position.size.width = ctx.screen_size.size.width;
|
||||||
|
self.common.floats_in = FloatContext::new(self.common.num_floats);
|
||||||
}
|
}
|
||||||
|
|
||||||
//position was set to the containing block by the flow's parent
|
//position was set to the containing block by the flow's parent
|
||||||
|
@ -240,7 +246,7 @@ impl BlockFlowData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assign_height_block(@mut self, ctx: &LayoutContext) {
|
pub fn assign_height_block(@mut self, ctx: &mut LayoutContext) {
|
||||||
let mut cur_y = Au(0);
|
let mut cur_y = Au(0);
|
||||||
let mut top_offset = Au(0);
|
let mut top_offset = Au(0);
|
||||||
|
|
||||||
|
@ -251,6 +257,28 @@ impl BlockFlowData {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO(eatkinson): the translation here is probably
|
||||||
|
// totally wrong. We need to do it right or pages
|
||||||
|
// with floats will look very strange.
|
||||||
|
|
||||||
|
// Floats for blocks work like this:
|
||||||
|
// self.floats_in -> child[0].floats_in
|
||||||
|
// visit child[0]
|
||||||
|
// child[i-1].floats_out -> child[i].floats_in
|
||||||
|
// visit child[i]
|
||||||
|
// repeat until all children are visited.
|
||||||
|
// last_child.floats_out -> self.floats_out (done at the end of this function)
|
||||||
|
let mut float_ctx = self.common.floats_in.clone();
|
||||||
|
for BlockFlow(self).each_child |kid| {
|
||||||
|
do kid.with_mut_base |child_node| {
|
||||||
|
child_node.floats_in = float_ctx.clone();
|
||||||
|
}
|
||||||
|
kid.assign_height(ctx);
|
||||||
|
do kid.with_mut_base |child_node| {
|
||||||
|
float_ctx = child_node.floats_out.translate(Point2D(Au(0), -child_node.position.size.height));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
for BlockFlow(self).each_child |kid| {
|
for BlockFlow(self).each_child |kid| {
|
||||||
do kid.with_mut_base |child_node| {
|
do kid.with_mut_base |child_node| {
|
||||||
child_node.position.origin.y = cur_y;
|
child_node.position.origin.y = cur_y;
|
||||||
|
@ -281,6 +309,8 @@ impl BlockFlowData {
|
||||||
//TODO(eatkinson): compute heights using the 'height' property.
|
//TODO(eatkinson): compute heights using the 'height' property.
|
||||||
self.common.position.size.height = height + noncontent_height;
|
self.common.position.size.height = height + noncontent_height;
|
||||||
|
|
||||||
|
|
||||||
|
self.common.floats_out = float_ctx.translate(Point2D(Au(0), self.common.position.size.height));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn build_display_list_block<E:ExtraDisplayListData>(@mut self,
|
pub fn build_display_list_block<E:ExtraDisplayListData>(@mut self,
|
||||||
|
|
|
@ -8,7 +8,7 @@ use css::node_style::StyledNode;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData, ToGfxColor};
|
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData, ToGfxColor};
|
||||||
use layout::flow::FlowContext;
|
use layout::flow::FlowContext;
|
||||||
use layout::model::BoxModel;
|
use layout::model::{BoxModel, MaybeAuto};
|
||||||
use layout::text;
|
use layout::text;
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
|
@ -370,11 +370,41 @@ pub impl RenderBox {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Guess the intrinsic width of this box for
|
||||||
|
/// computation of min and preferred widths.
|
||||||
|
//
|
||||||
|
// TODO(eatkinson): this is unspecified in
|
||||||
|
// CSS 2.1, but we need to do something reasonable
|
||||||
|
// here. What this function does currently is
|
||||||
|
// NOT reasonable.
|
||||||
|
//
|
||||||
|
// TODO(eatkinson): integrate with
|
||||||
|
// get_min_width and get_pref_width?
|
||||||
|
priv fn guess_width (&self) -> Au {
|
||||||
|
do self.with_base |base| {
|
||||||
|
if(!base.node.is_element()) {
|
||||||
|
Au(0)
|
||||||
|
} else {
|
||||||
|
|
||||||
|
let w = MaybeAuto::from_width(self.style().width(), Au(0)).spec_or_default(Au(0));
|
||||||
|
let ml = MaybeAuto::from_margin(self.style().margin_left(), Au(0)).spec_or_default(Au(0));
|
||||||
|
let mr = MaybeAuto::from_margin(self.style().margin_right(), Au(0)).spec_or_default(Au(0));
|
||||||
|
let pl = base.model.compute_padding_length(self.style().padding_left(), Au(0));
|
||||||
|
let pr = base.model.compute_padding_length(self.style().padding_right(), Au(0));
|
||||||
|
let bl = base.model.compute_border_width(self.style().border_left_width());
|
||||||
|
let br = base.model.compute_border_width(self.style().border_right_width());
|
||||||
|
|
||||||
|
w + ml + mr + pl + pr + bl + br
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Returns the *minimum width* of this render box as defined by the CSS specification.
|
/// Returns the *minimum width* of this render box as defined by the CSS specification.
|
||||||
fn get_min_width(&self, _: &LayoutContext) -> Au {
|
fn get_min_width(&self, _: &LayoutContext) -> Au {
|
||||||
// FIXME(pcwalton): I think we only need to calculate this if the damage says that CSS
|
// FIXME(pcwalton): I think we only need to calculate this if the damage says that CSS
|
||||||
// needs to be restyled.
|
// needs to be restyled.
|
||||||
match *self {
|
|
||||||
|
self.guess_width() + match *self {
|
||||||
// TODO: This should account for the minimum width of the box element in isolation.
|
// TODO: This should account for the minimum width of the box element in isolation.
|
||||||
// That includes borders, margins, and padding, but not child widths. The block
|
// That includes borders, margins, and padding, but not child widths. The block
|
||||||
// `FlowContext` will combine the width of this element and that of its children to
|
// `FlowContext` will combine the width of this element and that of its children to
|
||||||
|
@ -397,7 +427,7 @@ pub impl RenderBox {
|
||||||
|
|
||||||
/// Returns the *preferred width* of this render box as defined by the CSS specification.
|
/// Returns the *preferred width* of this render box as defined by the CSS specification.
|
||||||
fn get_pref_width(&self, _: &LayoutContext) -> Au {
|
fn get_pref_width(&self, _: &LayoutContext) -> Au {
|
||||||
match *self {
|
self.guess_width() + match *self {
|
||||||
// TODO: This should account for the preferred width of the box element in isolation.
|
// TODO: This should account for the preferred width of the box element in isolation.
|
||||||
// That includes borders, margins, and padding, but not child widths. The block
|
// That includes borders, margins, and padding, but not child widths. The block
|
||||||
// `FlowContext` will combine the width of this element and that of its children to
|
// `FlowContext` will combine the width of this element and that of its children to
|
||||||
|
|
|
@ -6,6 +6,7 @@
|
||||||
|
|
||||||
use layout::aux::LayoutAuxMethods;
|
use layout::aux::LayoutAuxMethods;
|
||||||
use layout::block::BlockFlowData;
|
use layout::block::BlockFlowData;
|
||||||
|
use layout::float::FloatFlowData;
|
||||||
use layout::box::{GenericRenderBoxClass, ImageRenderBox, ImageRenderBoxClass, RenderBox};
|
use layout::box::{GenericRenderBoxClass, ImageRenderBox, ImageRenderBoxClass, RenderBox};
|
||||||
use layout::box::{RenderBoxBase, RenderBoxType, RenderBox_Generic, RenderBox_Image};
|
use layout::box::{RenderBoxBase, RenderBoxType, RenderBox_Generic, RenderBox_Image};
|
||||||
use layout::box::{RenderBox_Text, UnscannedTextRenderBox, UnscannedTextRenderBoxClass};
|
use layout::box::{RenderBox_Text, UnscannedTextRenderBox, UnscannedTextRenderBoxClass};
|
||||||
|
@ -22,6 +23,7 @@ use newcss::values::{CSSDisplayTableRowGroup, CSSDisplayTableHeaderGroup, CSSDis
|
||||||
use newcss::values::{CSSDisplayTableRow, CSSDisplayTableColumnGroup, CSSDisplayTableColumn};
|
use newcss::values::{CSSDisplayTableRow, CSSDisplayTableColumnGroup, CSSDisplayTableColumn};
|
||||||
use newcss::values::{CSSDisplayTableCell, CSSDisplayTableCaption};
|
use newcss::values::{CSSDisplayTableCell, CSSDisplayTableCaption};
|
||||||
use newcss::values::{CSSDisplayNone};
|
use newcss::values::{CSSDisplayNone};
|
||||||
|
use newcss::values::{CSSFloatNone};
|
||||||
use script::dom::element::*;
|
use script::dom::element::*;
|
||||||
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
|
use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId};
|
||||||
use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId};
|
use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId};
|
||||||
|
@ -350,7 +352,22 @@ pub impl LayoutTreeBuilder {
|
||||||
Some(gen) => Some(gen.flow)
|
Some(gen) => Some(gen.flow)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// TODO(eatkinson): use the value of the float property to
|
||||||
|
// determine whether to float left or right.
|
||||||
|
let is_float = if (node.is_element()) {
|
||||||
|
match node.style().float() {
|
||||||
|
CSSFloatNone => false,
|
||||||
|
_ => true
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
let new_generator = match (display, parent_generator.flow, sibling_flow) {
|
let new_generator = match (display, parent_generator.flow, sibling_flow) {
|
||||||
|
(CSSDisplayBlock, BlockFlow(_), _) if is_float => {
|
||||||
|
self.create_child_generator(node, parent_generator, Flow_Float)
|
||||||
|
},
|
||||||
(CSSDisplayBlock, BlockFlow(info), _) => match (info.is_root, node.parent_node()) {
|
(CSSDisplayBlock, BlockFlow(info), _) => match (info.is_root, node.parent_node()) {
|
||||||
// If this is the root node, then use the root flow's
|
// If this is the root node, then use the root flow's
|
||||||
// context. Otherwise, make a child block context.
|
// context. Otherwise, make a child block context.
|
||||||
|
@ -383,8 +400,6 @@ pub impl LayoutTreeBuilder {
|
||||||
|
|
||||||
// TODO(eatkinson): blocks that are children of inlines need
|
// TODO(eatkinson): blocks that are children of inlines need
|
||||||
// to split their parent flows.
|
// to split their parent flows.
|
||||||
//
|
|
||||||
// TODO(eatkinson): floats and positioned elements.
|
|
||||||
_ => parent_generator
|
_ => parent_generator
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -520,7 +535,7 @@ pub impl LayoutTreeBuilder {
|
||||||
let result = match ty {
|
let result = match ty {
|
||||||
Flow_Absolute => AbsoluteFlow(@mut info),
|
Flow_Absolute => AbsoluteFlow(@mut info),
|
||||||
Flow_Block => BlockFlow(@mut BlockFlowData::new(info)),
|
Flow_Block => BlockFlow(@mut BlockFlowData::new(info)),
|
||||||
Flow_Float => FloatFlow(@mut info),
|
Flow_Float => FloatFlow(@mut FloatFlowData::new(info)),
|
||||||
Flow_InlineBlock => InlineBlockFlow(@mut info),
|
Flow_InlineBlock => InlineBlockFlow(@mut info),
|
||||||
Flow_Inline => InlineFlow(@mut InlineFlowData::new(info)),
|
Flow_Inline => InlineFlow(@mut InlineFlowData::new(info)),
|
||||||
Flow_Root => BlockFlow(@mut BlockFlowData::new_root(info)),
|
Flow_Root => BlockFlow(@mut BlockFlowData::new_root(info)),
|
||||||
|
|
223
src/components/main/layout/float.rs
Normal file
223
src/components/main/layout/float.rs
Normal file
|
@ -0,0 +1,223 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
|
use layout::box::{RenderBox};
|
||||||
|
use layout::context::LayoutContext;
|
||||||
|
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||||
|
use layout::display_list_builder::{FlowDisplayListBuilderMethods};
|
||||||
|
use layout::flow::{FloatFlow, FlowData};
|
||||||
|
use layout::model::{MaybeAuto};
|
||||||
|
use layout::float_context::{FloatContext, PlacementInfo, FloatLeft};
|
||||||
|
|
||||||
|
use core::cell::Cell;
|
||||||
|
use geom::point::Point2D;
|
||||||
|
use geom::rect::Rect;
|
||||||
|
use gfx::display_list::DisplayList;
|
||||||
|
use gfx::geometry::Au;
|
||||||
|
use gfx::geometry;
|
||||||
|
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||||
|
|
||||||
|
pub struct FloatFlowData {
|
||||||
|
/// Data common to all flows.
|
||||||
|
common: FlowData,
|
||||||
|
|
||||||
|
/// The associated render box.
|
||||||
|
box: Option<RenderBox>,
|
||||||
|
|
||||||
|
containing_width: Au,
|
||||||
|
|
||||||
|
|
||||||
|
/// Index into the box list for inline floats
|
||||||
|
index: Option<uint>,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FloatFlowData {
|
||||||
|
pub fn new(common: FlowData) -> FloatFlowData {
|
||||||
|
FloatFlowData {
|
||||||
|
common: common,
|
||||||
|
containing_width: Au(0),
|
||||||
|
box: None,
|
||||||
|
index: None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn teardown(&mut self) {
|
||||||
|
self.common.teardown();
|
||||||
|
for self.box.each |box| {
|
||||||
|
box.teardown();
|
||||||
|
}
|
||||||
|
self.box = None;
|
||||||
|
self.index = None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl FloatFlowData {
|
||||||
|
pub fn bubble_widths_float(@mut self, ctx: &LayoutContext) {
|
||||||
|
let mut min_width = Au(0);
|
||||||
|
let mut pref_width = Au(0);
|
||||||
|
|
||||||
|
self.common.num_floats = 1;
|
||||||
|
|
||||||
|
for FloatFlow(self).each_child |child_ctx| {
|
||||||
|
//assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
|
||||||
|
|
||||||
|
do child_ctx.with_mut_base |child_node| {
|
||||||
|
min_width = geometry::max(min_width, child_node.min_width);
|
||||||
|
pref_width = geometry::max(pref_width, child_node.pref_width);
|
||||||
|
child_node.floats_in = FloatContext::new(child_node.num_floats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.box.map(|&box| {
|
||||||
|
let style = box.style();
|
||||||
|
do box.with_model |model| {
|
||||||
|
model.compute_borders(style)
|
||||||
|
}
|
||||||
|
|
||||||
|
min_width = min_width.add(&box.get_min_width(ctx));
|
||||||
|
pref_width = pref_width.add(&box.get_pref_width(ctx));
|
||||||
|
});
|
||||||
|
|
||||||
|
self.common.min_width = min_width;
|
||||||
|
self.common.pref_width = pref_width;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assign_widths_float(@mut self, _: &LayoutContext) {
|
||||||
|
debug!("assign_widths_block: assigning width for flow %?", self.common.id);
|
||||||
|
// position.size.width is set by parent even though we don't know
|
||||||
|
// position.origin yet.
|
||||||
|
let mut remaining_width = self.common.position.size.width;
|
||||||
|
self.containing_width = remaining_width;
|
||||||
|
let mut x_offset = Au(0);
|
||||||
|
|
||||||
|
for self.box.each |&box| {
|
||||||
|
let style = box.style();
|
||||||
|
do box.with_model |model| {
|
||||||
|
// Can compute padding here since we know containing block width.
|
||||||
|
model.compute_padding(style, remaining_width);
|
||||||
|
|
||||||
|
// Margins for floats are 0 if auto.
|
||||||
|
let margin_top = MaybeAuto::from_margin(style.margin_top(),
|
||||||
|
remaining_width).spec_or_default(Au(0));
|
||||||
|
let margin_bottom = MaybeAuto::from_margin(style.margin_bottom(),
|
||||||
|
remaining_width).spec_or_default(Au(0));
|
||||||
|
let margin_left = MaybeAuto::from_margin(style.margin_left(),
|
||||||
|
remaining_width).spec_or_default(Au(0));
|
||||||
|
let margin_right = MaybeAuto::from_margin(style.margin_right(),
|
||||||
|
remaining_width).spec_or_default(Au(0));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
let shrink_to_fit = geometry::min(self.common.pref_width,
|
||||||
|
geometry::max(self.common.min_width,
|
||||||
|
remaining_width));
|
||||||
|
|
||||||
|
|
||||||
|
let width = MaybeAuto::from_width(style.width(),
|
||||||
|
remaining_width).spec_or_default(shrink_to_fit);
|
||||||
|
|
||||||
|
model.margin.top = margin_top;
|
||||||
|
model.margin.right = margin_right;
|
||||||
|
model.margin.bottom = margin_bottom;
|
||||||
|
model.margin.left = margin_left;
|
||||||
|
|
||||||
|
self.common.position.size.width = width;
|
||||||
|
x_offset = model.offset();
|
||||||
|
remaining_width = width;
|
||||||
|
}
|
||||||
|
|
||||||
|
do box.with_mut_base |base| {
|
||||||
|
//The associated box is the border box of this flow
|
||||||
|
base.position.origin.x = base.model.margin.left;
|
||||||
|
|
||||||
|
let pb = base.model.padding.left + base.model.padding.right +
|
||||||
|
base.model.border.left + base.model.border.right;
|
||||||
|
base.position.size.width = remaining_width + pb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for FloatFlow(self).each_child |kid| {
|
||||||
|
//assert!(kid.starts_block_flow() || kid.starts_inline_flow());
|
||||||
|
|
||||||
|
do kid.with_mut_base |child_node| {
|
||||||
|
child_node.position.origin.x = x_offset;
|
||||||
|
child_node.position.size.width = remaining_width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn assign_height_float(@mut self, ctx: &mut LayoutContext) {
|
||||||
|
for FloatFlow(self).each_child |kid| {
|
||||||
|
kid.assign_height(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut cur_y = Au(0);
|
||||||
|
let mut top_offset = Au(0);
|
||||||
|
|
||||||
|
for self.box.each |&box| {
|
||||||
|
do box.with_model |model| {
|
||||||
|
top_offset = model.margin.top + model.border.top + model.padding.top;
|
||||||
|
cur_y += top_offset;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for FloatFlow(self).each_child |kid| {
|
||||||
|
do kid.with_mut_base |child_node| {
|
||||||
|
child_node.position.origin.y = cur_y;
|
||||||
|
cur_y += child_node.position.size.height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let height = cur_y - top_offset;
|
||||||
|
|
||||||
|
let mut noncontent_height = Au(0);
|
||||||
|
self.box.map(|&box| {
|
||||||
|
do box.with_mut_base |base| {
|
||||||
|
//The associated box is the border box of this flow
|
||||||
|
base.position.origin.y = base.model.margin.top;
|
||||||
|
|
||||||
|
noncontent_height = base.model.padding.top + base.model.padding.bottom +
|
||||||
|
base.model.border.top + base.model.border.bottom;
|
||||||
|
base.position.size.height = height + noncontent_height;
|
||||||
|
|
||||||
|
noncontent_height += base.model.margin.top + base.model.margin.bottom;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
//TODO(eatkinson): compute heights using the 'height' property.
|
||||||
|
self.common.position.size.height = height + noncontent_height;
|
||||||
|
|
||||||
|
let info = PlacementInfo {
|
||||||
|
width: self.common.position.size.width,
|
||||||
|
height: self.common.position.size.height,
|
||||||
|
ceiling: Au(0),
|
||||||
|
max_width: self.containing_width,
|
||||||
|
f_type: FloatLeft,
|
||||||
|
};
|
||||||
|
|
||||||
|
self.common.floats_out = self.common.floats_in.add_float(&info);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn build_display_list_float<E:ExtraDisplayListData>(@mut self,
|
||||||
|
builder: &DisplayListBuilder,
|
||||||
|
dirty: &Rect<Au>,
|
||||||
|
offset: &Point2D<Au>,
|
||||||
|
list: &Cell<DisplayList<E>>) {
|
||||||
|
self.box.map(|&box| {
|
||||||
|
box.build_display_list(builder, dirty, offset, list)
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
// go deeper into the flow tree
|
||||||
|
let flow = FloatFlow(self);
|
||||||
|
for flow.each_child |child| {
|
||||||
|
flow.build_display_list_for_child(builder, child, dirty, offset, list)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,28 +1,32 @@
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* 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/. */
|
||||||
|
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
use geom::size::Size2D;
|
use geom::size::Size2D;
|
||||||
use geom::rect::Rect;
|
use geom::rect::Rect;
|
||||||
use gfx::geometry::{Au, max, min};
|
use gfx::geometry::{Au, max, min};
|
||||||
use core::util::replace;
|
use core::util::replace;
|
||||||
|
|
||||||
enum FloatType{
|
pub enum FloatType{
|
||||||
FloatLeft,
|
FloatLeft,
|
||||||
FloatRight
|
FloatRight
|
||||||
}
|
}
|
||||||
|
|
||||||
priv struct FloatContextBase{
|
struct FloatContextBase{
|
||||||
float_data: ~[Option<FloatData>],
|
float_data: ~[Option<FloatData>],
|
||||||
floats_used: uint,
|
floats_used: uint,
|
||||||
max_y : Au,
|
max_y : Au,
|
||||||
offset: Point2D<Au>
|
offset: Point2D<Au>
|
||||||
}
|
}
|
||||||
|
|
||||||
priv struct FloatData{
|
struct FloatData{
|
||||||
bounds: Rect<Au>,
|
bounds: Rect<Au>,
|
||||||
f_type: FloatType
|
f_type: FloatType
|
||||||
}
|
}
|
||||||
|
|
||||||
/// All information necessary to place a float
|
/// All information necessary to place a float
|
||||||
struct PlacementInfo{
|
pub struct PlacementInfo{
|
||||||
width: Au, // The dimensions of the float
|
width: Au, // The dimensions of the float
|
||||||
height: Au,
|
height: Au,
|
||||||
ceiling: Au, // The minimum top of the float, as determined by earlier elements
|
ceiling: Au, // The minimum top of the float, as determined by earlier elements
|
||||||
|
@ -32,18 +36,26 @@ struct PlacementInfo{
|
||||||
|
|
||||||
/// Wrappers around float methods. To avoid allocating data we'll never use,
|
/// Wrappers around float methods. To avoid allocating data we'll never use,
|
||||||
/// destroy the context on modification.
|
/// destroy the context on modification.
|
||||||
enum FloatContext {
|
pub enum FloatContext {
|
||||||
Invalid,
|
Invalid,
|
||||||
Valid(FloatContextBase)
|
Valid(FloatContextBase)
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FloatContext {
|
impl FloatContext {
|
||||||
fn new(num_floats: uint) -> FloatContext {
|
pub fn new(num_floats: uint) -> FloatContext {
|
||||||
Valid(FloatContextBase::new(num_floats))
|
Valid(FloatContextBase::new(num_floats))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
priv fn with_base<R>(&mut self, callback: &fn(&mut FloatContextBase) -> R) -> R {
|
pub fn clone(&mut self) -> FloatContext {
|
||||||
|
match *self {
|
||||||
|
Invalid => fail!("Can't clone an invalid float context"),
|
||||||
|
Valid(_) => replace(self, Invalid)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline(always)]
|
||||||
|
fn with_base<R>(&mut self, callback: &fn(&mut FloatContextBase) -> R) -> R {
|
||||||
match *self {
|
match *self {
|
||||||
Invalid => fail!("Float context no longer available"),
|
Invalid => fail!("Float context no longer available"),
|
||||||
Valid(ref mut base) => callback(base)
|
Valid(ref mut base) => callback(base)
|
||||||
|
@ -51,7 +63,7 @@ impl FloatContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn with_base<R>(&self, callback: &fn(&FloatContextBase) -> R) -> R {
|
pub fn with_base<R>(&self, callback: &fn(&FloatContextBase) -> R) -> R {
|
||||||
match *self {
|
match *self {
|
||||||
Invalid => fail!("Float context no longer available"),
|
Invalid => fail!("Float context no longer available"),
|
||||||
Valid(ref base) => callback(base)
|
Valid(ref base) => callback(base)
|
||||||
|
@ -59,7 +71,7 @@ impl FloatContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn translate(&mut self, trans: Point2D<Au>) -> FloatContext {
|
pub fn translate(&mut self, trans: Point2D<Au>) -> FloatContext {
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
base.translate(trans);
|
base.translate(trans);
|
||||||
}
|
}
|
||||||
|
@ -67,14 +79,14 @@ impl FloatContext {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn available_rect(&mut self, top: Au, height: Au, max_x: Au) -> Option<Rect<Au>> {
|
pub fn available_rect(&mut self, top: Au, height: Au, max_x: Au) -> Option<Rect<Au>> {
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
base.available_rect(top, height, max_x)
|
base.available_rect(top, height, max_x)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
fn add_float(&mut self, info: &PlacementInfo) -> FloatContext{
|
pub fn add_float(&mut self, info: &PlacementInfo) -> FloatContext{
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
base.add_float(info);
|
base.add_float(info);
|
||||||
}
|
}
|
||||||
|
@ -84,9 +96,8 @@ impl FloatContext {
|
||||||
|
|
||||||
impl FloatContextBase{
|
impl FloatContextBase{
|
||||||
fn new(num_floats: uint) -> FloatContextBase {
|
fn new(num_floats: uint) -> FloatContextBase {
|
||||||
let new_data = do vec::build_sized(num_floats) |push_fun| {
|
debug!("Creating float context of size %?", num_floats);
|
||||||
push_fun(None);
|
let new_data = vec::from_elem(num_floats, None);
|
||||||
};
|
|
||||||
FloatContextBase {
|
FloatContextBase {
|
||||||
float_data: new_data,
|
float_data: new_data,
|
||||||
floats_used: 0,
|
floats_used: 0,
|
||||||
|
@ -166,6 +177,7 @@ impl FloatContextBase{
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_float(&mut self, info: &PlacementInfo) {
|
fn add_float(&mut self, info: &PlacementInfo) {
|
||||||
|
debug!("Floats_used: %?, Floats available: %?", self.floats_used, self.float_data.len());
|
||||||
assert!(self.floats_used < self.float_data.len() &&
|
assert!(self.floats_used < self.float_data.len() &&
|
||||||
self.float_data[self.floats_used].is_none());
|
self.float_data[self.floats_used].is_none());
|
||||||
|
|
||||||
|
@ -177,6 +189,7 @@ impl FloatContextBase{
|
||||||
f_type: info.f_type
|
f_type: info.f_type
|
||||||
};
|
};
|
||||||
self.float_data[self.floats_used] = Some(new_float);
|
self.float_data[self.floats_used] = Some(new_float);
|
||||||
|
self.floats_used += 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Given necessary info, finds the position of the float in
|
/// Given necessary info, finds the position of the float in
|
|
@ -26,10 +26,12 @@
|
||||||
/// similar methods.
|
/// similar methods.
|
||||||
|
|
||||||
use layout::block::BlockFlowData;
|
use layout::block::BlockFlowData;
|
||||||
|
use layout::float::FloatFlowData;
|
||||||
use layout::box::RenderBox;
|
use layout::box::RenderBox;
|
||||||
use layout::context::LayoutContext;
|
use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||||
use layout::inline::{InlineFlowData};
|
use layout::inline::{InlineFlowData};
|
||||||
|
use layout::float_context::{FloatContext, Invalid};
|
||||||
|
|
||||||
use core::cell::Cell;
|
use core::cell::Cell;
|
||||||
use geom::point::Point2D;
|
use geom::point::Point2D;
|
||||||
|
@ -44,7 +46,7 @@ use servo_util::tree::{TreeNode, TreeNodeRef, TreeUtils};
|
||||||
pub enum FlowContext {
|
pub enum FlowContext {
|
||||||
AbsoluteFlow(@mut FlowData),
|
AbsoluteFlow(@mut FlowData),
|
||||||
BlockFlow(@mut BlockFlowData),
|
BlockFlow(@mut BlockFlowData),
|
||||||
FloatFlow(@mut FlowData),
|
FloatFlow(@mut FloatFlowData),
|
||||||
InlineBlockFlow(@mut FlowData),
|
InlineBlockFlow(@mut FlowData),
|
||||||
InlineFlow(@mut InlineFlowData),
|
InlineFlow(@mut InlineFlowData),
|
||||||
TableFlow(@mut FlowData),
|
TableFlow(@mut FlowData),
|
||||||
|
@ -70,10 +72,10 @@ impl FlowContext {
|
||||||
pub fn teardown(&self) {
|
pub fn teardown(&self) {
|
||||||
match *self {
|
match *self {
|
||||||
AbsoluteFlow(data) |
|
AbsoluteFlow(data) |
|
||||||
FloatFlow(data) |
|
|
||||||
InlineBlockFlow(data) |
|
InlineBlockFlow(data) |
|
||||||
TableFlow(data) => data.teardown(),
|
TableFlow(data) => data.teardown(),
|
||||||
BlockFlow(data) => data.teardown(),
|
BlockFlow(data) => data.teardown(),
|
||||||
|
FloatFlow(data) => data.teardown(),
|
||||||
InlineFlow(data) => data.teardown()
|
InlineFlow(data) => data.teardown()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -110,7 +112,7 @@ impl TreeNodeRef<FlowData> for FlowContext {
|
||||||
BlockFlow(info) => {
|
BlockFlow(info) => {
|
||||||
callback(&info.common)
|
callback(&info.common)
|
||||||
}
|
}
|
||||||
FloatFlow(info) => callback(info),
|
FloatFlow(info) => callback(&info.common),
|
||||||
InlineBlockFlow(info) => callback(info),
|
InlineBlockFlow(info) => callback(info),
|
||||||
InlineFlow(info) => {
|
InlineFlow(info) => {
|
||||||
callback(&info.common)
|
callback(&info.common)
|
||||||
|
@ -124,7 +126,7 @@ impl TreeNodeRef<FlowData> for FlowContext {
|
||||||
BlockFlow(info) => {
|
BlockFlow(info) => {
|
||||||
callback(&mut info.common)
|
callback(&mut info.common)
|
||||||
}
|
}
|
||||||
FloatFlow(info) => callback(info),
|
FloatFlow(info) => callback(&mut info.common),
|
||||||
InlineBlockFlow(info) => callback(info),
|
InlineBlockFlow(info) => callback(info),
|
||||||
InlineFlow(info) => {
|
InlineFlow(info) => {
|
||||||
callback(&mut info.common)
|
callback(&mut info.common)
|
||||||
|
@ -156,6 +158,9 @@ pub struct FlowData {
|
||||||
min_width: Au,
|
min_width: Au,
|
||||||
pref_width: Au,
|
pref_width: Au,
|
||||||
position: Rect<Au>,
|
position: Rect<Au>,
|
||||||
|
floats_in: FloatContext,
|
||||||
|
floats_out: FloatContext,
|
||||||
|
num_floats: uint,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TreeNode<FlowContext> for FlowData {
|
impl TreeNode<FlowContext> for FlowData {
|
||||||
|
@ -216,6 +221,9 @@ impl FlowData {
|
||||||
min_width: Au(0),
|
min_width: Au(0),
|
||||||
pref_width: Au(0),
|
pref_width: Au(0),
|
||||||
position: Au::zero_rect(),
|
position: Au::zero_rect(),
|
||||||
|
floats_in: Invalid,
|
||||||
|
floats_out: Invalid,
|
||||||
|
num_floats: 0,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -264,6 +272,7 @@ impl<'self> FlowContext {
|
||||||
match *self {
|
match *self {
|
||||||
BlockFlow(info) => info.bubble_widths_block(ctx),
|
BlockFlow(info) => info.bubble_widths_block(ctx),
|
||||||
InlineFlow(info) => info.bubble_widths_inline(ctx),
|
InlineFlow(info) => info.bubble_widths_inline(ctx),
|
||||||
|
FloatFlow(info) => info.bubble_widths_float(ctx),
|
||||||
_ => fail!(fmt!("Tried to bubble_widths of flow: f%d", self.id()))
|
_ => fail!(fmt!("Tried to bubble_widths of flow: f%d", self.id()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -272,6 +281,7 @@ impl<'self> FlowContext {
|
||||||
match *self {
|
match *self {
|
||||||
BlockFlow(info) => info.assign_widths_block(ctx),
|
BlockFlow(info) => info.assign_widths_block(ctx),
|
||||||
InlineFlow(info) => info.assign_widths_inline(ctx),
|
InlineFlow(info) => info.assign_widths_inline(ctx),
|
||||||
|
FloatFlow(info) => info.assign_widths_float(ctx),
|
||||||
_ => fail!(fmt!("Tried to assign_widths of flow: f%d", self.id()))
|
_ => fail!(fmt!("Tried to assign_widths of flow: f%d", self.id()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -280,6 +290,7 @@ impl<'self> FlowContext {
|
||||||
match *self {
|
match *self {
|
||||||
BlockFlow(info) => info.assign_height_block(ctx),
|
BlockFlow(info) => info.assign_height_block(ctx),
|
||||||
InlineFlow(info) => info.assign_height_inline(ctx),
|
InlineFlow(info) => info.assign_height_inline(ctx),
|
||||||
|
FloatFlow(info) => info.assign_height_float(ctx),
|
||||||
_ => fail!(fmt!("Tried to assign_height of flow: f%d", self.id()))
|
_ => fail!(fmt!("Tried to assign_height of flow: f%d", self.id()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -296,6 +307,7 @@ impl<'self> FlowContext {
|
||||||
match *self {
|
match *self {
|
||||||
BlockFlow(info) => info.build_display_list_block(builder, dirty, offset, list),
|
BlockFlow(info) => info.build_display_list_block(builder, dirty, offset, list),
|
||||||
InlineFlow(info) => info.build_display_list_inline(builder, dirty, offset, list),
|
InlineFlow(info) => info.build_display_list_inline(builder, dirty, offset, list),
|
||||||
|
FloatFlow(info) => info.build_display_list_float(builder, dirty, offset, list),
|
||||||
_ => fail!(fmt!("Tried to build_display_list_recurse of flow: %?", self))
|
_ => fail!(fmt!("Tried to build_display_list_recurse of flow: %?", self))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -412,7 +424,7 @@ impl<'self> FlowContext {
|
||||||
};
|
};
|
||||||
|
|
||||||
do self.with_base |base| {
|
do self.with_base |base| {
|
||||||
fmt!("f%? %? size %?", base.id, repr, base.position)
|
fmt!("f%? %? floats %?", base.id, repr, base.num_floats)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,6 +10,7 @@ use layout::context::LayoutContext;
|
||||||
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
|
||||||
use layout::flow::{FlowContext, FlowData, InlineFlow};
|
use layout::flow::{FlowContext, FlowData, InlineFlow};
|
||||||
use layout::text::{UnscannedMethods, adapt_textbox_with_range};
|
use layout::text::{UnscannedMethods, adapt_textbox_with_range};
|
||||||
|
use layout::float_context::FloatContext;
|
||||||
|
|
||||||
use core::util;
|
use core::util;
|
||||||
use geom::{Point2D, Rect, Size2D};
|
use geom::{Point2D, Rect, Size2D};
|
||||||
|
@ -25,6 +26,7 @@ use newcss::values::{CSSLineHeightNormal, CSSLineHeightNumber, CSSLineHeightLeng
|
||||||
|
|
||||||
use servo_util::range::Range;
|
use servo_util::range::Range;
|
||||||
use std::deque::Deque;
|
use std::deque::Deque;
|
||||||
|
use servo_util::tree::{TreeNodeRef, TreeUtils};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Lineboxes are represented as offsets into the child list, rather than
|
Lineboxes are represented as offsets into the child list, rather than
|
||||||
|
@ -394,7 +396,7 @@ impl TextRunScanner {
|
||||||
|
|
||||||
struct PendingLine {
|
struct PendingLine {
|
||||||
range: Range,
|
range: Range,
|
||||||
width: Au
|
bounds: Rect<Au>
|
||||||
}
|
}
|
||||||
|
|
||||||
struct LineboxScanner {
|
struct LineboxScanner {
|
||||||
|
@ -413,8 +415,8 @@ impl LineboxScanner {
|
||||||
flow: inline,
|
flow: inline,
|
||||||
new_boxes: ~[],
|
new_boxes: ~[],
|
||||||
work_list: @mut Deque::new(),
|
work_list: @mut Deque::new(),
|
||||||
pending_line: PendingLine {mut range: Range::empty(), mut width: Au(0)},
|
pending_line: PendingLine {mut range: Range::empty(), mut bounds: Rect(Point2D(Au(0), Au(0)), Size2D(Au(0), Au(0)))},
|
||||||
line_spans: ~[]
|
line_spans: ~[],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -427,7 +429,7 @@ impl LineboxScanner {
|
||||||
|
|
||||||
fn reset_linebox(&mut self) {
|
fn reset_linebox(&mut self) {
|
||||||
self.pending_line.range.reset(0,0);
|
self.pending_line.range.reset(0,0);
|
||||||
self.pending_line.width = Au(0);
|
self.pending_line.bounds = Rect(Point2D(Au(0), Au(0)), Size2D(Au(0), Au(0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn scan_for_lines(&mut self, ctx: &LayoutContext) {
|
pub fn scan_for_lines(&mut self, ctx: &LayoutContext) {
|
||||||
|
@ -508,7 +510,7 @@ impl LineboxScanner {
|
||||||
linebox_align = CSSTextAlignLeft;
|
linebox_align = CSSTextAlignLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
let slack_width = self.flow.position().size.width - self.pending_line.width;
|
let slack_width = self.flow.position().size.width - self.pending_line.bounds.size.width;
|
||||||
match linebox_align {
|
match linebox_align {
|
||||||
// So sorry, but justified text is more complicated than shuffling linebox coordinates.
|
// So sorry, but justified text is more complicated than shuffling linebox coordinates.
|
||||||
// TODO(Issue #213): implement `text-align: justify`
|
// TODO(Issue #213): implement `text-align: justify`
|
||||||
|
@ -548,7 +550,7 @@ impl LineboxScanner {
|
||||||
|
|
||||||
// return value: whether any box was appended.
|
// return value: whether any box was appended.
|
||||||
fn try_append_to_line(&mut self, ctx: &LayoutContext, in_box: RenderBox) -> bool {
|
fn try_append_to_line(&mut self, ctx: &LayoutContext, in_box: RenderBox) -> bool {
|
||||||
let remaining_width = self.flow.position().size.width - self.pending_line.width;
|
let remaining_width = self.flow.position().size.width - self.pending_line.bounds.size.width;
|
||||||
let in_box_width = in_box.position().size.width;
|
let in_box_width = in_box.position().size.width;
|
||||||
let line_is_empty: bool = self.pending_line.range.length() == 0;
|
let line_is_empty: bool = self.pending_line.range.length() == 0;
|
||||||
|
|
||||||
|
@ -639,7 +641,7 @@ impl LineboxScanner {
|
||||||
self.pending_line.range.reset(self.new_boxes.len(), 0);
|
self.pending_line.range.reset(self.new_boxes.len(), 0);
|
||||||
}
|
}
|
||||||
self.pending_line.range.extend_by(1);
|
self.pending_line.range.extend_by(1);
|
||||||
self.pending_line.width += box.position().size.width;
|
self.pending_line.bounds.size.width += box.position().size.width;
|
||||||
self.new_boxes.push(box);
|
self.new_boxes.push(box);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -696,6 +698,15 @@ impl InlineFlowData {
|
||||||
pub fn bubble_widths_inline(@mut self, ctx: &mut LayoutContext) {
|
pub fn bubble_widths_inline(@mut self, ctx: &mut LayoutContext) {
|
||||||
let mut scanner = TextRunScanner::new();
|
let mut scanner = TextRunScanner::new();
|
||||||
scanner.scan_for_runs(ctx, InlineFlow(self));
|
scanner.scan_for_runs(ctx, InlineFlow(self));
|
||||||
|
let mut num_floats = 0;
|
||||||
|
|
||||||
|
for InlineFlow(self).each_child |kid| {
|
||||||
|
do kid.with_mut_base |base| {
|
||||||
|
num_floats += base.num_floats;
|
||||||
|
base.floats_in = FloatContext::new(base.num_floats);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
{
|
{
|
||||||
let this = &mut *self;
|
let this = &mut *self;
|
||||||
|
@ -711,12 +722,13 @@ impl InlineFlowData {
|
||||||
|
|
||||||
this.common.min_width = min_width;
|
this.common.min_width = min_width;
|
||||||
this.common.pref_width = pref_width;
|
this.common.pref_width = pref_width;
|
||||||
|
this.common.num_floats = num_floats;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// 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 boxes. When called
|
||||||
/// on this context, the context has had its width set by the parent context.
|
/// on this context, the context has had its width set by the parent context.
|
||||||
pub fn assign_widths_inline(@mut self, ctx: &mut LayoutContext) {
|
pub fn assign_widths_inline(@mut self, _: &mut LayoutContext) {
|
||||||
// Initialize content box widths if they haven't been initialized already.
|
// Initialize content box widths if they haven't been initialized already.
|
||||||
//
|
//
|
||||||
// TODO: Combine this with `LineboxScanner`'s walk in the box list, or put this into
|
// TODO: Combine this with `LineboxScanner`'s walk in the box list, or put this into
|
||||||
|
@ -745,9 +757,11 @@ impl InlineFlowData {
|
||||||
} // End of for loop.
|
} // End of for loop.
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scanner = LineboxScanner::new(InlineFlow(self));
|
for InlineFlow(self).each_child |kid| {
|
||||||
scanner.scan_for_lines(ctx);
|
do kid.with_mut_base |base| {
|
||||||
|
base.position.size.width = self.common.position.size.width;
|
||||||
|
}
|
||||||
|
}
|
||||||
// There are no child contexts, so stop here.
|
// There are no child contexts, so stop here.
|
||||||
|
|
||||||
// TODO(Issue #225): once there are 'inline-block' elements, this won't be
|
// TODO(Issue #225): once there are 'inline-block' elements, this won't be
|
||||||
|
@ -757,7 +771,18 @@ impl InlineFlowData {
|
||||||
// 'inline-block' box that created this flow before recursing.
|
// 'inline-block' box that created this flow before recursing.
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn assign_height_inline(&mut self, _: &mut LayoutContext) {
|
pub fn assign_height_inline(@mut self, ctx: &mut LayoutContext) {
|
||||||
|
|
||||||
|
for InlineFlow(self).each_child |kid| {
|
||||||
|
kid.assign_height(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// TODO(eatkinson): line boxes need to shrink if there are floats
|
||||||
|
let mut scanner = LineboxScanner::new(InlineFlow(self));
|
||||||
|
scanner.scan_for_lines(ctx);
|
||||||
|
self.common.floats_out = self.common.floats_in.clone();
|
||||||
|
|
||||||
// TODO(#226): Get the CSS `line-height` property from the containing block's style to
|
// TODO(#226): Get the CSS `line-height` property from the containing block's style to
|
||||||
// determine minimum linebox height.
|
// determine minimum linebox height.
|
||||||
//
|
//
|
||||||
|
@ -774,10 +799,8 @@ impl InlineFlowData {
|
||||||
let mut linebox_height = Au(0);
|
let mut linebox_height = Au(0);
|
||||||
let mut baseline_offset = Au(0);
|
let mut baseline_offset = Au(0);
|
||||||
|
|
||||||
let boxes = &mut self.boxes;
|
|
||||||
|
|
||||||
for line_span.eachi |box_i| {
|
for line_span.eachi |box_i| {
|
||||||
let cur_box = boxes[box_i]; // FIXME: borrow checker workaround
|
let cur_box = self.boxes[box_i];
|
||||||
|
|
||||||
// Compute the height and bounding box of each box.
|
// Compute the height and bounding box of each box.
|
||||||
let bounding_box = match cur_box {
|
let bounding_box = match cur_box {
|
||||||
|
@ -849,7 +872,7 @@ impl InlineFlowData {
|
||||||
|
|
||||||
// Now go back and adjust the Y coordinates to match the baseline we determined.
|
// Now go back and adjust the Y coordinates to match the baseline we determined.
|
||||||
for line_span.eachi |box_i| {
|
for line_span.eachi |box_i| {
|
||||||
let cur_box = boxes[box_i];
|
let cur_box = self.boxes[box_i];
|
||||||
|
|
||||||
// TODO(#226): This is completely wrong. We need to use the element's `line-height`
|
// TODO(#226): This is completely wrong. We need to use the element's `line-height`
|
||||||
// when calculating line box height. Then we should go back over and set Y offsets
|
// when calculating line box height. Then we should go back over and set Y offsets
|
||||||
|
|
|
@ -225,9 +225,9 @@ impl Layout {
|
||||||
for layout_root.traverse_preorder |flow| {
|
for layout_root.traverse_preorder |flow| {
|
||||||
flow.assign_widths(&mut layout_ctx);
|
flow.assign_widths(&mut layout_ctx);
|
||||||
};
|
};
|
||||||
for layout_root.traverse_postorder |flow| {
|
|
||||||
flow.assign_height(&mut layout_ctx);
|
// For now, this is an inorder traversal
|
||||||
};
|
layout_root.assign_height(&mut layout_ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build the display list if necessary, and send it to the renderer.
|
// Build the display list if necessary, and send it to the renderer.
|
||||||
|
|
|
@ -112,7 +112,7 @@ impl BoxModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Helper function to compute the border width in app units from the CSS border width.
|
/// Helper function to compute the border width in app units from the CSS border width.
|
||||||
priv fn compute_border_width(&self, width: CSSBorderWidth) -> Au {
|
pub fn compute_border_width(&self, width: CSSBorderWidth) -> Au {
|
||||||
match width {
|
match width {
|
||||||
CSSBorderWidthLength(Px(v)) |
|
CSSBorderWidthLength(Px(v)) |
|
||||||
CSSBorderWidthLength(Em(v)) |
|
CSSBorderWidthLength(Em(v)) |
|
||||||
|
@ -126,7 +126,7 @@ impl BoxModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au) -> Au {
|
pub fn compute_padding_length(&self, padding: CSSPadding, content_box_width: Au) -> Au {
|
||||||
match padding {
|
match padding {
|
||||||
CSSPaddingLength(Px(v)) |
|
CSSPaddingLength(Px(v)) |
|
||||||
CSSPaddingLength(Pt(v)) |
|
CSSPaddingLength(Pt(v)) |
|
||||||
|
|
|
@ -73,7 +73,8 @@ pub mod layout {
|
||||||
pub mod inline;
|
pub mod inline;
|
||||||
pub mod model;
|
pub mod model;
|
||||||
pub mod text;
|
pub mod text;
|
||||||
pub mod floats;
|
pub mod float_context;
|
||||||
|
pub mod float;
|
||||||
mod aux;
|
mod aux;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue