diff options
author | Eric Atkinson <eatkinson@mozilla.com> | 2013-06-24 09:37:09 -0700 |
---|---|---|
committer | Eric Atkinson <eatkinson@mozilla.com> | 2013-06-24 16:07:02 -0700 |
commit | 0c63dda2904a77116218b07532d2f80cb159ae7d (patch) | |
tree | 000c22b26ecc114f360c62c820c7e08884929bb7 | |
parent | 94e7a86b7efe8b8c8d8ede0f3104c3893ff9a37a (diff) | |
download | servo-0c63dda2904a77116218b07532d2f80cb159ae7d.tar.gz servo-0c63dda2904a77116218b07532d2f80cb159ae7d.zip |
Allow floats to have specified heights
-rw-r--r-- | src/components/main/layout/block.rs | 2 | ||||
-rw-r--r-- | src/components/main/layout/box_builder.rs | 16 | ||||
-rw-r--r-- | src/components/main/layout/float.rs | 25 | ||||
-rw-r--r-- | src/components/main/layout/float_context.rs | 22 | ||||
-rw-r--r-- | src/components/main/layout/flow.rs | 8 | ||||
-rw-r--r-- | src/components/main/layout/model.rs | 12 |
6 files changed, 73 insertions, 12 deletions
diff --git a/src/components/main/layout/block.rs b/src/components/main/layout/block.rs index 175ee60073e..656d17530be 100644 --- a/src/components/main/layout/block.rs +++ b/src/components/main/layout/block.rs @@ -267,7 +267,7 @@ impl BlockFlowData { // 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) + // last_child.floats_out -> self.floats_out (done at the end of this method) let mut float_ctx = self.common.floats_in.clone(); for BlockFlow(self).each_child |kid| { do kid.with_mut_base |child_node| { diff --git a/src/components/main/layout/box_builder.rs b/src/components/main/layout/box_builder.rs index 6ec2092af99..0e478ba2654 100644 --- a/src/components/main/layout/box_builder.rs +++ b/src/components/main/layout/box_builder.rs @@ -161,6 +161,18 @@ impl BoxGenerator { assert!(block.box.is_none()); block.box = Some(new_box); }, + FloatFlow(float) => { + debug!("BoxGenerator[f%d]: point b", float.common.id); + let new_box = self.make_box(ctx, box_type, node, self.flow, builder); + + debug!("BoxGenerator[f%d]: attaching box[b%d] to float flow (node: %s)", + float.common.id, + new_box.id(), + node.debug_str()); + + assert!(float.box.is_none()); + float.box = Some(new_box); + }, _ => warn!("push_node() not implemented for flow f%d", self.flow.id()), } } @@ -384,7 +396,9 @@ pub impl LayoutTreeBuilder { // Inlines that are children of blocks create new flows if their // previous sibling was a block. (CSSDisplayInline, BlockFlow(*), Some(BlockFlow(*))) | - (CSSDisplayInlineBlock, BlockFlow(*), Some(BlockFlow(*))) => { + (CSSDisplayInlineBlock, BlockFlow(*), Some(BlockFlow(*))) | + (CSSDisplayInline, BlockFlow(*), Some(FloatFlow(*))) | + (CSSDisplayInlineBlock, BlockFlow(*), Some(FloatFlow(*))) => { self.create_child_generator(node, parent_generator, Flow_Inline) } diff --git a/src/components/main/layout/float.rs b/src/components/main/layout/float.rs index 5bd25784424..c63c21dbf25 100644 --- a/src/components/main/layout/float.rs +++ b/src/components/main/layout/float.rs @@ -85,7 +85,7 @@ impl FloatFlowData { } pub fn assign_widths_float(@mut self, _: &LayoutContext) { - debug!("assign_widths_block: assigning width for flow %?", self.common.id); + debug!("assign_widths_float: 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; @@ -117,13 +117,13 @@ impl FloatFlowData { let width = MaybeAuto::from_width(style.width(), remaining_width).spec_or_default(shrink_to_fit); + debug!("assign_widths_float -- width: %?", width); 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; } @@ -138,6 +138,8 @@ impl FloatFlowData { } } + self.common.position.size.width = remaining_width; + for FloatFlow(self).each_child |kid| { //assert!(kid.starts_block_flow() || kid.starts_inline_flow()); @@ -170,7 +172,7 @@ impl FloatFlowData { } } - let height = cur_y - top_offset; + let mut height = cur_y - top_offset; let mut noncontent_height = Au(0); self.box.map(|&box| { @@ -186,12 +188,23 @@ impl FloatFlowData { } }); - //TODO(eatkinson): compute heights using the 'height' property. - self.common.position.size.height = height + noncontent_height; + + //TODO(eatkinson): compute heights properly using the 'height' property. + for self.box.each |&box| { + + let height_prop = + MaybeAuto::from_height(box.style().height(), Au(0)).spec_or_default(Au(0)); + + height = geometry::max(height, height_prop) + noncontent_height; + debug!("assign_height_float -- height: %?", height); + do box.with_mut_base |base| { + base.position.size.height = height; + } + } let info = PlacementInfo { width: self.common.position.size.width, - height: self.common.position.size.height, + height: height, ceiling: Au(0), max_width: self.containing_width, f_type: FloatLeft, diff --git a/src/components/main/layout/float_context.rs b/src/components/main/layout/float_context.rs index dd35b4f91cb..0d026ecc942 100644 --- a/src/components/main/layout/float_context.rs +++ b/src/components/main/layout/float_context.rs @@ -55,7 +55,7 @@ impl FloatContext { } #[inline(always)] - fn with_base<R>(&mut self, callback: &fn(&mut FloatContextBase) -> R) -> R { + fn with_mut_base<R>(&mut self, callback: &fn(&mut FloatContextBase) -> R) -> R { match *self { Invalid => fail!("Float context no longer available"), Valid(ref mut base) => callback(base) @@ -72,7 +72,7 @@ impl FloatContext { #[inline(always)] pub fn translate(&mut self, trans: Point2D<Au>) -> FloatContext { - do self.with_base |base| { + do self.with_mut_base |base| { base.translate(trans); } replace(self, Invalid) @@ -87,11 +87,18 @@ impl FloatContext { #[inline(always)] pub fn add_float(&mut self, info: &PlacementInfo) -> FloatContext{ - do self.with_base |base| { + do self.with_mut_base |base| { base.add_float(info); } replace(self, Invalid) } + + #[inline(always)] + pub fn last_float_pos(&mut self) -> Point2D<Au> { + do self.with_base |base| { + base.last_float_pos() + } + } } impl FloatContextBase{ @@ -110,6 +117,15 @@ impl FloatContextBase{ self.offset += trans; } + fn last_float_pos(&self) -> Point2D<Au> { + assert!(self.floats_used > 0, "Error: tried to access FloatContext with no floats in it"); + + match self.float_data[self.floats_used - 1] { + None => fail!("FloatContext error: floats should never be None here"), + Some(float) => float.bounds.origin + } + } + /// Returns a rectangle that encloses the region from top to top + height, /// with width small enough that it doesn't collide with any floats. max_x /// is the x-coordinate beyond which floats have no effect (generally diff --git a/src/components/main/layout/flow.rs b/src/components/main/layout/flow.rs index 0d60eb117a6..e2c14ce22e9 100644 --- a/src/components/main/layout/flow.rs +++ b/src/components/main/layout/flow.rs @@ -420,11 +420,17 @@ impl<'self> FlowContext { None => ~"BlockFlow", } }, + FloatFlow(float) => { + match float.box { + Some(box) => fmt!("FloatFlow(box=b%d)", box.id()), + None => ~"FloatFlow", + } + }, _ => ~"(Unknown flow)" }; do self.with_base |base| { - fmt!("f%? %? floats %?", base.id, repr, base.num_floats) + fmt!("f%? %? floats %? size %?", base.id, repr, base.num_floats, base.position) } } } diff --git a/src/components/main/layout/model.rs b/src/components/main/layout/model.rs index 44bf3417a89..bd465db83b9 100644 --- a/src/components/main/layout/model.rs +++ b/src/components/main/layout/model.rs @@ -20,6 +20,7 @@ use newcss::units::{Em, Pt, Px}; use newcss::values::{CSSBorderWidth, CSSBorderWidthLength, CSSBorderWidthMedium}; use newcss::values::{CSSBorderWidthThick, CSSBorderWidthThin}; use newcss::values::{CSSWidth, CSSWidthLength, CSSWidthPercentage, CSSWidthAuto}; +use newcss::values::{CSSHeight, CSSHeightLength, CSSHeightPercentage, CSSHeightAuto}; use newcss::values::{CSSMargin, CSSMarginLength, CSSMarginPercentage, CSSMarginAuto}; use newcss::values::{CSSPadding, CSSPaddingLength, CSSPaddingPercentage}; /// Encapsulates the borders, padding, and margins, which we collectively call the "box model". @@ -61,6 +62,17 @@ impl MaybeAuto{ } } + pub fn from_height(height: CSSHeight, cb_height: Au) -> MaybeAuto{ + match height { + CSSHeightAuto => Auto, + CSSHeightPercentage(percent) => Specified(cb_height.scale_by(percent/100.0)), + //FIXME(eatkinson): Compute pt and em values properly + CSSHeightLength(Px(v)) | + CSSHeightLength(Pt(v)) | + CSSHeightLength(Em(v)) => Specified(Au::from_frac_px(v)), + } + } + pub fn spec_or_default(&self, default: Au) -> Au{ match *self{ Auto => default, |