aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorBruno de Oliveira Abinader <bruno.d@partner.samsung.com>2013-11-29 10:47:30 -0400
committerBruno de Oliveira Abinader <bruno.d@partner.samsung.com>2013-12-03 14:36:31 -0400
commitac45d70a4ace71380358fdec918e1c4438ae2e43 (patch)
treedbe38879889fd0e53886b87c26b9c69d66cb1a27 /src
parenta0c6075b4d766da8f0414405f9e1f76c8c90acc4 (diff)
downloadservo-ac45d70a4ace71380358fdec918e1c4438ae2e43.tar.gz
servo-ac45d70a4ace71380358fdec918e1c4438ae2e43.zip
Remove 'FloatFlow'
Removes 'FloatFlow' in favor of FloatBlockFlow, which is cointained inside BlockFlow in a 'has-a' relationship. This avoids a bunch of duplicated code. This patch is for: https://github.com/mozilla/servo/issues/1281
Diffstat (limited to 'src')
-rw-r--r--src/components/main/layout/block.rs378
-rw-r--r--src/components/main/layout/construct.rs7
-rw-r--r--src/components/main/layout/float.rs333
-rw-r--r--src/components/main/layout/flow.rs14
-rwxr-xr-xsrc/components/main/servo.rc1
5 files changed, 321 insertions, 412 deletions
diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs
index 995c35397d4..9890666a924 100644
--- a/src/components/main/layout/block.rs
+++ b/src/components/main/layout/block.rs
@@ -10,7 +10,7 @@ use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
use layout::flow::{BlockFlowClass, FlowClass, Flow, FlowData, ImmutableFlowUtils};
use layout::flow;
use layout::model::{MaybeAuto, Specified, Auto, specified_or_none, specified};
-use layout::float_context::{FloatContext, Invalid};
+use layout::float_context::{FloatContext, PlacementInfo, Invalid, FloatType};
use std::cell::Cell;
use geom::point::Point2D;
@@ -20,6 +20,34 @@ use gfx::display_list::DisplayList;
use servo_util::geometry::{Au, to_frac_px};
use servo_util::geometry;
+pub struct FloatedBlockInfo {
+ containing_width: Au,
+
+ /// Offset relative to where the parent tried to position this flow
+ rel_pos: Point2D<Au>,
+
+ /// Index into the box list for inline floats
+ index: Option<uint>,
+
+ /// Number of floated children
+ floated_children: uint,
+
+ /// Left or right?
+ float_type: FloatType
+}
+
+impl FloatedBlockInfo {
+ pub fn new(float_type: FloatType) -> FloatedBlockInfo {
+ FloatedBlockInfo {
+ containing_width: Au(0),
+ rel_pos: Point2D(Au(0), Au(0)),
+ index: None,
+ floated_children: 0,
+ float_type: float_type
+ }
+ }
+}
+
pub struct BlockFlow {
/// Data common to all flows.
base: FlowData,
@@ -28,7 +56,10 @@ pub struct BlockFlow {
box: Option<@RenderBox>,
/// Whether this block flow is the root flow.
- is_root: bool
+ is_root: bool,
+
+ // Additional floating flow members.
+ float: Option<~FloatedBlockInfo>
}
impl BlockFlow {
@@ -36,7 +67,8 @@ impl BlockFlow {
BlockFlow {
base: base,
box: None,
- is_root: false
+ is_root: false,
+ float: None
}
}
@@ -44,7 +76,17 @@ impl BlockFlow {
BlockFlow {
base: base,
box: Some(box),
- is_root: false
+ is_root: false,
+ float: None
+ }
+ }
+
+ pub fn float_from_box(base: FlowData, float_type: FloatType, box: @RenderBox) -> BlockFlow {
+ BlockFlow {
+ base: base,
+ box: Some(box),
+ is_root: false,
+ float: Some(~FloatedBlockInfo::new(float_type))
}
}
@@ -52,15 +94,30 @@ impl BlockFlow {
BlockFlow {
base: base,
box: None,
- is_root: true
+ is_root: true,
+ float: None
+ }
+ }
+
+ pub fn new_float(base: FlowData, float_type: FloatType) -> BlockFlow {
+ BlockFlow {
+ base: base,
+ box: None,
+ is_root: false,
+ float: Some(~FloatedBlockInfo::new(float_type))
}
}
+ pub fn is_float(&self) -> bool {
+ self.float.is_some()
+ }
+
pub fn teardown(&mut self) {
for box in self.box.iter() {
box.teardown();
}
self.box = None;
+ self.float = None;
}
/// Computes left and right margins and width based on CSS 2.1 section 10.3.3.
@@ -115,6 +172,63 @@ impl BlockFlow {
(width_Au, left_margin_Au, right_margin_Au)
}
+ fn compute_block_margins(&self, box: @RenderBox, remaining_width: Au, available_width: Au) -> (Au, Au, Au) {
+ let base = box.base();
+ let style = base.style();
+
+ let (width, maybe_margin_left, maybe_margin_right) =
+ (MaybeAuto::from_style(style.Box.width, remaining_width),
+ MaybeAuto::from_style(style.Margin.margin_left, remaining_width),
+ MaybeAuto::from_style(style.Margin.margin_right, remaining_width));
+
+ let (width, margin_left, margin_right) = self.compute_horiz(width,
+ maybe_margin_left,
+ maybe_margin_right,
+ available_width);
+
+ // 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'.
+ let (width, margin_left, margin_right) = {
+ match specified_or_none(style.Box.max_width, remaining_width) {
+ Some(value) if value < width => self.compute_horiz(Specified(value),
+ maybe_margin_left,
+ maybe_margin_right,
+ available_width),
+ _ => (width, margin_left, margin_right)
+ }
+ };
+
+ // 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 (width, margin_left, margin_right) = {
+ let computed_min_width = specified(style.Box.min_width, remaining_width);
+ if computed_min_width > width {
+ self.compute_horiz(Specified(computed_min_width),
+ maybe_margin_left,
+ maybe_margin_right,
+ available_width)
+ } else {
+ (width, margin_left, margin_right)
+ }
+ };
+
+ return (width, margin_left, margin_right);
+ }
+
+ fn compute_float_margins(&self, box: @RenderBox, remaining_width: Au) -> (Au, Au, Au) {
+ let style = box.base().style();
+ let margin_left = MaybeAuto::from_style(style.Margin.margin_left,
+ remaining_width).specified_or_zero();
+ let margin_right = MaybeAuto::from_style(style.Margin.margin_right,
+ remaining_width).specified_or_zero();
+ let shrink_to_fit = geometry::min(self.base.pref_width,
+ geometry::max(self.base.min_width, remaining_width));
+ let width = MaybeAuto::from_style(style.Box.width,
+ remaining_width).specified_or_default(shrink_to_fit);
+ debug!("assign_widths_float -- width: {}", width);
+ return (width, margin_left, margin_right);
+ }
+
// inline(always) because this is only ever called by in-order or non-in-order top-level
// methods
#[inline(always)]
@@ -252,12 +366,104 @@ impl BlockFlow {
}
}
+ fn assign_height_float_inorder(&mut self) {
+ // assign_height_float was already called by the traversal function
+ // so this is well-defined
+
+ let mut height = Au(0);
+ let mut clearance = Au(0);
+ let mut full_noncontent_width = Au(0);
+ let mut margin_height = Au(0);
+
+ for box in self.box.iter() {
+ let base = box.base();
+ height = base.position.borrow().ptr.size.height;
+ clearance = match base.clear() {
+ None => Au(0),
+ Some(clear) => self.base.floats_in.clearance(clear),
+ };
+
+ let noncontent_width = base.padding.left + base.padding.right + base.border.left +
+ base.border.right;
+
+ full_noncontent_width = noncontent_width + base.margin.left + base.margin.right;
+ margin_height = base.margin.top + base.margin.bottom;
+ }
+
+ let info = PlacementInfo {
+ width: self.base.position.size.width + full_noncontent_width,
+ height: height + margin_height,
+ ceiling: clearance,
+ max_width: self.float.get_ref().containing_width,
+ f_type: self.float.get_ref().float_type,
+ };
+
+ // Place the float and return the FloatContext back to the parent flow.
+ // After, grab the position and use that to set our position.
+ self.base.floats_out = self.base.floats_in.add_float(&info);
+ self.float.get_mut_ref().rel_pos = self.base.floats_out.last_float_pos();
+ }
+
+ fn assign_height_float(&mut self, ctx: &mut LayoutContext) {
+ // Now that we've determined our height, propagate that out.
+ let has_inorder_children = self.base.num_floats > 0;
+ if has_inorder_children {
+ let mut float_ctx = FloatContext::new(self.float.get_ref().floated_children);
+ for kid in self.base.child_iter() {
+ flow::mut_base(*kid).floats_in = float_ctx.clone();
+ kid.assign_height_inorder(ctx);
+ float_ctx = flow::mut_base(*kid).floats_out.clone();
+ }
+ }
+ let mut cur_y = Au(0);
+ let mut top_offset = Au(0);
+
+ for &box in self.box.iter() {
+ let base = box.base();
+ top_offset = base.margin.top + base.border.top + base.padding.top;
+ cur_y = cur_y + top_offset;
+ }
+
+ for kid in self.base.child_iter() {
+ let child_base = flow::mut_base(*kid);
+ child_base.position.origin.y = cur_y;
+ cur_y = cur_y + child_base.position.size.height;
+ }
+
+ let mut height = cur_y - top_offset;
+
+ let mut noncontent_height;
+ let box = self.box.as_ref().unwrap();
+ let base = box.base();
+ let mut position_ref = base.position.mutate();
+ let position = &mut position_ref.ptr;
+
+ // The associated box is the border box of this flow.
+ position.origin.y = base.margin.top;
+
+ noncontent_height = base.padding.top + base.padding.bottom + base.border.top +
+ base.border.bottom;
+
+ //TODO(eatkinson): compute heights properly using the 'height' property.
+ let height_prop = MaybeAuto::from_style(base.style().Box.height,
+ Au::new(0)).specified_or_zero();
+
+ height = geometry::max(height, height_prop) + noncontent_height;
+ debug!("assign_height_float -- height: {}", height);
+
+ position.size.height = height;
+ }
+
pub fn build_display_list_block<E:ExtraDisplayListData>(
&mut self,
builder: &DisplayListBuilder,
dirty: &Rect<Au>,
list: &Cell<DisplayList<E>>)
-> bool {
+ if self.is_float() {
+ return self.build_display_list_float(builder, dirty, list);
+ }
+
if self.base.node.is_iframe_element() {
let x = self.base.abs_position.x + do self.box.map_default(Au::new(0)) |box| {
let base = box.base();
@@ -302,6 +508,39 @@ impl BlockFlow {
false
}
+
+ pub fn build_display_list_float<E:ExtraDisplayListData>(&mut self,
+ builder: &DisplayListBuilder,
+ dirty: &Rect<Au>,
+ list: &Cell<DisplayList<E>>)
+ -> bool {
+ //TODO: implement iframe size messaging
+ if self.base.node.is_iframe_element() {
+ error!("float iframe size messaging not implemented yet");
+ }
+ let abs_rect = Rect(self.base.abs_position, self.base.position.size);
+ if !abs_rect.intersects(dirty) {
+ return true;
+ }
+
+
+ let offset = self.base.abs_position + self.float.get_ref().rel_pos;
+ // add box that starts block context
+ for box in self.box.iter() {
+ box.build_display_list(builder, dirty, &offset, list)
+ }
+
+
+ // TODO: handle any out-of-flow elements
+
+ // go deeper into the flow tree
+ for child in self.base.child_iter() {
+ let child_base = flow::mut_base(*child);
+ child_base.abs_position = offset + child_base.position.origin;
+ }
+
+ false
+ }
}
impl Flow for BlockFlow {
@@ -334,10 +573,16 @@ impl Flow for BlockFlow {
let child_base = flow::mut_base(*child_ctx);
min_width = geometry::max(min_width, child_base.min_width);
pref_width = geometry::max(pref_width, child_base.pref_width);
-
num_floats = num_floats + child_base.num_floats;
}
+ if self.is_float() {
+ self.base.num_floats = 1;
+ self.float.get_mut_ref().floated_children = num_floats;
+ } else {
+ self.base.num_floats = num_floats;
+ }
+
/* if not an anonymous block context, add in block box's widths.
these widths will not include child elements, just padding etc. */
for box in self.box.iter() {
@@ -355,16 +600,20 @@ impl Flow for BlockFlow {
self.base.min_width = min_width;
self.base.pref_width = pref_width;
- self.base.num_floats = num_floats;
}
-
+
/// 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.
///
/// Dual boxes 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_block: assigning width for flow {}", self.base.id);
+ fn assign_widths(&mut self, ctx: &mut LayoutContext) {
+ if self.is_float() {
+ debug!("assign_widths_float: assigning width for flow {}", self.base.id);
+ } else {
+ debug!("assign_widths_block: assigning width for flow {}", self.base.id);
+ }
+
if self.is_root {
debug!("Setting root position");
self.base.position.origin = Au::zero_point();
@@ -377,12 +626,19 @@ impl Flow for BlockFlow {
let mut remaining_width = self.base.position.size.width;
let mut x_offset = Au::new(0);
+ if self.is_float() {
+ // Parent usually sets this, but floats are never inorder
+ self.base.is_inorder = false;
+ }
+
for &box in self.box.iter() {
- let base = box.mut_base();
+ let base = box.base();
+ let mut_base = box.mut_base();
let style = base.style();
+ let mut_position = &mut base.position.mutate().ptr;
// Can compute padding here since we know containing block width.
- base.compute_padding(style, remaining_width);
+ mut_base.compute_padding(style, remaining_width);
// Margins are 0 right now so base.noncontent_width() is just borders + padding.
let available_width = remaining_width - base.noncontent_width();
@@ -393,58 +649,38 @@ impl Flow for BlockFlow {
let margin_bottom = MaybeAuto::from_style(style.Margin.margin_bottom,
remaining_width).specified_or_zero();
- let (width, maybe_margin_left, maybe_margin_right) =
- (MaybeAuto::from_style(style.Box.width, remaining_width),
- MaybeAuto::from_style(style.Margin.margin_left, remaining_width),
- MaybeAuto::from_style(style.Margin.margin_right, remaining_width));
-
- let (width, margin_left, margin_right) = self.compute_horiz(width,
- maybe_margin_left,
- maybe_margin_right,
- available_width);
-
- // 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'.
- let (width, margin_left, margin_right) = {
- match specified_or_none(style.Box.max_width, remaining_width) {
- Some(value) if value < width => self.compute_horiz(Specified(value),
- maybe_margin_left,
- maybe_margin_right,
- available_width),
- _ => (width, margin_left, margin_right)
- }
- };
- // 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 (width, margin_left, margin_right) = {
- let computed_min_width = specified(style.Box.min_width, remaining_width);
- if computed_min_width > width {
- self.compute_horiz(Specified(computed_min_width),
- maybe_margin_left,
- maybe_margin_right,
- available_width)
- } else {
- (width, margin_left, margin_right)
- }
+ let (width, margin_left, margin_right) = if self.is_float() {
+ self.compute_float_margins(box, remaining_width)
+ } else {
+ self.compute_block_margins(box, remaining_width, available_width)
};
- base.margin.top = margin_top;
- base.margin.right = margin_right;
- base.margin.bottom = margin_bottom;
- base.margin.left = margin_left;
+ mut_base.margin.top = margin_top;
+ mut_base.margin.right = margin_right;
+ mut_base.margin.bottom = margin_bottom;
+ mut_base.margin.left = margin_left;
x_offset = base.offset();
remaining_width = width;
//The associated box is the border box of this flow
- let position_ref = base.position.mutate();
- position_ref.ptr.origin.x = base.margin.left;
+ mut_position.origin.x = base.margin.left;
+
let padding_and_borders = base.padding.left + base.padding.right +
base.border.left + base.border.right;
- position_ref.ptr.size.width = remaining_width + padding_and_borders;
+ mut_position.size.width = remaining_width + padding_and_borders;
}
- let has_inorder_children = self.base.is_inorder || self.base.num_floats > 0;
+ if self.is_float() {
+ self.base.position.size.width = remaining_width;
+ }
+
+ let has_inorder_children = if self.is_float() {
+ self.base.num_floats > 0
+ } else {
+ self.base.is_inorder || self.base.num_floats > 0
+ };
+
for kid in self.base.child_iter() {
assert!(kid.starts_block_flow() || kid.starts_inline_flow());
@@ -460,19 +696,29 @@ impl Flow for BlockFlow {
}
fn assign_height_inorder(&mut self, ctx: &mut LayoutContext) {
- debug!("assign_height_inorder: assigning height for block {}", self.base.id);
- self.assign_height_block_base(ctx, true);
+ if self.is_float() {
+ debug!("assign_height_inorder_float: assigning height for float {}", self.base.id);
+ self.assign_height_float_inorder();
+ } else {
+ debug!("assign_height_inorder: assigning height for block {}", self.base.id);
+ self.assign_height_block_base(ctx, true);
+ }
}
fn assign_height(&mut self, ctx: &mut LayoutContext) {
- debug!("assign_height: assigning height for block {}", self.base.id);
- // This is the only case in which a block flow can start an inorder
- // subtraversal.
- if self.is_root && self.base.num_floats > 0 {
- self.assign_height_inorder(ctx);
- return;
+ if self.is_float() {
+ debug!("assign_height_float: assigning height for float {}", self.base.id);
+ self.assign_height_float(ctx);
+ } else {
+ debug!("assign_height: assigning height for block {}", self.base.id);
+ // This is the only case in which a block flow can start an inorder
+ // subtraversal.
+ if self.is_root && self.base.num_floats > 0 {
+ self.assign_height_inorder(ctx);
+ return;
+ }
+ self.assign_height_block_base(ctx, false);
}
- self.assign_height_block_base(ctx, false);
}
fn collapse_margins(&mut self,
@@ -482,6 +728,12 @@ impl Flow for BlockFlow {
top_offset: &mut Au,
collapsing: &mut Au,
collapsible: &mut Au) {
+ if self.is_float() {
+ // Margins between a floated box and any other box do not collapse.
+ *collapsing = Au::new(0);
+ return;
+ }
+
for &box in self.box.iter() {
let base = box.base();
@@ -515,7 +767,7 @@ impl Flow for BlockFlow {
if self.is_root {
~"BlockFlow(root)"
} else {
- let txt = ~"BlockFlow: ";
+ let txt = if self.is_float() { ~"FloatFlow: " } else { ~"BlockFlow: " };
txt.append(match self.box {
Some(rb) => {
rb.debug_str()
diff --git a/src/components/main/layout/construct.rs b/src/components/main/layout/construct.rs
index ea4f70af101..9341727e227 100644
--- a/src/components/main/layout/construct.rs
+++ b/src/components/main/layout/construct.rs
@@ -25,7 +25,6 @@ use layout::block::BlockFlow;
use layout::box::{GenericRenderBox, ImageRenderBox, RenderBox, RenderBoxBase};
use layout::box::{UnscannedTextRenderBox};
use layout::context::LayoutContext;
-use layout::float::FloatFlow;
use layout::float_context::FloatType;
use layout::flow::{Flow, FlowData, MutableFlowUtils};
use layout::inline::InlineFlow;
@@ -360,13 +359,13 @@ impl<'self> FlowConstructor<'self> {
flow
}
- /// Builds the flow for a node with `float: {left|right}`. This yields a `FloatFlow` with a
- /// `BlockFlow` underneath it.
+ /// Builds the flow for a node with `float: {left|right}`. This yields a float `BlockFlow` with
+ /// a `BlockFlow` underneath it.
fn build_flow_for_floated_block(&self, node: AbstractNode<LayoutView>, float_type: FloatType)
-> ~Flow: {
let base = FlowData::new(self.next_flow_id(), node);
let box = self.build_box_for_node(node);
- let mut flow = ~FloatFlow::from_box(base, float_type, box) as ~Flow:;
+ let mut flow = ~BlockFlow::float_from_box(base, float_type, box) as ~Flow:;
self.build_children_of_block_flow(&mut flow, node);
flow
}
diff --git a/src/components/main/layout/float.rs b/src/components/main/layout/float.rs
deleted file mode 100644
index b6d123844b1..00000000000
--- a/src/components/main/layout/float.rs
+++ /dev/null
@@ -1,333 +0,0 @@
-/* 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, RenderBoxUtils};
-use layout::context::LayoutContext;
-use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
-use layout::flow::{FloatFlowClass, FlowClass, Flow, FlowData};
-use layout::flow;
-use layout::model::{MaybeAuto};
-use layout::float_context::{FloatContext, PlacementInfo, FloatType};
-
-use std::cell::Cell;
-use geom::point::Point2D;
-use geom::rect::Rect;
-use gfx::display_list::DisplayList;
-use servo_util::geometry::Au;
-use servo_util::geometry;
-
-pub struct FloatFlow {
- /// Data common to all flows.
- base: FlowData,
-
- /// The associated render box.
- box: Option<@RenderBox>,
-
- containing_width: Au,
-
- /// Offset relative to where the parent tried to position this flow
- rel_pos: Point2D<Au>,
-
- /// Left or right?
- float_type: FloatType,
-
- /// Index into the box list for inline floats
- index: Option<uint>,
-
- /// Number of floated children
- floated_children: uint,
-
-}
-
-impl FloatFlow {
- pub fn new(base: FlowData, float_type: FloatType) -> FloatFlow {
- FloatFlow {
- base: base,
- containing_width: Au(0),
- box: None,
- index: None,
- float_type: float_type,
- rel_pos: Point2D(Au(0), Au(0)),
- floated_children: 0,
- }
- }
-
- pub fn from_box(base: FlowData, float_type: FloatType, box: @RenderBox) -> FloatFlow {
- FloatFlow {
- base: base,
- containing_width: Au(0),
- box: Some(box),
- index: None,
- float_type: float_type,
- rel_pos: Point2D(Au(0), Au(0)),
- floated_children: 0,
- }
- }
-
- pub fn teardown(&mut self) {
- for box in self.box.iter() {
- box.teardown();
- }
- self.box = None;
- self.index = None;
- }
-
- pub fn build_display_list_float<E:ExtraDisplayListData>(&mut self,
- builder: &DisplayListBuilder,
- dirty: &Rect<Au>,
- list: &Cell<DisplayList<E>>)
- -> bool {
- //TODO: implement iframe size messaging
- if self.base.node.is_iframe_element() {
- error!("float iframe size messaging not implemented yet");
- }
- let abs_rect = Rect(self.base.abs_position, self.base.position.size);
- if !abs_rect.intersects(dirty) {
- return true;
- }
-
-
- let offset = self.base.abs_position + self.rel_pos;
- // add box that starts block context
- for box in self.box.iter() {
- box.build_display_list(builder, dirty, &offset, list)
- }
-
-
- // TODO: handle any out-of-flow elements
-
- // go deeper into the flow tree
- for child in self.base.child_iter() {
- let child_base = flow::mut_base(*child);
- child_base.abs_position = offset + child_base.position.origin;
- }
-
- false
- }
-
- fn debug_str(&self) -> ~str {
- ~"FloatFlow"
- }
-}
-
-impl Flow for FloatFlow {
- fn class(&self) -> FlowClass {
- FloatFlowClass
- }
-
- fn as_float<'a>(&'a mut self) -> &'a mut FloatFlow {
- self
- }
-
- fn bubble_widths(&mut self, _: &mut LayoutContext) {
- let mut min_width = Au(0);
- let mut pref_width = Au(0);
- let mut num_floats = 0;
-
- for child_ctx in self.base.child_iter() {
- //assert!(child_ctx.starts_block_flow() || child_ctx.starts_inline_flow());
-
- let child_base = flow::mut_base(*child_ctx);
- min_width = geometry::max(min_width, child_base.min_width);
- pref_width = geometry::max(pref_width, child_base.pref_width);
- num_floats = num_floats + child_base.num_floats;
- }
-
- self.base.num_floats = 1;
- self.floated_children = num_floats;
-
- for box in self.box.iter() {
- {
- box.mut_base().compute_borders(box.base().style());
- }
-
- let (this_minimum_width, this_preferred_width) = box.minimum_and_preferred_widths();
- min_width = min_width + this_minimum_width;
- pref_width = pref_width + this_preferred_width;
- }
-
- self.base.min_width = min_width;
- self.base.pref_width = pref_width;
- }
-
- fn assign_widths(&mut self, _: &mut LayoutContext) {
- debug!("assign_widths_float: assigning width for flow {}", self.base.id);
- // position.size.width is set by parent even though we don't know
- // position.origin yet.
- let mut remaining_width = self.base.position.size.width;
- self.containing_width = remaining_width;
- let mut x_offset = Au(0);
-
- // Parent usually sets this, but floats are never inorder
- self.base.is_inorder = false;
-
- for &box in self.box.iter() {
- let base = box.base();
- let mut_base = box.mut_base();
- let style = base.style();
- let mut position_ref = base.position.mutate();
- let position = &mut position_ref.ptr;
-
- // Can compute padding here since we know containing block width.
- mut_base.compute_padding(style, remaining_width);
-
- // Margins for floats are 0 if auto.
- let margin_top = MaybeAuto::from_style(style.Margin.margin_top,
- remaining_width).specified_or_zero();
- let margin_bottom = MaybeAuto::from_style(style.Margin.margin_bottom,
- remaining_width).specified_or_zero();
- let margin_left = MaybeAuto::from_style(style.Margin.margin_left,
- remaining_width).specified_or_zero();
- let margin_right = MaybeAuto::from_style(style.Margin.margin_right,
- remaining_width).specified_or_zero();
-
-
- let shrink_to_fit = geometry::min(self.base.pref_width,
- geometry::max(self.base.min_width, remaining_width));
-
-
- let width = MaybeAuto::from_style(style.Box.width,
- remaining_width).specified_or_default(shrink_to_fit);
- debug!("assign_widths_float -- width: {}", width);
-
- mut_base.margin.top = margin_top;
- mut_base.margin.right = margin_right;
- mut_base.margin.bottom = margin_bottom;
- mut_base.margin.left = margin_left;
-
- x_offset = base.offset();
- remaining_width = width;
-
- // The associated box is the border box of this flow.
- position.origin.x = base.margin.left;
-
- let padding_and_borders = base.padding.left + base.padding.right +
- base.border.left + base.border.right;
- position.size.width = remaining_width + padding_and_borders;
- }
-
- self.base.position.size.width = remaining_width;
-
- let has_inorder_children = self.base.num_floats > 0;
- for kid in self.base.child_iter() {
- //assert!(kid.starts_block_flow() || kid.starts_inline_flow());
-
- let child_base = flow::mut_base(*kid);
- child_base.position.origin.x = x_offset;
- child_base.position.size.width = remaining_width;
- child_base.is_inorder = has_inorder_children;
-
- if !child_base.is_inorder {
- child_base.floats_in = FloatContext::new(0);
- }
- }
- }
-
- fn assign_height_inorder(&mut self, _: &mut LayoutContext) {
- debug!("assign_height_inorder_float: assigning height for float {}", self.base.id);
- // assign_height_float was already called by the traversal function
- // so this is well-defined
-
- let mut height = Au(0);
- let mut clearance = Au(0);
- let mut full_noncontent_width = Au(0);
- let mut margin_height = Au(0);
-
- for box in self.box.iter() {
- let base = box.base();
- height = base.position.borrow().ptr.size.height;
- clearance = match base.clear() {
- None => Au(0),
- Some(clear) => self.base.floats_in.clearance(clear),
- };
-
- let noncontent_width = base.padding.left + base.padding.right + base.border.left +
- base.border.right;
-
- full_noncontent_width = noncontent_width + base.margin.left + base.margin.right;
- margin_height = base.margin.top + base.margin.bottom;
- }
-
- let info = PlacementInfo {
- width: self.base.position.size.width + full_noncontent_width,
- height: height + margin_height,
- ceiling: clearance,
- max_width: self.containing_width,
- f_type: self.float_type,
- };
-
- // Place the float and return the FloatContext back to the parent flow.
- // After, grab the position and use that to set our position.
- self.base.floats_out = self.base.floats_in.add_float(&info);
- self.rel_pos = self.base.floats_out.last_float_pos();
- }
-
- fn assign_height(&mut self, ctx: &mut LayoutContext) {
- // Now that we've determined our height, propagate that out.
- let has_inorder_children = self.base.num_floats > 0;
- if has_inorder_children {
- let mut float_ctx = FloatContext::new(self.floated_children);
- for kid in self.base.child_iter() {
- flow::mut_base(*kid).floats_in = float_ctx.clone();
- kid.assign_height_inorder(ctx);
- float_ctx = flow::mut_base(*kid).floats_out.clone();
- }
- }
- debug!("assign_height_float: assigning height for float {}", self.base.id);
- let mut cur_y = Au(0);
- let mut top_offset = Au(0);
-
- for &box in self.box.iter() {
- let base = box.base();
- top_offset = base.margin.top + base.border.top + base.padding.top;
- cur_y = cur_y + top_offset;
- }
-
- for kid in self.base.child_iter() {
- let child_base = flow::mut_base(*kid);
- child_base.position.origin.y = cur_y;
- cur_y = cur_y + child_base.position.size.height;
- }
-
- let mut height = cur_y - top_offset;
-
- let mut noncontent_height;
- let box = self.box.as_ref().unwrap();
- let base = box.base();
- let mut position_ref = base.position.mutate();
- let position = &mut position_ref.ptr;
-
- // The associated box is the border box of this flow.
- position.origin.y = base.margin.top;
-
- noncontent_height = base.padding.top + base.padding.bottom + base.border.top +
- base.border.bottom;
-
- //TODO(eatkinson): compute heights properly using the 'height' property.
- let height_prop = MaybeAuto::from_style(base.style().Box.height,
- Au::new(0)).specified_or_zero();
-
- height = geometry::max(height, height_prop) + noncontent_height;
- debug!("assign_height_float -- height: {}", height);
-
- position.size.height = height;
-
- }
-
- fn collapse_margins(&mut self,
- _: bool,
- _: &mut bool,
- _: &mut Au,
- _: &mut Au,
- collapsing: &mut Au,
- _: &mut Au) {
- // Margins between a floated box and any other box do not collapse.
- *collapsing = Au::new(0);
- }
-
- fn debug_str(&self) -> ~str {
- ~"FloatFlow"
- }
-}
-
diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs
index 2ad37fa0d82..ecf6d34e47d 100644
--- a/src/components/main/layout/flow.rs
+++ b/src/components/main/layout/flow.rs
@@ -29,7 +29,6 @@ use css::node_style::StyledNode;
use layout::block::BlockFlow;
use layout::box::RenderBox;
use layout::context::LayoutContext;
-use layout::float::FloatFlow;
use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData};
use layout::float_context::{FloatContext, Invalid};
use layout::incremental::RestyleDamage;
@@ -74,11 +73,6 @@ pub trait Flow {
fail!("called as_inline() on a non-inline flow")
}
- /// If this is a float flow, returns the underlying object. Fails otherwise.
- fn as_float<'a>(&'a mut self) -> &'a mut FloatFlow {
- fail!("called as_float() on a non-float flow")
- }
-
// Main methods
/// Pass 1 of reflow: computes minimum and preferred widths.
@@ -217,7 +211,6 @@ pub trait MutableFlowUtils {
pub enum FlowClass {
AbsoluteFlowClass,
BlockFlowClass,
- FloatFlowClass,
InlineBlockFlowClass,
InlineFlowClass,
TableFlowClass,
@@ -395,7 +388,7 @@ impl<'self> ImmutableFlowUtils for &'self Flow {
/// Returns true if this flow is a block or a float flow.
fn is_block_like(self) -> bool {
match self.class() {
- BlockFlowClass | FloatFlowClass => true,
+ BlockFlowClass => true,
AbsoluteFlowClass | InlineBlockFlowClass | InlineFlowClass | TableFlowClass => false,
}
}
@@ -408,7 +401,7 @@ impl<'self> ImmutableFlowUtils for &'self Flow {
/// Returns true if this flow is a block flow, an inline-block flow, or a float flow.
fn starts_block_flow(self) -> bool {
match self.class() {
- BlockFlowClass | InlineBlockFlowClass | FloatFlowClass => true,
+ BlockFlowClass | InlineBlockFlowClass => true,
AbsoluteFlowClass | InlineFlowClass | TableFlowClass => false,
}
}
@@ -417,7 +410,7 @@ impl<'self> ImmutableFlowUtils for &'self Flow {
fn starts_inline_flow(self) -> bool {
match self.class() {
InlineFlowClass => true,
- AbsoluteFlowClass | BlockFlowClass | FloatFlowClass | InlineBlockFlowClass |
+ AbsoluteFlowClass | BlockFlowClass | InlineBlockFlowClass |
TableFlowClass => false,
}
}
@@ -525,7 +518,6 @@ impl<'self> MutableFlowUtils for &'self mut Flow {
match self.class() {
BlockFlowClass => self.as_block().build_display_list_block(builder, dirty, list),
InlineFlowClass => self.as_inline().build_display_list_inline(builder, dirty, list),
- FloatFlowClass => self.as_float().build_display_list_float(builder, dirty, list),
_ => fail!("Tried to build_display_list_recurse of flow: {:?}", self),
};
diff --git a/src/components/main/servo.rc b/src/components/main/servo.rc
index 227bae8ab2a..f286368b332 100755
--- a/src/components/main/servo.rc
+++ b/src/components/main/servo.rc
@@ -81,7 +81,6 @@ pub mod layout {
pub mod context;
pub mod display_list_builder;
pub mod float_context;
- pub mod float;
pub mod flow;
pub mod layout_task;
pub mod inline;