mirror of
https://github.com/servo/servo.git
synced 2025-08-09 07:25:35 +01:00
layout: Rewrite intrinsic inline-size and automatic table layout to
match L. David Baron's work-in-progress specification. http://dbaron.org/css/intrinsic/ Column spans are not yet supported. This effectively adds support for percentage widths, and it also fixes many bugs, improving the layout of Google and Wikipedia.
This commit is contained in:
parent
c9ce56a85d
commit
c7e619dfe7
20 changed files with 1081 additions and 618 deletions
|
@ -14,11 +14,11 @@ use flow::{TableRowGroupFlowClass, FlowClass, Flow, ImmutableFlowUtils};
|
|||
use flow;
|
||||
use fragment::Fragment;
|
||||
use layout_debug;
|
||||
use table::{InternalTable, TableFlow};
|
||||
use model::IntrinsicISizesContribution;
|
||||
use table::{ColumnInlineSize, InternalTable, TableFlow};
|
||||
use wrapper::ThreadSafeLayoutNode;
|
||||
|
||||
use servo_util::geometry::Au;
|
||||
use std::cmp::max;
|
||||
use std::fmt;
|
||||
|
||||
/// A table formatting context.
|
||||
|
@ -26,14 +26,8 @@ use std::fmt;
|
|||
pub struct TableRowGroupFlow {
|
||||
pub block_flow: BlockFlow,
|
||||
|
||||
/// Column inline-sizes
|
||||
pub col_inline_sizes: Vec<Au>,
|
||||
|
||||
/// Column min inline-sizes.
|
||||
pub col_min_inline_sizes: Vec<Au>,
|
||||
|
||||
/// Column pref inline-sizes.
|
||||
pub col_pref_inline_sizes: Vec<Au>,
|
||||
/// Information about the inline-sizes of each column.
|
||||
pub column_inline_sizes: Vec<ColumnInlineSize>,
|
||||
}
|
||||
|
||||
impl TableRowGroupFlow {
|
||||
|
@ -42,9 +36,7 @@ impl TableRowGroupFlow {
|
|||
-> TableRowGroupFlow {
|
||||
TableRowGroupFlow {
|
||||
block_flow: BlockFlow::from_node_and_fragment(node, fragment),
|
||||
col_inline_sizes: vec!(),
|
||||
col_min_inline_sizes: vec!(),
|
||||
col_pref_inline_sizes: vec!(),
|
||||
column_inline_sizes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -53,9 +45,7 @@ impl TableRowGroupFlow {
|
|||
-> TableRowGroupFlow {
|
||||
TableRowGroupFlow {
|
||||
block_flow: BlockFlow::from_node(constructor, node),
|
||||
col_inline_sizes: vec!(),
|
||||
col_min_inline_sizes: vec!(),
|
||||
col_pref_inline_sizes: vec!(),
|
||||
column_inline_sizes: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -64,8 +54,8 @@ impl TableRowGroupFlow {
|
|||
}
|
||||
|
||||
fn initialize_offsets(&mut self) -> (Au, Au, Au) {
|
||||
// TODO: If border-collapse: collapse, block-start_offset, block-end_offset, and inline-start_offset
|
||||
// should be updated. Currently, they are set as Au(0).
|
||||
// TODO: If border-collapse: collapse, block-start_offset, block-end_offset, and
|
||||
// inline-start_offset should be updated. Currently, they are set as Au(0).
|
||||
(Au(0), Au(0), Au(0))
|
||||
}
|
||||
|
||||
|
@ -120,16 +110,8 @@ impl Flow for TableRowGroupFlow {
|
|||
&mut self.block_flow
|
||||
}
|
||||
|
||||
fn col_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<Au> {
|
||||
&mut self.col_inline_sizes
|
||||
}
|
||||
|
||||
fn col_min_inline_sizes<'a>(&'a self) -> &'a Vec<Au> {
|
||||
&self.col_min_inline_sizes
|
||||
}
|
||||
|
||||
fn col_pref_inline_sizes<'a>(&'a self) -> &'a Vec<Au> {
|
||||
&self.col_pref_inline_sizes
|
||||
fn column_inline_sizes<'a>(&'a mut self) -> &'a mut Vec<ColumnInlineSize> {
|
||||
&mut self.column_inline_sizes
|
||||
}
|
||||
|
||||
/// Recursively (bottom-up) determines the context's preferred and minimum inline-sizes. When
|
||||
|
@ -143,49 +125,47 @@ impl Flow for TableRowGroupFlow {
|
|||
/// used in fixed table layout calculation.
|
||||
fn bubble_inline_sizes(&mut self) {
|
||||
let _scope = layout_debug_scope!("table_rowgroup::bubble_inline_sizes {:s}",
|
||||
self.block_flow.base.debug_id());
|
||||
|
||||
let mut min_inline_size = Au(0);
|
||||
let mut pref_inline_size = Au(0);
|
||||
self.block_flow.base.debug_id());
|
||||
|
||||
let mut computation = IntrinsicISizesContribution::new();
|
||||
for kid in self.block_flow.base.child_iter() {
|
||||
assert!(kid.is_table_row());
|
||||
|
||||
// calculate min_inline-size & pref_inline-size for automatic table layout calculation
|
||||
// 'self.col_min_inline-sizes' collects the maximum value of cells' min-inline-sizes for each column.
|
||||
// 'self.col_pref_inline-sizes' collects the maximum value of cells' pref-inline-sizes for each column.
|
||||
if self.col_inline_sizes.is_empty() { // First Row
|
||||
assert!(self.col_min_inline_sizes.is_empty() && self.col_pref_inline_sizes.is_empty());
|
||||
// 'self.col_inline-sizes' collects the specified column inline-sizes from the first table-row for fixed table layout calculation.
|
||||
self.col_inline_sizes = kid.col_inline_sizes().clone();
|
||||
self.col_min_inline_sizes = kid.col_min_inline_sizes().clone();
|
||||
self.col_pref_inline_sizes = kid.col_pref_inline_sizes().clone();
|
||||
// Calculate minimum and preferred inline sizes for automatic table layout.
|
||||
if self.column_inline_sizes.is_empty() {
|
||||
// We're the first row.
|
||||
debug_assert!(self.column_inline_sizes.is_empty());
|
||||
self.column_inline_sizes = kid.column_inline_sizes().clone();
|
||||
} else {
|
||||
min_inline_size = TableFlow::update_col_inline_sizes(&mut self.col_min_inline_sizes, kid.col_min_inline_sizes());
|
||||
pref_inline_size = TableFlow::update_col_inline_sizes(&mut self.col_pref_inline_sizes, kid.col_pref_inline_sizes());
|
||||
let mut child_intrinsic_sizes =
|
||||
TableFlow::update_column_inline_sizes(&mut self.column_inline_sizes,
|
||||
kid.column_inline_sizes());
|
||||
|
||||
// update the number of column inline-sizes from table-rows.
|
||||
let num_cols = self.col_inline_sizes.len();
|
||||
let num_child_cols = kid.col_min_inline_sizes().len();
|
||||
for i in range(num_cols, num_child_cols) {
|
||||
self.col_inline_sizes.push(Au::new(0));
|
||||
let new_kid_min = kid.col_min_inline_sizes()[i];
|
||||
self.col_min_inline_sizes.push(kid.col_min_inline_sizes()[i]);
|
||||
let new_kid_pref = kid.col_pref_inline_sizes()[i];
|
||||
self.col_pref_inline_sizes.push(kid.col_pref_inline_sizes()[i]);
|
||||
min_inline_size = min_inline_size + new_kid_min;
|
||||
pref_inline_size = pref_inline_size + new_kid_pref;
|
||||
let column_count = self.column_inline_sizes.len();
|
||||
let child_column_count = kid.column_inline_sizes().len();
|
||||
for i in range(column_count, child_column_count) {
|
||||
let this_column_inline_size = (*kid.column_inline_sizes())[i];
|
||||
|
||||
// FIXME(pcwalton): Ignoring the percentage here seems dubious.
|
||||
child_intrinsic_sizes.minimum_inline_size =
|
||||
child_intrinsic_sizes.minimum_inline_size +
|
||||
this_column_inline_size.minimum_length;
|
||||
child_intrinsic_sizes.preferred_inline_size =
|
||||
child_intrinsic_sizes.preferred_inline_size +
|
||||
this_column_inline_size.preferred;
|
||||
self.column_inline_sizes.push(this_column_inline_size);
|
||||
}
|
||||
|
||||
computation.union_block(&child_intrinsic_sizes)
|
||||
}
|
||||
}
|
||||
|
||||
self.block_flow.base.intrinsic_inline_sizes.minimum_inline_size = min_inline_size;
|
||||
self.block_flow.base.intrinsic_inline_sizes.preferred_inline_size = max(
|
||||
min_inline_size, pref_inline_size);
|
||||
self.block_flow.base.intrinsic_inline_sizes = computation.finish()
|
||||
}
|
||||
|
||||
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When
|
||||
/// called on this context, the context has had its inline-size set by the parent context.
|
||||
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments.
|
||||
/// When called on this context, the context has had its inline-size set by the parent context.
|
||||
fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
|
||||
let _scope = layout_debug_scope!("table_rowgroup::assign_inline_sizes {:s}",
|
||||
self.block_flow.base.debug_id());
|
||||
|
@ -199,9 +179,14 @@ impl Flow for TableRowGroupFlow {
|
|||
let content_inline_size = containing_block_inline_size;
|
||||
|
||||
let inline_size_computer = InternalTable;
|
||||
inline_size_computer.compute_used_inline_size(&mut self.block_flow, ctx, containing_block_inline_size);
|
||||
inline_size_computer.compute_used_inline_size(&mut self.block_flow,
|
||||
ctx,
|
||||
containing_block_inline_size);
|
||||
|
||||
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, Some(self.col_inline_sizes.clone()));
|
||||
self.block_flow.propagate_assigned_inline_size_to_children(
|
||||
inline_start_content_edge,
|
||||
content_inline_size,
|
||||
Some(self.column_inline_sizes.as_slice()));
|
||||
}
|
||||
|
||||
fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue