diff --git a/src/components/main/layout/box_builder.rs b/src/components/main/layout/box_builder.rs index 07e9e6e3b3b..9311627d8dd 100644 --- a/src/components/main/layout/box_builder.rs +++ b/src/components/main/layout/box_builder.rs @@ -24,7 +24,8 @@ use newcss::values::{CSSDisplayTableRowGroup, CSSDisplayTableHeaderGroup, CSSDis use newcss::values::{CSSDisplayTableRow, CSSDisplayTableColumnGroup, CSSDisplayTableColumn}; use newcss::values::{CSSDisplayTableCell, CSSDisplayTableCaption}; use newcss::values::{CSSDisplayNone}; -use newcss::values::{CSSFloatNone}; +use newcss::values::{CSSFloatNone, CSSFloatLeft, CSSFloatRight}; +use layout::float_context::{FloatLeft, FloatRight}; use script::dom::element::*; use script::dom::node::{AbstractNode, CommentNodeTypeId, DoctypeNodeTypeId}; use script::dom::node::{ElementNodeTypeId, LayoutView, TextNodeTypeId}; @@ -370,17 +371,18 @@ impl LayoutTreeBuilder { // determine whether to float left or right. let is_float = if (node.is_element()) { match node.style().float() { - CSSFloatNone => false, - _ => true + CSSFloatNone => None, + CSSFloatLeft => Some(FloatLeft), + CSSFloatRight => Some(FloatRight) } } else { - false + None }; 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(_), _) if !is_float.is_none() => { + self.create_child_generator(node, parent_generator, Flow_Float(is_float.get())) } (CSSDisplayBlock, BlockFlow(info), _) => match (info.is_root, node.parent_node()) { @@ -574,13 +576,13 @@ impl LayoutTreeBuilder { pub fn make_flow(&mut self, ty: FlowContextType, node: AbstractNode) -> FlowContext { let info = FlowData::new(self.next_flow_id(), node); let result = match ty { - Flow_Absolute => AbsoluteFlow(@mut info), - Flow_Block => BlockFlow(@mut BlockFlowData::new(info)), - Flow_Float => FloatFlow(@mut FloatFlowData::new(info)), - Flow_InlineBlock => InlineBlockFlow(@mut info), - Flow_Inline => InlineFlow(@mut InlineFlowData::new(info)), - Flow_Root => BlockFlow(@mut BlockFlowData::new_root(info)), - Flow_Table => TableFlow(@mut info), + Flow_Absolute => AbsoluteFlow(@mut info), + Flow_Block => BlockFlow(@mut BlockFlowData::new(info)), + Flow_Float(f_type) => FloatFlow(@mut FloatFlowData::new(info, f_type)), + Flow_InlineBlock => InlineBlockFlow(@mut info), + Flow_Inline => InlineFlow(@mut InlineFlowData::new(info)), + Flow_Root => BlockFlow(@mut BlockFlowData::new_root(info)), + Flow_Table => TableFlow(@mut info), }; debug!("LayoutTreeBuilder: created flow: %s", result.debug_str()); result diff --git a/src/components/main/layout/float.rs b/src/components/main/layout/float.rs index 426ae8d6281..3d67a742fa0 100644 --- a/src/components/main/layout/float.rs +++ b/src/components/main/layout/float.rs @@ -8,7 +8,7 @@ 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 layout::float_context::{FloatContext, PlacementInfo, FloatLeft, FloatType}; use std::cell::Cell; use geom::point::Point2D; @@ -27,21 +27,25 @@ pub struct FloatFlowData { containing_width: Au, - /// Parent clobbers our position, so store it separately + /// Offset relative to where the parent tried to position this flow rel_pos: Point2D, + /// Left or right? + float_type: FloatType, + /// Index into the box list for inline floats index: Option, } impl FloatFlowData { - pub fn new(common: FlowData) -> FloatFlowData { + pub fn new(common: FlowData, float_type: FloatType) -> FloatFlowData { FloatFlowData { common: common, containing_width: Au(0), box: None, index: None, + float_type: float_type, rel_pos: Point2D(Au(0), Au(0)), } } @@ -210,7 +214,7 @@ impl FloatFlowData { height: height, ceiling: Au(0), max_width: self.containing_width, - f_type: FloatLeft, + f_type: self.float_type, }; // Place the float and return the FloatContext back to the parent flow. diff --git a/src/components/main/layout/float_context.rs b/src/components/main/layout/float_context.rs index f384c718d60..5b364705587 100644 --- a/src/components/main/layout/float_context.rs +++ b/src/components/main/layout/float_context.rs @@ -225,6 +225,7 @@ impl FloatContextBase{ f_type: info.f_type }; self.float_data[self.floats_used] = Some(new_float); + self.max_y = max(self.max_y, new_float.bounds.origin.y); self.floats_used += 1; } @@ -240,16 +241,26 @@ impl FloatContextBase{ let maybe_location = self.available_rect(float_y, info.height, info.max_width); debug!("place_float: Got available rect: %? for y-pos: %?", maybe_location, float_y); match maybe_location { + // If there are no floats blocking us, return the current location // TODO(eatknson): integrate with overflow - None => return Point2D(Au(0), float_y), + None => return match info.f_type { + FloatLeft => Point2D(Au(0), float_y), + FloatRight => Point2D(info.max_width - info.width, float_y) + }, + Some(rect) => { assert!(rect.origin.y + rect.size.height != float_y, "Non-terminating float placement"); // Place here if there is enough room if (rect.size.width >= info.width) { - return Point2D(rect.origin.x, float_y); + return match info.f_type { + FloatLeft => Point2D(rect.origin.x, float_y), + FloatRight => { + Point2D(rect.origin.x + rect.size.width - info.width, float_y) + } + }; } // Try to place at the next-lowest location. diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs index ccfe21b9250..d6bc65d73c0 100644 --- a/src/components/main/layout/flow.rs +++ b/src/components/main/layout/flow.rs @@ -31,7 +31,7 @@ use layout::box::RenderBox; use layout::context::LayoutContext; use layout::display_list_builder::{DisplayListBuilder, ExtraDisplayListData}; use layout::inline::{InlineFlowData}; -use layout::float_context::{FloatContext, Invalid}; +use layout::float_context::{FloatContext, Invalid, FloatType}; use std::cell::Cell; use std::uint; @@ -56,7 +56,7 @@ pub enum FlowContext { pub enum FlowContextType { Flow_Absolute, Flow_Block, - Flow_Float, + Flow_Float(FloatType), Flow_InlineBlock, Flow_Inline, Flow_Root,