Fix up problems with float placement

This commit is contained in:
Eric Atkinson 2013-06-24 16:06:45 -07:00
parent 0c63dda290
commit 49f80fd894
3 changed files with 34 additions and 10 deletions

View file

@ -249,11 +249,13 @@ impl BlockFlowData {
pub fn assign_height_block(@mut self, ctx: &mut 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);
let mut left_offset = Au(0);
for self.box.each |&box| { for self.box.each |&box| {
do box.with_model |model| { do box.with_model |model| {
top_offset = model.margin.top + model.border.top + model.padding.top; top_offset = model.margin.top + model.border.top + model.padding.top;
cur_y += top_offset; cur_y += top_offset;
left_offset = model.offset();
} }
} }
@ -268,7 +270,7 @@ impl BlockFlowData {
// visit child[i] // visit child[i]
// repeat until all children are visited. // repeat until all children are visited.
// last_child.floats_out -> self.floats_out (done at the end of this method) // last_child.floats_out -> self.floats_out (done at the end of this method)
let mut float_ctx = self.common.floats_in.clone(); let mut float_ctx = self.common.floats_in.translate(Point2D(-left_offset, -top_offset));
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.floats_in = float_ctx.clone(); child_node.floats_in = float_ctx.clone();
@ -310,7 +312,7 @@ impl BlockFlowData {
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)); self.common.floats_out = float_ctx.translate(Point2D(left_offset, 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,

View file

@ -27,6 +27,8 @@ pub struct FloatFlowData {
containing_width: Au, containing_width: Au,
/// Parent clobbers our position, so store it separately
rel_pos: Point2D<Au>,
/// Index into the box list for inline floats /// Index into the box list for inline floats
index: Option<uint>, index: Option<uint>,
@ -40,6 +42,7 @@ impl FloatFlowData {
containing_width: Au(0), containing_width: Au(0),
box: None, box: None,
index: None, index: None,
rel_pos: Point2D(Au(0), Au(0)),
} }
} }
@ -210,10 +213,10 @@ impl FloatFlowData {
f_type: FloatLeft, f_type: FloatLeft,
}; };
// Place the float and return the FloatContext back to the parent flow.
// After, grab the position and use that to set our position.
self.common.floats_out = self.common.floats_in.add_float(&info); self.common.floats_out = self.common.floats_in.add_float(&info);
self.rel_pos = self.common.floats_out.last_float_pos();
} }
pub fn build_display_list_float<E:ExtraDisplayListData>(@mut self, pub fn build_display_list_float<E:ExtraDisplayListData>(@mut self,
@ -221,15 +224,17 @@ impl FloatFlowData {
dirty: &Rect<Au>, dirty: &Rect<Au>,
offset: &Point2D<Au>, offset: &Point2D<Au>,
list: &Cell<DisplayList<E>>) { list: &Cell<DisplayList<E>>) {
let offset = *offset + self.rel_pos;
self.box.map(|&box| { self.box.map(|&box| {
box.build_display_list(builder, dirty, offset, list) box.build_display_list(builder, dirty, &offset, list)
}); });
// go deeper into the flow tree // go deeper into the flow tree
let flow = FloatFlow(self); let flow = FloatFlow(self);
for flow.each_child |child| { for flow.each_child |child| {
flow.build_display_list_for_child(builder, child, dirty, offset, list) flow.build_display_list_for_child(builder, child, dirty, &offset, list)
} }
} }
} }

View file

@ -122,7 +122,10 @@ impl FloatContextBase{
match self.float_data[self.floats_used - 1] { match self.float_data[self.floats_used - 1] {
None => fail!("FloatContext error: floats should never be None here"), None => fail!("FloatContext error: floats should never be None here"),
Some(float) => float.bounds.origin Some(float) => {
debug!("Returning float position: %?", float.bounds.origin + self.offset);
float.bounds.origin + self.offset
}
} }
} }
@ -135,6 +138,10 @@ impl FloatContextBase{
(max(top_1, top_2), min(bottom_1, bottom_2)) (max(top_1, top_2), min(bottom_1, bottom_2))
} }
debug!("available_rect: trying to find space at %?", top);
let top = top - self.offset.y;
// Relevant dimensions for the right-most left float // Relevant dimensions for the right-most left float
let mut (max_left, l_top, l_bottom) = (Au(0) - self.offset.x, None, None); let mut (max_left, l_top, l_bottom) = (Au(0) - self.offset.x, None, None);
// Relevant dimensions for the left-most right float // Relevant dimensions for the left-most right float
@ -183,7 +190,15 @@ impl FloatContextBase{
(None, None, None, None) => return None, (None, None, None, None) => return None,
_ => fail!("Reached unreachable state when computing float area") _ => fail!("Reached unreachable state when computing float area")
}; };
assert!(max_left < min_right, "Float position error");
// When the window is smaller than the float, we will return a rect
// with negative width.
assert!(max_left < min_right
|| max_left > max_x - self.offset.x
|| min_right < Au(0) - self.offset.x
,"Float position error");
//TODO(eatkinson): do we need to do something similar for heights?
assert!(top < bottom, "Float position error"); assert!(top < bottom, "Float position error");
Some(Rect{ Some(Rect{
@ -212,11 +227,13 @@ impl FloatContextBase{
/// LOCAL COORDINATES. i.e. must be translated before placed /// LOCAL COORDINATES. i.e. must be translated before placed
/// in the float list /// in the float list
fn place_float(&self, info: &PlacementInfo) -> Point2D<Au>{ fn place_float(&self, info: &PlacementInfo) -> Point2D<Au>{
debug!("place_float: Placing float with width %? and height %?", info.width, info.height);
// Can't go any higher than previous floats or // Can't go any higher than previous floats or
// previous elements in the document. // previous elements in the document.
let mut float_y = max(info.ceiling, self.max_y); let mut float_y = max(info.ceiling, self.max_y + self.offset.y);
loop { loop {
let maybe_location = self.available_rect(float_y, info.height, info.max_width); 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 { match maybe_location {
// If there are no floats blocking us, return the current location // If there are no floats blocking us, return the current location
// TODO(eatknson): integrate with overflow // TODO(eatknson): integrate with overflow