diff options
Diffstat (limited to 'components/layout/table_wrapper.rs')
-rw-r--r-- | components/layout/table_wrapper.rs | 155 |
1 files changed, 94 insertions, 61 deletions
diff --git a/components/layout/table_wrapper.rs b/components/layout/table_wrapper.rs index 7ec0ed874a4..5003dca66c1 100644 --- a/components/layout/table_wrapper.rs +++ b/components/layout/table_wrapper.rs @@ -21,7 +21,7 @@ use floats::FloatKind; use flow::{TableWrapperFlowClass, FlowClass, Flow, ImmutableFlowUtils}; use flow::{IMPACTED_BY_LEFT_FLOATS, IMPACTED_BY_RIGHT_FLOATS}; use fragment::{Fragment, FragmentBoundsIterator}; -use table::ColumnInlineSize; +use table::{ColumnComputedInlineSize, ColumnIntrinsicInlineSize}; use wrapper::ThreadSafeLayoutNode; use servo_util::geometry::Au; @@ -43,13 +43,7 @@ pub struct TableWrapperFlow { pub block_flow: BlockFlow, /// Intrinsic column inline sizes according to INTRINSIC § 4.1 - pub intrinsic_column_inline_sizes: Vec<ColumnInlineSize>, - - /// Computed inline-size for each column. - /// - /// FIXME: This should be a separate type that only contains computed inline - /// sizes. - pub column_inline_sizes: Vec<ColumnInlineSize>, + pub column_intrinsic_inline_sizes: Vec<ColumnIntrinsicInlineSize>, /// Table-layout property pub table_layout: TableLayout, @@ -68,8 +62,7 @@ impl TableWrapperFlow { }; TableWrapperFlow { block_flow: block_flow, - intrinsic_column_inline_sizes: vec!(), - column_inline_sizes: vec!(), + column_intrinsic_inline_sizes: vec!(), table_layout: table_layout } } @@ -86,8 +79,7 @@ impl TableWrapperFlow { }; TableWrapperFlow { block_flow: block_flow, - intrinsic_column_inline_sizes: vec!(), - column_inline_sizes: vec!(), + column_intrinsic_inline_sizes: vec!(), table_layout: table_layout } } @@ -105,14 +97,15 @@ impl TableWrapperFlow { }; TableWrapperFlow { block_flow: block_flow, - intrinsic_column_inline_sizes: vec!(), - column_inline_sizes: vec!(), + column_intrinsic_inline_sizes: vec!(), table_layout: table_layout } } /// Calculates table column sizes for automatic layout per INTRINSIC § 4.3. - fn calculate_table_column_sizes_for_automatic_layout(&mut self) { + fn calculate_table_column_sizes_for_automatic_layout( + &mut self, + intermediate_column_inline_sizes: &mut [IntermediateColumnInlineSize]) { // Find the padding and border of our first child, which is the table itself. // // This is a little weird because we're computing border/padding/margins for our child, @@ -141,9 +134,9 @@ impl TableWrapperFlow { // Compute all the guesses for the column sizes, and sum them. let mut total_guess = AutoLayoutCandidateGuess::new(); let guesses: Vec<AutoLayoutCandidateGuess> = - self.column_inline_sizes.iter().map(|column_inline_size| { - let guess = AutoLayoutCandidateGuess::from_column_inline_size( - column_inline_size, + self.column_intrinsic_inline_sizes.iter().map(|column_intrinsic_inline_size| { + let guess = AutoLayoutCandidateGuess::from_column_intrinsic_inline_size( + column_intrinsic_inline_size, available_inline_size); total_guess = total_guess + guess; guess @@ -153,12 +146,11 @@ impl TableWrapperFlow { let selection = SelectedAutoLayoutCandidateGuess::select(&total_guess, available_inline_size); let mut total_used_inline_size = Au(0); - for (column_inline_size, guess) in self.column_inline_sizes - .iter_mut() - .zip(guesses.iter()) { - column_inline_size.minimum_length = guess.calculate(selection); - column_inline_size.percentage = 0.0; - total_used_inline_size = total_used_inline_size + column_inline_size.minimum_length + for (intermediate_column_inline_size, guess) in + intermediate_column_inline_sizes.iter_mut().zip(guesses.iter()) { + intermediate_column_inline_size.size = guess.calculate(selection); + intermediate_column_inline_size.percentage = 0.0; + total_used_inline_size = total_used_inline_size + intermediate_column_inline_size.size } // Distribute excess inline-size if necessary per INTRINSIC § 4.4. @@ -168,13 +160,17 @@ impl TableWrapperFlow { if excess_inline_size > Au(0) && selection == UsePreferredGuessAndDistributeExcessInlineSize { let mut info = ExcessInlineSizeDistributionInfo::new(); - for column_inline_size in self.column_inline_sizes.iter() { - info.update(column_inline_size) + for column_intrinsic_inline_size in self.column_intrinsic_inline_sizes.iter() { + info.update(column_intrinsic_inline_size) } let mut total_distributed_excess_size = Au(0); - for column_inline_size in self.column_inline_sizes.iter_mut() { - info.distribute_excess_inline_size_to_column(column_inline_size, + for (intermediate_column_inline_size, column_intrinsic_inline_size) in + intermediate_column_inline_sizes.iter_mut() + .zip(self.column_intrinsic_inline_sizes + .iter()) { + info.distribute_excess_inline_size_to_column(intermediate_column_inline_size, + column_intrinsic_inline_size, excess_inline_size, &mut total_distributed_excess_size) } @@ -234,11 +230,11 @@ impl Flow for TableWrapperFlow { } fn bubble_inline_sizes(&mut self) { - // Get the column inline-sizes info from the table flow. + // Get the intrinsic column inline-sizes info from the table flow. for kid in self.block_flow.base.child_iter() { debug_assert!(kid.is_table_caption() || kid.is_table()); if kid.is_table() { - self.intrinsic_column_inline_sizes = kid.column_inline_sizes().clone() + self.column_intrinsic_inline_sizes = kid.column_intrinsic_inline_sizes().clone() } } @@ -253,7 +249,14 @@ impl Flow for TableWrapperFlow { "table_wrapper" }); - self.column_inline_sizes = self.intrinsic_column_inline_sizes.clone(); + let mut intermediate_column_inline_sizes = self.column_intrinsic_inline_sizes + .iter() + .map(|column_intrinsic_inline_size| { + IntermediateColumnInlineSize { + size: column_intrinsic_inline_size.minimum_length, + percentage: column_intrinsic_inline_size.percentage, + } + }).collect::<Vec<_>>(); // Table wrappers are essentially block formatting contexts and are therefore never // impacted by floats. @@ -273,7 +276,8 @@ impl Flow for TableWrapperFlow { match self.table_layout { FixedLayout => {} AutoLayout => { - self.calculate_table_column_sizes_for_automatic_layout() + self.calculate_table_column_sizes_for_automatic_layout( + intermediate_column_inline_sizes.as_mut_slice()) } } @@ -283,12 +287,29 @@ impl Flow for TableWrapperFlow { // In case of fixed layout, column inline-sizes are calculated in table flow. let assigned_column_inline_sizes = match self.table_layout { FixedLayout => None, - AutoLayout => Some(self.column_inline_sizes.as_slice()) + AutoLayout => { + Some(intermediate_column_inline_sizes.iter().map(|sizes| { + ColumnComputedInlineSize { + size: sizes.size, + } + }).collect::<Vec<_>>()) + } }; - self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, - content_inline_size, - assigned_column_inline_sizes); + match assigned_column_inline_sizes { + None => { + self.block_flow.propagate_assigned_inline_size_to_children( + inline_start_content_edge, + content_inline_size, + None) + } + Some(ref assigned_column_inline_sizes) => { + self.block_flow.propagate_assigned_inline_size_to_children( + inline_start_content_edge, + content_inline_size, + Some(assigned_column_inline_sizes.as_slice())); + } + } } @@ -395,27 +416,28 @@ impl AutoLayoutCandidateGuess { } /// Fills in the inline-size guesses for this column per INTRINSIC § 4.3. - fn from_column_inline_size(column_inline_size: &ColumnInlineSize, assignable_inline_size: Au) - -> AutoLayoutCandidateGuess { + fn from_column_intrinsic_inline_size(column_intrinsic_inline_size: &ColumnIntrinsicInlineSize, + assignable_inline_size: Au) + -> AutoLayoutCandidateGuess { let minimum_percentage_guess = - max(assignable_inline_size.scale_by(column_inline_size.percentage), - column_inline_size.minimum_length); + max(assignable_inline_size.scale_by(column_intrinsic_inline_size.percentage), + column_intrinsic_inline_size.minimum_length); AutoLayoutCandidateGuess { - minimum_guess: column_inline_size.minimum_length, + minimum_guess: column_intrinsic_inline_size.minimum_length, minimum_percentage_guess: minimum_percentage_guess, // FIXME(pcwalton): We need the notion of *constrainedness* per INTRINSIC § 4 to // implement this one correctly. - minimum_specified_guess: if column_inline_size.percentage > 0.0 { + minimum_specified_guess: if column_intrinsic_inline_size.percentage > 0.0 { minimum_percentage_guess - } else if column_inline_size.constrained { - column_inline_size.preferred + } else if column_intrinsic_inline_size.constrained { + column_intrinsic_inline_size.preferred } else { - column_inline_size.minimum_length + column_intrinsic_inline_size.minimum_length }, - preferred_guess: if column_inline_size.percentage > 0.0 { + preferred_guess: if column_intrinsic_inline_size.percentage > 0.0 { minimum_percentage_guess } else { - column_inline_size.preferred + column_intrinsic_inline_size.preferred }, } } @@ -526,19 +548,21 @@ impl ExcessInlineSizeDistributionInfo { } } - fn update(&mut self, column_inline_size: &ColumnInlineSize) { - if !column_inline_size.constrained && column_inline_size.percentage == 0.0 { + fn update(&mut self, column_intrinsic_inline_size: &ColumnIntrinsicInlineSize) { + if !column_intrinsic_inline_size.constrained && + column_intrinsic_inline_size.percentage == 0.0 { self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage = self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage + - column_inline_size.preferred; + column_intrinsic_inline_size.preferred; self.count_of_nonconstrained_columns_with_no_percentage += 1 } - if column_inline_size.constrained && column_inline_size.percentage == 0.0 { + if column_intrinsic_inline_size.constrained && + column_intrinsic_inline_size.percentage == 0.0 { self.preferred_inline_size_of_constrained_columns_with_no_percentage = self.preferred_inline_size_of_constrained_columns_with_no_percentage + - column_inline_size.preferred + column_intrinsic_inline_size.preferred } - self.total_percentage += column_inline_size.percentage; + self.total_percentage += column_intrinsic_inline_size.percentage; self.column_count += 1 } @@ -547,23 +571,25 @@ impl ExcessInlineSizeDistributionInfo { /// /// `#[inline]` so the compiler will hoist out the branch, which is loop-invariant. #[inline] - fn distribute_excess_inline_size_to_column(&self, - column_inline_size: &mut ColumnInlineSize, - excess_inline_size: Au, - total_distributed_excess_size: &mut Au) { + fn distribute_excess_inline_size_to_column( + &self, + intermediate_column_inline_size: &mut IntermediateColumnInlineSize, + column_intrinsic_inline_size: &ColumnIntrinsicInlineSize, + excess_inline_size: Au, + total_distributed_excess_size: &mut Au) { let proportion = if self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage > Au(0) { - column_inline_size.preferred.to_subpx() / + column_intrinsic_inline_size.preferred.to_subpx() / self.preferred_inline_size_of_nonconstrained_columns_with_no_percentage .to_subpx() } else if self.count_of_nonconstrained_columns_with_no_percentage > 0 { 1.0 / (self.count_of_nonconstrained_columns_with_no_percentage as CSSFloat) } else if self.preferred_inline_size_of_constrained_columns_with_no_percentage > Au(0) { - column_inline_size.preferred.to_subpx() / + column_intrinsic_inline_size.preferred.to_subpx() / self.preferred_inline_size_of_constrained_columns_with_no_percentage.to_subpx() } else if self.total_percentage > 0.0 { - column_inline_size.percentage / self.total_percentage + column_intrinsic_inline_size.percentage / self.total_percentage } else { 1.0 / (self.column_count as CSSFloat) }; @@ -573,7 +599,14 @@ impl ExcessInlineSizeDistributionInfo { let amount_to_distribute = min(excess_inline_size.scale_by(proportion), excess_inline_size - *total_distributed_excess_size); *total_distributed_excess_size = *total_distributed_excess_size + amount_to_distribute; - column_inline_size.minimum_length = column_inline_size.minimum_length + + intermediate_column_inline_size.size = intermediate_column_inline_size.size + amount_to_distribute } } + +/// An intermediate column size assignment. +struct IntermediateColumnInlineSize { + size: Au, + percentage: f64, +} + |