mirror of
https://github.com/servo/servo.git
synced 2025-08-03 20:50:07 +01:00
layout: Adjust the position of block formatting contexts based on float
placement. Improves Reddit considerably. Closes #3456.
This commit is contained in:
parent
a6ff0479d9
commit
3bb4020ff8
5 changed files with 58 additions and 3 deletions
|
@ -16,7 +16,7 @@
|
||||||
|
|
||||||
use construct::FlowConstructor;
|
use construct::FlowConstructor;
|
||||||
use context::LayoutContext;
|
use context::LayoutContext;
|
||||||
use floats::{ClearBoth, ClearLeft, ClearRight, FloatKind, Floats, PlacementInfo};
|
use floats::{ClearBoth, ClearLeft, ClearRight, FloatKind, FloatLeft, Floats, PlacementInfo};
|
||||||
use flow::{BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
use flow::{BaseFlow, BlockFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
||||||
use flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal, mut_base};
|
use flow::{MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal, mut_base};
|
||||||
use flow;
|
use flow;
|
||||||
|
@ -37,7 +37,7 @@ use gfx::display_list::{FloatStackingLevel, PositionedDescendantStackingLevel};
|
||||||
use gfx::display_list::{RootOfStackingContextLevel};
|
use gfx::display_list::{RootOfStackingContextLevel};
|
||||||
use gfx::render_task::RenderLayer;
|
use gfx::render_task::RenderLayer;
|
||||||
use servo_msg::compositor_msg::{FixedPosition, LayerId, Scrollable};
|
use servo_msg::compositor_msg::{FixedPosition, LayerId, Scrollable};
|
||||||
use servo_util::geometry::Au;
|
use servo_util::geometry::{Au, MAX_AU};
|
||||||
use servo_util::logical_geometry::WritingMode;
|
use servo_util::logical_geometry::WritingMode;
|
||||||
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
|
use servo_util::logical_geometry::{LogicalPoint, LogicalRect, LogicalSize};
|
||||||
use std::cmp::{max, min};
|
use std::cmp::{max, min};
|
||||||
|
@ -1463,6 +1463,39 @@ impl BlockFlow {
|
||||||
_ => NonformattingContext,
|
_ => NonformattingContext,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Per CSS 2.1 § 9.5, block formatting contexts' inline widths and positions are affected by
|
||||||
|
/// the presence of floats. This is the part of the assign-heights traversal that computes
|
||||||
|
/// the final inline position and width for such flows.
|
||||||
|
///
|
||||||
|
/// Note that this is part of the assign-block-sizes traversal, not the assign-inline-sizes
|
||||||
|
/// traversal as one might expect. That is because, in general, float placement cannot occur
|
||||||
|
/// until heights are assigned. To work around this unfortunate circular dependency, by the
|
||||||
|
/// time we get here we have already estimated the width of the block formatting context based
|
||||||
|
/// on the floats we could see at the time of inline-size assignment. The job of this function,
|
||||||
|
/// therefore, is not only to assign the final size but also to perform the layout again for
|
||||||
|
/// this block formatting context if our speculation was wrong.
|
||||||
|
fn assign_inline_position_for_formatting_context(&mut self) {
|
||||||
|
debug_assert!(self.formatting_context_type() != NonformattingContext);
|
||||||
|
|
||||||
|
let info = PlacementInfo {
|
||||||
|
size: LogicalSize::new(
|
||||||
|
self.fragment.style.writing_mode,
|
||||||
|
self.base.position.size.inline + self.fragment.margin.inline_start_end() +
|
||||||
|
self.fragment.border_padding.inline_start_end(),
|
||||||
|
self.fragment.border_box.size.block),
|
||||||
|
ceiling: self.base.position.start.b,
|
||||||
|
max_inline_size: MAX_AU,
|
||||||
|
kind: FloatLeft,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Offset our position by whatever displacement is needed to not impact the floats.
|
||||||
|
let rect = self.base.floats.place_between_floats(&info);
|
||||||
|
self.base.position.start.i = self.base.position.start.i + rect.start.i;
|
||||||
|
|
||||||
|
// TODO(pcwalton): If the inline-size of this flow is different from the size we estimated
|
||||||
|
// earlier, lay it out again.
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Flow for BlockFlow {
|
impl Flow for BlockFlow {
|
||||||
|
@ -1626,7 +1659,7 @@ impl Flow for BlockFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Move in from the inline-start border edge
|
// Move in from the inline-start border edge.
|
||||||
let inline_start_content_edge = self.fragment.border_box.start.i + self.fragment.border_padding.inline_start;
|
let inline_start_content_edge = self.fragment.border_box.start.i + self.fragment.border_padding.inline_start;
|
||||||
let padding_and_borders = self.fragment.border_padding.inline_start_end();
|
let padding_and_borders = self.fragment.border_padding.inline_start_end();
|
||||||
let content_inline_size = self.fragment.border_box.size.inline - padding_and_borders;
|
let content_inline_size = self.fragment.border_box.size.inline - padding_and_borders;
|
||||||
|
@ -1652,6 +1685,10 @@ impl Flow for BlockFlow {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if self.formatting_context_type() != NonformattingContext {
|
||||||
|
self.assign_inline_position_for_formatting_context();
|
||||||
|
}
|
||||||
|
|
||||||
let impacted = self.base.flags.impacted_by_floats();
|
let impacted = self.base.flags.impacted_by_floats();
|
||||||
if impacted {
|
if impacted {
|
||||||
self.assign_block_size(layout_context);
|
self.assign_block_size(layout_context);
|
||||||
|
|
|
@ -9,6 +9,7 @@ use geom::size::Size2D;
|
||||||
|
|
||||||
use serialize::{Encodable, Encoder};
|
use serialize::{Encodable, Encoder};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use std::i32;
|
||||||
use std::num::{NumCast, Zero};
|
use std::num::{NumCast, Zero};
|
||||||
use std::fmt;
|
use std::fmt;
|
||||||
|
|
||||||
|
@ -72,6 +73,8 @@ impl Default for Au {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub static MAX_AU: Au = Au(i32::MAX);
|
||||||
|
|
||||||
impl<E, S: Encoder<E>> Encodable<S, E> for Au {
|
impl<E, S: Encoder<E>> Encodable<S, E> for Au {
|
||||||
fn encode(&self, e: &mut S) -> Result<(), E> {
|
fn encode(&self, e: &mut S) -> Result<(), E> {
|
||||||
e.emit_f64(to_frac_px(*self))
|
e.emit_f64(to_frac_px(*self))
|
||||||
|
|
|
@ -139,3 +139,4 @@ flaky_gpu,flaky_linux == acid2_noscroll.html acid2_ref_broken.html
|
||||||
== img_block_maxwidth_a.html img_block_maxwidth_ref.html
|
== img_block_maxwidth_a.html img_block_maxwidth_ref.html
|
||||||
== img_block_maxwidth_b.html img_block_maxwidth_ref.html
|
== img_block_maxwidth_b.html img_block_maxwidth_ref.html
|
||||||
== float_clearance_a.html float_clearance_ref.html
|
== float_clearance_a.html float_clearance_ref.html
|
||||||
|
== block_formatting_context_a.html block_formatting_context_ref.html
|
||||||
|
|
7
tests/ref/block_formatting_context_a.html
Normal file
7
tests/ref/block_formatting_context_a.html
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div style="float: left;">4913</div>
|
||||||
|
<div style="overflow: hidden;">RIP Richard Kiel</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
7
tests/ref/block_formatting_context_ref.html
Normal file
7
tests/ref/block_formatting_context_ref.html
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
<div style="float: left;">4913</div>
|
||||||
|
<div>RIP Richard Kiel</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
Loading…
Add table
Add a link
Reference in a new issue