mirror of
https://github.com/servo/servo.git
synced 2025-06-17 04:44:28 +00:00
layout: Implement floated list items.
This patch also makes Servo not crash when `generated_containing_block_rect()` is called on a list item (as, for example, GitHub does), and for good measure I added the fix to other flows as well.
This commit is contained in:
parent
c8e68fa45c
commit
d891c677aa
9 changed files with 110 additions and 12 deletions
|
@ -860,8 +860,8 @@ impl<'a> FlowConstructor<'a> {
|
|||
|
||||
/// Builds a flow for a node with `display: table`. This yields a `TableWrapperFlow` with
|
||||
/// possibly other `TableCaptionFlow`s or `TableFlow`s underneath it.
|
||||
fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode,
|
||||
float_value: float::T) -> ConstructionResult {
|
||||
fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode, float_value: float::T)
|
||||
-> ConstructionResult {
|
||||
let fragment = Fragment::new_from_specific_info(node, SpecificFragmentInfo::TableWrapper);
|
||||
let wrapper_flow = match float_value {
|
||||
float::T::none => box TableWrapperFlow::from_node_and_fragment(node, fragment),
|
||||
|
@ -974,7 +974,12 @@ impl<'a> FlowConstructor<'a> {
|
|||
|
||||
/// Builds a flow for a node with `display: list-item`. This yields a `ListItemFlow` with
|
||||
/// possibly other `BlockFlow`s or `InlineFlow`s underneath it.
|
||||
fn build_flow_for_list_item(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||
fn build_flow_for_list_item(&mut self, node: &ThreadSafeLayoutNode, flotation: float::T)
|
||||
-> ConstructionResult {
|
||||
let flotation = match flotation {
|
||||
float::T::none => None,
|
||||
flotation => Some(FloatKind::from_property(flotation)),
|
||||
};
|
||||
let marker_fragment = match node.style().get_list().list_style_image {
|
||||
Some(ref url) => {
|
||||
Some(Fragment::new_from_specific_info(
|
||||
|
@ -1012,11 +1017,17 @@ impl<'a> FlowConstructor<'a> {
|
|||
let initial_fragment;
|
||||
match node.style().get_list().list_style_position {
|
||||
list_style_position::T::outside => {
|
||||
flow = box ListItemFlow::from_node_and_marker(self, node, marker_fragment);
|
||||
flow = box ListItemFlow::from_node_marker_and_flotation(self,
|
||||
node,
|
||||
marker_fragment,
|
||||
flotation);
|
||||
initial_fragment = None;
|
||||
}
|
||||
list_style_position::T::inside => {
|
||||
flow = box ListItemFlow::from_node_and_marker(self, node, None);
|
||||
flow = box ListItemFlow::from_node_marker_and_flotation(self,
|
||||
node,
|
||||
None,
|
||||
flotation);
|
||||
initial_fragment = marker_fragment;
|
||||
}
|
||||
}
|
||||
|
@ -1181,8 +1192,9 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
|
|||
}
|
||||
|
||||
// List items contribute their own special flows.
|
||||
(display::T::list_item, _, _) => {
|
||||
node.set_flow_construction_result(self.build_flow_for_list_item(node))
|
||||
(display::T::list_item, float_value, _) => {
|
||||
node.set_flow_construction_result(self.build_flow_for_list_item(node,
|
||||
float_value))
|
||||
}
|
||||
|
||||
// Inline items that are absolutely-positioned contribute inline fragment construction
|
||||
|
|
|
@ -11,6 +11,7 @@ use block::BlockFlow;
|
|||
use construct::FlowConstructor;
|
||||
use context::LayoutContext;
|
||||
use display_list_builder::ListItemFlowDisplayListBuilding;
|
||||
use floats::FloatKind;
|
||||
use flow::{Flow, FlowClass};
|
||||
use fragment::{Fragment, FragmentBorderBoxIterator};
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
@ -18,6 +19,7 @@ use wrapper::ThreadSafeLayoutNode;
|
|||
use geom::{Point2D, Rect};
|
||||
use gfx::display_list::DisplayList;
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::logical_geometry::LogicalRect;
|
||||
use servo_util::opts;
|
||||
use style::ComputedValues;
|
||||
use style::computed_values::list_style_type;
|
||||
|
@ -34,12 +36,17 @@ pub struct ListItemFlow {
|
|||
}
|
||||
|
||||
impl ListItemFlow {
|
||||
pub fn from_node_and_marker(constructor: &mut FlowConstructor,
|
||||
pub fn from_node_marker_and_flotation(constructor: &mut FlowConstructor,
|
||||
node: &ThreadSafeLayoutNode,
|
||||
marker_fragment: Option<Fragment>)
|
||||
marker_fragment: Option<Fragment>,
|
||||
flotation: Option<FloatKind>)
|
||||
-> ListItemFlow {
|
||||
ListItemFlow {
|
||||
block_flow: BlockFlow::from_node(constructor, node),
|
||||
block_flow: if let Some(flotation) = flotation {
|
||||
BlockFlow::float_from_node(constructor, node, flotation)
|
||||
} else {
|
||||
BlockFlow::from_node(constructor, node)
|
||||
},
|
||||
marker: marker_fragment,
|
||||
}
|
||||
}
|
||||
|
@ -93,6 +100,10 @@ impl Flow for ListItemFlow {
|
|||
self.block_flow.compute_absolute_position()
|
||||
}
|
||||
|
||||
fn place_float_if_applicable<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
|
||||
self.block_flow.place_float_if_applicable(layout_context)
|
||||
}
|
||||
|
||||
fn update_late_computed_inline_position_if_necessary(&mut self, inline_position: Au) {
|
||||
self.block_flow.update_late_computed_inline_position_if_necessary(inline_position)
|
||||
}
|
||||
|
@ -116,6 +127,10 @@ impl Flow for ListItemFlow {
|
|||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn generated_containing_block_rect(&self) -> LogicalRect<Au> {
|
||||
self.block_flow.generated_containing_block_rect()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_border_boxes(&self,
|
||||
iterator: &mut FragmentBorderBoxIterator,
|
||||
stacking_context_position: &Point2D<Au>) {
|
||||
|
|
|
@ -15,6 +15,7 @@ use wrapper::ThreadSafeLayoutNode;
|
|||
|
||||
use geom::{Point2D, Rect};
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::logical_geometry::LogicalRect;
|
||||
use std::fmt;
|
||||
use style::ComputedValues;
|
||||
use std::sync::Arc;
|
||||
|
@ -86,6 +87,10 @@ impl Flow for TableCaptionFlow {
|
|||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn generated_containing_block_rect(&self) -> LogicalRect<Au> {
|
||||
self.block_flow.generated_containing_block_rect()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_border_boxes(&self,
|
||||
iterator: &mut FragmentBorderBoxIterator,
|
||||
stacking_context_position: &Point2D<Au>) {
|
||||
|
|
|
@ -17,6 +17,7 @@ use wrapper::ThreadSafeLayoutNode;
|
|||
|
||||
use geom::{Point2D, Rect};
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::logical_geometry::LogicalRect;
|
||||
use std::fmt;
|
||||
use style::{UnsignedIntegerAttribute, ComputedValues};
|
||||
use std::sync::Arc;
|
||||
|
@ -167,6 +168,10 @@ impl Flow for TableCellFlow {
|
|||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn generated_containing_block_rect(&self) -> LogicalRect<Au> {
|
||||
self.block_flow.generated_containing_block_rect()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_border_boxes(&self,
|
||||
iterator: &mut FragmentBorderBoxIterator,
|
||||
stacking_context_position: &Point2D<Au>) {
|
||||
|
|
|
@ -20,6 +20,7 @@ use wrapper::ThreadSafeLayoutNode;
|
|||
|
||||
use geom::{Point2D, Rect};
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::logical_geometry::LogicalRect;
|
||||
use std::cmp::max;
|
||||
use std::fmt;
|
||||
use style::ComputedValues;
|
||||
|
@ -320,6 +321,10 @@ impl Flow for TableRowFlow {
|
|||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn generated_containing_block_rect(&self) -> LogicalRect<Au> {
|
||||
self.block_flow.generated_containing_block_rect()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_border_boxes(&self,
|
||||
iterator: &mut FragmentBorderBoxIterator,
|
||||
stacking_context_position: &Point2D<Au>) {
|
||||
|
|
|
@ -17,6 +17,7 @@ use wrapper::ThreadSafeLayoutNode;
|
|||
|
||||
use geom::{Point2D, Rect};
|
||||
use servo_util::geometry::Au;
|
||||
use servo_util::logical_geometry::LogicalRect;
|
||||
use std::fmt;
|
||||
use style::ComputedValues;
|
||||
use std::sync::Arc;
|
||||
|
@ -155,6 +156,10 @@ impl Flow for TableRowGroupFlow {
|
|||
self.block_flow.compute_overflow()
|
||||
}
|
||||
|
||||
fn generated_containing_block_rect(&self) -> LogicalRect<Au> {
|
||||
self.block_flow.generated_containing_block_rect()
|
||||
}
|
||||
|
||||
fn iterate_through_fragment_border_boxes(&self,
|
||||
iterator: &mut FragmentBorderBoxIterator,
|
||||
stacking_context_position: &Point2D<Au>) {
|
||||
|
|
|
@ -233,3 +233,4 @@ fragment=top != ../html/acid2.html acid2_ref.html
|
|||
== filter_sepia_a.html filter_sepia_ref.html
|
||||
== mix_blend_mode_a.html mix_blend_mode_ref.html
|
||||
!= text_overflow_a.html text_overflow_ref.html
|
||||
== floated_list_item_a.html floated_list_item_ref.html
|
||||
|
|
26
tests/ref/floated_list_item_a.html
Normal file
26
tests/ref/floated_list_item_a.html
Normal file
|
@ -0,0 +1,26 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Tests that list items can be floated. -->
|
||||
<style>
|
||||
ul div {
|
||||
display: list-item;
|
||||
float: left;
|
||||
list-style: none;
|
||||
margin: 0;
|
||||
}
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<div>Foo</div>
|
||||
<div>Bar</div>
|
||||
<div>Baz</div>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
24
tests/ref/floated_list_item_ref.html
Normal file
24
tests/ref/floated_list_item_ref.html
Normal file
|
@ -0,0 +1,24 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<!-- Tests that list items can be floated. -->
|
||||
<style>
|
||||
ul div {
|
||||
float: left;
|
||||
margin: 0;
|
||||
}
|
||||
ul {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<ul>
|
||||
<div>Foo</div>
|
||||
<div>Bar</div>
|
||||
<div>Baz</div>
|
||||
</ul>
|
||||
</body>
|
||||
</html>
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue